1
0

4 Commits 4f294b13ba ... 555a1e4ada

Autor SHA1 Nachricht Datum
  mlchen 555a1e4ada fix:5364【库存台账】拆批操作,计量数量没法除以包装规格,下面的整包分配没法拆分,这里看怎么限制下 vor 3 Tagen
  xieyong a6340d78ec fix: 重置选择状态和分页信息,确保对话框关闭时清空相关数据 vor 4 Tagen
  xieyong 376073504b Merge branch 'dev' of http://110.41.163.243:9980/kd-aiot/kd-aiot-frontend-wms into dev vor 5 Tagen
  xieyong e047dbb98b refactor: 重构选择类型组件,替换表格组件并优化数据处理逻辑 vor 5 Tagen

+ 60 - 27
src/views/warehouseManagement/stockLedger/components/BatchChangeDialog.vue

@@ -200,7 +200,7 @@
           <el-table-column label="计量数量">
             <template slot-scope="{ row }">
               <el-input
-                v-if="!hasPacking && !isAutoMeasureTarget(row.target)"
+                v-if="!hasPacking"
                 v-model="row.target.measureQuantity"
                 maxlength="19"
                 :disabled="Boolean(pendingApproveId)"
@@ -595,6 +595,14 @@
     return decimal(value).decimalPlaces(6).toFixed(6);
   }
 
+  function formatDecimal(value) {
+    return decimal(value)
+      .decimalPlaces(6)
+      .toFixed(6)
+      .replace(/\.0+$/, '')
+      .replace(/(\.\d*?)0+$/, '$1');
+  }
+
   function isEmptyDecimal(value) {
     return value == null || String(value).trim() === '';
   }
