Quellcode durchsuchen

Merge branch 'dev' of http://110.41.163.243:9980/kd-aiot/kd-aiot-frontend into dev

xieyong vor 4 Tagen
Ursprung
Commit
cacb0862e7

+ 5 - 3
src/views/material/BOMmanage/components/baseInfo.vue

@@ -35,10 +35,12 @@
         </el-col>
         <el-col :span="4" label-width="78px">
           <el-form-item label="版本号:" prop="type">
-            <span v-if="dataInfo.versions && dataInfo.versions.includes('V')">{{
-              dataInfo.versions
+            <!-- 版本为空就留空 -->
+            <span v-if="dataInfo.versions">{{
+              dataInfo.versions.includes('V')
+                ? dataInfo.versions
+                : 'V' + dataInfo.versions + '.0'
             }}</span>
-            <span v-else> V{{ dataInfo.versions }}.0</span>
           </el-form-item>
         </el-col>
         <el-col :span="4" label-width="80px">

+ 142 - 11
src/views/material/BOMmanage/components/detailedList.vue

@@ -9,7 +9,7 @@
       :pagination="pagination"
       :datasource="datasource"
       :page-size="20"
-      :cache-key="useNewColumns ? 'routed_detailed_list_v2' : 'routed_detailed_list'"
+      :cache-key="useNewColumns ? 'routed_detailed_list_v3' : 'routed_detailed_list'"
       class="dict-table"
       tool-class="ele-toolbar-actions"
       :height="tableHeight"
@@ -76,9 +76,17 @@
         </el-input>
       </template>
 
+      <!-- 序号:与新 columns 方案绑定。新方案按层级单独计数(同层 1、2、3…),老方案用连续行号 -->
+      <template v-slot:rowIndex="{ row, $index }">
+        {{ rowIndexText(row, $index) }}
+      </template>
+
+      <!-- 总重:前端按 用量 × 单重 计算(用量/单重改了立即跟着变) -->
+      <template v-slot:totalWeight="{ row }">{{ totalWeightOf(row) }}</template>
+
       <template v-slot:versions="{ row }"> 
+        <!-- 版本为空就留空,不显示"无" -->
         <template v-if="row.versions">V{{ row.versions }}.0</template>
-        <template v-else>无</template>
       </template>
 
       <template v-slot:rootCategoryLevelId="{ row }"
@@ -154,7 +162,7 @@
               v-for="item in row.resourceBomVersionList"
               :key="item.versions"
               :value="item.versions"
-              :label="'V' + item.versions + '.0'"
+              :label="item.versions ? 'V' + item.versions + '.0' : ''"
             ></el-option>
           </el-select>
         </div>
@@ -292,9 +300,15 @@
 
     data() {
       return {
+        // 当前分页位置
+        currentPage: 1,
+        currentLimit: 20,
+        // 层级序号:rowId -> 该行在“同层级”里的序号(跨页连续)
+        levelSeqMap: {},
+        levelSeqKey: '',
         produceTypeList,
         clientEnvironmentId: this.$store.state.user.info.clientEnvironmentId,
-        // 是否启用新 columns 方案(true=新方案,false=老方案)
+        // 是否启用新 columns 方案(true=新方案,false=老方案);序号方案与新 columns 方案绑定
         useNewColumns: false,
         pagination: {
           tableTotal: 0
@@ -488,23 +502,27 @@
             width: 100
           },
           {
-            prop: 'sn',
-            label: '明细表序号',
+            // 序号:普通列 + 前端插槽渲染行号(见模板 v-slot:rowIndex),不绑定 sn;
+            // 也不能用 type: 'index':index 列不在列设置缓存里,会被 ele-pro-table 排到最前面。
+            prop: 'rowIndex',
+            columnKey: 'rowIndex',
+            label: '序号',
             align: 'center',
-            width: 120,
-            showOverflowTooltip: true
+            width: 90,
+            showOverflowTooltip: true,
+            slot: 'rowIndex'
           },
           {
             prop: 'categoryCode',
             label: '物料编码',
             showOverflowTooltip: true,
-            width: 120
+            width: 180
           },
           {
             prop: 'imgCode',
             label: '零部件图号(规格型号)',
             showOverflowTooltip: true,
-            width: 150
+            width: 120
           },
           {
             prop: 'versions',
@@ -556,6 +574,7 @@
           {
             prop: 'totalWeight',
             label: '总重',
+            slot: 'totalWeight',
             showOverflowTooltip: true,
             align: 'right',
             width: 100
@@ -719,6 +738,9 @@
       // this.getZeroPartPros('zeroPartPros');
       this.getContactList();
       this.getRuntianConfig();
+      // 打开组件时自愈一次列缓存(新老两套列方案各一份),避免“列配置变了 → 新列被顶到第一列”
+      this.healColumnsCache('routed_detailed_list', this.oldColumnsConfig);
+      this.healColumnsCache('routed_detailed_list_v3', this.newColumnsConfig);
     },
 
     props: {
@@ -820,6 +842,107 @@
     },
 
     methods: {
+      // 序号方案与新 columns 方案绑定:老方案用连续行号,新方案按层级计数
+      rowIndexText(row, index) {
+        if (!this.useNewColumns) {
+          return (this.currentPage - 1) * this.currentLimit + index + 1;
+        }
+        return this.levelSeqMap[row.id] != null
+          ? this.levelSeqMap[row.id]
+          : this.levelSeq(row, index);
+      },
+
+      // 拉整棵树的清单,算出每行在“同层级”里的序号(跨页也连续)
+      async ensureLevelSeqMap(where) {
+        const attr = this.attributeData || {};
+        const key = [attr.id, attr.bomType, JSON.stringify(where || {})].join('|');
+        if (this.levelSeqKey === key) {
+          return;
+        }
+        try {
+          const res = await getBomPageCategoryId({
+            ...(where || {}),
+            pageNum: 1,
+            size: 100000,
+            id: attr.id,
+            bomType: attr.bomType
+          });
+          const map = {};
+          const counters = {};
+          ((res && res.list) || []).forEach((item) => {
+            const level = String(item.level == null ? '' : item.level);
+            counters[level] = (counters[level] || 0) + 1;
+            map[item.id] = counters[level];
+          });
+          this.levelSeqMap = map;
+          this.levelSeqKey = key;
+        } catch (e) {
+          // 取不到就退化成“当前页内按层级计数”
+        }
+      },
+
+      // 兜底:当前页内按层级计数(同层 1、2、3…,层级变了重新从 1 开始)
+      // 例:层级 1、1、2、2 → 序号 1、2、1、2
+      levelSeq(row, index) {
+        const table = this.$refs.table;
+        const rows = (table && typeof table.getData === 'function' && table.getData()) || [];
+        const level = row ? String(row.level == null ? '' : row.level) : '';
+        let seq = 0;
+        const end = Math.min(index, rows.length - 1);
+        for (let i = 0; i <= end; i++) {
+          const current = rows[i];
+          const currentLevel = current ? String(current.level == null ? '' : current.level) : '';
+          if (currentLevel === level) {
+            seq += 1;
+          }
+        }
+        return seq;
+      },
+
+      // 总重 = 单台用量 × 单重(前端计算)
+      totalWeightOf(row) {
+        const toNumber = (v) =>
+          v === null || v === undefined || v === '' ? null : Number(v);
+        const dosage = toNumber(row && row.dosage);
+        const netWeight = toNumber(row && row.netWeight);
+        if (dosage === null || netWeight === null) {
+          return '';
+        }
+        if (isNaN(dosage) || isNaN(netWeight)) {
+          return '';
+        }
+        return (dosage * netWeight).toFixed(2);
+      },
+
+      // ele-pro-table 的列顺序是按 localStorage 里的列缓存恢复的:配置里新增/删除列之后,
+      // 旧缓存里没有新列 → 新列会被排到第一列(表现为“序号跑到第一列,点列重置才恢复”)。
+      // 这里做一次自愈:缓存的列集合与当前配置不一致就清掉,让列顺序回到配置顺序。
+      healColumnsCache(cacheKey, columns) {
+        const key = cacheKey + 'Cols';
+        try {
+          const raw = localStorage.getItem(key);
+          if (!raw) {
+            return;
+          }
+          const cached = JSON.parse(raw);
+          if (!Array.isArray(cached) || !cached.length) {
+            return;
+          }
+          const wanted = (columns || [])
+            .filter((c) => c && c.type !== 'index' && c.columnKey !== 'index')
+            .map((c) => c.columnKey || c.prop)
+            .filter((k) => !!k);
+          const cachedKeys = cached.map((c) => c.id);
+          // 只判断“配置里有、缓存里没有”的列(这类列才会被 ele-pro-table 排到第一列);
+          // 缓存里多出来的列(比如操作列)不用管。
+          const missing = wanted.filter((k) => !cachedKeys.includes(k));
+          if (missing.length) {
+            localStorage.removeItem(key);
+          }
+        } catch (e) {
+          localStorage.removeItem(key);
+        }
+      },
       attributeTypeText(v) {
         if (v) {
           let a = this.attributeList.find((item) => item.value == v);
@@ -838,7 +961,7 @@
         });
       },
 
-      // 根据系统参数 is_runtian 判断是否启用新 columns 方案
+      // 根据系统参数 is_runtian 判断是否启用新 columns 方案;序号方案随之切换
       // 兼容常见返回:'1' / 1 / { value: 1 } / { paramValue: '1' } / true
       async getRuntianConfig() {
         try {
@@ -926,6 +1049,9 @@
 
       /* 表格数据源 */
       async datasource({ where, page, limit }) {
+        // 序号跨页连续用
+        this.currentPage = page || 1;
+        this.currentLimit = limit || 20;
         // let that = this;
         // console.log(getBomPageCategoryId({
         //   ...where,
@@ -984,6 +1110,11 @@
           bomType: this.attributeData.bomType
         });
 
+        // 新 columns 方案下序号按层级计数且跨页连续:拉一次整棵树的清单算出每行在同层级里的序号
+        if (this.useNewColumns) {
+          await this.ensureLevelSeqMap(where);
+        }
+
         if (this.isList) {
           data = this.listTow;
         }

+ 4 - 6
src/views/material/BOMmanage/detailsPop.vue

@@ -641,11 +641,9 @@
       },
 
       getTreeDataList() {
-        if (this.searchObj.versions) {
-          this.getTreeData();
-        } else {
-          this.getVersion();
-        }
+        // 选「空版本」也要按空版本加载:versions 为空时不能走 getVersion(),
+        // 那里会把 this.searchObj.versions 重置成版本列表的最后一个(表现就是"自动切回最新版")。
+        this.getTreeData();
       },
 
       exportFn() {
@@ -746,7 +744,7 @@
           isTemp: this.searchObj.isTemp || 0
         };
         versionList(param).then((res) => {
-          this.versList = res || [];
+                    this.versList = res || [];
           if (type == 'del' || type == 'add') {
             if (this.versList.length >= 1) {
               // if (!this.searchObj.versions) {

+ 92 - 19
src/views/material/BOMmanage/index.vue

@@ -24,7 +24,7 @@
           @sort-change="onSortChange"
           :page-size="pageSize"
           @columns-change="handleColumnChange"
-          :cache-key="cacheKeyUrl"
+          :cache-key="useNewColumns ? cacheKeyUrl : cacheKeyUrlOld"
         >
           <template v-slot:approvalStatus="{ row }">
             <el-link
@@ -36,6 +36,14 @@
             </el-link>
           </template>
 
+          <!-- 序号:前端自己渲染行号 -->
+          <template v-slot:rowIndex="{ $index }">{{
+            (currentPage - 1) * currentLimit + $index + 1
+          }}</template>
+
+          <!-- 总重:前端按 用量 × 单重 计算(用量/单重改了立即跟着变) -->
+          <template v-slot:totalWeight="{ row }">{{ totalWeightOf(row) }}</template>
+
           <template v-slot:code="{ row }">
             <el-link
               type="primary"
@@ -46,8 +54,8 @@
           </template>
 
           <template v-slot:versions="{ row }">
+            <!-- 版本为空就留空,不显示"无" -->
             <template v-if="row.versions">V{{ row.versions }}.0</template>
-            <template v-else>无</template>
           </template>
           <template v-slot:isTemp="{ row }">
             <el-tag size="mini" v-if="row.isTemp == 1">主数据</el-tag>
@@ -339,24 +347,29 @@
             width: 100
           },
           {
-            prop: 'sn',
-            label: '明细表序号',
+            // 序号:普通列 + 前端插槽渲染行号(见模板 v-slot:rowIndex)
+            // 不能用 type: 'index':index 列不在列设置缓存里,ele-pro-table(columnsSort 默认 true)
+            // 会把找不到缓存位置的列排到最前面,所以它永远显示在第一列。
+            prop: 'rowIndex',
+            columnKey: 'rowIndex',
+            label: '序号',
+            width: 90,
             align: 'center',
-            width: 120,
-            showOverflowTooltip: true
+            showOverflowTooltip: true,
+            slot: 'rowIndex'
           },
           {
             prop: 'code',
             label: '物料编码',
             slot: 'code',
             showOverflowTooltip: true,
-            width: 120
+            width: 180
           },
           {
             prop: 'imgCode',
             label: '零部件图号(规格型号)',
             showOverflowTooltip: true,
-            width: 150
+            width: 120
           },
           {
             prop: 'versions',
@@ -408,6 +421,7 @@
           {
             prop: 'totalWeight',
             label: '总重',
+            slot: 'totalWeight',
             showOverflowTooltip: true,
             align: 'right',
             width: 100
@@ -486,6 +500,9 @@
           // }
         ],
         sort: {},
+        // 当前分页位置:序号要跨页连续(第 2 页从 21 开始,不重置)
+        currentPage: 1,
+        currentLimit: 20,
         rootCategoryLevelIdList: [
           {
             label: '产品',
@@ -552,7 +569,10 @@
         radioSubmit: 1,
         currentNodeData: {},
         pageSize: this.$store.state.tablePageSize,
-        cacheKeyUrl: '68be265a-material-BOMmanage',
+        // 序号列由 type:index 改成 rowIndex 数据列,换 key 清一次列设置缓存
+        // (ele-pro-table 按列 key 从 localStorage 恢复列顺序,新列不在旧缓存里会被排到最前)
+        cacheKeyUrl: '68be265a-material-BOMmanage-v3',
+        cacheKeyUrlOld: '68be265a-material-BOMmanage-old-v1',
         isUpload: true
       };
     },
@@ -562,7 +582,8 @@
         return this.$store.state.user.info.clientEnvironmentId;
       },
       ...mapGetters(['user']),
-      // 是否启用新 columns 方案:activeName 为 PBOM (1/'1') 且 is_runtian === 1
+      // 是否启用新 columns 方案:PBOM(activeName 为 1/'1')且系统参数 is_runtian === 1。
+      // 序号方案与新 columns 方案绑定:新方案用 rowIndex(跨页连续),老方案沿用 type:index。
       useNewColumns() {
         const isPBOM = this.activeName == 1 || this.activeName === '1';
         const val = this.isRuntianValue;
@@ -610,8 +631,55 @@
       this.getDictList('productionType');
       this.getAttriButeList('inventory_type');
       this.getRuntianConfig();
+      // 新老两套列方案各有自己的列设置缓存,打开页面时自愈一次
+      this.healColumnsCache(this.cacheKeyUrlOld, this.oldColumnsConfig);
+      this.healColumnsCache(this.cacheKeyUrl, this.newColumnsConfig);
     },
     methods: {
+      // 总重 = 单台用量 × 单重(前端计算)
+      totalWeightOf(row) {
+        const toNumber = (v) =>
+          v === null || v === undefined || v === '' ? null : Number(v);
+        const dosage = toNumber(row && row.dosage);
+        const netWeight = toNumber(row && row.netWeight);
+        if (dosage === null || netWeight === null) {
+          return '';
+        }
+        if (isNaN(dosage) || isNaN(netWeight)) {
+          return '';
+        }
+        return (dosage * netWeight).toFixed(2);
+      },
+
+      // ele-pro-table 的列顺序是按 localStorage 里的列缓存恢复的:配置里新增/删除列之后,
+      // 旧缓存里没有新列 → 新列会被排到第一列(表现为“序号跑到第一列,点列重置才恢复”)。
+      // 这里做一次自愈:缓存的列集合与当前配置不一致就清掉,让列顺序回到配置顺序。
+      healColumnsCache(cacheKey, columns) {
+        const key = cacheKey + 'Cols';
+        try {
+          const raw = localStorage.getItem(key);
+          if (!raw) {
+            return;
+          }
+          const cached = JSON.parse(raw);
+          if (!Array.isArray(cached) || !cached.length) {
+            return;
+          }
+          const wanted = (columns || [])
+            .filter((c) => c && c.type !== 'index' && c.columnKey !== 'index')
+            .map((c) => c.columnKey || c.prop)
+            .filter((k) => !!k);
+          const cachedKeys = cached.map((c) => c.id);
+          // 只判断“配置里有、缓存里没有”的列(这类列才会被 ele-pro-table 排到第一列);
+          // 缓存里多出来的列(比如操作列)不用管。
+          const missing = wanted.filter((k) => !cachedKeys.includes(k));
+          if (missing.length) {
+            localStorage.removeItem(key);
+          }
+        } catch (e) {
+          localStorage.removeItem(key);
+        }
+      },
       attributeTypeText(v) {
         if (v) {
           let a = this.attributeList.find((item) => item.value == v);
@@ -764,7 +832,17 @@
       },
 
       /* 表格数据源 */
-      datasource({ where, page, limit }) {
+      datasource({ where, page, limit, sorter }) {
+        // 序号跨页连续用
+        this.currentPage = page || 1;
+        this.currentLimit = limit || this.pageSize || 20;
+        // 排序用表格维护的 sorter:翻页时 ele-pro-table 会把它一起带过来,不会被重置
+        const sortProp =
+          sorter && sorter.order
+            ? sorter.prop || (sorter.column && sorter.column.prop)
+            : null;
+        const sortOrder = sorter && sorter.order ? sorter.order : null;
+        this.sort = sortProp && sortOrder ? { orderBy: sortOrder, sortName: sortProp } : {};
         return getBomPageList({
           ...where,
           ...this.sort,
@@ -798,14 +876,9 @@
       },
 
       onSortChange(e) {
-        console.log(111111111, e);
-
-        let sort = {
-          orderBy: e.order,
-          sortName: e.prop
-        };
-        this.sort = sort;
-        this.reload();
+        // 排序状态交给表格保存:翻页时 ele-pro-table 会把 sorter 一起带下来,
+        // 这样“点了表头排序、翻页后又变回默认顺序”的问题就没了。
+        this.$refs.table.reload({ sorter: { prop: e.prop, order: e.order } });
       },
 
       handDel(row) {