695593266@qq.com 6 日 前
コミット
a29679fb0c

+ 146 - 0
src/views/factoryCalendar/components/factoryCalendar.scss

@@ -954,11 +954,139 @@
     }
 
     .team-queue-plan .queue-name-only {
+      display: flex;
+      align-items: center;
+      gap: 4px;
       margin: 0;
       color: #303133;
       font-size: 16px;
       font-weight: 600;
       line-height: 22px;
+      white-space: nowrap;
+
+      .queue-name-label {
+        flex: 0 0 auto;
+        color: #7a8798;
+        font-size: 13px;
+        font-weight: 500;
+      }
+
+      .queue-name-text {
+        min-width: 0;
+        overflow: hidden;
+        text-overflow: ellipsis;
+        white-space: nowrap;
+      }
+    }
+
+    .team-queue-item {
+      position: relative;
+      padding: 0;
+      overflow: hidden;
+      border-color: #dfeaf5;
+      border-left: 0;
+      background:
+        linear-gradient(135deg, rgba(64, 158, 255, 0.08), transparent 42%),
+        linear-gradient(180deg, #ffffff, #f7fbff);
+      box-shadow:
+        inset 0 1px 0 rgba(255, 255, 255, 0.9),
+        0 8px 18px rgba(31, 45, 61, 0.05);
+      transition:
+        border-color 0.18s ease,
+        box-shadow 0.18s ease,
+        transform 0.18s ease;
+
+      &::before {
+        content: '';
+        position: absolute;
+        left: 0;
+        top: 0;
+        bottom: 0;
+        width: 4px;
+        background: linear-gradient(180deg, #67c23a, #25b8a8);
+      }
+
+      &:hover {
+        border-color: #b9dcff;
+        box-shadow:
+          inset 0 1px 0 rgba(255, 255, 255, 0.94),
+          0 12px 24px rgba(64, 158, 255, 0.1);
+        transform: translateY(-1px);
+      }
+    }
+
+    .team-queue-plan {
+      display: grid;
+      grid-template-columns: 42px minmax(0, 1fr) auto;
+      gap: 12px;
+      align-items: center;
+      min-height: 72px;
+      padding: 13px 14px 13px 16px;
+    }
+
+    .queue-avatar {
+      display: flex;
+      width: 42px;
+      height: 42px;
+      align-items: center;
+      justify-content: center;
+      border: 1px solid #cfe7ff;
+      border-radius: 8px;
+      background: linear-gradient(180deg, #eef7ff, #dff0ff);
+      color: #1677ff;
+      font-size: 20px;
+      box-shadow:
+        inset 0 1px 0 rgba(255, 255, 255, 0.86),
+        0 8px 14px rgba(64, 158, 255, 0.1);
+    }
+
+    .queue-info {
+      min-width: 0;
+    }
+
+    .team-queue-plan .queue-user-name {
+      display: flex;
+      min-width: 0;
+      align-items: center;
+      gap: 4px;
+      margin-top: 7px;
+      color: #6d7f92;
+      font-size: 13px;
+      line-height: 20px;
+      white-space: nowrap;
+      overflow: hidden;
+      text-overflow: ellipsis;
+
+      i {
+        flex: 0 0 auto;
+        color: #67c23a;
+        font-size: 14px;
+      }
+
+      span {
+        flex: 0 0 auto;
+      }
+
+      strong {
+        min-width: 0;
+        overflow: hidden;
+        color: #425466;
+        font-weight: 600;
+        text-overflow: ellipsis;
+        white-space: nowrap;
+      }
+    }
+
+    .queue-badge {
+      flex: 0 0 auto;
+      padding: 3px 9px;
+      border: 1px solid #d9f2d0;
+      border-radius: 12px;
+      background: #f0f9eb;
+      color: #3b8f22;
+      font-size: 12px;
+      line-height: 18px;
+      font-weight: 600;
     }
 
     .plan-metrics {
@@ -3546,11 +3674,29 @@
     }
 
     .team-queue-plan .queue-name-only {
+      display: flex;
+      align-items: center;
+      gap: 4px;
       margin: 0;
       color: #303133;
       font-size: 16px;
       font-weight: 600;
       line-height: 22px;
+      white-space: nowrap;
+
+      .queue-name-label {
+        flex: 0 0 auto;
+        color: #7a8798;
+        font-size: 13px;
+        font-weight: 500;
+      }
+
+      .queue-name-text {
+        min-width: 0;
+        overflow: hidden;
+        text-overflow: ellipsis;
+        white-space: nowrap;
+      }
     }
 
     .plan-metrics {

+ 33 - 38
src/views/factoryCalendar/index.vue

@@ -487,6 +487,7 @@
               <div slot="content" class="plan-tooltip">
                 <template v-if="isTeamQueueDrawer">
                   <div>排班名称:{{ getRelatedQueueName(plan) }}</div>
+                  <div>人员:{{ getRelatedQueueUserName(plan) || '-' }}</div>
                 </template>
                 <template v-else>
                   <div>
@@ -509,11 +510,30 @@
                   <div>结束时间:{{ plan.displayEndTime || '-' }}</div>
                 </template>
               </div>
-              <div class="plan-item">
+              <div
+                class="plan-item"
+                :class="{ 'team-queue-item': isTeamQueueDrawer }"
+              >
                 <div v-if="isTeamQueueDrawer" class="plan-main team-queue-plan">
-                  <div class="plan-name queue-name-only">
-                    {{ getRelatedQueueName(plan) }}
+                  <div class="queue-avatar">
+                    <i class="el-icon-user-solid"></i>
+                  </div>
+                  <div class="queue-info">
+                    <div class="plan-name queue-name-only">
+                      <span class="queue-name-label">排班名称:</span>
+                      <span class="queue-name-text">
+                        {{ getRelatedQueueName(plan) }}
+                      </span>
+                    </div>
+                    <div class="queue-user-name">
+                      <i class="el-icon-user"></i>
+                      <span>人员:</span>
+                      <strong>
+                        {{ getRelatedQueueUserName(plan) || '-' }}
+                      </strong>
+                    </div>
                   </div>
+                  <div class="queue-badge">排班</div>
                 </div>
                 <div v-else class="plan-main">
                   <div class="plan-topline">
@@ -2360,6 +2380,9 @@
       getRelatedQueueName(plan = {}) {
         return plan.teamQueueName || '-';
       },
+      getRelatedQueueUserName(plan = {}) {
+        return plan.userName || '';
+      },
       getDetailPlanCount(details = []) {
         const relatedPlans = this.getDetailRelatedPlans(details);
         if (relatedPlans.length) {
@@ -3390,29 +3413,10 @@
           const calendar = this.calendars.find(
             (item) => item.id === this.adjustForm.calendarId
           );
-          const duplicateConflict = this.hasDuplicateDetail(
-            calendar.id,
-            this.adjustForm.adjustDate,
-            this.adjustForm.startTime,
-            this.adjustForm.endTime
-          )
-            ? [
-                {
-                  message: '同一日期同一日历类型已存在重叠时段'
-                }
-              ]
-            : [];
-          const conflict = [
-            ...duplicateConflict,
-            ...this.checkConflict({
-              calendarType: calendar.calendarType,
-              calendarDate: this.adjustForm.adjustDate,
-              startTime: this.adjustForm.startTime,
-              endTime: this.adjustForm.endTime,
-              dateType: this.getAdjustDateType(this.adjustForm.adjustType),
-              scheduleStatus: this.adjustForm.adjustType === 2 ? 0 : 1
-            })
-          ];
+          if (!calendar) {
+            this.$message.error('请选择关联日历');
+            return;
+          }
           const saveApply = async () => {
             const originalDetails = this.details.filter(
               (item) =>
@@ -3440,7 +3444,7 @@
               expireTime: this.adjustForm.expireTime,
               applyReason: this.adjustForm.applyReason,
               applyStatus: 0,
-              isConflict: conflict.length ? 1 : 0,
+              isConflict: 0,
               applyUserName: '当前用户',
               applyTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
               approveNode: '',
@@ -3455,8 +3459,7 @@
                 newContent: adjustRow.newContent,
                 effectiveTime: this.adjustForm.effectiveTime,
                 expireTime: this.adjustForm.expireTime,
-                applyReason: this.adjustForm.applyReason,
-                forceSubmit: true
+                applyReason: this.adjustForm.applyReason
               });
               await this.loadRemoteAdjustData();
               this.invalidateConflictCache();
@@ -3468,15 +3471,7 @@
               this.$message.error(e?.message || '提交审批失败,请检查接口返回');
             }
           };
-          if (conflict.length) {
-            this.$confirm(
-              `预校验发现 ${conflict.length} 条冲突,是否强制提交审批?`,
-              '冲突提示',
-              { type: 'warning' }
-            ).then(saveApply);
-          } else {
-            saveApply();
-          }
+          saveApply();
         });
       },
       openApproveDialog(row, status) {

+ 14 - 4
src/views/material/product/components/QualityInfo.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="other">
     <fieldset :disabled="disabled" style="border: none; padding: 0; margin: 0;">
-    <el-form label-width="130px" ref="form" :model="form" :rules="rules">
+    <el-form label-width="130px" ref="form" :model="formModel" :rules="rules">
       <div class="divider">
         <div class="title">
           <div class="ele-bg-primary"></div>
@@ -10,7 +10,7 @@
         <div class="ele-bg-primary ele-width"></div>
       </div>
       <el-row :gutter="24">
-        <el-col :span="8" v-for="(item, index) in form" :key="index">
+        <el-col :span="8" v-for="(item, index) in formList" :key="index">
           <el-form-item
             :label="
               item.dataType == 1
@@ -125,8 +125,8 @@
   export default {
     props: {
       form: {
-        type: Object,
-        default: {}
+        type: Array,
+        default: () => []
       },
       disabled: {
         type: Boolean,
@@ -134,6 +134,16 @@
       }
     },
     components: {},
+    computed: {
+      formList() {
+        return Array.isArray(this.form) ? this.form : [];
+      },
+      formModel() {
+        return {
+          list: this.formList
+        };
+      }
+    },
     data() {
       return {
         qualityTemplateList: [],

+ 21 - 4
src/views/material/product/components/link-msg.vue

@@ -425,6 +425,23 @@
       this.requestDict('重量单位');
     },
     methods: {
+      getTableData(data) {
+        if (Array.isArray(data)) {
+          return data;
+        }
+        if (Array.isArray(data?.list)) {
+          return data.list;
+        }
+        if (Array.isArray(data?.records)) {
+          return data.records;
+        }
+        if (data && typeof data === 'object') {
+          return Object.values(data).reduce((list, item) => {
+            return list.concat(Array.isArray(item) ? item : []);
+          }, []);
+        }
+        return [];
+      },
       //BOM列表
       async getBomData() {
         const data = await getBomAssociationList({
@@ -433,12 +450,12 @@
           bomType: 1,
           isTemp: 0
         });
-        this.bomData = data || [];
+        this.bomData = this.getTableData(data);
       },
       //工艺路线
       async getRoutingData() {
         const data = await getBomRoutingList(this.id);
-        this.pathData = data || [];
+        this.pathData = this.getTableData(data);
       },
       // 关联设备
       async getEqData() {
@@ -448,7 +465,7 @@
           categoryLevelGroupId: this.categoryLevelGroupId
         });
 
-        this.eqData = data;
+        this.eqData = this.getTableData(data);
       },
       // 关联舟皿
       async getModuleData() {
@@ -458,7 +475,7 @@
           categoryLevelGroupId: this.categoryLevelGroupId
         });
 
-        this.moduleData = data;
+        this.moduleData = this.getTableData(data);
       },
       // 关联供应商/生产厂家
       async contactQueryByCategoryIdsAPI(type) {

+ 33 - 9
src/views/material/product/detail.vue

@@ -844,6 +844,7 @@
 
         ruleCode: null,
         codeShow: false,
+        autoCodeRouteKey: '',
 
         status: null,
         isNetWeight: 0,
@@ -1022,9 +1023,7 @@
       //   const code = await getCode(this.ruleCode);
       //   this.$set(this.form, 'code', code);
       // }
-      if (this.status != 0) {
-        this.getCode();
-      }
+      await this.generateCodeIfNeeded();
       this.getFieldModel();
 
       // this.getDictList('zeroPartPros');
@@ -1101,9 +1100,7 @@
       //   const code = await getCode(this.ruleCode);
       //   this.$set(this.form, 'code', code);
       // }
-      if (this.status != 0) {
-        this.getCode();
-      }
+      await this.generateCodeIfNeeded();
       this.getFieldModel();
       this.getAttributeList('inventory_type');
 
@@ -1438,9 +1435,7 @@
           //   this.$set(this.form, 'code', code);
           // }
           // console.log(this.form, 'this.form');
-          if (this.status != 0) {
-            this.getCode();
-          }
+          await this.generateCodeIfNeeded(true);
         }
 
         this.$forceUpdate();
@@ -1461,6 +1456,35 @@
         this.$set(this.form, 'code', val);
       },
 