@@ -680,8 +688,8 @@
         return this.packingRows.length > 0;
       },
       mergeMeasureQuantity() {
-        return this.sources
-          .reduce(
+        return formatDecimal(
+          this.sources.reduce(
             (sum, source) =>
               sum.plus(
                 decimal(source.stockCountBase).minus(
@@ -690,7 +698,7 @@
               ),
             new BigNumber(0)
           )
-          .toFixed(6);
+        );
       },
       targetRows() {
         return this.targets.map((target) => {
@@ -921,7 +929,19 @@
           (max, target) => Math.max(max, target.targetDetailId),
           0
         );
-        this.targets.push(this.createTarget(maxId + 1));
+        const target = this.createTarget(maxId + 1);
+        this.targets.push(target);
+        if (this.hasPacking) {
+          this.syncTargetPackingMinimums();
+        } else {
+          this.handleMeasureQuantityInput(this.targets[0]);
+          const weightRemainder = decimal(this.sources[0].weight).minus(
+            this.sum(this.targets.slice(0, -1), 'weight')
+          );
+          target.weight = formatDecimal(
+            weightRemainder.isNegative() ? 0 : weightRemainder
+          );
+        }
       },
       removeTarget(targetDetailId) {
         if (this.targets.length <= 2)
@@ -937,6 +957,11 @@
         this.targets = this.targets.filter(
           (target) => target.targetDetailId !== targetDetailId
         );
+        if (this.hasPacking) {
+          this.syncTargetPackingMinimums();
+        } else {
+          this.handleMeasureQuantityInput(this.targets[0]);
+        }
         if (this.batchPackingTargetId === targetDetailId) {
           this.batchPackingTargetId = null;
         }
@@ -954,8 +979,8 @@
           row.targetDetailId = null;
         });
         const target = this.targets[0];
-        target.measureQuantity = this.sources
-          .reduce(
+        target.measureQuantity = formatDecimal(
+          this.sources.reduce(
             (sum, source) =>
               sum.plus(
                 decimal(source.stockCountBase).minus(
@@ -964,7 +989,7 @@
               ),
             new BigNumber(0)
           )
-          .toFixed(6);
+        );
         target.packageQuantity = this.sum(this.sources, 'packingQuantity');
         target.weight = this.sum(this.sources, 'weight');
         this.syncTargetPackingMinimums();
@@ -982,8 +1007,9 @@
       isAutoMeasureTarget(target) {
         return (
           this.mode === 'split' &&
-          this.targets.length === 2 &&
-          target.targetDetailId === this.targets[1].targetDetailId
+          this.targets.length > 1 &&
+          target.targetDetailId ===
+            this.targets[this.targets.length - 1].targetDetailId
         );
       },
       /** 将勾选的整包装一次分配到同一目标子批次。 */
@@ -1087,35 +1113,42 @@
           );
           const measureMinimum = decimal(this.sum(packages, 'measureQuantity'));
           const weightMinimum = decimal(this.sum(packages, 'weight'));
-          target.measureQuantity = measureMinimum.toFixed(6);
-          target.weight = weightMinimum.toFixed(6);
+          target.measureQuantity = formatDecimal(measureMinimum);
+          target.weight = formatDecimal(weightMinimum);
         });
         if (this.mode === 'split') {
           const lastTarget = this.targets[this.targets.length - 1];
           const assigned = this.targets.slice(0, -1);
-          lastTarget.measureQuantity = decimal(source.stockCountBase)
-            .minus(this.sum(assigned, 'measureQuantity'))
-            .max(0)
-            .toFixed(6);
-          lastTarget.weight = decimal(source.weight)
-            .minus(this.sum(assigned, 'weight'))
-            .max(0)
-            .toFixed(6);
+          const measureRemainder = decimal(source.stockCountBase).minus(
+            this.sum(assigned, 'measureQuantity')
+          );
+          const weightRemainder = decimal(source.weight).minus(
+            this.sum(assigned, 'weight')
+          );
+          lastTarget.measureQuantity = formatDecimal(
+            measureRemainder.isNegative() ? 0 : measureRemainder
+          );
+          lastTarget.weight = formatDecimal(
+            weightRemainder.isNegative() ? 0 : weightRemainder
+          );
         }
       },
       handleMeasureQuantityInput(target) {
         if (
           this.mode !== 'split' ||
-          this.targets.length !== 2 ||
           this.isAutoMeasureTarget(target) ||
           !this.sources.length
         ) {
           return;
         }
+        const lastTarget = this.targets[this.targets.length - 1];
+        const assigned = this.targets.filter((item) => item !== lastTarget);
         const remainder = decimal(this.sources[0].stockCountBase).minus(
-          decimal(target.measureQuantity)
+          this.sum(assigned, 'measureQuantity')
+        );
+        lastTarget.measureQuantity = formatDecimal(
+          remainder.isNegative() ? 0 : remainder
         );
-        this.targets[1].measureQuantity = remainder.max(0).toFixed(6);
       },
       validateTargetLimit(target, field) {
         if (this.mode !== 'split' || !this.sources.length) return;
@@ -1133,7 +1166,7 @@
         const label = field === 'measureQuantity' ? '计量数量' : '重量';
         target[field] = '';
         this.$message.warning(
-          `目标子批次${label}累计不能超过来源库存${label} ${limit.toFixed(6)}`
+          `目标子批次${label}累计不能超过来源库存${label} ${formatDecimal(limit)}`
         );
       },
       targetLabel(id) {
@@ -1151,9 +1184,9 @@
           .join('、');
       },
       sum(rows, key) {
-        return rows
-          .reduce((sum, row) => sum.plus(decimal(row[key])), new BigNumber(0))
-          .toFixed(6);
+        return formatDecimal(
+          rows.reduce((sum, row) => sum.plus(decimal(row[key])), new BigNumber(0))
+        );
       },
       total(key) {
         return this.sum(this.sources, key);

+ 184 - 200
src/views/warehouseManagement/stocktaking/plan/components/selectType.vue

@@ -9,26 +9,6 @@
     >
       <div class="search_box">
         <el-row :gutter="15">
-          <!-- <el-col :span="6">
-            <el-form label-width="80px" class="ele-form-search">
-              <el-form-item label="所属工厂" prop="factoryId">
-                <el-select
-                  filterable
-                  placeholder="请选择"
-                  v-model="factoryId"
-                  clearable
-                  class="w100"
-                >
-                  <el-option
-                    v-for="item in factoryList"
-                    :key="item.id"
-                    :label="item.name"
-                    :value="item.id"
-                  ></el-option>
-                </el-select>
-              </el-form-item>
-            </el-form>
-          </el-col> -->
           <el-col :span="dimension == 2 ? 4 : 8">
             <el-input
               v-model="value"
@@ -97,140 +77,23 @@
           />
         </div>
         <div class="flex_right">
-          <el-table
+          <ele-pro-table
             ref="multipleTable"
-            :data="tableData"
-            border
-            tooltip-effect="dark"
-            height="455px"
-            style="width: 100%"
-            :header-cell-style="{ background: '#F0F3F3', border: 'none' }"
-            @selection-change="handleSelectionChange"
-          >
-            <el-table-column
-              :selectable="selectable"
-              type="selection"
-              width="55"
-              align="center"
-            >
-            </el-table-column>
-            <el-table-column width="55px" label="序号" type="index">
-            </el-table-column>
-            <el-table-column
-              prop="categoryCode"
-              label="物品编码"
-              :show-overflow-tooltip="true"
-            ></el-table-column>
-            <el-table-column
-              prop="categoryName"
-              label="物品名称"
-              :show-overflow-tooltip="true"
-            ></el-table-column>
-            <el-table-column
-              width="150"
-              prop="categoryLevelPath"
-              label="产品分类"
-              :show-overflow-tooltip="true"
-            ></el-table-column>
-            <el-table-column
-              v-if="dimension == 2"
-              prop="batchNo"
-              label="批次号"
-              :show-overflow-tooltip="true"
-            ></el-table-column>
-            <el-table-column
-              prop="brandNum"
-              label="牌号"
-              :show-overflow-tooltip="true"
-            ></el-table-column>
-            <el-table-column
-              prop="categoryModel"
-              label="型号"
-              :show-overflow-tooltip="true"
-            ></el-table-column>
-            <el-table-column
-              prop="specification"
-              label="规格"
-              :show-overflow-tooltip="true"
-            ></el-table-column>
-            <el-table-column
-              v-for="(item, index) in newColumns"
-              :label="item.label"
-              :align="item.align"
-              :prop="item.prop"
-              :show-overflow-tooltip="item.showOverflowTooltip"
-            ></el-table-column>
-            <el-table-column
-              prop="lockQuantity"
-              label="锁库数量"
-              :show-overflow-tooltip="true"
-            ></el-table-column>
-            <el-table-column
-              prop="availableQuantity"
-              label="可用数量"
-              :formatter="formatAvailableQuantity"
-              :show-overflow-tooltip="true"
-            ></el-table-column>
-            <el-table-column
-              prop="measureQuantity"
-              label="计量数量"
-              :formatter="formatMeasureQuantity"
-              :show-overflow-tooltip="true"
-            ></el-table-column>
-            <el-table-column
-              prop="measureUnit"
-              label="计量单位"
-              :show-overflow-tooltip="true"
-            ></el-table-column>
-            <el-table-column
-              prop="weightUnit"
-              label="重量单位"
-              :show-overflow-tooltip="true"
-            ></el-table-column>
-            <el-table-column
-              prop="weight"
-              label="重量"
-              :show-overflow-tooltip="true"
-            ></el-table-column>
-            <el-table-column
-              prop="weightUnit"
-              label="重量单位"
-              :show-overflow-tooltip="true"
-            ></el-table-column>
-            <el-table-column
-              prop="warehouseName"
-              label="仓库"
-              :show-overflow-tooltip="true"
-            ></el-table-column>
-            <el-table-column
-              prop="inventoryCycle"
-              label="存货周期"
-              :show-overflow-tooltip="true"
-            ></el-table-column>
-            <el-table-column
-              prop="colorKey"
-              label="颜色"
-              :show-overflow-tooltip="true"
-            ></el-table-column>
-            <el-table-column
-              prop="modelKey"
-              label="机型"
-              :show-overflow-tooltip="true"
-            ></el-table-column>
-          </el-table>
-          <div class="right mt10">
-            <el-pagination
-              background
-              layout="total, sizes, prev, pager, next, jumper"
-              :total="total"
-              :page-sizes="[15, 30, 50, 100, 500]"
-              :page-size.sync="pages.size"
-              :current-page.sync="pages.pageNum"
-              @current-change="handleCurrentChange"
-              @size-change="handleSizeChange"
-            >
-            </el-pagination>
-          </div>
+            :columns="columns"
+            :datasource="_getInformation"
+            height="calc(100vh - 365px)"
+            style="margin-bottom: 15px"
+            full-height="calc(100vh - 116px)"
+            tool-class="ele-toolbar-form"
+            :selection.sync="selection"
+            :page-size="15"
+            :page-sizes="[15, 30, 50, 100, 500]"
+            row-key="categoryId"
+            :init-load="false"
+            :where="searchWhere"
+            :cache-key="cacheKeyUrl"
+            @columns-change="handleColumnChange"
+          ></ele-pro-table>
         </div>
       </div>
       <div class="select-btn">
@@ -245,7 +108,9 @@
   import AssetTree from './assetTree.vue';
   import { getProductList, getBatchList } from '@/api/ruleManagement/plan';
   import { fieldModel } from '@/api/codeManagement';
+  import tabMixins from '@/mixins/tableColumnsMixin';
   export default {
+    mixins: [tabMixins],
     props: {
       visibleDialog: {
         type: Boolean,
@@ -273,9 +138,6 @@
       }
     },
     watch: {
-      tableData(val) {
-        this.doLayout();
-      },
       visibleDialog: {
         handler(v) {
           if (v) {
@@ -286,7 +148,7 @@
       },
       dimension() {
         this.resetSearchFields();
-        this.pages.pageNum = 1;
+        this.reload();
       }
     },
     components: { AssetTree },
@@ -302,7 +164,7 @@
         treeType: '',
         treeList: [],
         tableData: [],
-        multipleSelection: [],
+        selection: [],
         pages1: { classificationIdList: [] },
         pages: {
           pageNum: 1,
@@ -311,10 +173,149 @@
         total: 0,
         curType: '',
         classificationId: '',
-        memoSelection: [],
-        newColumns: [] // 动态表头
+        searchWhere: {},
+        newColumns: [], // 动态表头
+        columnsVersion: 1,
+        // 该 dialog 唯一表标识,用于列配置缓存与服务端保存
+        cacheKeyUrl: 'wms-warehouseManagement-stocktaking-plan-selectType'
       };
     },
+    computed: {
+      columns() {
+        // 引用 columnsVersion,使 tabMixins 更新列配置时本计算属性重新求值
+        // eslint-disable-next-line no-unused-vars
+        const version = this.columnsVersion;
+        const cols = [
+          {
+            columnKey: 'selection',
+            type: 'selection',
+            width: 55,
+            align: 'center',
+            reserveSelection: true,
+            selectable: (row) => !this.selectionIds.includes(row.categoryId)
+          },
+          {
+            columnKey: 'index',
+            label: '序号',
+            type: 'index',
+            width: 55,
+            align: 'center'
+          },
+          {
+            prop: 'categoryCode',
+            label: '物品编码',
+            align: 'center',
+            showOverflowTooltip: true
+          },
+          {
+            prop: 'categoryName',
+            label: '物品名称',
+            align: 'center',
+            showOverflowTooltip: true
+          },
+          {
+            prop: 'categoryLevelPath',
+            label: '产品分类',
+            width: 150,
+            align: 'center',
+            showOverflowTooltip: true
+          }
+        ];
+        if (this.dimension == 2) {
+          cols.push({
+            prop: 'batchNo',
+            label: '批次号',
+            align: 'center',
+            showOverflowTooltip: true
+          });
+        }
+        cols.push(
+          {
+            prop: 'brandNum',
+            label: '牌号',
+            align: 'center',
+            showOverflowTooltip: true
+          },
+          {
+            prop: 'categoryModel',
+            label: '型号',
+            align: 'center',
+            showOverflowTooltip: true
+          },
+          {
+            prop: 'specification',
+            label: '规格',
+            align: 'center',
+            showOverflowTooltip: true
+          },
+          ...this.newColumns,
+          {
+            prop: 'lockQuantity',
+            label: '锁库数量',
+            align: 'center',
+            showOverflowTooltip: true
+          },
+          {
+            prop: 'availableQuantity',
+            label: '可用数量',
+            align: 'center',
+            showOverflowTooltip: true,
+            formatter: (_row, _column, _cellValue) =>
+              this.formatAvailableQuantity(_row)
+          },
+          {
+            prop: 'measureQuantity',
+            label: '计量数量',
+            align: 'center',
+            showOverflowTooltip: true,
+            formatter: (_row) => _row.stockCountBase
+          },
+          {
+            prop: 'measureUnit',
+            label: '计量单位',
+            align: 'center',
+            showOverflowTooltip: true
+          },
+          {
+            prop: 'weightUnit',
+            label: '重量单位',
+            align: 'center',
+            showOverflowTooltip: true
+          },
+          {
+            prop: 'weight',
+            label: '重量',
+            align: 'center',
+            showOverflowTooltip: true
+          },
+          {
+            prop: 'warehouseName',
+            label: '仓库',
+            align: 'center',
+            showOverflowTooltip: true
+          },
+          {
+            prop: 'inventoryCycle',
+            label: '存货周期',
+            align: 'center',
+            showOverflowTooltip: true
+          },
+          {
+            prop: 'colorKey',
+            label: '颜色',
+            align: 'center',
+            showOverflowTooltip: true
+          },
+          {
+            prop: 'modelKey',
+            label: '机型',
+            align: 'center',
+            showOverflowTooltip: true
+          }
+        );
+        return cols;
+      }
+    },
     created() {
       this.getFieldModel();
     },
@@ -326,24 +327,13 @@
         const result = (inventoryBalance * 100 - lock * 100) / 100;
         return Math.max(0, Math.round(result * 100) / 100);
       },
-      formatMeasureQuantity(row) {
-        return row.stockCountBase;
-      },
-      selectable(row) {
-        return !this.selectionIds.includes(row.categoryId);
-      },
-      doLayout() {
-        let that = this;
-        this.$nextTick(() => {
-          that.$refs.multipleTable.doLayout();
-        });
-      },
       // 获取动态表头
       getFieldModel() {
         fieldModel({ fieldModel: 't_main_category' }).then((res) => {
           let newRes = res.map((m) => {
             return {
               prop: 'extField.' + m.prop,
+              columnKey: 'extField.' + m.prop,
               label: m.label,
               align: 'center',
               showOverflowTooltip: true
@@ -352,14 +342,20 @@
           this.newColumns = [...newRes];
         });
       },
+      /* 刷新表格 */
+      reload(where) {
+        this.$nextTick(() => {
+          if (this.$refs.multipleTable) {
+            this.$refs.multipleTable.reload({ page: 1, where: where || {} });
+          }
+        });
+      },
       handleSearch() {
-        this.pages.pageNum = 1;
-        this.initData();
+        this.reload();
       },
       handleReset() {
         this.resetSearchFields();
-        this.pages.pageNum = 1;
-        this.initData();
+        this.reload();
       },
       resetSearchFields() {
         this.value = '';
@@ -369,7 +365,7 @@
         this.warehouseName = '';
       },
       onConfirm() {
-        this.$emit('selectTableData', [...this.multipleSelection]);
+        this.$emit('selectTableData', [...this.selection]);
         this.closeWindows();
       },
       getTreeList() {
@@ -379,9 +375,6 @@
           });
         });
       },
-      handleSelectionChange(val) {
-        this.multipleSelection = val;
-      },
       handleNodeClick(data) {
         if (data) {
           this.classificationId = data.id;
@@ -390,35 +383,29 @@
           this.classificationId = '';
           this.curType = '';
         }
-        this.initData();
+        this.reload();
       },
       closeWindows() {
-        this.multipleSelection = [];
+        this.selection = [];
+        if (this.$refs.multipleTable) {
+          this.$refs.multipleTable.setSelectedRows([]);
+        }
         this.resetSearchFields();
         this.$emit('update:loadTree', false);
         this.$emit('update:visibleDialog', false);
         this.pages.pageNum = 1;
       },
-      handleCurrentChange(e) {
-        this.initData();
-      },
-      handleSizeChange(e) {
-        this.pages.pageNum = 1;
-        this.initData();
-      },
-      initData() {
-        this._getInformation();
-      },
-      async _getInformation() {
-        console.log(this.warehouseId);
+      async _getInformation({ page, limit, where }) {
         const params = {
-          ...this.pages,
+          pageNum: page,
+          size: limit,
           keyWord: this.value,
           colorKey: this.colorKey,
           modelKey: this.modelKey,
           warehouseName: this.warehouseName,
           warehouseId: this.warehouseId,
-          categoryLevelId: this.classificationId
+          categoryLevelId: this.classificationId,
+          ...(where || {})
         };
         if (this.dimension == 2) {
           params.batchNo = this.batchNo;
@@ -429,10 +416,7 @@
         } else {
           res = await getBatchList(params);
         }
-        if (res && this.classificationId == params.categoryLevelId) {
-          this.tableData = res.list;
-          this.total = res.count;
-        }
+        return res || { list: [], count: 0 };
       }
     }
   };

