已修改11个文件
1560 ■■■■ 文件已修改
项目代码/WIDESEA_WMSClient/src/extension/inbound/extend/EmptyTrayInbound.vue 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WIDESEA_WMSClient/src/extension/inbound/extend/Pallet.vue 112 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WIDESEA_WMSClient/src/extension/outbound/extend/StockSelect.vue 480 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WIDESEA_WMSClient/src/extension/outbound/extend/outOrderDetail.vue 464 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WIDESEA_WMSClient/src/views/taskinfo/task.vue 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_InboundService/InboundOrderService.cs 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_Model/Models/Outbound/Dt_OutboundLockInfo.cs 20 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_Model/Models/Outbound/Dt_PickingRecord.cs 349 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_StockService/StockInfoDetailService.cs 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Inbound/InboundOrderController.cs 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_WMSServer/Properties/PublishProfiles/FolderProfile.pubxml 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/extension/inbound/extend/EmptyTrayInbound.vue
@@ -11,7 +11,7 @@
                <el-form-item label="托盘条码:">
                    <el-input v-model="form.palletCode" placeholder="请扫描/输入托盘条码" @keyup.enter="submit" @keyup.13="submit"
                        clearable maxlength="50" @paste="handlePaste" @input="handleInput" />
                        clearable maxlength="50" @paste="handlePaste" @input="handleInput" ref="boxCodeInput" />
                </el-form-item>
            </el-form>
        </template>
@@ -47,6 +47,9 @@
        open() {
            this.show = true
            this.getData();
            this.$nextTick(() => {
                this.focusInput()
            })
        },
        async getData() {
@@ -61,6 +64,7 @@
        async submit() {
            if (!this.form.palletCode) {
                this.$message.warning('请输入托盘条码')
                this.focusInput()
                return
            }
@@ -81,14 +85,20 @@
                )
                if (status) {
                    this.$message.success("组盘成功")
                    this.show = false
                    this.$emit('refresh')
                    this.$message.success("组盘成功");
                    // æ¸…空输入框数据
                    this.form.palletCode = '';
                    // èšç„¦å¹¶é€‰ä¸­è¾“入框
                    this.focusAndSelectInput();
                } else {
                    this.$message.error(message || '操作失败')
                    this.$message.error(message || '操作失败');
                    // å¤±è´¥æ—¶ä¸æ¸…理数据,但聚焦并选中输入框,方便修改
                    this.focusAndSelectInput();
                }
            } catch (error) {
                this.$message.error('请求异常')
                this.$message.error('请求异常');
                // å¼‚常时也不清理数据
                this.focusAndSelectInput();
            }
        },
@@ -101,6 +111,52 @@
        handlePaste(e) {
            // ç²˜è´´æ—¶è‡ªåŠ¨æäº¤
            setTimeout(this.submit, 100)
        },
        // èšç„¦å¹¶é€‰ä¸­è¾“入框
        focusAndSelectInput() {
            this.$nextTick(() => {
                setTimeout(() => {
                    const inputRef = this.$refs.boxCodeInput;
                    if (inputRef) {
                        // Element Plus/Element UI çš„处理方式
                        const inputEl = inputRef.$el ? inputRef.$el.querySelector('input') : inputRef;
                        if (inputEl) {
                            inputEl.focus();
                            inputEl.select();
                        }
                    }
                }, 100);
            });
        },
        // åªèšç„¦è¾“入框(不清空数据)
        focusInput() {
            this.$nextTick(() => {
                const inputRef = this.$refs.boxCodeInput;
                if (inputRef) {
                    const inputEl = inputRef.$el ? inputRef.$el.querySelector('input') : inputRef;
                    inputEl?.focus();
                }
            });
        },
        // æ¸…空表单数据
        clearForm() {
            this.form.palletCode = '';
            // ä¸æ¸…空 locationType,保持区域选择
        }
    },
    watch: {
        show(val) {
            if (val) {
                this.$nextTick(() => {
                    this.focusInput()
                })
            } else {
                // å…³é—­å¼¹çª—时清空表单
                this.clearForm();
            }
        }
    }
}
ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/extension/inbound/extend/Pallet.vue
@@ -103,6 +103,32 @@
        <el-alert :title="error" type="error" show-icon closable @close="error = ''" />
      </div>
      <!-- æœªç»„盘列表 -->
      <div class="unpallet-section compact">
        <el-card shadow="hover" class="compact-card unpallet-card">
          <div slot="header" class="compact-header">
            <span><i class="el-icon-tickets"></i> æœªç»„盘条码</span>
            <span class="list-actions">
              <el-tag type="primary" size="small">未组盘 {{ totalStockCount }}</el-tag>
            </span>
          </div>
          <div  class="table-container">
            <el-table :data="unpalletMaterials" stripe style="width: 100%" height="100%" size="small" v-loading="unpalletBarcodesLoading">
              <el-table-column type="index" label="序号" width="60" align="center"></el-table-column>
              <el-table-column prop="barcode" label="条码" min-width="140" show-overflow-tooltip></el-table-column>
              <el-table-column prop="materielCode" label="物料编码" min-width="150" show-overflow-tooltip></el-table-column>
              <el-table-column prop="batchNo" label="批次" min-width="150" show-overflow-tooltip></el-table-column>
              <el-table-column prop="orderQuantity" label="数量" min-width="130" align="right"></el-table-column>
              <el-table-column prop="unit" label="单位" width="80" align="center"></el-table-column>
              <el-table-column prop="supplyCode" label="供应商" min-width="130" show-overflow-tooltip></el-table-column>
            </el-table>
          </div>
        </el-card>
      </div>
      <!-- ç‰©æ–™åˆ—表 - å›ºå®šé«˜åº¦å¸¦æ»šåŠ¨æ¡ -->
      <div class="material-list compact">
        <el-card shadow="hover" class="compact-card">
@@ -110,7 +136,6 @@
            <span><i class="el-icon-tickets"></i> ç»„盘数据</span>
            <span class="list-actions">
              <el-tag type="primary" size="small">共 {{ materials.length }} æ¡</el-tag>
              <el-tag type="primary" size="small">未组盘 {{ totalStockCount }}</el-tag>
              <el-tag type="primary" size="small">未入库数量 {{ totalStockSum }}{{ uniqueUnit }}</el-tag>
              <el-tag v-if="trayBarcode" type="success" size="small">托盘: {{ trayBarcode }}</el-tag>
              <el-tag v-if="form.warehouseType" type="info" size="small">仓库: {{ currentWarehouseName }}</el-tag>
@@ -177,6 +202,10 @@
      error: '',
      debugMode: false,
      currentFocus: 'warehouse',
      unpalletBarcodes:[],
      unpalletBarcodesLoading: false,
      unpalletMaterials: [], // æœªç»„盘详细数据列表
      // æ‰«ç æžªç›¸å…³å˜é‡
      scanCode: '',
@@ -257,6 +286,7 @@
            this.initwarehouseTypes(); // åˆå§‹åŒ–仓库
            this.initLocationTypes(); // åˆå§‹åŒ–仓库区域
            this.fetchStockStatistics(); // åŠ è½½ç»Ÿè®¡æ•°æ®
            this.fetchUnpalletMaterialDetails();
          }, 300);
        });
      }
@@ -276,6 +306,7 @@
        this.backData = [];
        this.$refs.palletForm?.reset();
        this.fetchStockStatistics(); // å•据号变了,刷新统计
        this.fetchUnpalletMaterialDetails();
      }
    }
  },
