695593266@qq.com il y a 2 mois
Parent
commit
9432c5d10f

+ 17 - 3
src/api/productionPlan/index.js

@@ -371,6 +371,17 @@ export async function getProductKitting(params) {
   return Promise.reject(new Error(res.data.message));
 }
 
+// 根据生产计划ID查询金牛产品齐套数据
+export async function getJNProductKitting(params) {
+  const res = await request.get('/aps/productionplan/getJNProductKitting', {
+    params
+  });
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
 //发布计划是否需要审核
 export async function planIsReview(data) {
   const res = await request.post(
@@ -402,10 +413,13 @@ export async function taskReleaseWork(data) {
 }
 
 //提醒材料员领料
-export async function remindMaterialPicking(data) {
+export async function remindMaterialPicking(planCode) {
   const res = await request.post(
-    `/aps/productionplan/remindMaterialPicking`,
-    data
+    `/sys/notifysend/materialRequisitionReminderNotice`,
+    null,
+    {
+      params: { planCode }
+    }
   );
   if (res.data.code == 0) {
     return res.data.data;

+ 21 - 16
src/views/productionPlan/components/checkProductionPreparations.vue

@@ -256,6 +256,9 @@
     </ele-modal>
 
     <kitting-complete ref="kittingCompleteRef"></kitting-complete>
+    <kitting-complete-client9
+      ref="kittingCompleteClient9Ref"
+    ></kitting-complete-client9>
     <auxiliary-material
       ref="auxiliaryMaterialRef"
       @success="updateStatus"
@@ -276,11 +279,12 @@
   } from '@/api/productionPlan';
   import { listOrganizations, getUserPage } from '@/api/system/organization';
   import kittingComplete from './kittingComplete.vue';
+  import kittingCompleteClient9 from './kittingCompleteClient9.vue';
   import auxiliaryMaterial from './auxiliaryMaterial.vue';
   import { setFileUrl } from '@/components/addDoc/util.js';
 
   export default {
-    components: { kittingComplete, auxiliaryMaterial },
+    components: { kittingComplete, kittingCompleteClient9, auxiliaryMaterial },
     props: {
       type: {
         type: String,
@@ -459,6 +463,9 @@
     },
 
     computed: {
+      clientEnvironmentId() {
+        return this.$store.state.user.info.clientEnvironmentId;
+      },
       preReleaseTableData() {
         if (this.type == 'plan') {
           return this.preReleaseList.filter((item) => item.preType != 6);
@@ -703,7 +710,11 @@
           this.itemData.productionPlanId =
             this.itemData.productionPlanId || this.itemData.id;
           const list = [this.itemData];
-          this.$refs.kittingCompleteRef.open(list);
+          const refName =
+            this.clientEnvironmentId == 9
+              ? 'kittingCompleteClient9Ref'
+              : 'kittingCompleteRef';
+          this.$refs[refName].open(list);
         } else if (item.preType == '2') {
           const data = this.preReleaseList.find((it) => it.preType == 2);
           this.$refs.auxiliaryMaterialRef.open(this.itemData, data, 2);
@@ -830,26 +841,20 @@
       async remindMaterialPicking(row) {
         if (this.materialPickingRemindLoadingId) return;
 
-        const productionPlanId =
-          this.itemData.productionPlanId || this.itemData.id;
-        const params = {
-          ...row,
-          productionPlanId,
-          planId: productionPlanId,
-          preReleaseId: row.id,
-          preType: row.preType
-        };
-        if (this.type == 'order') {
-          params.apsWorkOrderId = this.itemData.id;
+        const planCode =
+          this.itemData.planCode || this.itemData.code || row.planCode;
+        if (!planCode) {
+          this.$message.warning('当前计划缺少计划编码,无法发送提醒');
+          return;
         }
 
         this.materialPickingRemindLoadingId = row.id;
-        await remindMaterialPicking(params)
+        await remindMaterialPicking(planCode)
           .then(() => {
             this.$message.success('已提醒材料员领料');
           })
           .catch((err) => {
-            this.$message.error(err.message || '提醒发送失败');
+            // this.$message.error(err.message || '提醒发送失败');
           })
           .finally(() => {
             this.materialPickingRemindLoadingId = '';
@@ -872,7 +877,7 @@
 
         if (index !== -1) {
           const data = this.preReleaseList[index];
-          data.statusStr = statusStr;
+          data.statusStr = statusStr == '不齐套' ? '缺料' : statusStr;
           this.$set(this.preReleaseList, index, data);
           this.updatePreRelease(data);
         }

+ 865 - 0
src/views/productionPlan/components/kittingCompleteClient9.vue

@@ -0,0 +1,865 @@
+<template>
+  <div>
+    <ele-modal
+      width="98vw"
+      :visible.sync="visible"
+      v-if="visible"
+      :close-on-click-modal="false"
+      custom-class="ele-dialog-form client9-kitting-modal"
+      title="齐套性检查"
+      :maxable="true"
+      append-to-body
+    >
+      <div v-loading="loading" class="client9-shell">
+        <section class="client9-overview">
+          <div class="overview-main">
+            <div class="overview-kicker">主材料齐套</div>
+            <div class="overview-title">
+              {{ displayValue(planInfo.productName) }}
+            </div>
+            <div class="overview-code">{{ displayValue(planCode) }}</div>
+          </div>
+          <div class="overview-metrics">
+            <div
+              v-for="item in summaryCards"
+              :key="item.label"
+              class="metric-item"
+              :class="item.type"
+            >
+              <span class="metric-label">{{ item.label }}</span>
+              <strong class="metric-value">{{ item.value }}</strong>
+            </div>
+          </div>
+        </section>
+
+        <section class="client9-info-grid">
+          <div v-for="item in planFields" :key="item.label" class="info-item">
+            <span class="info-label">{{ item.label }}</span>
+            <span class="info-value">{{ item.value }}</span>
+          </div>
+        </section>
+
+        <section class="result-insight" :class="resultStateClass">
+          <div class="result-status">
+            <span class="result-label">齐套结果</span>
+            <strong>{{
+              displayValue(primaryResult.finalFilledShortState)
+            }}</strong>
+          </div>
+          <div class="result-progress">
+            <div class="progress-meta">
+              <span>可用覆盖率</span>
+              <strong>{{ availabilityRate }}</strong>
+            </div>
+            <div class="progress-track">
+              <div
+                class="progress-bar"
+                :style="{ width: availabilityRate }"
+              ></div>
+            </div>
+          </div>
+          <div class="result-numbers">
+            <div
+              v-for="item in resultNumbers"
+              :key="item.label"
+              class="result-number"
+            >
+              <span>{{ item.label }}</span>
+              <strong>{{ item.value }}</strong>
+            </div>
+          </div>
+        </section>
+
+        <div class="form-wrapper table-panel">
+          <div
+            class="left-tree"
+            v-show="leftShow"
+            :style="{ width: leftWidth }"
+          >
+            <el-tree
+              ref="treeRef"
+              :expand-on-click-node="false"
+              :data="cardList"
+              :props="treeProps"
+              node-key="id"
+              highlight-current
+              @node-click="handleNodeClick"
+            ></el-tree>
+          </div>
+          <div :style="{ width: rightWidth }">
+            <ele-pro-table
+              ref="table"
+              :needPage="false"
+              :columns="columns"
+              :init-load="false"
+              :datasource="datasourceList"
+              row-key="jnKittingRowId"
+              :cache-key="`ProductionPlanClient9Table`"
+              border
+              height="calc(100vh - 530px)"
+              :selection.sync="selection"
+            >
+              <template v-slot:default>
+                <div class="detail-head">
+                  <div>
+                    <span class="detail-title">齐套明细</span>
+                    <span class="detail-subtitle">
+                      共 {{ datasourceAllList.length }} 条
+                    </span>
+                  </div>
+                  <span class="detail-bom">{{
+                    displayValue(currentBomText)
+                  }}</span>
+                </div>
+              </template>
+              <template v-slot:finalFilledShortState="{ row }">
+                <span
+                  class="status-pill"
+                  :class="getFinalStateClass(row.finalFilledShortState)"
+                >
+                  {{ displayValue(row.finalFilledShortState) }}
+                </span>
+              </template>
+            </ele-pro-table>
+          </div>
+        </div>
+      </div>
+
+      <div slot="footer">
+        <el-button plain @click="cancel">取消</el-button>
+      </div>
+    </ele-modal>
+  </div>
+</template>
+
+<script>
+  import { getJNProductKitting } from '@/api/productionPlan/index.js';
+
+  export default {
+    computed: {
+      planCode() {
+        return this.planInfo.productionPlanCode || this.planInfo.code || '';
+      },
+      planFields() {
+        return [
+          {
+            label: '规格',
+            value: this.displayValue(this.planInfo.specification)
+          },
+          {
+            label: '型号',
+            value: this.displayValue(this.planInfo.model)
+          },
+          {
+            label: '编码',
+            value: this.displayValue(this.planInfo.productCode)
+          },
+          {
+            label: '牌号',
+            value: this.displayValue(this.planInfo.brandNo)
+          },
+          {
+            label: '计划数量',
+            value: this.formatQuantityWithUnit(
+              this.planInfo.requiredFormingNum,
+              this.planInfo.measuringUnit || this.planInfo.unit
+            )
+          },
+          {
+            label: 'BOM',
+            value: this.displayValue(this.currentBomText)
+          }
+        ];
+      },
+      currentBomText() {
+        const bomName =
+          this.planInfo.bomName || this.planInfo.bomCategoryName || '';
+        const version =
+          this.planInfo.bomCategoryVersions || this.planInfo.versions || '';
+        const versionText = version
+          ? String(version).startsWith('V')
+            ? String(version)
+            : `V${version}.0`
+          : '';
+        if (bomName && versionText) return `${bomName} / ${versionText}`;
+        return bomName || versionText;
+      },
+      readyCount() {
+        return this.datasourceAllList.filter(
+          (item) => item.finalFilledShortState == '齐套'
+        ).length;
+      },
+      shortageCount() {
+        return this.datasourceAllList.filter(
+          (item) => item.finalFilledShortState == '缺料'
+        ).length;
+      },
+      readyRate() {
+        const total = this.datasourceAllList.length;
+        if (!total) return '0%';
+        return `${Math.round((this.readyCount / total) * 100)}%`;
+      },
+      summaryCards() {
+        return [
+          {
+            label: '物料项数',
+            value: this.datasourceAllList.length,
+            type: 'metric-total'
+          },
+          {
+            label: '齐套项',
+            value: this.readyCount,
+            type: 'metric-ready'
+          },
+          {
+            label: '缺料项',
+            value: this.shortageCount,
+            type: 'metric-risk'
+          },
+          {
+            label: '齐套率',
+            value: this.readyRate,
+            type: 'metric-rate'
+          }
+        ];
+      },
+      primaryResult() {
+        return this.datasourceAllList[0] || {};
+      },
+      resultNumbers() {
+        return [
+          {
+            label: '需求数量',
+            value: this.displayValue(this.primaryResult.needQuantity)
+          },
+          {
+            label: '可用数量',
+            value: this.displayValue(this.primaryResult.normalQuantity)
+          },
+          {
+            label: '库存数量',
+            value: this.displayValue(this.primaryResult.inventoryQuantity)
+          },
+          {
+            label: '最终缺料',
+            value: this.displayValue(this.primaryResult.finalFilledShortCount)
+          }
+        ];
+      },
+      availabilityRate() {
+        const needQuantity = Number(this.primaryResult.needQuantity || 0);
+        const normalQuantity = Number(this.primaryResult.normalQuantity || 0);
+        if (!needQuantity) return '0%';
+        const rate = Math.min(
+          100,
+          Math.max(0, Math.round((normalQuantity / needQuantity) * 100))
+        );
+        return `${rate}%`;
+      },
+      resultStateClass() {
+        if (this.primaryResult.finalFilledShortState == '缺料') {
+          return 'result-risk';
+        }
+        if (this.primaryResult.finalFilledShortState == '齐套') {
+          return 'result-ready';
+        }
+        return 'result-neutral';
+      },
+      columns() {
+        return [
+          {
+            width: 45,
+            type: 'selection',
+            columnKey: 'selection',
+            align: 'center',
+            fixed: 'left'
+          },
+          {
+            columnKey: 'index',
+            label: '序号',
+            type: 'index',
+            width: 55,
+            align: 'center',
+            fixed: 'left'
+          },
+          {
+            prop: 'needQuantity',
+            label: '需求数量',
+            align: 'center',
+            showOverflowTooltip: true
+          },
+          {
+            prop: 'normalQuantity',
+            label: '可用数量',
+            align: 'center',
+            showOverflowTooltip: true
+          },
+          {
+            prop: 'inventoryQuantity',
+            label: '库存数量',
+            align: 'center',
+            showOverflowTooltip: true
+          },
+          {
+            prop: 'finalFilledShortCount',
+            label: '最终缺料数量',
+            align: 'center',
+            showOverflowTooltip: true
+          },
+          {
+            slot: 'finalFilledShortState',
+            prop: 'finalFilledShortState',
+            label: '最终缺料状态',
+            align: 'center',
+            minWidth: 80,
+            fixed: 'right'
+          },
+          {
+            prop: 'message',
+            label: '消息内容',
+            align: 'center',
+            minWidth: 180,
+            showOverflowTooltip: true
+          }
+        ];
+      }
+    },
+    data() {
+      return {
+        visible: false,
+        loading: false,
+        planInfo: {
+          salesCode: ''
+        },
+        cardList: [],
+        treeProps: {
+          label: 'code',
+          children: 'children'
+        },
+        leftShow: false,
+        leftWidth: '0',
+        rightWidth: '100%',
+        datasourceAllList: [],
+        datasourceList: [],
+        planId: '',
+        selectNodeId: '',
+        produceType: 1,
+        selection: []
+      };
+    },
+    watch: {
+      leftShow(newVal) {
+        if (newVal) {
+          this.leftWidth = '230px';
+          this.rightWidth = 'calc(100% - 240px)';
+        } else {
+          this.leftWidth = '0';
+          this.rightWidth = '100%';
+        }
+      }
+    },
+    methods: {
+      async open(dataList, produceType) {
+        this.clearData();
+        this.produceType = produceType || 1;
+        this.visible = true;
+        this.cardList = Array.isArray(dataList) ? dataList : [];
+
+        this.$nextTick(() => {
+          if (this.$refs.table && this.$refs.table.reRenderTable) {
+            this.$refs.table.reRenderTable();
+          }
+        });
+
+        if (!this.cardList.length) return;
+
+        if (this.cardList.length === 1) {
+          this.leftShow = false;
+        } else {
+          this.leftShow = true;
+          const firstNodeKey = this.cardList[0].id;
+          this.$nextTick(() => {
+            if (this.$refs.treeRef) {
+              this.$refs.treeRef.setCurrentKey(firstNodeKey);
+            }
+          });
+        }
+
+        await this.handleNodeClick(this.cardList[0]);
+      },
+      async handleNodeClick(data) {
+        this.planInfo = data || {};
+        this.selectNodeId = this.planInfo.id || '';
+        this.planId = this.planInfo.productionPlanId || this.planInfo.id;
+        await this.getMaterialData();
+      },
+      async getMaterialData() {
+        if (!this.planId) {
+          this.resultProcess([]);
+          return;
+        }
+
+        this.loading = true;
+        try {
+          const result = await getJNProductKitting({ planId: this.planId });
+          this.resultProcess(result);
+        } catch (err) {
+          this.$message.error(err.message || '获取齐套数据失败');
+        } finally {
+          this.loading = false;
+        }
+      },
+      resultProcess(result) {
+        if (!Array.isArray(result) || result.length === 0) {
+          this.datasourceAllList = [];
+          this.datasourceList = [];
+          return;
+        }
+
+        this.datasourceAllList = result.map((item, index) => ({
+          ...item,
+          jnKittingRowId: `${this.planId}-${index}`
+        }));
+        this.datasourceList = this.datasourceAllList;
+      },
+      displayValue(value) {
+        if (value === 0) return 0;
+        return value || '-';
+      },
+      formatQuantityWithUnit(value, unit) {
+        const quantity = this.displayValue(value);
+        if (quantity === '-') return quantity;
+        return unit ? `${quantity} ${unit}` : quantity;
+      },
+      getFinalStateClass(value) {
+        if (value == '缺料') return 'statusRed';
+        if (value == '齐套') return 'statusGreen';
+        return 'statusNeutral';
+      },
+      cancel() {
+        this.clearData();
+        this.visible = false;
+      },
+      clearData() {
+        this.planInfo = {
+          salesCode: ''
+        };
+        this.datasourceList = [];
+        this.datasourceAllList = [];
+        this.selection = [];
+        this.cardList = [];
+        this.planId = '';
+        this.selectNodeId = '';
+      }
+    }
+  };
+</script>
+
+<style lang="scss" scoped>
+  :deep(.client9-kitting-modal) {
+    margin: 3vh auto 0 !important;
+    height: 94vh;
+    max-height: 94vh;
+    display: flex;
+    flex-direction: column;
+  }
+
+  :deep(.client9-kitting-modal .el-dialog__body) {
+    flex: 1;
+    min-height: 0;
+    background: #f6f8fb;
+    padding: 14px 24px 12px;
+    overflow: hidden;
+  }
+
+  :deep(.client9-kitting-modal .el-dialog__footer) {
+    flex-shrink: 0;
+    padding: 10px 24px 12px;
+  }
+
+  .client9-shell {
+    display: flex;
+    flex-direction: column;
+    height: 100%;
+    min-height: 0;
+    color: #1f2937;
+  }
+
+  .client9-overview {
+    display: flex;
+    align-items: stretch;
+    justify-content: space-between;
+    gap: 16px;
+    flex-shrink: 0;
+    padding: 14px 18px;
+    border: 1px solid #e5eef8;
+    border-radius: 8px;
+    background: linear-gradient(
+        135deg,
+        rgba(37, 99, 235, 0.08),
+        transparent 38%
+      ),
+      linear-gradient(90deg, #ffffff, #f8fbff);
+    box-shadow: 0 10px 26px rgba(15, 23, 42, 0.06);
+  }
+
+  .overview-main {
+    position: relative;
+    min-width: 240px;
+    padding-left: 14px;
+
+    &::before {
+      position: absolute;
+      top: 2px;
+      bottom: 2px;
+      left: 0;
+      width: 4px;
+      border-radius: 4px;
+      background: linear-gradient(180deg, #2563eb, #14b8a6);
+      content: '';
+    }
+  }
+
+  .overview-kicker {
+    color: #2563eb;
+    font-size: 13px;
+    font-weight: 600;
+    line-height: 20px;
+  }
+
+  .overview-title {
+    margin-top: 4px;
+    color: #111827;
+    font-size: 22px;
+    font-weight: 700;
+    line-height: 30px;
+    overflow-wrap: anywhere;
+  }
+
+  .overview-code {
+    margin-top: 6px;
+    color: #6b7280;
+    font-size: 13px;
+  }
+
+  .overview-metrics {
+    display: grid;
+    grid-template-columns: repeat(4, minmax(112px, 1fr));
+    gap: 10px;
+    width: min(640px, 56%);
+  }
+
+  .metric-item {
+    min-height: 64px;
+    padding: 10px 14px;
+    border: 1px solid #e5edf5;
+    border-radius: 8px;
+    background: rgba(255, 255, 255, 0.86);
+  }
+
+  .metric-label {
+    display: block;
+    color: #6b7280;
+    font-size: 12px;
+    line-height: 18px;
+  }
+
+  .metric-value {
+    display: block;
+    margin-top: 6px;
+    color: #111827;
+    font-size: 24px;
+    line-height: 28px;
+  }
+
+  .metric-ready .metric-value {
+    color: #0f766e;
+  }
+
+  .metric-risk .metric-value {
+    color: #dc2626;
+  }
+
+  .metric-rate .metric-value {
+    color: #2563eb;
+  }
+
+  .client9-info-grid {
+    display: grid;
+    grid-template-columns: repeat(6, minmax(130px, 1fr));
+    flex-shrink: 0;
+    gap: 8px;
+    margin: 10px 0 10px;
+  }
+
+  .info-item {
+    min-height: 52px;
+    padding: 8px 12px;
+    border: 1px solid #e8edf3;
+    border-radius: 8px;
+    background: #fff;
+  }
+
+  .info-label {
+    display: block;
+    color: #7b8494;
+    font-size: 12px;
+    line-height: 18px;
+  }
+
+  .info-value {
+    display: block;
+    margin-top: 4px;
+    color: #273142;
+    font-size: 14px;
+    font-weight: 600;
+    line-height: 20px;
+    overflow-wrap: anywhere;
+  }
+
+  .form-wrapper {
+    display: flex;
+  }
+
+  .result-insight {
+    display: grid;
+    grid-template-columns: 160px minmax(220px, 1fr) repeat(4, minmax(96px, 1fr));
+    align-items: center;
+    gap: 12px;
+    flex-shrink: 0;
+    min-height: 66px;
+    margin-bottom: 10px;
+    padding: 12px 16px;
+    border: 1px solid #e5edf5;
+    border-radius: 8px;
+    background: #fff;
+  }
+
+  .result-status {
+    display: flex;
+    flex-direction: column;
+    gap: 4px;
+
+    strong {
+      font-size: 20px;
+      line-height: 24px;
+    }
+  }
+
+  .result-label,
+  .progress-meta span,
+  .result-number span {
+    color: #7b8494;
+    font-size: 12px;
+    line-height: 18px;
+  }
+
+  .result-progress {
+    min-width: 0;
+  }
+
+  .progress-meta {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    margin-bottom: 8px;
+
+    strong {
+      color: #2563eb;
+      font-size: 18px;
+      line-height: 22px;
+    }
+  }
+
+  .progress-track {
+    height: 8px;
+    overflow: hidden;
+    border-radius: 8px;
+    background: #e5eaf2;
+  }
+
+  .progress-bar {
+    height: 100%;
+    border-radius: inherit;
+    background: linear-gradient(90deg, #2563eb, #14b8a6);
+    transition: width 0.2s ease;
+  }
+
+  .result-numbers {
+    display: contents;
+  }
+
+  .result-number {
+    min-width: 0;
+    padding-left: 12px;
+    border-left: 1px solid #edf2f7;
+
+    strong {
+      display: block;
+      margin-top: 4px;
+      color: #273142;
+      font-size: 18px;
+      line-height: 22px;
+    }
+  }
+
+  .result-ready {
+    border-color: #bfefe3;
+    background: linear-gradient(90deg, #f0fdfa, #ffffff 48%);
+
+    .result-status strong {
+      color: #0f766e;
+    }
+  }
+
+  .result-risk {
+    border-color: #fecdd3;
+    background: linear-gradient(90deg, #fff1f2, #ffffff 48%);
+
+    .result-status strong {
+      color: #dc2626;
+    }
+
+    .progress-bar {
+      background: linear-gradient(90deg, #f97316, #dc2626);
+    }
+  }
+
+  .result-neutral {
+    .result-status strong {
+      color: #64748b;
+    }
+  }
+
+  .table-panel {
+    flex: 1;
+    min-height: 0;
+    padding: 0;
+    border: 1px solid #e6edf5;
+    border-radius: 8px;
+    background: #fff;
+    overflow: hidden;
+  }
+
+  .detail-head {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    gap: 12px;
+    padding: 10px 14px;
+    border-bottom: 1px solid #edf2f7;
+    background: linear-gradient(180deg, #fbfdff, #f8fafc);
+  }
+
+  .detail-title {
+    color: #1f2937;
+    font-size: 14px;
+    font-weight: 700;
+  }
+
+  .detail-subtitle,
+  .detail-bom {
+    margin-left: 8px;
+    color: #8a94a6;
+    font-size: 12px;
+  }
+
+  .detail-bom {
+    margin-left: 0;
+    font-weight: 600;
+  }
+
+  .left-tree {
+    height: 100%;
+    max-height: 100%;
+    min-height: 0;
+    overflow: auto;
+    border-right: 1px solid #e6edf5;
+    background: #fbfdff;
+    margin-right: 10px;
+    padding: 10px;
+  }
+
+  .status-pill {
+    display: inline-flex;
+    align-items: center;
+    justify-content: center;
+    min-width: 48px;
+    height: 24px;
+    padding: 0 10px;
+    border-radius: 12px;
+    font-size: 12px;
+    font-weight: 600;
+  }
+
+  .statusRed {
+    color: #dc2626;
+    background: #fff1f2;
+    border: 1px solid #fecdd3;
+  }
+
+  .statusGreen {
+    color: #0f766e;
+    background: #ecfdf5;
+    border: 1px solid #bbf7d0;
+  }
+
+  .statusNeutral {
+    color: #64748b;
+    background: #f8fafc;
+    border: 1px solid #e2e8f0;
+  }
+
+  :deep(.ele-pro-table .el-table th) {
+    background: #f8fafc;
+    color: #2f3a4a;
+    font-weight: 700;
+  }
+
+  :deep(.ele-pro-table .el-table__row:hover > td) {
+    background: #f0f7ff;
+  }
+
+  @media (max-width: 1360px) {
+    .client9-overview {
+      flex-direction: column;
+    }
+
+    .overview-metrics {
+      width: 100%;
+    }
+
+    .client9-info-grid {
+      grid-template-columns: repeat(3, minmax(160px, 1fr));
+    }
+
+    .result-insight {
+      grid-template-columns: 150px minmax(200px, 1fr) repeat(
+          2,
+          minmax(110px, 1fr)
+        );
+    }
+
+    .result-numbers {
+      display: grid;
+      grid-template-columns: repeat(4, minmax(96px, 1fr));
+      grid-column: 1 / -1;
+      gap: 10px;
+    }
+  }
+
+  @media (max-width: 900px) {
+    .overview-metrics,
+    .client9-info-grid {
+      grid-template-columns: repeat(2, minmax(140px, 1fr));
+    }
+
+    .result-insight {
+      grid-template-columns: 1fr;
+    }
+
+    .result-numbers {
+      grid-template-columns: repeat(2, minmax(120px, 1fr));
+    }
+  }
+</style>

+ 15 - 1
src/views/productionPlan/index.vue

@@ -727,10 +727,20 @@
 
         return row.status == 3 || row.status == 2;
       },
+      isClientEnvironment9(clientEnvironmentId) {
+        return String(clientEnvironmentId) === '9';
+      },
+      filterColumnsByClientEnvironment(columns, clientEnvironmentId) {
+        if (!this.isClientEnvironment9(clientEnvironmentId)) {
+          return columns;
+        }
+        return columns.filter((column) => column.prop !== 'salesCode');
+      },
       setColumns() {
         let clientEnvironmentId =
           this.$store.state.user.info.clientEnvironmentId;
 
+        console.log('clientEnvironmentId11111', clientEnvironmentId);
         this.columns = [
           {
             width: 45,
@@ -1132,6 +1142,10 @@
             showOverflowTooltip: true
           }
         ];
+        this.columns = this.filterColumnsByClientEnvironment(
+          this.columns,
+          clientEnvironmentId
+        );
       },
 
       getPlanDotLine() {
@@ -1419,7 +1433,7 @@
             privateColumn.push({
               columnKey: 'action',
               label: '操作',
-              width: 380,
+              width: 360,
               align: 'center',
               resizable: false,
               fixed: 'right',

+ 74 - 14
src/views/saleOrder/salesToProductionNewTwo.vue

@@ -204,6 +204,7 @@
                 placeholder="选择日期"
                 value-format="yyyy-MM-dd HH:mm:ss"
                 @change="handleStartTimeChange(form)"
+                :disabled="isClient9"
               >
               </el-date-picker>
             </el-form-item>
@@ -230,6 +231,7 @@
                 placeholder="选择日期"
                 value-format="yyyy-MM-dd HH:mm:ss"
                 @change="handleEndTimeChange(form)"
+                :disabled="isClient9"
               >
               </el-date-picker>
             </el-form-item>
@@ -242,6 +244,7 @@
                 v-model="form.factoriesId"
                 style="width: 100%"
                 @change="factoriesIdFn"
+                :disabled="isClient9"
               >
                 <el-option
                   v-for="item of factoryList"
@@ -280,17 +283,26 @@
         <el-row> </el-row>
 
         <el-row :gutter="24" class="row-intro product_info">
-          <el-col v-bind="styleResponsive ? { lg: 3, md: 12 } : { span: 3 }">
+          <el-col
+            v-if="clientEnvironmentId != 9"
+            v-bind="styleResponsive ? { lg: 3, md: 12 } : { span: 3 }"
+          >
             <el-form-item label-width="88px" label="销售单数量:">{{
               form.codeNum
             }}</el-form-item>
           </el-col>
-          <el-col v-bind="styleResponsive ? { lg: 3, md: 12 } : { span: 3 }">
+          <el-col
+            v-if="clientEnvironmentId != 9"
+            v-bind="styleResponsive ? { lg: 3, md: 12 } : { span: 3 }"
+          >
             <el-form-item label-width="88px" label="订单总数量:"
               >{{ form.contractNum }}{{ form.measuringUnit }}</el-form-item
             >
           </el-col>
-          <el-col v-bind="styleResponsive ? { lg: 3, md: 12 } : { span: 4 }">
+          <el-col
+            v-if="clientEnvironmentId != 9"
+            v-bind="styleResponsive ? { lg: 3, md: 12 } : { span: 4 }"
+          >
             <el-form-item label-width="88px" label="订单总重量:">{{
               form.sumOrderWeight
             }}</el-form-item>
@@ -343,6 +355,7 @@
             prop="code"
             width="120"
             sortable
+            v-if="clientEnvironmentId != 9"
           >
           </el-table-column>
 
@@ -357,7 +370,10 @@
           <el-table-column label="行号" align="center" prop="lineNumber">
           </el-table-column>
           <el-table-column
-            :label="'订单数量' + (clientEnvironmentId == '4' ? '(方)' : '')"
+            :label="
+              (clientEnvironmentId == 9 ? '计划数量' : '订单数量') +
+              (clientEnvironmentId == '4' ? '(方)' : '')
+            "
             align="center"
             prop="contractNum"
             width="120"
@@ -368,7 +384,7 @@
             </template>
           </el-table-column>
           <el-table-column
-            label="订单重量"
+            :label="clientEnvironmentId == 9 ? '计划重量' : '订单重量'"
             align="center"
             prop="productSumWeight"
             width="120"
@@ -390,6 +406,7 @@
             label="生产编号"
             align="center"
             prop="productionCodes"
+            v-if="clientEnvironmentId != 9"
           >
           </el-table-column>
           <el-table-column
@@ -403,6 +420,7 @@
             :label="'欠交数量' + (clientEnvironmentId == '4' ? '(方)' : '')"
             align="center"
             prop="lackNum"
+            v-if="clientEnvironmentId != 9"
           >
           </el-table-column>
           <el-table-column
@@ -519,6 +537,7 @@
             align="center"
             prop="requiredFormingNum"
             width="120"
+            v-if="clientEnvironmentId != 9"
           >
             <template slot-scope="scope">
               <el-form-item
@@ -660,7 +679,12 @@
               {{ getDictValue('按单按库', row.orderLibraryType) }}
             </template>
           </el-table-column>
-          <el-table-column label="订单类型" align="center" prop="orderType">
+          <el-table-column
+            label="订单类型"
+            align="center"
+            prop="orderType"
+            v-if="clientEnvironmentId != 9"
+          >
             <template slot-scope="{ row }">
               {{ getDictValue('订单类型', row.orderType) }}
             </template>
@@ -670,6 +694,7 @@
             align="center"
             prop="deliveryTime"
             width="160"
+            v-if="clientEnvironmentId != 9"
           >
             <template slot-scope="scope">
               <el-form-item
@@ -700,7 +725,12 @@
             </template>
           </el-table-column>
 
-          <el-table-column label="生产交期" align="center" width="160">
+          <el-table-column
+            label="生产交期"
+            align="center"
+            width="160"
+            v-if="clientEnvironmentId != 9"
+          >
             <template slot-scope="scope">
               <el-form-item
                 label-width="0px"
@@ -734,6 +764,7 @@
             align="center"
             prop="reqMoldTime"
             width="180"
+            v-if="clientEnvironmentId != 9"
           >
             <template slot-scope="scope">
               <el-form-item
@@ -763,14 +794,25 @@
             </template>
           </el-table-column>
 
-          <el-table-column label="客户名称" align="center" prop="customerName">
+          <el-table-column
+            label="客户名称"
+            align="center"
+            prop="customerName"
+            v-if="clientEnvironmentId != 9"
+          >
           </el-table-column>
-          <el-table-column label="业务员" align="center" prop="salesman">
+          <el-table-column
+            label="业务员"
+            align="center"
+            prop="salesman"
+            v-if="clientEnvironmentId != 9"
+          >
           </el-table-column>
           <el-table-column
             label="交付要求"
             align="center"
             prop="deliveryRequirements"
+            v-if="clientEnvironmentId != 9"
           >
             <template slot-scope="{ row }">
               {{ getDictValue('交付要求', row.deliveryRequirements) }}
@@ -1030,6 +1072,9 @@
       clientEnvironmentId() {
         return this.$store.state.user.info.clientEnvironmentId;
       },
+      isClient9() {
+        return this.clientEnvironmentId == 9;
+      },
       // 是否开启响应式布局
       styleResponsive() {
         return this.$store.state.theme.styleResponsive;
@@ -1102,10 +1147,14 @@
         }
 
         const mergedColorList = Array.from(
-          new Set([...baseColorList, curColor].filter((v) => v !== '' && v != null))
+          new Set(
+            [...baseColorList, curColor].filter((v) => v !== '' && v != null)
+          )
         );
         const mergedModelList = Array.from(
-          new Set([...baseModelList, curModel].filter((v) => v !== '' && v != null))
+          new Set(
+            [...baseModelList, curModel].filter((v) => v !== '' && v != null)
+          )
         );
 
         this.$set(item, 'colorList', mergedColorList);
@@ -1481,10 +1530,18 @@
 
               // 把当前已选的值合并进可选列表,保证 el-select 能正确显示已选项
               const mergedColorList = Array.from(
-                new Set([...baseColorList, curColor].filter((v) => v !== '' && v != null))
+                new Set(
+                  [...baseColorList, curColor].filter(
+                    (v) => v !== '' && v != null
+                  )
+                )
               );
               const mergedModelList = Array.from(
-                new Set([...baseModelList, curModel].filter((v) => v !== '' && v != null))
+                new Set(
+                  [...baseModelList, curModel].filter(
+                    (v) => v !== '' && v != null
+                  )
+                )
               );
 
               return {
@@ -1655,7 +1712,10 @@
           this.$message.warning('请选择工艺路线');
           return;
         }
-        if (!this.form.salesOrders[0]?.reqMoldTime) {
+        if (
+          this.clientEnvironmentId != 9 &&
+          !this.form.salesOrders[0]?.reqMoldTime
+        ) {
           flag = false;
           this.$message.warning('请选择要求完成日期');
           return;

+ 2 - 2
vue.config.js

@@ -35,14 +35,14 @@ module.exports = {
         // target: 'http://192.168.1.103:18086',
         // target: 'http://192.168.1.158:18086',
         // target: 'http://192.168.158:18086',
-        target: 'http://192.168.1.251:18086',
+        // target: 'http://192.168.1.251:18086',
         // target: 'http://192.168.1.144:18086',
         // target: 'http://192.168.1.251:18186',
         // target: 'http://192.168.1.211:18086',
         // target: 'http://192.168.1.251:18186',
         // target: 'http://192.168.1.102:18086',
         // target: 'http://aiot.zoomwin.com.cn:51001/api',
-        // target: 'http://192.168.1.125:18086',
+        target: 'http://192.168.1.125:18086',
 
         // target: 'http://192.168.1.116:18086',