+      shouldAutoGenerateCode() {
+        const status = Number(this.status);
+        return !this.isReadOnly && (status === 1 || status === 2);
+      },
+
+      getAutoCodeRouteKey() {
+        const { t, id, categoryLevelId, categoryLevelPathId } =
+          this.$route.query;
+        return [
+          t || '',
+          id || '',
+          this.status || '',
+          this.form.categoryLevelId || categoryLevelId || '',
+          this.form.categoryLevelPathId || categoryLevelPathId || ''
+        ].join('|');
+      },
+
+      async generateCodeIfNeeded(force = false) {
+        if (!this.shouldAutoGenerateCode()) {
+          return;
+        }
+        const routeKey = this.getAutoCodeRouteKey();
+        if (!force && this.autoCodeRouteKey === routeKey) {
+          return;
+        }
+        this.autoCodeRouteKey = routeKey;
+        await this.getCode();
+      },
+
       async getCode() {
         let parentId = [];
         let categoryLevelPathId = this.PathInfo?.categoryLevelPathId

+ 3 - 3
vue.config.js

@@ -35,16 +35,16 @@ module.exports = {
         // target: 'http://192.168.1.3:18086',
         // target: 'http://192.168.1.158:18086',
         // target: 'http://192.168.1.176:18086',
-        // target: 'http://192.168.1.125:18086',
+        target: 'http://192.168.1.125:18086',
         // target: 'http://192.168.1.251:51005',
         // target: 'http://192.168.1.251:18186',
-        target: 'http://192.168.1.251:18086',
+        // target: 'http://192.168.1.251:18086',
         // target: 'http://192.168.1.251:18186',
         // target: 'http://192.168.1.3:18086',
         // target: 'http://192.168.1.251:18186', // 测试环境
         // target: 'http://192.168.1.251:18087',
         // target: 'http://192.168.1.116:18086',
-        // target: 'http://192.168.1.251:18086',
+        // target: 'http://192.168.1.125:18086',
         // target: 'http://192.168.1.11:18086', // 开发
         // target: 'http://192.168.1.116:18086', // 赵沙金
         // target: 'http://aiot.zoomwin.com.cn:51001/api',