@@ -316,6 +347,43 @@
        callback(new Error('请选择仓库区域'));
      } else {
        callback();
      }
    },
    // æ ¹æ®æ¡ç åˆ—表获取详细数据
    async fetchUnpalletMaterialDetails() {
      try {
        // å°è¯•调用接口获取详细数据
        // æ³¨æ„ï¼šå¦‚果这个接口不存在,可以注释掉或根据实际API调整
        const response = await http.post('/api/InboundOrder/UnPalletGroupBarcode?orderNo='+this.docNo, {
        });
        console.log('未组盘数据:', response.data);
        if (response.status && Array.isArray(response.data)) {
          this.unpalletMaterials = response.data;
          this.unpalletBarcodes = response.data.map(item => item.barcode || '');
          this.totalStockCount = response.data.length;
        } else {
          // å¦‚果接口返回格式不同,尝试其他方式
          // å¦‚果接口不存在,这里会进入catch,设置为空数组
          this.unpalletMaterials = [];
        }
      } catch (err) {
        console.warn('获取未组盘详细数据接口可能不存在,使用条码列表显示:', err);
        // å¦‚果接口不存在,将条码列表转换为简单的显示格式
        // æˆ–者保持为空,让用户知道需要选择仓库和区域来查看详细数据
        this.unpalletMaterials = this.unpalletBarcodes.map(barcode => ({
          barcode: barcode,
          materielCode: '-',
          batchNo: '-',
          stockQuantity: '-',
          unit: '-',
          supplyCode: '-',
          warehouseType: '-'
        }));
      }
    },
    /**
@@ -399,6 +467,7 @@
                console.log('仓库区域验证通过:', value);
                // åŒºåŸŸé€‰æ‹©åŽï¼Œè‡ªåŠ¨èšç„¦åˆ°æ‰˜ç›˜è¾“å…¥æ¡†
                this.focusLocationSelect();
                // åˆ·æ–°æœªç»„盘数据(根据选择的仓库和区域过滤)
              }
            });
          }, 100);
@@ -555,6 +624,8 @@
      this.trayBarcode = '';
      this.barcode = '';
      this.materials = [];
      this.unpalletBarcodes = [];
      this.unpalletMaterials = [];
      this.loading = false;
      this.error = '';
      this.scanCode = '';
@@ -814,6 +885,13 @@
            });
          });
          
          const removeIndex = this.unpalletMaterials.findIndex(item => item.barcode === currentBarcode);
          if (removeIndex > -1) {
            this.unpalletMaterials.splice(removeIndex, 1); // åˆ é™¤æœªç»„盘对应数据
            this.unpalletBarcodes = this.unpalletMaterials.map(item => item.barcode || ''); // æ›´æ–°æ¡ç æ•°ç»„
            this.totalStockCount = Math.max(0, this.totalStockCount - 1);
          }
          this.$message({
            message: `成功添加条码: ${currentBarcode}`,
            type: 'success',
@@ -1297,5 +1375,37 @@
    border: 1px solid #DCDFE6;
    border-radius: 4px;
  }
  .unpallet-section.compact {
  margin-bottom: 8px;
  flex-shrink: 0;
}
.unpallet-card {
  flex-shrink: 0;
}
.unpallet-barcode-list {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: 8px 0;
  max-height: 180px;
  overflow-y: auto;
}
.unpallet-barcode-list>>>.el-tag {
  cursor: pointer;
  max-width: calc(33.333% - 4px);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
@media (max-width: 768px) {
  .unpallet-barcode-list>>>.el-tag {
    max-width: calc(50% - 4px);
  }
}
}
</style>
ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/extension/outbound/extend/StockSelect.vue
@@ -15,22 +15,11 @@
              <el-divider direction="vertical"></el-divider>
              <span class="less-style">物料编号: {{ row.materielCode }} </span>
              <el-divider direction="vertical"></el-divider>
              <span class="less-style"
                >需求数量: {{ row.orderQuantity }}
              </span>
              <span class="less-style">需求数量: {{ row.qty }} </span>
              <el-divider direction="vertical"></el-divider>
              <span :class="selectionClass"
                >已选数量: {{ selectionSum }}
              </span>
              <span :class="selectionClass">已选数量: {{ selectionSum }} </span>
            </el-col>
            <el-col :span="8">
             <!--  <el-link
                type="primary"
                size="small"
                style="float: right; height: 20px"
                @click="getData(false)"
                >{{ kcname }}</el-link
              > -->
              <el-link
                type="primary"
                size="small"
@@ -38,17 +27,64 @@
                @click="getData"
                >刷新</el-link
              >
      <!--         <el-link
              <el-link
                type="primary"
                size="small"
                style="float: right; height: 20px; margin-right: 10px"
                @click="revokeAssign"
                >撤销分配</el-link
              > -->
                @click="openOutboundDialog"
                >直接出库</el-link
              >
            </el-col>
          </el-row>
        </el-alert>
      </div>
      <!-- æ–°å¢žç­›é€‰åŒºåŸŸ -->
      <div class="filter-area" style="margin: 10px 0; padding: 10px; background: #f8f9fa; border-radius: 4px;">
        <el-form :model="filterForm" inline @submit.prevent>
          <el-form-item label="物料编号:">
            <el-input
              v-model="filterForm.materielCode"
              placeholder="模糊筛选物料编号"
              clearable
              style="width: 180px"
              @input="filterTable"
            ></el-input>
          </el-form-item>
          <el-form-item label="物料条码:">
            <el-input
              v-model="filterForm.barcode"
              placeholder="模糊筛选物料条码"
              clearable
              style="width: 180px"
              @input="filterTable"
            ></el-input>
          </el-form-item>
          <el-form-item label="托盘编号:">
            <el-input
              v-model="filterForm.palletCode"
              placeholder="模糊筛选托盘编号"
              clearable
              style="width: 180px"
              @input="filterTable"
            ></el-input>
          </el-form-item>
          <el-form-item label="货位编号:">
            <el-input
              v-model="filterForm.locationCode"
              placeholder="模糊筛选货位编号"
              clearable
              style="width: 180px"
              @input="filterTable"
            ></el-input>
          </el-form-item>
          <el-form-item>
            <el-button type="primary" @click="filterTable">搜索</el-button>
            <el-button @click="resetFilter">重置</el-button>
          </el-form-item>
        </el-form>
      </div>
      <div class="box-table" style="margin-top: 1%">
        <el-table
          ref="singleTable"
@@ -59,7 +95,6 @@
          height="500px"
          @selection-change="handleSelectionChange"
        >
          >
          <el-table-column type="selection" width="55"> </el-table-column>
          <el-table-column
            label="序号"
@@ -92,185 +127,334 @@
        </el-table>
      </div>
      <template #footer>
       <!--  <el-button type="primary" size="small" @click="outbound"
          >直接出库</el-button
        >
        <el-button type="primary" size="small" @click="lockStock"
          >锁定库存</el-button
        > -->
        <!-- åŽ»æŽ‰é”å®šåº“å­˜æŒ‰é’®ï¼Œåªä¿ç•™å…³é—­æŒ‰é’® -->
        <el-button type="danger" size="small" @click="showDetialBox = false"
          >关闭</el-button
        >
      </template>
    </vol-box>
    <!-- å‡ºåº“站台选择弹窗(静态模板实现) -->
    <el-dialog
      v-model="showOutboundDialog"
      title="出库操作 - é€‰æ‹©å‡ºåº“站台"
      width="500px"
      :append-to-body="true"
    >
      <el-form
        :model="outboundForm"
        :rules="outboundRules"
        ref="outboundFormRef"
        label-width="100px"
        style="padding: 0 20px"
      >
        <el-form-item label="出库站台" prop="selectedPlatform" style="margin-bottom: 24px">
          <el-select
            v-model="outboundForm.selectedPlatform"
            placeholder="请选择出库站台(3-12)"
            style="width: 100%; height: 40px"
          >
            <el-option
              v-for="platform in platformOptions"
              :key="platform.value"
              :label="platform.label"
              :value="platform.value"
            ></el-option>
          </el-select>
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="showOutboundDialog = false" style="margin-right: 8px">取消</el-button>
        <el-button type="primary" @click="confirmOutbound">确定出库</el-button>
      </template>
    </el-dialog>
  </div>
</template>
<script>
import VolBox from "@/components/basic/VolBox.vue";
import { fa } from "element-plus/es/locales.mjs";
import { ElMessage } from "element-plus";
export default {
  components: { VolBox },
  data() {
    return {
      row: null,
      kcname: "",
      pkcx: false,
      row: null, // æŽ¥æ”¶çˆ¶ç»„件传递的完整数据(包含明细ID集合)
      showDetialBox: false,
      tableData: [],
      originalTableData: [], // å­˜å‚¨åŽŸå§‹æ•°æ®ï¼Œç”¨äºŽç­›é€‰
      tableColumns: [
        {
          prop: "materielCode",
          title: "物料编号",
          type: "string",
          width: 150,
        },
        {
          prop: "materielName",
          title: "物料名称",
          type: "string",
          width: 150,
        },
        {
          prop: "palletCode",
          title: "托盘编号",
          type: "string",
          width: 150,
        },
        {
          prop: "locationCode",
          title: "货位编号",
          type: "string",
          width: 180,
        },
        {
          prop: "useableQuantity",
          title: "可用数量",
          type: "string",
        },
        { prop: "materielCode", title: "物料编号", type: "string", width: 150 },
        { prop: "barcode", title: "物料条码", type: "string", width: 150 },
        { prop: "palletCode", title: "托盘编号", type: "string", width: 150 },
        { prop: "locationCode", title: "货位编号", type: "string", width: 180 },
        { prop: "useableQuantity", title: "可用数量", type: "string" },
      ],
      selection: [],
      selectionSum: 0,
      selection: [], // é€‰ä¸­çš„库存数据
      selectionSum: 0, // å·²é€‰æ•°é‡æ€»å’Œ
      selectionClass: "less-style",
      originalQuantity: 0,
      // ç­›é€‰è¡¨å•数据
      filterForm: {
        materielCode: "",
        barcode: "",
        palletCode: "",
        locationCode: ""
      },
      // å‡ºåº“弹窗相关数据
      showOutboundDialog: false,
      outboundForm: { selectedPlatform: "" }, // è¡¨å•绑定数据
      outboundRules: {
        selectedPlatform: [
          { required: true, message: "请选择出库站台", trigger: "change" },
        ],
      },
      platformOptions: [
        { label: "站台2", value: "2-1" },
        { label: "站台3", value: "3-1" },
      ],
      pkcx: false, // æ–°å¢žï¼šé»˜è®¤false(如果需要可从父组件传递)
    };
  },
  methods: {
    open(row) {
      console.log(row);
      this.row = row;
    // æŽ¥æ”¶çˆ¶ç»„件传递的数据(包含明细ID集合和物料信息)
    open(data) {
      this.row = data; // data结构:{materielCode, materielName, qty, orderNo, detailIds, mainOrderId, groupRow}
      this.showDetialBox = true;
      this.originalQuantity = this.row.lockQuantity;
      this.selectionSum = this.row.lockQuantity;
      this.getData();
      if (this.selectionSum == this.row.orderQuantity) {
        this.selectionClass = "equle-style";
      } else if (this.selectionSum < this.row.orderQuantity) {
        this.selectionClass = "less-style";
      } else {
        this.selectionClass = "more-style";
      }
      this.getData(); // åŠ è½½åº“å­˜æ•°æ®
      this.updateSelectionClass(); // åˆå§‹åŒ–已选数量样式
      console.log("接收的分组明细ID集合:", this.row.detailIds);
      console.log("查询库存的物料编码:", this.row.materielCode);
    },
    lockStock() {
    // æ‰“开出库弹窗
    openOutboundDialog() {
      if (this.selection.length === 0) {
        return ElMessage.error("请选择库存数据");
      }
      // æ ¡éªŒæ˜Žç»†ID集合
      if (!this.row?.detailIds || this.row.detailIds.length === 0) {
        return ElMessage.error("没有获取到单据明细ID,无法出库");
      }
      // é‡ç½®è¡¨å•避免残留值
      this.outboundForm.selectedPlatform = "";
      this.showOutboundDialog = true;
    },
    // æ ¸å¿ƒä¿®æ”¹ï¼šURL拼接传递int[] orderDetailId(重复参数名)和station,请求体传库存数据
    confirmOutbound() {
      this.$refs.outboundFormRef.validate((valid) => {
        if (!valid) return;
        // æ ¡éªŒé€‰ä¸­åº“存和明细ID
        if (this.selection.length <= 0) {
          return this.$message.error("请勾选库存数据");
        }
        if (!this.row?.detailIds || this.row.detailIds.length === 0) {
          return this.$message.error("没有获取到单据明细ID,无法出库");
        }
        try {
          // 1. è½¬æ¢ID为整数数组(确保后端能识别为int[])
          const orderDetailId = this.row.detailIds.map(id => {
            const num = Number(id);
            if (isNaN(num) || !Number.isInteger(num)) {
              throw new Error(`ID ${id} ä¸æ˜¯æœ‰æ•ˆçš„æ•´æ•°`);
            }
            return num;
          });
          // 2. æ‹¼æŽ¥URL:int[] ç”¨é‡å¤å‚数名格式(?orderDetailId=1&orderDetailId=2&...)
          let url = "api/Task/GenerateOutboundTask";
          // æ‹¼æŽ¥ID数组参数
          const idParams = orderDetailId.map(id => `orderDetailId=${id}`).join("&");
          // æ‹¼æŽ¥ç«™å°å‚æ•°
          const stationParam = `station=${encodeURIComponent(this.outboundForm.selectedPlatform)}`;
          // å®Œæ•´URL(处理参数拼接逻辑)
          const fullUrl = idParams
            ? `${url}?${idParams}&${stationParam}`
            : `${url}?${stationParam}`;
          console.log("出库请求URL:", fullUrl);
          // 3. å‘送请求:URL拼接ID和站台,请求体传库存数据(适配FromBody)
          this.http
            .post(fullUrl, this.selection, "数据处理中")
            .then((x) => {
              if (!x.status) return this.$message.error(x.message);
              this.$message.success("操作成功");
              this.showDetialBox = false;
              this.$emit("parentCall", ($vue) => {
                $vue.getData(); // åˆ·æ–°çˆ¶ç»„件数据
              });
            })
            .catch((err) => {
              console.error("出库失败:", err);
              this.$message.error(`出库失败:${err.message || '请稍后重试'}`);
            });
        } catch (err) {
          this.$message.error(err.message);
        }
      });
    },
    // æŒ‰ç¬¬ä¸€ä¸ªç‰©æ–™ç¼–码查询库存数据
    getData() {
      const url = "api/StockInfo/GetSelectViewDTOs?materielCode=";
      // ä½¿ç”¨çˆ¶ç»„件传递的物料编码(第一个明细的编码)
      this.http
        .post(
          "api/OutboundOrderDetail/LockOutboundStock?id=" + this.row.id,
          this.selection,
          "数据处理中"
        )
        .then((x) => {
          if (!x.status) return this.$message.error(x.message);
          this.$message.success("操作成功");
          this.showDetialBox = false;
          this.$emit("parentCall", ($vue) => {
            $vue.getData();
          });
        });
    },
    outbound() {
      if (this.selection.length <= 0) {
        return this.$message.error("请勾选");
      }
      let url = this.pkcx
        ? "api/Task/GenerateOutboundTask?orderDetailId="
        : "api/Task/GenerateOutboundTask?orderDetailId=";
      this.http
        .post(url + this.row.id, this.selection, "数据处理中")
        .then((x) => {
          if (!x.status) return this.$message.error(x.message);
          this.$message.success("操作成功");
          this.showDetialBox = false;
          this.$emit("parentCall", ($vue) => {
            $vue.getData();
          });
        });
    },
    getData(a) {
      if (!a) this.pkcx = !this.pkcx;
      let url = this.pkcx
        ? "api/StockInfo/GetStockSelectViews?materielCode="
        : "api/StockInfo/GetStockSelectViews?materielCode=";
      this.kcname = this.pkcx ? "立库库存" : "平库库存";
      this.http
        .post(
          url + this.row.materielCode + "&orderId=" + this.row.orderId,
          url + this.row.materielCode + "&orderNo=" + (this.row.upperOrderNo || this.row.orderNo),
          null,
          "查询中"
        )
        .then((x) => {
          this.tableData = x;
          this.tableData = x || [];
          this.originalTableData = [...this.tableData]; // ä¿å­˜åŽŸå§‹æ•°æ®
          // åˆ·æ–°åŽæ¸…空之前的选择和计数
          this.clearSelection();
          this.selectionSum = 0;
          this.originalQuantity = 0;
          this.updateSelectionClass();
          // åˆ·æ–°åŽé‡ç½®ç­›é€‰æ¡ä»¶
          this.resetFilter();
        })
        .catch((err) => {
          console.error("库存查询失败:", err);
          ElMessage.error("库存查询失败,请稍后重试");
          this.tableData = [];
          this.originalTableData = [];
        });
    },
    // æ’¤é”€æŒ‡å®šåº“存(如果需要)
    revokeAssign() {
      console.log(this.row);
      this.http
        .post(
          "api/OutboundOrderDetail/RevokeLockOutboundStock?id=" + this.row.id,
          null,
          "数据处理中"
        )
        .then((x) => {
          if (!x.status) return this.$message.error(x.message);
          this.$message.success("操作成功");
          this.showDetialBox = false;
          this.$emit("parentCall", ($vue) => {
            $vue.getData();
      if (!this.row?.detailIds || this.row.detailIds.length === 0) {
        return ElMessage.error("没有获取到单据明细ID,无法撤销");
      }
      try {
        // ID转为整数数组,拼接URL
        const detailIds = this.row.detailIds.map(id => Number(id));
        const idParams = detailIds.map(id => `detailIds=${id}`).join("&");
        const url = `api/OutboundOrderDetail/RevokeLockOutboundStock?id=${this.row.mainOrderId}&${idParams}`;
        this.http
          .post(url, null, "数据处理中")
          .then((x) => {
            if (!x.status) return ElMessage.error(x.message);
            ElMessage.success("撤销成功");
            this.showDetialBox = false;
            this.$emit("parentCall", ($vue) => {
              $vue.getData();
            });
          });
        });
      } catch (err) {
        this.$message.error(`撤销失败:${err.message}`);
      }
    },
    // å¤„理表格选择变化(计算已选数量)
    handleSelectionChange(val) {
      this.selection = val;
      this.selectionSum =
        val.reduce(
          (accumulator, currentValue) =>
            accumulator + currentValue["useableQuantity"],
          0
        ) + this.originalQuantity;
      if (this.selectionSum == this.row.orderQuantity) {
      // è®¡ç®—已选数量(转数字避免字符串拼接)
      this.selectionSum = val.reduce(
        (acc, curr) => acc + Number(curr.useableQuantity || 0),
        0
      ) + this.originalQuantity;
      this.updateSelectionClass();
    },
    // æ›´æ–°å·²é€‰æ•°é‡æ ·å¼ï¼ˆå¯¹æ¯”分组总需求数量)
    updateSelectionClass() {
      if (!this.row) return;
      if (this.selectionSum === this.row.qty) {
        this.selectionClass = "equle-style";
      } else if (this.selectionSum < this.row.orderQuantity) {
      } else if (this.selectionSum < this.row.qty) {
        this.selectionClass = "less-style";
      } else {
        this.selectionClass = "more-style";
      }
    },
    // åˆ‡æ¢è¡¨æ ¼é€‰æ‹©
    toggleSelection(rows) {
      if (rows) {
        rows.forEach((row) => {
          this.$refs.singleTable.toggleRowSelection(row);
        });
      } else {
      rows
        ? rows.forEach((row) => this.$refs.singleTable.toggleRowSelection(row))
        : this.clearSelection();
    },
    // æ¸…空选择
    clearSelection() {
      if (this.$refs.singleTable) {
        this.$refs.singleTable.clearSelection();
      }
    },
    clearSelection() {
      this.$refs.singleTable.clearSelection();
    },
    // è¡Œç‚¹å‡»äº‹ä»¶
    handleRowClick(row) {
      this.$refs.singleTable.toggleRowSelection(row);
    },
    // å›¾æ ‡æŒ‰é’®ç‚¹å‡»å ä½æ–¹æ³•(可根据需求扩展)
    tableButtonClick(row, item) {
      console.log("图标按钮点击:", item.title, row);
    },
    // ç­›é€‰è¡¨æ ¼æ•°æ®
    filterTable() {
      if (!this.originalTableData.length) return;
      // è§£æž„筛选条件并转为小写(忽略大小写)
      const { materielCode, barcode, palletCode, locationCode } = this.filterForm;
      const mc = materielCode.toLowerCase().trim();
      const bc = barcode.toLowerCase().trim();
      const pc = palletCode.toLowerCase().trim();
      const lc = locationCode.toLowerCase().trim();
      // æ¨¡ç³Šç­›é€‰é€»è¾‘
      this.tableData = this.originalTableData.filter(item => {
        // æ¯ä¸ªå­—段都做空值处理和小写转换,支持模糊匹配
        const itemMc = (item.materielCode || "").toLowerCase();
        const itemBc = (item.barcode || "").toLowerCase();
        const itemPc = (item.palletCode || "").toLowerCase();
        const itemLc = (item.locationCode || "").toLowerCase();
        return (
          itemMc.includes(mc) &&
          itemBc.includes(bc) &&
          itemPc.includes(pc) &&
          itemLc.includes(lc)
        );
      });
      // ç­›é€‰åŽæ¸…空选择状态
      this.clearSelection();
      this.selectionSum = 0;
      this.updateSelectionClass();
    },
    // é‡ç½®ç­›é€‰æ¡ä»¶
    resetFilter() {
      this.filterForm = {
        materielCode: "",
        barcode: "",
        palletCode: "",
        locationCode: ""
      };
      // æ¢å¤åŽŸå§‹æ•°æ®
      this.tableData = [...this.originalTableData];
      // é‡ç½®é€‰æ‹©çŠ¶æ€
      this.clearSelection();
      this.selectionSum = 0;
      this.updateSelectionClass();
    }
  },
};
</script>
<style scoped>
.less-style {
  color: black;
@@ -282,6 +466,12 @@
.more-style {
  color: red;
}
/* ç­›é€‰åŒºåŸŸæ ·å¼ä¼˜åŒ– */
.filter-area :deep(.el-form-item) {
  margin-bottom: 0;
  margin-right: 10px;
}
</style>
@@ -296,12 +486,10 @@
.box-table .el-table tbody tr:hover > td {
  background-color: #d8e0d4 !important;
  /* color: #ffffff; */
}
.box-table .el-table tbody tr.current-row > td {
  background-color: #f0f9eb !important;
  /* color: #ffffff; */
}
.el-table .success-row {
ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/extension/outbound/extend/outOrderDetail.vue
@@ -60,7 +60,7 @@
      <div class="box-table" style="margin-top: 1%">
        <el-table
          ref="singleTable"
          :data="tableData"
          :data="groupedTableData"
          style="width: 100%; height: 100%"
          highlight-current-row
          @current-change="handleCurrentChange"
@@ -77,38 +77,127 @@
            align="center"
          ></el-table-column>
          <el-table-column
            v-for="(item, index) in tableColumns.filter((x) => !x.hidden)"
            :key="index"
            :prop="item.prop"
            :label="item.title"
            :width="item.width"
            prop="materielCode"
            label="物料编号"
            width="120"
            align="center"
          ></el-table-column>
          <el-table-column
            prop="materielName"
            label="物料名称"
            width="150"
            align="center"
          ></el-table-column>
          <el-table-column
            prop="batchNo"
            label="批次号"
            width="90"
            align="center"
          ></el-table-column>
          <el-table-column
            prop="supplyCode"
            label="供应商编号"
            width="90"
            align="center"
          ></el-table-column>
          <el-table-column
            prop="orderQuantity"
            label="单据数量"
            width="90"
            align="center"
          ></el-table-column>
          <el-table-column
            prop="lockQuantity"
            label="锁定数量"
            width="90"
            align="center"
          ></el-table-column>
          <el-table-column
            prop="overOutQuantity"
            label="已出数量"
            width="90"
            align="center"
          ></el-table-column>
          <el-table-column
            prop="moveQty"
            label="挪料数量"
            width="90"
            align="center"
          ></el-table-column>
          <el-table-column
            prop="unit"
            label="单位"
            width="80"
            align="center"
          ></el-table-column>
          <el-table-column
            prop="orderDetailStatus"
            label="订单明细状态"
            width="90"
            align="center"
          >
            <template #default="scoped">
              <div v-if="item.type == 'icon'">
                <el-tooltip
                  class="item"
                  effect="dark"
                  :content="item.title"
                  placement="bottom"
              <el-tag size="small">
                {{ getDictionaryForGroup(scoped.row) }}
              </el-tag>
            </template>
          </el-table-column>
          <el-table-column
            prop="assignStock"
            label="指定库存"
            width="90"
            align="center"
            :hidden="mainBusinessType !== '22'"
          >
            <template #default="scoped">
              <el-tooltip
                class="item"
                effect="dark"
                content="指定库存"
                placement="bottom"
              >
                <el-link
                  type="primary"
                  :disabled="getButtonEnable('assignStock', scoped.row)"
                  @click="handleAssignStock(scoped.row)"
                >
                  <el-link
                    type="primary"
                    :disabled="getButtonEnable(item.prop, scoped.row)"
                    @click="tableButtonClick(scoped.row, item)"
                  >
                    <i :class="item.icon" style="font-size: 22px"></i>
                  </el-link>
                </el-tooltip>
              </div>
              <div v-else-if="item.type == 'tag'">
                <el-tag size="small">
                  {{ getDictionary(scoped.row, item) }}
                </el-tag>
              </div>
              <div v-else>
                {{ scoped.row[item.prop] }}
              </div>
                  <i class="el-icon-s-grid" style="font-size: 22px"></i>
                </el-link>
              </el-tooltip>
            </template>
          </el-table-column>
          <el-table-column
            prop="viewDetail"
            label="出库详细"
            width="90"
            align="center"
          >
            <template #default="scoped">
              <el-tooltip
                class="item"
                effect="dark"
                content="查看出库详细"
                placement="bottom"
              >
                <el-link
                  type="primary"
                  @click="handleViewDetail(scoped.row)"
                >
                  <i class="el-icon-s-operation" style="font-size: 22px"></i>
                </el-link>
              </el-tooltip>
            </template>
          </el-table-column>
          <el-table-column
            prop="detailCount"
            label="明细数量"
            width="80"
            align="center"
          >
            <template #default="scoped">
              <el-tag type="info" size="small">
                {{ scoped.row.detailCount }}
              </el-tag>
            </template>
          </el-table-column>
        </el-table>
@@ -152,129 +241,9 @@
      flag: false,
      currentRow: null,
      selection: [],
      tableData: [],
      mainBusinessType: null, // æ–°å¢žï¼šå­˜å‚¨ä¸»å•据的businessType
      tableColumns: [
        {
          prop: "id",
          title: "Id",
          type: "int",
          width: 90,
          hidden: true,
        },
        {
          prop: "orderId",
          title: "出库单主键",
          type: "string",
          width: 90,
          hidden: true,
        },
        {
          prop: "materielCode",
          title: "物料编号",
          type: "string",
          width: 120,
        },
        {
          prop: "materielName",
          title: "物料名称",
          type: "string",
          width: 150,
        },
        {
          prop: "batchNo",
          title: "批次号",
          type: "string",
          width: 90,
        },
        {
          prop: "supplyCode",
          title: "供应商编号",
          type: "string",
          width: 90,
        },
        {
          prop: "orderQuantity",
          title: "单据数量",
          type: "string",
          width: 90,
        },
        {
          prop: "lockQuantity",
          title: "锁定数量",
          type: "int",
          width: 90,
        },
        {
          prop: "overOutQuantity",
          title: "已出数量",
          type: "string",
          width: 90,
        },
        {
          prop: "moveQty",
          title: "挪料数量",
          type: "string",
          width: 90,
        },
        {
          prop: "unit",
          title: "单位",
          type: "string",
          width: 80,
        },
        {
          prop: "orderDetailStatus",
          title: "订单明细状态",
          type: "tag",
          width: 90,
          bindKey: "orderDetailStatusEnum",
        },
        {
          prop: "assignStock",
          title: "指定库存",
          type: "icon",
          width: 90,
          hidden: true, // é»˜è®¤éšè—
          icon: "el-icon-s-grid",
        },
        {
          prop: "viewDetail",
          title: "出库详细",
          type: "icon",
          width: 90,
          icon: "el-icon-s-operation",
        },
        {
          prop: "creater",
          title: "创建人",
          type: "string",
          width: 90,
        },
        {
          prop: "createDate",
          title: "创建时间",
          type: "datetime",
          width: 160,
        },
        {
          prop: "modifier",
          title: "修改人",
          type: "string",
          width: 100,
        },
        {
          prop: "modifyDate",
          title: "修改时间",
          type: "datetime",
          width: 160,
        },
        {
          prop: "remark",
          title: "备注",
          type: "string",
        },
      ],
      tableData: [], // åŽŸå§‹æ•°æ®
      groupedTableData: [], // åˆ†ç»„后的数据
      mainBusinessType: null, // å­˜å‚¨ä¸»å•据的businessType
      paginations: {
        sort: "id",
        order: "desc",
@@ -329,15 +298,50 @@
      }
    },
  methods: {
    toggleAssignStockColumn() {
      const assignStockColumn = this.tableColumns.find(
        (item) => item.prop === "assignStock"
      );
      if (assignStockColumn) {
        // businessType为22时显示,否则隐藏
        assignStockColumn.hidden = this.mainBusinessType !=='22';
      }
    // æ ¹æ®ç‰©æ–™ç¼–号、批次、供应商分组数据
    groupDataByMaterial() {
      const groups = {};
      this.tableData.forEach(item => {
        // æž„建分组键,批次和供应商可以为空
        const groupKey = `${item.materielCode}_${item.batchNo || ''}_${item.supplyCode || ''}`;
        if (!groups[groupKey]) {
          // åˆ›å»ºæ–°åˆ†ç»„
          groups[groupKey] = {
            materielCode: item.materielCode,
            materielName: item.materielName,
            batchNo: item.batchNo || '-',
            supplyCode: item.supplyCode || '-',
            orderQuantity: 0,
            lockQuantity: 0,
            overOutQuantity: 0,
            moveQty: 0,
            unit: item.unit,
            orderDetailStatus: item.orderDetailStatus,
            detailCount: 0,
            originalDetails: [] // ä¿å­˜åŽŸå§‹æ˜Žç»†æ•°æ®
          };
        }
        // ç´¯åŠ æ•°é‡
        groups[groupKey].orderQuantity += item.orderQuantity || 0;
        groups[groupKey].lockQuantity += item.lockQuantity || 0;
        groups[groupKey].overOutQuantity += item.overOutQuantity || 0;
        groups[groupKey].moveQty += item.moveQty || 0;
        groups[groupKey].detailCount += 1;
        groups[groupKey].originalDetails.push(item);
        // å¦‚果状态不同,可以用第一个状态或特殊处理
        // è¿™é‡Œä½¿ç”¨ç¬¬ä¸€ä¸ªæ˜Žç»†çš„状态
      });
      // è½¬æ¢ä¸ºæ•°ç»„
      this.groupedTableData = Object.values(groups);
      console.log('分组后的数据:', this.groupedTableData);
    },
    open(row) {
      this.row = row;
      this.showDetialBox = true;
@@ -346,8 +350,8 @@
      this.mainBusinessType = row.businessType;
      this.getDictionaryData();
      this.getData();
      this.toggleAssignStockColumn();
    },
    getData() {
      var wheres = [{ name: "orderId", value: this.row.id }];
      var param = {
@@ -361,25 +365,66 @@
        .post("api/OutboundOrderDetail/GetPageData", param, "查询中")
        .then((x) => {
          this.tableData = x.rows;
          this.toggleAssignStockColumn(); // æ•°æ®åŠ è½½åŽé‡æ–°ç¡®è®¤åˆ—æ˜¾éš
          // åˆ†ç»„数据
          this.groupDataByMaterial();
        });
    },
    tableButtonClick(row, column) {
      if (column.prop == "assignStock") {
        this.$refs.child.open(row);
      } else if (column.prop == "NoStockOut") {
        this.$refs.NoStockOut.open(row);
    // é‡ç‚¹ä¿®æ”¹ï¼šå¤„理指定库存点击事件 - ä¼ é€’完整的分组明细信息
    handleAssignStock(row) {
      // ä¼ é€’完整的分组明细数据(包含所有原始明细ID和物料信息)
      if (row.originalDetails && row.originalDetails.length > 0) {
        this.$refs.child.open({
          // ç‰©æ–™åŸºæœ¬ä¿¡æ¯ï¼ˆå–第一个明细的信息)
          materielCode: row.originalDetails[0].materielCode,
          materielName: row.originalDetails[0].materielName,
          // åˆ†ç»„后的总需求数量
          qty: row.orderQuantity,
          // ä¸»å•据编号
          upperOrderNo: this.row.upperOrderNo,
          // å…³é”®ï¼šå½“前分组的所有明细ID集合
          detailIds: row.originalDetails.map(detail => detail.id),
          // ä¸»å•据ID
          mainOrderId: this.row.id,
          // å®Œæ•´åˆ†ç»„行信息(备用)
          groupRow: row
        });
      } else {
        this.$refs.selectedStock.open(row);
        ElMessage.warning("该分组没有明细数据,无法指定库存");
      }
    },
    handleViewDetail(row) {
      // æŸ¥çœ‹åˆ†ç»„明细的详细信息
      if (row.originalDetails && row.originalDetails.length > 0) {
        // è¿™é‡Œå¯ä»¥æ‰“开一个新的弹窗显示所有明细,或者使用第一个明细
        this.$refs.selectedStock.open(row.originalDetails[0]);
      }
    },
    lockstocks() {
      if (this.selection.length === 0) {
        return this.$message.error("请选择单据明细");
      }
      var keys = this.selection.map((item) => item.id);
      // èŽ·å–æ‰€æœ‰é€‰ä¸­åˆ†ç»„çš„åŽŸå§‹æ˜Žç»†ID
      const detailIds = [];
      this.selection.forEach(group => {
        if (group.originalDetails && group.originalDetails.length > 0) {
          group.originalDetails.forEach(detail => {
            if (detail.id) {
              detailIds.push(detail.id);
            }
          });
        }
      });
      if (detailIds.length === 0) {
        return this.$message.error("没有找到可锁定的明细");
      }
      this.http
        .post("api/OutboundOrderDetail/LockOutboundStocks", keys, "数据处理中")
        .post("api/OutboundOrderDetail/LockOutboundStocks", detailIds, "数据处理中")
        .then((x) => {
          if (!x.status) return this.$message.error(x.message);
          this.$message.success("操作成功");
@@ -389,24 +434,44 @@
          });
        });
    },
    handleOpenPicking() {
      this.$router.push({
        path: "/outbound/picking",
        query: { orderId: this.row.id, orderNo: this.row.orderNo },
      });
    },
    handleOpenBatchPicking() {
      this.$router.push({
        path: "/outbound/batchpicking",
        query: { orderId: this.row.id, orderNo: this.row.orderNo },
      });
    },
    outbound() {
        const savedStation = stationManager.getStation();
      console.log(savedStation);
      if (this.selection.length === 0) {
        return this.$message.error("请选择单据明细");
      }
      // èŽ·å–æ‰€æœ‰é€‰ä¸­åˆ†ç»„çš„åŽŸå§‹æ˜Žç»†ID
      const detailIds = [];
      this.selection.forEach(group => {
        if (group.originalDetails && group.originalDetails.length > 0) {
          group.originalDetails.forEach(detail => {
            if (detail.id) {
              detailIds.push(detail.id);
            }
          });
        }
      });
      if (detailIds.length === 0) {
        return this.$message.error("没有找到可出库的明细");
      }
      const platformOptions = [
        { label: "站台2", value: "2-1" },
        { label: "站台3", value: "3-1" },
@@ -465,7 +530,7 @@
                  },
                }, [
                  h(ElSelect, {
                    placeholder: "请选择出库站台(3-12)",
                    placeholder: "请选择出库站台",
                    modelValue: formData.selectedPlatform,
                    "onUpdate:modelValue": (val) => {
                      formData.selectedPlatform = val;
@@ -509,9 +574,8 @@
                        return;
                      }
                      const keys = this.selection.map((item) => item.id);
                      const requestParams = {
                        taskIds: keys,
                        taskIds: detailIds,
                        outboundPlatform: formData.selectedPlatform,
                      };
@@ -548,6 +612,7 @@
      vnode.appContext = this.$.appContext;
      render(vnode, mountNode);
    },
    outboundbatch() {
       const savedStation = stationManager.getStation();
      console.log(savedStation);
@@ -557,6 +622,16 @@
      if (this.selection.length > 1) {
        return this.$message.error("只能选择一条单据明细进行分批出库");
      }
      const selectedGroup = this.selection[0];
      if (!selectedGroup.originalDetails || selectedGroup.originalDetails.length === 0) {
        return this.$message.error("没有找到明细数据");
      }
      // åˆ†æ‰¹å‡ºåº“通常针对单个明细
      // è¿™é‡Œä½¿ç”¨ç¬¬ä¸€ä¸ªæ˜Žç»†
      const selectedDetail = selectedGroup.originalDetails[0];
      const platformOptions = [
        { label: "站台2", value: "2-1" },
        { label: "站台3", value: "3-1" },
@@ -629,7 +704,7 @@
                  },
                }, [
                  h(ElSelect, {
                    placeholder: "请选择出库站台(3-12)",
                    placeholder: "请选择出库站台",
                    modelValue: formData.selectedPlatform,
                    "onUpdate:modelValue": (val) => {
                      formData.selectedPlatform = val;
@@ -667,6 +742,7 @@
                    step: "0.01",
                    precision: 2,
                    min: 0.01,
                    max: selectedDetail.orderQuantity - selectedDetail.overOutQuantity - selectedDetail.lockQuantity - selectedDetail.moveQty,
                  }),
                ]),
                h("div", {
@@ -698,9 +774,8 @@
                        return;
                      }
                      const keys = this.selection.map((item) => item.id);
                      const requestParams = {
                        orderDetailId: keys[0],
                        orderDetailId: selectedDetail.id,
                        outboundPlatform: formData.selectedPlatform,
                        batchQuantity: formData.outboundDecimal,
                      };
@@ -735,52 +810,52 @@
        }
      );
      vnode.appContext = this.$.appContext;
      vnode.appContext = this.$appContext;
      render(vnode, mountNode);
    },
    setCurrent(row) {
      this.$refs.singleTable.setCurrentRow(row);
    },
    handleCurrentChange(val) {
      this.currentRow = val;
    },
    getButtonEnable(propName, row) {
      if (propName == "assignStock") {
        if (
          row.orderDetailStatus !== 0 &&
          row.orderDetailStatus !== 60 &&
          row.orderDetailStatus !== 70 &&
          row.orderDetailStatus !== 80
          row.orderDetailStatus !== 70
        ) {
          return true;
        } else {
          return false;
        } else {
          return true;
        }
      }
      return false;
    },
    parentCall(fun) {
      if (typeof fun != "function") {
        return console.log("扩展组件需要传入一个回调方法才能获取父级Vue对象");
      }
      fun(this);
    },
    handleRowClick(row) {
      this.$refs.singleTable.toggleRowSelection(row);
    },
    handleSelectionChange(val) {
      this.selection = val;
    },
    getDictionaryData() {
      if (this.dictionaryList) {
        return;
      }
      var param = [];
      this.tableColumns.forEach((x) => {
        if (x.type == "tag" && x.bindKey != "") {
          param.push(x.bindKey);
        }
      });
      var param = ["orderDetailStatusEnum"];
      this.http
        .post("api/Sys_Dictionary/GetVueDictionary", param, "查询中")
        .then((x) => {
@@ -789,21 +864,22 @@
          }
        });
    },
    getDictionary(row, column) {
    getDictionaryForGroup(row) {
      if (this.dictionaryList) {
        var item = this.dictionaryList.find((x) => x.dicNo == column.bindKey);
        var item = this.dictionaryList.find((x) => x.dicNo == "orderDetailStatusEnum");
        if (item) {
          var dicItem = item.data.find((x) => x.key == row[column.prop]);
          var dicItem = item.data.find((x) => x.key == row.orderDetailStatus);
          if (dicItem) {
            return dicItem.value;
          } else {
            return row[column.prop];
            return row.orderDetailStatus;
          }
        } else {
          return row[column.prop];
          return row.orderDetailStatus;
        }
      }
      return row[column.prop];
      return row.orderDetailStatus;
    },
  },
};
ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/views/taskinfo/task.vue
@@ -90,14 +90,14 @@
        width: 120,
        align: "left",
      },
      // {
      //   field: "taskType",
      //   title: "任务类型",
      //   type: "int",
      //   width: 120,
      //   align: "left",
      //   bind: { key: "taskType", data: [] },
      // },
      {
        field: "taskType",
        title: "任务类型",
        type: "int",
        width: 120,
        align: "left",
        bind: { key: "taskType", data: [] },
      },
      {
        field: "taskStatus",
        title: "任务状态",
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_InboundService/InboundOrderService.cs
@@ -645,15 +645,19 @@
                {
                    resultDTO.UniqueUnit = "";
                }
                var validDetails = _stockDetailRepository.Db.Queryable<Dt_StockInfoDetail>().Where(s => s.OrderNo == orderNo).ToList();
                resultDTO.StockSumQuantity = orderDetail.Details.Sum(d => d.OrderQuantity);
                resultDTO.StockCount = orderDetail.Details.Count;
                if (validDetails.Any())
                {
                    resultDTO.StockSumQuantity -= validDetails.Sum(d => d.StockQuantity);
                    // æ˜Žç»†è®°å½•数:符合条件的有效记录条数
                    resultDTO.StockCount -= validDetails.Count;
                }
                var inbound =_inboundOrderRepository.Db.Queryable<Dt_InboundOrder>().Where(x => x.InboundOrderNo == orderNo);
                var inboundDetails = _inboundOrderDetailRepository.Db.Queryable<Dt_InboundOrderDetail>().Where(x => x.OrderId == inbound.First().Id).ToList();
                resultDTO.StockSumQuantity = inboundDetails.Where(x=>x.ReceiptQuantity==0).Sum(x=>x.OrderQuantity);
                resultDTO.StockCount = inboundDetails.Where(x => x.ReceiptQuantity == 0).Count();
                //var validDetails = _stockDetailRepository.Db.Queryable<Dt_StockInfoDetail>().Where(s => s.OrderNo == orderNo).ToList();
                //resultDTO.StockSumQuantity = orderDetail.Details.Sum(d => d.OrderQuantity);
                //resultDTO.StockCount = orderDetail.Details.Count;
                //if (validDetails.Any())
                //{
                //    resultDTO.StockSumQuantity -= validDetails.Sum(d => d.StockQuantity);
                //    // æ˜Žç»†è®°å½•数:符合条件的有效记录条数
                //    resultDTO.StockCount -= validDetails.Count;
                //}
                return content.OK("", resultDTO);
            }
            catch (Exception ex)
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_Model/Models/Outbound/Dt_OutboundLockInfo.cs
@@ -111,7 +111,7 @@
        public string SupplyCode { get; set; }
        [SugarColumn(ColumnName = "lineNo", ColumnDescription = "行号")]
        public string? lineNo { get; set; }
        public string lineNo { get; set; }
        public string WarehouseCode { get; set; }
        /// <summary>