+ 2 - 0
src/views/warehouseManagement/stocktaking/work/components/disposeDialog.vue

@@ -462,6 +462,8 @@
         this.pages.keyWord = '';
         this.selection = [];
         this.controlTableData = [];
+        this.selectionIds = [];
+        this.pages.pageNum = 1;
         this.visibleDialog = false;
       },
       async _getInformation() {

+ 3 - 3
vue.config.js

@@ -2,7 +2,7 @@
  * @Author: mlchen 374826075@qq.com
  * @Date: 2026-07-21 09:26:11
  * @LastEditors: mlchen 374826075@qq.com
- * @LastEditTime: 2026-09-29 15:53:40
+ * @LastEditTime: 2026-10-10 15:17:10
  * @FilePath: /kd-aiot-frontend-wms/vue.config.js
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
@@ -43,8 +43,8 @@ module.exports = {
         // target: 'http://124.71.68.31:50001',
         // target: 'http://192.168.1.132:18086',
         // target: 'http://192.168.1.105:18086', //开发
-        target: 'http://localhost:18090', //开发
-        // target: 'http://192.168.1.251:18086', //测试
+        // target: 'http://localhost:18090', //开发
+        target: 'http://192.168.1.251:18086', //测试
         // target: 'http://192.168.1.116:18086',
 
         // target: 'http://192.168.1.116:18086',