@@ -120,33 +120,43 @@
        [SugarColumn(IsNullable = false, ColumnDescription = "状态")]
        public int Status { get; set; }
        [SugarColumn(Length = 100)]
        [SugarColumn(Length = 100, ColumnDescription = "当前条码")]
        public string CurrentBarcode { get; set; } // å½“前条码(拆包后可能变化)
        [SugarColumn(IsNullable = false, ColumnDescription = "原始锁定数量")]
        public decimal OriginalLockQuantity { get; set; } // åŽŸå§‹é”å®šæ•°é‡
        public int IsSplitted { get; set; } // æ˜¯å¦å·²æ‹†åŒ… 0-否 1-是
        [SugarColumn(  ColumnDescription = "拆包父锁定Id")]
        public int? ParentLockId { get; set; }
        [SugarColumn(IsNullable = false, Length = 50, ColumnDescription = "操作者")]
        public string Operator { get; set; }
        [SugarColumn(  ColumnDescription = "物料条码数量")]
        public decimal BarcodeQty { get; set; }
        [SugarColumn(ColumnDescription = "物料单位")]
        public string BarcodeUnit { get; set; }
        [SugarColumn(ColumnDescription = "分批出库批次号")]
        public string OutboundBatchNo { get; set; }
        [Navigate(NavigateType.OneToOne, nameof(StockInfo))]//一对一 SchoolId是StudentA类里面的
        public Dt_StockInfo StockInfo { get; set; } //不能赋值只能是null
        [SugarColumn(ColumnDescription = "是否分配")]
        public int IsUnallocated { get; set; } = 0;
        [SugarColumn(ColumnDescription = "厂区")]
        public string FactoryArea { get; set; }
        /// <summary>
        /// å‰©ä½™æ•°é‡
        /// </summary>
        [SqlSugar.SugarColumn(IsIgnore = true)]
        public decimal RemainQuantity => AssignQuantity - PickedQty;
        public int ReturnToMESStatus { get; set; }
    }
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_Model/Models/Outbound/Dt_PickingRecord.cs
@@ -12,91 +12,166 @@
    /// <summary>
    /// æ‹£é€‰è®°å½•表
    /// </summary>
    [SugarTable(nameof(Dt_PickingRecord), "拣选记录表")]
    public class Dt_PickingRecord : BaseEntity
    [SugarTable("Dt_PickingRecord")]
    public class Dt_PickingRecord : BaseEntity
    {
        [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
        /// <summary>
        /// ä¸»é”®ID
        /// </summary>
        [SugarColumn(IsPrimaryKey = true, IsIdentity = true, ColumnDescription = "")]
        public int Id { get; set; }
        /// <summary>
        /// ä»»åŠ¡å·
        /// </summary>
        [SugarColumn(ColumnDescription = "")]
        public int TaskNo { get; set; }
        public string OrderNo { get; set; }
        /// <summary>
        /// ç‰©æ–™æ¡ç 
        /// </summary>
        [SugarColumn(ColumnDescription = "物料条码")]
        public string Barcode { get; set; }
        /// <summary>
        /// å‡ºåº“详情ID
        /// </summary>
        [SugarColumn(ColumnDescription = "出库详情ID")]
        public int OrderDetailId { get; set; }
        public string PalletCode { get; set; }
        public int OutStockLockId { get; set; }
        public string MaterielCode { get; set; }
        [SugarColumn(Length = 100)]
        public string Barcode { get; set; }
        /// <summary>
        /// æœ¬æ¬¡æ‹£é€‰æ•°é‡
        /// </summary>
        [SugarColumn(ColumnDescription = "本次拣选数量")]
        public decimal PickQuantity { get; set; }
        public DateTime PickTime { get; set; } = DateTime.Now;
        /// <summary>
        /// æ‹£é€‰æ—¶é—´
        /// </summary>
        [SugarColumn(ColumnDescription = "拣选时间")]
        public DateTime PickTime { get; set; }
        [SugarColumn(Length = 50)]
        public string Operator { get; set; }
        [SugarColumn(Length = 50)]
        /// <summary>
        /// æ‹£é€‰åº“位
        /// </summary>
        [SugarColumn(ColumnDescription = "拣选库位")]
        public string LocationCode { get; set; }
        /// <summary>
        /// æ‰˜ç›˜ç¼–号
        /// </summary>
        [SugarColumn(ColumnDescription = "托盘编号")]
        public int StockId { get; set; }
        public string BatchNo { get; set; }
        /// <summary>
        /// æ“ä½œç±»åž‹ï¼š0-拣选 1-回库
        /// </summary>
        [SugarColumn(ColumnDescription = "操作类型:0-拣选 1-回库")]
        public string Operator { get; set; }
        public bool IsCancelled { get; set; }
        /// <summary>
        /// è®¢å•号
        /// </summary>
        [SugarColumn(ColumnDescription = "订单号")]
        public string OrderNo { get; set; }
        public DateTime? CancelTime { get; set; }
        /// <summary>
        /// æ–™ç®±å·
        /// </summary>
        [SugarColumn(ColumnDescription = "料箱号")]
        public string PalletCode { get; set; }
        public string CancelOperator { get; set; }
        /// <summary>
        /// å‡ºåº“锁定ID
        /// </summary>
        [SugarColumn(ColumnDescription = "出库锁定ID")]
        public int? OutStockLockId { get; set; }
        /// <summary>
        /// ç‰©æ–™ç¼–号
        /// </summary>
        [SugarColumn(ColumnDescription = "物料编号")]
        public string MaterielCode { get; set; }
        /// <summary>
        /// åŽ‚åŒº
        /// </summary>
        [SugarColumn(ColumnDescription = "厂区")]
        public string FactoryArea { get; set; }
        /// <summary>
        /// ä»“库
        /// é»˜è®¤å€¼:
        ///</summary>
        [SugarColumn(ColumnName = "warehouseCode", ColumnDescription = "仓库")]
        public string? WarehouseCode { get; set; }
        /// <summary>
        /// è¡Œå·
        /// é»˜è®¤å€¼:
        ///</summary>
        [SugarColumn(ColumnName = "lineNo", ColumnDescription = "行号")]
        public string? lineNo { get; set; }
        /// <summary>
        /// ä¾›åº”商编号
        /// é»˜è®¤å€¼:
        ///</summary>
        [SugarColumn(ColumnName = "supplyCode", ColumnDescription = "供应商编号")]
        public string? SupplyCode { get; set; }
        /// æ‰¹æ¬¡å·
        /// </summary>
        [SugarColumn(ColumnDescription = "批次号")]
        public string BatchNo { get; set; }
        /// <summary>
        /// æ•°é‡
        /// é»˜è®¤å€¼:
        ///</summary>
        [SugarColumn(ColumnName = "barcodeQty", ColumnDescription = "数量")]
        /// æ˜¯å¦å–消拣选
        /// </summary>
        [SugarColumn(ColumnDescription = "是否取消拣选")]
        public bool IsCancelled { get; set; }
        /// <summary>
        /// å–消时间
        /// </summary>
        [SugarColumn(ColumnDescription = "取消时间")]
        public DateTime? CancelTime { get; set; }
        /// <summary>
        /// å–消人
        /// </summary>
        [SugarColumn(ColumnDescription = "取消人")]
        public string CancelOperator { get; set; }
        /// <summary>
        /// ä»“库编号
        /// </summary>
        [SugarColumn(ColumnDescription = "仓库编号")]
        public string WarehouseCode { get; set; }
        /// <summary>
        /// è¡Œå·
        /// </summary>
        [SugarColumn(ColumnDescription = "行号")]
        public string lineNo { get; set; }
        /// <summary>
        /// ä¾›åº”商编号
        /// </summary>
        [SugarColumn(ColumnDescription = "供应商编号")]
        public string SupplyCode { get; set; }
        /// <summary>
        /// ç‰©æ–™æ•°é‡
        /// </summary>
        [SugarColumn(ColumnDescription = "物料数量")]
        public decimal BarcodeQty { get; set; }
        /// <summary>
        /// å•位
        /// é»˜è®¤å€¼:
        ///</summary>
        [SugarColumn(ColumnName = "barcodeUnit", ColumnDescription = "单位")]
        public string BarcodeUnit { get; set; } = null!;
        /// ç‰©æ–™å•位
        /// </summary>
        [SugarColumn(ColumnDescription = "物料单位")]
        public string BarcodeUnit { get; set; }
        /// <summary>
        ///
        /// é»˜è®¤å€¼:
        ///</summary>
        [SugarColumn(ColumnName = "barcodemoveQty", ColumnDescription = "数量")]
        /// ç‰©æ–™æŒªæ–™æ•°é‡
        /// </summary>
        [SugarColumn(ColumnDescription = "物料挪料数量")]
        public decimal BarcodeMoveQty { get; set; }
        /// <summary>
        /// å›žä¼ MES
        /// </summary>
        [SugarColumn(ColumnDescription = "回传MES")]
        public int ReturnToMESStatus { get; set; }
        /// <summary>
        /// å›žä¼ MES唯一号
        /// </summary>
        [SugarColumn(ColumnDescription = "回传MES唯一号")]
        public string FeedBackMesDocumentNo { get; set; }
    }
    }
    /// <summary>
    /// å›žåº“记录表
@@ -127,48 +202,170 @@
    /// <summary>
    /// æ‹†åŒ…记录表
    /// </summary>
    [SugarTable("Dt_SplitPackageRecord")]
    [SugarTable("Dt_SplitPackageRecord")] // æ˜¾å¼æŒ‡å®šè¡¨åï¼Œä¸Žæ•°æ®åº“一致
    public class Dt_SplitPackageRecord : BaseEntity
    {
        [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
        public int Id { get; set; }
        public string OrderNo { get; set; }
        public int? TaskNum { get; set; }
        public string PalletCode { get; set; }
        public int StockId { get; set; }
        public bool IsReverted { get; set; } = false;
        /// <summary>
        /// ä¸»é”®ID
        /// </summary>
        [SugarColumn(IsPrimaryKey = true, IsIdentity = true, ColumnDescription = "")]
        public long Id { get; set; }
        public bool IsAutoSplit { get; set; } = false;
        public int OutStockLockInfoId { get; set; } // å…³è”的出库锁定信息
        public string OriginalBarcode { get; set; } // åŽŸæ¡ç 
        public string NewBarcode { get; set; } // æ–°æ¡ç 
        /// <summary>
        /// åŽŸæ¡ç 
        /// </summary>
        [SugarColumn(ColumnDescription = "原条码")]
        public string OriginalBarcode { get; set; }
        public string FactoryArea { get; set; }
        /// <summary>
        /// æ–°æ¡ç 
        /// </summary>
        [SugarColumn(ColumnDescription = "新条码")]
        public string NewBarcode { get; set; }
        /// <summary>
        /// åŽŸæ•°é‡
        /// </summary>
        [SugarColumn(ColumnDescription = "原数量")]
        public decimal OriginalQty { get; set; }
        /// <summary>
        /// æ‹†åˆ†æ•°é‡ï¼ˆæ–°æ¡ç æ•°é‡ï¼‰
        /// </summary>
        [SugarColumn(ColumnDescription = "拆分数量(新条码数量)")]
        public decimal SplitQty { get; set; }
        /// <summary>
        /// æ‰¹æ¬¡å·
        /// </summary>
        [SugarColumn(ColumnDescription = "批次号")]
        public string BatchNo { get; set; }
        /// <summary>
        /// åº“位编号
        /// </summary>
        [SugarColumn(ColumnDescription = "库位编号")]
        public string LocationId { get; set; }
        /// <summary>
        /// æ‹†åŒ…æ—¶é—´
        /// </summary>
        [SugarColumn(ColumnDescription = "拆包时间")]
        public DateTime SplitTime { get; set; }
        /// <summary>
        /// çŠ¶æ€ï¼š0-已拆分 1-新条码已回传MES
        /// </summary>
        [SugarColumn(ColumnDescription = "状态:0-已拆分 1-新条码已回传MES")]
        public int Status { get; set; }
        /// <summary>
        /// ä»»åŠ¡å·
        /// </summary>
        [SugarColumn(ColumnDescription = "任务号")]
        public int? TaskNum { get; set; }
        /// <summary>
        /// å‰©ä½™æ•°é‡ï¼ˆåŽŸæ¡ç å‰©ä½™ï¼‰
        /// </summary>
        [SugarColumn(ColumnDescription = "剩余数量(原条码剩余)")]
        public decimal RemainQuantity { get; set; }
        public string MaterielCode { get; set; } // ç‰©æ–™ç¼–码
        public DateTime SplitTime { get; set; } = DateTime.Now;
        public string Operator { get; set; } // æ“ä½œäºº
        public int Status { get; set; } // çŠ¶æ€ï¼š1-已拆包 2-已拣选 3-已回库
        /// <summary>
        /// ç‰©æ–™ç¼–号
        /// </summary>
        [SugarColumn(ColumnDescription = "物料编号")]
        public string MaterielCode { get; set; }
        public DateTime RevertTime { get; set; }
        /// <summary>
        /// æ‰˜ç›˜ç¼–号
        /// </summary>
        [SugarColumn(ColumnDescription = "托盘编号")]
        public string PalletCode { get; set; }
        public string RevertOperator { get; set; }
        /// <summary>
        /// æ’¤é”€æ‹†åŒ…
        /// </summary>
        [SugarColumn(ColumnDescription = "撤销拆包")]
        public bool IsReverted { get; set; }
        /// <summary>
        /// é”å®šè®°å½•Id
        /// </summary>
        [SugarColumn(ColumnDescription = "锁定记录Id")]
        public int OutStockLockInfoId { get; set; }
        /// <summary>
        /// æ“ä½œäºº
        /// </summary>
        [SugarColumn(ColumnDescription = "操作人")]
        public string Operator { get; set; }
        /// <summary>
        /// å•号
        /// </summary>
        [SugarColumn(ColumnDescription = "单号")]
        public string OrderNo { get; set; }
        /// <summary>
        /// åº“å­˜id
        /// </summary>
        [SugarColumn(ColumnDescription = "库存id")]
        public int StockId { get; set; }
        /// <summary>
        /// åŽ‚åŒº
        /// </summary>
        [SugarColumn(ColumnDescription = "厂区")]
        public string FactoryArea { get; set; }
        /// <summary>
        /// æ’¤é”€æ—¶é—´
        /// </summary>
        [SugarColumn(ColumnDescription = "撤销时间")]
        public DateTime? RevertTime { get; set; }
        /// <summary>
        /// ä¸Šä¸€æ¡æ‹†åˆ†è®°å½•ID
        /// </summary>
        [SugarColumn(ColumnDescription = "")]
        public int PreviousSplitRecordId { get; set; }
        [SugarColumn(IsNullable = true)]
        public decimal? OriginalStockQuantity { get; set; }
        /// <summary>
        /// åº“存数
        /// </summary>
        [SugarColumn(ColumnDescription = "库存数")]
        public decimal OriginalStockQuantity { get; set; }
        /// <summary>
        /// æ‹†åŒ…前的库存数量
        /// </summary>
        [SugarColumn(ColumnDescription = "拆包前的库存数量")]
        public decimal StockBeforeSplit { get; set; }
        /// <summary>
        /// æ‹†åŒ…前分配数
        /// </summary>
        [SugarColumn(ColumnDescription = "拆包前分配数")]
        public decimal AssignBeforeSplit { get; set; }
        /// <summary>
        /// æ’¤é”€æ“ä½œäºº
        /// </summary>
        [SugarColumn(ColumnDescription = "")]
        public string RevertOperator { get; set; }
        /// <summary>
        /// æ˜¯å¦è‡ªåŠ¨æ‹†åŒ…
        /// </summary>
        [SugarColumn(ColumnDescription = "是否自动拆包")]
        public bool IsAutoSplit { get; set; }
    }
    /// <summary>
    /// ç©ºç®±å–走记录表
    /// </summary>
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_StockService/StockInfoDetailService.cs
@@ -1,10 +1,13 @@
using SqlSugar;
using WIDESEA_Common.StockEnum;
using System.Collections.Generic;
using WIDESEA_Core;
using WIDESEA_Core.BaseRepository;
using WIDESEA_Core.BaseServices;
using WIDESEA_Core.Enums;
using WIDESEA_Core.Helper;
using WIDESEA_Core.HttpContextUser;
using WIDESEA_Core.Utilities;
using WIDESEA_DTO.Stock;
using WIDESEA_IStockService;
using WIDESEA_Model.Models;
@@ -33,9 +36,11 @@
        public PageGridData<StockInfoDetailWithPalletDto> GetPageData2(PageDataOptions options)
        {
            string wheres = ValidatePageOptions(options);
            var sugarQueryable = Db.Queryable<Dt_StockInfoDetail>().InnerJoin<Dt_StockInfo>((detail, item) => detail.StockId == item.Id);
            var sugarQueryable = Db.Queryable<Dt_StockInfoDetail>().InnerJoin<Dt_StockInfo>((detail, item) => detail.StockId == item.Id)
                .Where((detail, item) => item.StockStatus == StockStatusEmun.入库完成.ObjToInt());
            Dictionary<string, SqlSugar.OrderByType> orderbyDic = GetPageDataSort(options, TProperties);
            List<OrderByModel> orderByModels = new List<OrderByModel>();
@@ -45,9 +50,10 @@
                {
                    OrderByModel orderByModel = new()
                    {
                        FieldName = "detail."+item.Key,
                        FieldName = "detail." + item.Key,
                        OrderByType = item.Value
                    };
                    orderByModels.Add(orderByModel);
                }
                else
                {
@@ -56,8 +62,9 @@
                        FieldName = item.Key,
                        OrderByType = item.Value
                    };
                    orderByModels.Add(orderByModel);
                }
                //orderByModels.Add(orderByModel);
            }
            int totalCount = 0;
            List<SearchParameters> searchParametersList = new List<SearchParameters>();
@@ -72,7 +79,6 @@
                    {
                        foreach (var param in searchParametersList)
                        {
                            // åŒ¹é…æ‰˜ç›˜ç¼–号查询条件(小写字段名)
                            if (param.Name.Equals(nameof(Dt_StockInfo.PalletCode).FirstLetterToLower(), StringComparison.OrdinalIgnoreCase)
                                && !string.IsNullOrEmpty(param.Value?.ToString()))
                            {
@@ -84,8 +90,7 @@
                catch (Exception ex)
                {
                }
            }
            }
            var data = sugarQueryable
             .WhereIF(!wheres.IsNullOrEmpty(), wheres)
             .OrderBy(orderByModels)
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Inbound/InboundOrderController.cs
@@ -66,7 +66,11 @@
        [HttpPost, Route("Test"), AllowAnonymous, MethodParamsValidate]
        public async Task<WebResponseContent> Test()
        {
        {
            //var seq = await _dailySequenceService.GetNextSequenceAsync();
            //var SDDD= "WSLOT" + DateTime.Now.ToString("yyyyMMdd") + seq.ToString()?.PadLeft(5, '0');
            //var originalTask = _taskRepository.Db.Queryable<Dt_Task>().First();
            //var result = _task_HtyService.DeleteAndMoveIntoHty(originalTask, OperateTypeEnum.人工删除);
@@ -90,7 +94,7 @@
            //var  ddddssss = "WSLOT" + DateTime.Now.ToString("yyyyMMddHHmmss") + ssss.ToString().PadLeft(5, '0');
            //erpApiService.GetSuppliersAsync();
           // erpApiService.GetMaterialUnitAsync();
            // erpApiService.GetMaterialUnitAsync();
            //var sss = await _invokeMESService.NewMaterielToMes(new WIDESEA_DTO.Basic.MaterielToMesDTO
            //{
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_WMSServer/Properties/PublishProfiles/FolderProfile.pubxml
@@ -4,13 +4,13 @@
-->
<Project>
  <PropertyGroup>
    <DeleteExistingFiles>false</DeleteExistingFiles>
    <DeleteExistingFiles>true</DeleteExistingFiles>
    <ExcludeApp_Data>false</ExcludeApp_Data>
    <LaunchSiteAfterPublish>true</LaunchSiteAfterPublish>
    <LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
    <LastUsedPlatform>Any CPU</LastUsedPlatform>
    <PublishProvider>FileSystem</PublishProvider>
    <PublishUrl>E:\IISText\HuanAn\WMS</PublishUrl>
    <PublishUrl>D:\ALD</PublishUrl>
    <WebPublishMethod>FileSystem</WebPublishMethod>
    <_TargetId>Folder</_TargetId>
    <SiteUrlToLaunchAfterPublish />