1
heshaofeng
2026-01-13 1866b69e8f67e382a0a75268d63e6418c8ae02e7
1
已删除1个文件
已修改10个文件
861 ■■■■ 文件已修改
项目代码/WIDESEA_WMSClient/config/buttons.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WIDESEA_WMSClient/src/extension/inbound/Dt_AllocateOrder.js 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WIDESEA_WMSClient/src/extension/inbound/allocateinboundOrder.js 273 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WIDESEA_WMSClient/src/extension/inbound/inboundOrder.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WIDESEA_WMSClient/src/extension/outbound/outboundOrder.js 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WIDESEA_WMSClient/src/views/Home.vue 437 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/BigGreenService/BigGreenService.cs 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_IInboundService/IInboundOrderService.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_InboundService/InboundOrderService.cs 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Inbound/InboundOrderController.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目资料/接口文档/~$es接口文档.docx 补丁 | 查看 | 原始文档 | blame | 历史
ÏîÄ¿´úÂë/WIDESEA_WMSClient/config/buttons.js
@@ -319,7 +319,7 @@
    name: "关闭单据",
    icon: '',
    class: '',
    value: 'CloseOrder',
    value: ' ',
    type: 'warning',
    onClick: function () {
    }
ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/extension/inbound/Dt_AllocateOrder.js
@@ -404,7 +404,6 @@
          param.wheres.push(...wheres);
        return true;
        return true;
      },
      searchAfter(result) {
        //查询后,result返回的查询数据,可以在显示到表格前处理表格的值
ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/extension/inbound/allocateinboundOrder.js
@@ -5,12 +5,13 @@
import { ElDialog , ElForm, ElFormItem, ElInput, ElButton, ElMessage ,ElSelect ,ElOption } from 'element-plus'; // å¼•å…¥ElMessage,解决提示无反应
import gridBody from '../inbound/extend/Pallet.vue'
import gridHeader from './extend/EmptyTrayInbound.vue'
import gridFooter from "./extend/UndoPalletGroup.vue";
let extension = {
    components: {
      //查询界面扩展组件
      gridHeader: gridHeader,
      gridBody: gridBody,
      gridFooter: '',
      gridFooter: gridFooter,
      //新建、编辑弹出框扩展组件
      modelHeader: '',
      modelBody: '',
@@ -44,207 +45,8 @@
      //     this.$emit('openPalletDialog', targetRow.orderNo);
      //   }
      // },
      {
                name: '撤销组盘',
                type: 'primary',
                value: '撤销组盘',
                onClick: function () {
                    console.log('撤销组盘按钮被点击');
                    const mountNode = document.createElement('div');
                    document.body.appendChild(mountNode);
                    // å“åº”式表单数据:托盘号(必填)
                    const formData = reactive({
                        palletCode: '', // æ‰˜ç›˜å·è¾“入框
                        barcode:''
                    });
                    // æäº¤è¡¨å•的统一逻辑
                    const submitForm = async () => {
                        const formRef = vnode.component.refs.cancelPalletForm;
                        try {
                            // æ‰§è¡Œè¡¨å•校验(托盘号必填)
                            await formRef.validate();
                        } catch (err) {
                            ElMessage.warning('请输入有效的托盘号');
                            return;
                        }
                        // å‘起撤销组盘请求
                        try {
                            //console.log('发起撤销组盘请求,托盘号:', formData.palletCode.trim());
                            const response = await http.post('/api/InboundOrder/UndoPalletGroup?palletCode='+formData.palletCode.trim()+'&barcode='+formData.barcode.trim());
                            const { status, message, data } = response;
                            if (status) {
                                ElMessage.success(`撤销组盘成功,托盘号:${formData.palletCode.trim()}`);
                                this.refresh(); // æˆåŠŸåŽåˆ·æ–°åˆ—è¡¨
                                // å…³é—­å¯¹è¯æ¡†
                                render(null, mountNode);
                                document.body.removeChild(mountNode);
                            } else {
                                console.log('撤销组盘失败,后端提示:', message);
                                ElMessage.error(message || data?.message || '撤销组盘失败');
                                selectPalletCodeInput(); // é€‰ä¸­è¾“入框方便重新输入
                            }
                        } catch (error) {
                            console.error('撤销组盘请求异常:', error);
                            ElMessage.error('网络异常或接口错误,请稍后重试');
                            selectPalletCodeInput();
                        }
                    };
                    // é€‰ä¸­è¾“入框文本(方便重新输入)
                    const selectPalletCodeInput = () => {
                        setTimeout(() => {
                            const inputRef = vnode.component.refs.palletCodeInput;
                            if (inputRef) {
                                const targetInput = inputRef.$el?.querySelector('input') || inputRef;
                                targetInput?.focus();
                                targetInput?.select();
                            }
                        }, 100);
                    };
                    // åˆ›å»ºå¯¹è¯æ¡†VNode
                    const vnode = createVNode(ElDialog, {
                        title: '撤销组盘',
                        width: '400px',
                        modelValue: true,
                        appendToBody: true,
                        onOpened: () => {
                            // å¯¹è¯æ¡†æ‰“开后自动聚焦输入框
                            setTimeout(() => {
                                const inputRef = vnode.component.refs.palletCodeInput;
                                inputRef?.focus();
                            }, 100);
                        },
                        'onUpdate:modelValue': (isVisible) => {
                            if (!isVisible) {
                                render(null, mountNode);
                                document.body.removeChild(mountNode);
                            }
                        }
                    }, {
                        default: () => h(ElForm, {
                            model: formData,
                            rules: {
                                palletCode: [
                                    { required: true, message: '请输入托盘号', trigger: ['blur', 'enter'] },
                                    { min: 1, max: 50, message: '托盘号长度不能超过50个字符', trigger: ['blur', 'input'] }
                                ]
                            },
                            ref: 'cancelPalletForm'
                        }, [
                            // æ‰˜ç›˜å·è¾“入项
                            h(ElFormItem, { label: '托盘号', prop: 'palletCode', required: true }, [
                                h(ElInput, {
                                    type: 'text',
                                    modelValue: formData.palletCode,
                                    'onUpdate:modelValue': (val) => {
                                        formData.palletCode = val;
                                    },
                                    ref: 'palletCodeInput',
                                    placeholder: '扫码输入或手动输入托盘号',
                                    maxLength: 50,
                                    // ç›‘听回车事件(扫码枪默认会发送回车)
                                    onKeydown: (e) => {
                                        if (e.key === 'Enter') {
                                            e.preventDefault();
                                            submitForm();
                                        }
                                    }
                                })
                            ]),
                            h(ElFormItem,{label: '条码', prop: 'barcode'},[
                              h(ElInput, {
                                type: 'text',
                                modelValue: formData.barcode,
                                'onUpdate:modelValue': (val) => {
                                    formData.barcode = val;
                                },
                                placeholder: '可选,扫码输入或手动输入条码',
                                maxLength: 50,
                                onKeydown: (e) => {
                                    if (e.key === 'Enter') {
                                        e.preventDefault();
                                        submitForm();
                                    }
                                  }
                              })
                            ]),
                            // åº•部按钮区
                            h('div', { style: { textAlign: 'right', marginTop: '16px' } }, [
                                h(ElButton, {
                                    type: 'text',
                                    onClick: () => {
                                        render(null, mountNode);
                                        document.body.removeChild(mountNode);
                                        ElMessage.info('取消撤销组盘');
                                    }
                                }, '取消'),
                                h(ElButton, {
                                    type: 'primary',
                                    onClick: submitForm.bind(this) // ç»‘定this上下文
                                }, '确认撤销')
                            ])
                        ])
                    });
                    vnode.appContext = this.$.appContext;
                    render(vnode, mountNode);
                }
            },
      {
  name: '分批入库',
  type: 'primary',
  value: '分批入库',
  onClick: async function () {
    console.log('分批入库按钮被点击,开始校验');
    const selectedRows = this.$refs.table.getSelected();
    // æ ¡éªŒ1:是否选中行(至少选择一条)
    if (selectedRows.length === 0) {
      console.log('校验不通过:未选中任何单据');
      ElMessage.warning('请选择至少一条单据');
      return;
    }
    // æ”¶é›†æ‰€æœ‰é€‰ä¸­å•据的编号(过滤无单据号的异常行)
    const inboundOrderNos = selectedRows
      .filter(row => row.orderNo)
      .map(row => row.orderNo);
    // æ ¡éªŒ2:是否有有效单据号
    if (inboundOrderNos.length === 0) {
      console.log('校验不通过:选中单据无有效编号');
      ElMessage.warning('选中的单据中无有效编号,请重新选择');
      return;
    }
    try {
      console.log('发起分批入库请求,参数:', { inboundOrderNos});
      const response = await http.post('/api/InboundOrder/BatchOrderFeedbackToMes', {
        orderNos: inboundOrderNos,
        inout:1
      });
      const { status, message, data } = response;
      if (status) {
        console.log('分批入库成功,后端返回:', data);
        ElMessage.success(`分批入库成功!共处理${inboundOrderNos.length}条单据`);
        this.refresh(); // å…¥åº“成功后刷新列表(复用原有逻辑)
      } else {
        console.log('分批入库失败,后端提示:', message);
        ElMessage.error(message || data?.message || '分批入库失败');
      }
    } catch (error) {
      console.error('分批入库请求异常:', error);
      ElMessage.error('网络异常或接口错误,请稍后重试');
    }
  }
},], box: [], detail: [] },
], box: [], detail: [] },
    methods: {
       //下面这些方法可以保留也可以删除
      onInit() {  
@@ -260,6 +62,73 @@
               this.$refs.gridHeader.open();
            }
        }
        var UndoPalletGroupBtn = this.buttons.find(
        (x) => x.value == "UndoPalletGroup"
      );
      if (UndoPalletGroupBtn != null) {
        UndoPalletGroupBtn.onClick = () => {
          this.$refs.gridFooter.open();
        };
      }
      var BatchInOrderFeedbackToMesBtn = this.buttons.find(
        (x) => x.value == "BatchInOrderFeedbackToMes"
      );
      if (BatchInOrderFeedbackToMesBtn != null) {
        BatchInOrderFeedbackToMesBtn.onClick = () => {
          var rows = this.$refs.table.getSelected();
          // æ ¡éªŒæ˜¯å¦æœ‰é€‰ä¸­æ•°æ®
          if (!rows || rows.length === 0) {
            return this.$Message.error("请先选择需要处理的单据");
          }
          if (rows.length > 1) {
            return this.$Message.error("请选择一条数据");
          }
          this.http.post(`api/Inbound/BatchInOrderFeedbackToMes?id=${rows[0].id}`, {}, "数据处理中...")
            .then((x) => {
              if (x.status) {
                this.$Message.success(x.message);
                this.refresh();
              } else {
                return this.$Message.error(x.message);
              }
            })
            .catch((error) => {
              // å¢žåŠ å¼‚å¸¸æ•èŽ·ï¼Œå¤„ç†ç½‘ç»œé”™è¯¯ç­‰æƒ…å†µ
              //_this.$Message.error('请求失败:' + (error.message || '未知错误'));
            });
        };
      }
      var CloseOrderBtn = this.buttons.find(
        (x) => x.value == "CloseOrder"
      );
      if (CloseOrderBtn != null) {
        CloseOrderBtn.onClick = () => {
          var rows = this.$refs.table.getSelected();
          // æ ¡éªŒæ˜¯å¦æœ‰é€‰ä¸­æ•°æ®
          if (!rows || rows.length === 0) {
            return this.$Message.error("请先选择需要关闭的单据");
          }
          if (rows.length > 1) {
            return this.$Message.error("请选择一条单据");
          }
          this.http.post(`api/InboundOrder/HandCloseOrder?orderIds=${rows[0].orderNo}`, {}, "数据处理中...")
            .then((x) => {
              if (x.status) {
                this.$Message.success(x.message);
                this.refresh();
              } else {
                return this.$Message.error(x.message);
              }
            })
            .catch((error) => {
              // å¢žåŠ å¼‚å¸¸æ•èŽ·ï¼Œå¤„ç†ç½‘ç»œé”™è¯¯ç­‰æƒ…å†µ
              //_this.$Message.error('请求失败:' + (error.message || '未知错误'));
            });
        };
      }
      },
      onInited() {
        
ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/extension/inbound/inboundOrder.js
@@ -82,7 +82,7 @@
          if (rows.length > 1) {
            return this.$Message.error("请选择一条单据");
          }
          this.http.post(`api/InboundOrder/HandCloseOrder?orderIds=${rows[0].id}`, {}, "数据处理中...")
          this.http.post(`api/InboundOrder/HandCloseOrder?orderIds=${rows[0].inboundOrderNo}`, {}, "数据处理中...")
            .then((x) => {
              if (x.status) {
                this.$Message.success(x.message);
ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/extension/outbound/outboundOrder.js
@@ -555,6 +555,34 @@
      //框架初始化配置后
      //如果要配置明细表,在此方法操作
      //this.detailOptions.columns.forEach(column=>{ });
      var CloseOrderBtn = this.buttons.find(
              (x) => x.value == "CloseOrder"
            );
            if (CloseOrderBtn != null) {
              CloseOrderBtn.onClick = () => {
                var rows = this.$refs.table.getSelected();
                // æ ¡éªŒæ˜¯å¦æœ‰é€‰ä¸­æ•°æ®
                if (!rows || rows.length === 0) {
                  return this.$Message.error("请先选择需要关闭的单据");
                }
                if (rows.length > 1) {
                  return this.$Message.error("请选择一条单据");
                }
                this.http.post(`api/InboundOrder/HandCloseOrder?orderIds=${rows[0].orderNo}`, {}, "数据处理中...")
                  .then((x) => {
                    if (x.status) {
                      this.$Message.success(x.message);
                      this.refresh();
                    } else {
                      return this.$Message.error(x.message);
                    }
                  })
                  .catch((error) => {
                    // å¢žåŠ å¼‚å¸¸æ•èŽ·ï¼Œå¤„ç†ç½‘ç»œé”™è¯¯ç­‰æƒ…å†µ
                    //_this.$Message.error('请求失败:' + (error.message || '未知错误'));
                  });
              };
            }
    },
    searchBefore(param) {
ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/views/Home.vue
@@ -2,85 +2,120 @@
  <div class="wms-dashboard">
    <!-- ç»Ÿè®¡å¡ç‰‡åŒºåŸŸ - ç»‘定响应式数据 -->
    <el-row :gutter="20" class="stats-card-row">
  <el-col :span="4">
    <div class="stats-card">
      <div class="metric-icon">
        <el-icon :size="32">
          <Box />
        </el-icon>
      </div>
      <div class="card-title">总库存</div>
      <div class="card-value">{{ formatNumber(bigscreendata.totalStockQuantity) }}</div>
    </div>
  </el-col>
  <el-col :span="4">
    <div class="stats-card">
      <div class="metric-icon">
        <el-icon :size="32">
          <Document />
        </el-icon>
      </div>
      <div class="card-title">待出库订单</div>
      <div class="card-value">{{ bigscreendata.unOutBoundOrderCount }}</div>
    </div>
  </el-col>
  <el-col :span="4">
    <div class="stats-card">
      <div class="metric-icon">
        <el-icon :size="32">
          <Download />
        </el-icon>
      </div>
      <div class="card-title">今日入库完成数</div>
      <div class="card-value">{{ bigscreendata.inboundCount }}</div>
    </div>
  </el-col>
  <el-col :span="4">
    <div class="stats-card">
      <div class="metric-icon">
        <el-icon :size="32">
          <Upload />
        </el-icon>
      </div>
      <div class="card-title">今日出库完成数</div>
      <div class="card-value">{{ bigscreendata.outboundCount }}</div>
    </div>
  </el-col>
  <el-col :span="4">
    <div class="stats-card">
      <div class="metric-icon">
        <el-icon :size="32">
          <Box />
        </el-icon>
      </div>
      <div class="card-title">有货料箱</div>
      <div class="card-value">{{ formatNumber(bigscreendata.inStockPallet) }}</div>
    </div>
  </el-col>
  <el-col :span="4">
    <div class="stats-card">
      <div class="metric-icon">
        <el-icon :size="32">
          <Box />
        </el-icon>
      </div>
      <div class="card-title">空箱数量</div>
      <div class="card-value">{{ formatNumber(bigscreendata.freeStockPallet) }}</div>
    </div>
  </el-col>
</el-row>
      <el-col :span="4">
        <div class="stats-card">
          <div class="metric-icon">
            <el-icon :size="32">
              <Box />
            </el-icon>
          </div>
          <div class="card-title">总库存</div>
          <div class="card-value">{{ formatNumber(bigscreendata.totalStockQuantity) }}</div>
        </div>
      </el-col>
      <el-col :span="4">
        <div class="stats-card">
          <div class="metric-icon">
            <el-icon :size="32">
              <Document />
            </el-icon>
          </div>
          <div class="card-title">待出库订单</div>
          <div class="card-value">{{ bigscreendata.unOutBoundOrderCount }}</div>
        </div>
      </el-col>
      <el-col :span="4">
        <div class="stats-card">
          <div class="metric-icon">
            <el-icon :size="32">
              <Download />
            </el-icon>
          </div>
          <div class="card-title">今日入库完成数</div>
          <div class="card-value">{{ bigscreendata.inboundCount }}</div>
        </div>
      </el-col>
      <el-col :span="4">
        <div class="stats-card">
          <div class="metric-icon">
            <el-icon :size="32">
              <Upload />
            </el-icon>
          </div>
          <div class="card-title">今日出库完成数</div>
          <div class="card-value">{{ bigscreendata.outboundCount }}</div>
        </div>
      </el-col>
      <el-col :span="4">
        <div class="stats-card">
          <div class="metric-icon">
            <el-icon :size="32">
              <Box />
            </el-icon>
          </div>
          <div class="card-title">有货料箱</div>
          <div class="card-value">{{ formatNumber(bigscreendata.inStockPallet) }}</div>
        </div>
      </el-col>
      <el-col :span="4">
        <div class="stats-card">
          <div class="metric-icon">
            <el-icon :size="32">
              <Box />
            </el-icon>
          </div>
          <div class="card-title">空箱数量</div>
          <div class="card-value">{{ formatNumber(bigscreendata.freeStockPallet) }}</div>
        </div>
      </el-col>
    </el-row>
    <!-- å›¾è¡¨åŒºåŸŸï¼ˆç¬¬ä¸€è¡Œï¼‰ -->
    <el-row :gutter="20" class="chart-row">
      <el-col :span="12">
        <!-- æ›¿æ¢el-card为div,保留chart-card类名 -->
      <el-col :span="8">
        <div class="chart-card">
          <div class="chart-title">库位利用率</div>
          <div ref="locationRateRef" class="chart-container"></div>
        </div>
      </el-col>
      <el-col :span="12">
      <!-- ä¸´æœŸä¿¡æ¯æ”¹ä¸ºè¡¨æ ¼ -->
      <el-col :span="8">
        <div class="chart-card">
          <div class="chart-title">物料临期信息</div>
          <!-- ä¸´æœŸç‰©æ–™è¡¨æ ¼ -->
          <div class="expiration-table-container">
            <el-table
              :data="expirationTableData"
              border
              stripe
              style="width: 100%;"
              :empty-text="emptyText"
            >
              <el-table-column prop="materielCode" label="物料编码" align="center" />
              <el-table-column prop="materielName" label="物料名称" align="center" show-overflow-tooltip />
              <el-table-column prop="batchNo" label="批次号" align="center" />
              <el-table-column prop="validDate" label="有效期" align="center" />
              <el-table-column label="临期等级" align="center">
                <template #default="{ row }">
                  <span :class="getExpireLevelClass(row.expireLevel)">{{ row.expireLevel }}</span>
                </template>
              </el-table-column>
              <el-table-column prop="daysToExpiration" label="临期天数" align="center">
                <template #default="{ row }">
                  <span :class="row.daysToExpiration < 0 ? 'text-red' : ''">
                    {{ row.daysToExpiration < 0 ? '已过期' : `${row.daysToExpiration}天` }}
                  </span>
                </template>
              </el-table-column>
              <!-- <el-table-column prop="barcode" label="条码" align="center" /> -->
              <el-table-column prop="stockQuantity" label="库存数量" align="center" />
              <el-table-column prop="locationCode" label="库位" align="center" />
              <el-table-column prop="palletCode" label="托盘编号" align="center" />
            </el-table>
          </div>
        </div>
      </el-col>
      <el-col :span="8">
        <div class="chart-card">
          <div class="chart-title">近7日出入库趋势(图像化走势)</div>
          <div ref="stockTrendRef" class="chart-container"></div>
@@ -95,7 +130,6 @@
    <!-- è¡¨æ ¼åŒºåŸŸ - ç»‘定后端作业数据 -->
    <el-row :gutter="20" class="table-row" width="100%">
      <el-col :span="24">
        <!-- æ›¿æ¢el-card为div,保留table-card类名 -->
        <div class="table-card">
          <div class="table-title">实时作业监控</div>
          <el-table :data="showTaskList" border style="width: 100%;">
@@ -125,9 +159,13 @@
</template>
<script setup>
import { ref, onMounted, onUnmounted, nextTick } from 'vue';
import { ref, onMounted, onUnmounted, nextTick, computed } from 'vue';
import * as echarts from 'echarts';
import http from "@/api/http.js";
// è¡¥å……缺失的图标导入
import { Box, Document, Download, Upload } from '@element-plus/icons-vue';
// è¡¥å……ElMessage导入
import { ElMessage } from 'element-plus';
// å“åº”式数据
const month = ref('month');
@@ -146,9 +184,86 @@
  taskList: [],
  inboundCount: 0,
  outboundCount: 0,
  inventoryLocationDist: [], // åº“存库位分布数据
  exceptionTypeTrend: []     // å¼‚常类型趋势数据
  inventoryLocationDist: [],
  exceptionTypeTrend: [],
  nearExpirationList: []      // æ”¹ä¸ºæ•°ç»„类型,匹配新数据结构
});
// ä¸´æœŸè¡¨æ ¼æ•°æ®ï¼ˆè®¡ç®—属性:适配新的数组数据结构)
const expirationTableData = computed(() => {
  // æ–°æ•°æ®ç»“构是数组,直接取数组并处理空值
  const expirationList = bigscreendata.value.nearExpirationList || [];
  // ç¬¬ä¸€æ­¥ï¼šåŽ»é‡ - æŒ‰ ç‰©æ–™ç¼–码+批次号+托盘编号+有效期 å”¯ä¸€æ ‡è¯†åŽ»é‡
  const uniqueMap = new Map();
  expirationList.forEach(item => {
    // æ‹¼æŽ¥å”¯ä¸€æ ‡è¯†ï¼ˆå¤„理空值,避免因空值导致重复判断错误)
    const uniqueKey = [
      item.materielCode || '未知编码',
      item.batchNo || '未知批次',
      item.palletCode || '未知托盘',
    ].join('|'); // ç”¨ç‰¹æ®Šå­—符分隔,避免字段值拼接后混淆
    // åªä¿ç•™ç¬¬ä¸€æ¬¡å‡ºçŽ°çš„è®°å½•
    if (!uniqueMap.has(uniqueKey)) {
      uniqueMap.set(uniqueKey, item);
    }
  });
  // æå–去重后的数组
  const uniqueExpirationList = Array.from(uniqueMap.values());
  // ç¬¬äºŒæ­¥ï¼šéåŽ†åŽ»é‡åŽçš„æ•°æ®ï¼Œè¡¥å……ä¸´æœŸç­‰çº§å’Œé»˜è®¤å€¼
  return uniqueExpirationList.map(item => {
    // æå–当前物料的临期天数(核心字段)
    const daysToExpiration = item.daysToExpiration || 0;
    // è®¡ç®—临期等级
    let expireLevel = '';
    if (daysToExpiration < 0) {
      expireLevel = '已过期';
    } else if (daysToExpiration <= 7) {
      expireLevel = '7天内临期';
    } else if (daysToExpiration <= 15) {
      expireLevel = '15天内临期';
    } else if (daysToExpiration <= 30) {
      expireLevel = '30天内临期';
    } else {
      expireLevel = '30天以上';
    }
    return {
      materielCode: item.materielCode || '未知编码',
      materielName: item.materielName || '未知名称',
      batchNo: item.batchNo || '未知批次',
      validDate: item.validDate || '未知有效期',
      daysToExpiration: daysToExpiration,
      expireLevel: expireLevel,
      stockQuantity: item.stockQuantity || 0,
      locationCode: item.locationCode || '未知库位',
      palletCode: item.palletCode || '未知托盘',
      unit: item.unit || 'PCS'
    };
  });
});
// ç©ºæ•°æ®æç¤ºæ–‡æœ¬ï¼ˆä¿®æ­£åˆ¤æ–­é€»è¾‘)
const emptyText = computed(() => {
  const expirationList = bigscreendata.value.nearExpirationList || [];
  // æ•°ç»„长度为0时显示空提示,否则不显示(原逻辑写反了)
  return expirationList.length === 0 ? '暂无临期物料数据' : '';
});
// èŽ·å–ä¸´æœŸç­‰çº§æ ·å¼ç±»
const getExpireLevelClass = (level) => {
  switch(level) {
    case '已过期': return 'expire-level expired';
    case '7天内临期': return 'expire-level urgent';
    case '15天内临期': return 'expire-level warning';
    case '30天内临期': return 'expire-level normal';
    case '30天以上': return 'expire-level low';
    default: return 'expire-level default';
  }
};
const taskStatusMap = {
  100: "新建",
@@ -171,57 +286,54 @@
  990: "任务异常",
  110: "提升机执行中"
};
// èŽ·å–ä»»åŠ¡çŠ¶æ€æ–‡æœ¬
const getTaskStatusText = (statusNum) => {
  // å¤„理空值、无效值,兜底显示“未知状态”
  if (statusNum === undefined || statusNum === null || isNaN(statusNum)) {
    return "未知状态";
  }
  // ç²¾å‡†åŒ¹é…æ˜ å°„值,无匹配则返回“未知状态”
  return taskStatusMap[statusNum] || "未知状态";
};
const showTaskList = ref([]); // è¡¨æ ¼æ˜¾ç¤ºçš„5条任务(轮播用)
const currentTaskIndex = ref(5); // ä¸‹ä¸€ä¸ªè¦æ˜¾ç¤ºçš„任务索引(初始从第6条开始,前5条默认显示)
let taskCarouselTimer = null; // è½®æ’­å®šæ—¶å™¨
// è¡¨æ ¼æ˜¾ç¤ºçš„任务列表(轮播用)
const showTaskList = ref([]);
const currentTaskIndex = ref(5);
let taskCarouselTimer = null;
// æ•°å­—格式化(千分位分隔)
const formatNumber = (num) => {
  if (!num) return '0';
  return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
};
// ä»»åŠ¡åˆ—è¡¨è½®æ’­é€»è¾‘
const startTaskCarousel = () => {
  // æ¸…除旧定时器,防止重复启动
  if (taskCarouselTimer) clearInterval(taskCarouselTimer);
  const totalTask = bigscreendata.value.taskList.length;
  // ä»»åŠ¡æ•°<=5时,不轮播(没有更多任务可换)
  if (totalTask <= 5) {
    showTaskList.value = [...bigscreendata.value.taskList];
    return;
  }
  // å¯åЍ5秒定时器
  taskCarouselTimer = setInterval(() => {
    // 1. æ–°å¢žä¸‹1条任务到显示列表末尾
    showTaskList.value.push(bigscreendata.value.taskList[currentTaskIndex.value]);
    // 2. åˆ é™¤åˆ—表最前面1条旧任务(始终保持5条)
    showTaskList.value.shift();
    // 3. æ›´æ–°ä¸‹ä¸€ä¸ªä»»åŠ¡ç´¢å¼•ï¼Œè¶…å‡ºæ€»æ•°åˆ™é‡ç½®ï¼ˆå¾ªçŽ¯è½®æ’­ï¼‰
    currentTaskIndex.value++;
    if (currentTaskIndex.value >= totalTask) {
      currentTaskIndex.value = 0; // é‡ç½®ä¸º0,循环播放
      currentTaskIndex.value = 0;
    }
  }, 5000); // 5秒间隔
  }, 5000);
};
// èŽ·å–ä»»åŠ¡ç±»åž‹æ–‡æœ¬
const getTaskTypeText = (taskTypeNum) => {
  // å¤„理空值/无效值
  if (!taskTypeNum || isNaN(taskTypeNum)) return "未知类型";
  
  // å¯¹åº”后端TaskEnumHelper的分组规则
  if (taskTypeNum >= 500 && taskTypeNum < 900) return "入库";
  if (taskTypeNum >= 100 && taskTypeNum < 500) return "出库";
  if (taskTypeNum >= 900 && taskTypeNum < 1000) return "移库";
  return "其他作业"; // å…œåº•
  return "其他作业";
};
// èŽ·å–ä»»åŠ¡çŠ¶æ€æ ·å¼ç±»
@@ -230,15 +342,14 @@
    return "status-unknown";
  }
  
  // æ ¹æ®çŠ¶æ€èŒƒå›´è¿”å›žä¸åŒæ ·å¼
  if (statusNum >= 900) return "status-completed"; // å®Œæˆ
  if (statusNum >= 400) return "status-processing"; // è¾“送线执行中
  if (statusNum >= 300) return "status-processing"; // AGV执行中
  if (statusNum >= 200) return "status-processing"; // å †åž›æœºæ‰§è¡Œä¸­
  if (statusNum >= 100) return "status-pending"; // æ–°å»ºã€å·²å‘送
  if (statusNum === 970) return "status-suspended"; // æŒ‚èµ·
  if (statusNum === 980) return "status-canceled"; // å–消
  if (statusNum === 990) return "status-error"; // å¼‚常
  if (statusNum >= 900) return "status-completed";
  if (statusNum >= 400) return "status-processing";
  if (statusNum >= 300) return "status-processing";
  if (statusNum >= 200) return "status-processing";
  if (statusNum >= 100) return "status-pending";
  if (statusNum === 970) return "status-suspended";
  if (statusNum === 980) return "status-canceled";
  if (statusNum === 990) return "status-error";
  
  return "status-unknown";
};
@@ -247,34 +358,32 @@
const getTypeClass = (taskTypeNum) => {
  if (!taskTypeNum || isNaN(taskTypeNum)) return "type-unknown";
  
  // å¯¹åº”后端TaskEnumHelper的分组规则
  if (taskTypeNum >= 500 && taskTypeNum < 900) return "type-inbound"; // å…¥åº“
  if (taskTypeNum >= 100 && taskTypeNum < 500) return "type-outbound"; // å‡ºåº“
  if (taskTypeNum >= 900 && taskTypeNum < 1000) return "type-transfer"; // ç§»åº“
  if (taskTypeNum >= 500 && taskTypeNum < 900) return "type-inbound";
  if (taskTypeNum >= 100 && taskTypeNum < 500) return "type-outbound";
  if (taskTypeNum >= 900 && taskTypeNum < 1000) return "type-transfer";
  
  return "type-other"; // å…¶ä»–作业
  return "type-other";
};
// èŽ·å–åŽç«¯å¤§å±æ•°æ®
const fetchBigGreenData = async () => {
  try {
    debugger
    const res = await http.get('/api/BigScreen/GetBigGreenData');
    console.log('大屏数据', res);
    
    bigscreendata.value = res.data || res;
    // æ•°æ®æ›´æ–°åŽåˆ·æ–°å›¾è¡¨
    // æ•°æ®æ›´æ–°åŽåˆ·æ–°å›¾è¡¨å’Œè¡¨æ ¼
    nextTick(() => {
      const total = bigscreendata.value.taskList.length;
      // åˆå§‹åŒ–显示前5条(不足5条则显示全部)
      showTaskList.value = total >=5 
        ? [...bigscreendata.value.taskList.slice(0,5)] 
        : [...bigscreendata.value.taskList];
      startTaskCarousel(); // å¯åŠ¨ä»»åŠ¡è½®æ’­
      startTaskCarousel();
      refreshCharts();
    });
  } catch (error) {
    ElMessage.error('数据获取失败,请检查后端接口是否正常');
    console.error('数据获取失败:', error);
  }
};
@@ -292,23 +401,21 @@
const locationRateRef = ref(null);
const exceptionTrendRef = ref(null);
// å›¾è¡¨å®žä¾‹ï¼ˆå…¨å±€ç®¡ç†ï¼Œç”¨äºŽé”€æ¯å’Œresize)
// å›¾è¡¨å®žä¾‹ï¼ˆå…¨å±€ç®¡ç†ï¼‰
let inventoryPieChart = null;
let stockTrendChart = null;
let locationRateChart = null;
let exceptionTrendChart = null;
// åˆå§‹åŒ–库存库位分布饼图(关联后端数据)
// åˆå§‹åŒ–库存库位分布饼图
const initInventoryPie= () => {
  if (!inventoryPieRef.value) return;
  // é”€æ¯æ—§å®žä¾‹ï¼Œé˜²æ­¢å†…存泄漏
  if (inventoryPieChart) {
    inventoryPieChart.dispose();
  }
  inventoryPieChart = echarts.init(inventoryPieRef.value);
  // ä¼˜å…ˆä½¿ç”¨åŽç«¯æ•°æ®ï¼Œæ— æ•°æ®åˆ™ç”¨é»˜è®¤å€¼
  const locationData = bigscreendata.value.inventoryLocationDist.length 
    ? bigscreendata.value.inventoryLocationDist
    : [
@@ -361,7 +468,7 @@
  return inventoryPieChart;
};
// åˆå§‹åŒ–è¿‘7日出入库趋势图(关联后端数据)
// åˆå§‹åŒ–è¿‘7日出入库趋势图
const initStockTrend = () => {
  if (!stockTrendRef.value) return;
@@ -370,15 +477,11 @@
  }
  stockTrendChart = echarts.init(stockTrendRef.value);
  // ä¼˜å…ˆä½¿ç”¨åŽç«¯æ•°æ®
  const trendData = bigscreendata.value.dailyInOutBoundList;
  console.log('出入库趋势数据', trendData);
  // è®¡ç®—数据中的最大值,用于设置Y轴范围
  const maxInbound = Math.max(...trendData.map(item => item.dailyInboundQuantity || 0));
  const maxOutbound = Math.max(...trendData.map(item => item.dailyOutboundQuantity || 0));
  const maxInbound = trendData.length ? Math.max(...trendData.map(item => item.dailyInboundQuantity || 0)) : 0;
  const maxOutbound = trendData.length ? Math.max(...trendData.map(item => item.dailyOutboundQuantity || 0)) : 0;
  const maxValue = Math.max(maxInbound, maxOutbound);
  console.log('最大值计算结果:', { maxInbound, maxOutbound, maxValue });
  const option = {
    tooltip: {
@@ -407,7 +510,6 @@
      type: 'value',
      name: '数量',
      min: 0,
      // æ ¹æ®æ•°æ®åŠ¨æ€è®¾ç½®æœ€å¤§å€¼ï¼Œç•™å‡ºä¸€äº›ç©ºé—´
      max: maxValue > 0 ? Math.ceil(maxValue * 1.2) : 10
    },
    series: [
@@ -438,18 +540,15 @@
  return stockTrendChart;
};
// åˆå§‹åŒ–库位利用率环形图(修正:统一实例管理,关联后端数据)
// åˆå§‹åŒ–库位利用率环形图
const initLocationRate = () => {
  if (!locationRateRef.value) return;
  // é”€æ¯æ—§å®žä¾‹
  if (locationRateChart) {
    locationRateChart.dispose();
  }
  locationRateChart = echarts.init(locationRateRef.value);
  // ä¼˜å…ˆä½¿ç”¨åŽç«¯æ•°æ®ï¼Œæ— æ•°æ®åˆ™ç”¨é»˜è®¤å€¼
  console.log('库位利用率数据', bigscreendata.value.locationUtilizationRate);
  const utilizationRate = bigscreendata.value.locationUtilizationRate || 0;
  const freeRate = 100 - utilizationRate;
@@ -507,7 +606,7 @@
  return locationRateChart;
};
// åˆå§‹åŒ–异常类型统计趋势图(关联后端数据)
// åˆå§‹åŒ–异常类型统计趋势图
const initExceptionTrend = () => {
  if (!exceptionTrendRef.value) return;
@@ -516,7 +615,6 @@
  }
  exceptionTrendChart = echarts.init(exceptionTrendRef.value);
  // ä¼˜å…ˆä½¿ç”¨åŽç«¯æ•°æ®
  const exceptionData = bigscreendata.value.exceptionTypeTrend.length
    ? bigscreendata.value.exceptionTypeTrend
    : {
@@ -602,11 +700,11 @@
  return exceptionTrendChart;
};
// åˆ·æ–°æ‰€æœ‰å›¾è¡¨ï¼ˆç§»é™¤æ— æ•ˆé›·è¾¾å›¾é€»è¾‘)
// åˆ·æ–°æ‰€æœ‰å›¾è¡¨
const refreshCharts = () => {
  const charts = [
    initStockTrend,
    initLocationRate,
    initLocationRate
  ];
  charts.forEach(initFunc => {
@@ -633,7 +731,7 @@
  });
};
// ç»„件挂载时:先请求数据,再初始化图表
// ç»„件挂载时
onMounted(() => {
  // å…ˆèŽ·å–åŽç«¯æ•°æ®
  fetchBigGreenData();
@@ -647,7 +745,7 @@
  });
});
// ç»„件卸载时:销毁图表实例,移除事件监听
// ç»„件卸载时
onUnmounted(() => {
  const charts = [
    inventoryPieChart,
@@ -661,7 +759,7 @@
      chart.dispose();
    }
  });
  clearInterval(taskCarouselTimer); // æ¸…除轮播定时器
  clearInterval(taskCarouselTimer);
  window.removeEventListener('resize', handleResize);
});
</script>
@@ -692,7 +790,7 @@
  margin-bottom: 20px;
}
/* æ ¸å¿ƒä¿®æ”¹ï¼šè¡¥å……div版card的基础样式,模拟el-card的视觉效果 */
/* æ ¸å¿ƒæ ·å¼ï¼šå¡ç‰‡åŸºç¡€æ ·å¼ */
.stats-card, .chart-card, .table-card {
  background: #fff;
  border-radius: 8px;
@@ -712,7 +810,6 @@
  overflow: hidden;
  background: linear-gradient(145deg, #ffffff 0%, #f9fafc 100%);
}
.stats-card:hover {
  transform: translateY(-6px) scale(1.02);
@@ -735,7 +832,6 @@
  transition: all 0.3s ease;
}
.card-title {
  font-size: 15px;
  color: #606266;
@@ -745,23 +841,16 @@
}
.card-value {
  font-size: 26px;
  font-weight: 600;
  margin: 4px 0;
  background: linear-gradient(to right, #409eff, #36cfc9);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}
.card-value {
  font-size: 32px;
  font-weight: 700;
  margin: 8px 0 4px;
  color: #2c3e50;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
  line-height: 1.2;
  background: linear-gradient(to right, #409eff, #36cfc9);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}
.card-change {
@@ -799,6 +888,58 @@
  box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.03);
}
/* ä¸´æœŸç‰©æ–™è¡¨æ ¼å®¹å™¨æ ·å¼ */
.expiration-table-container {
  width: 100%;
  height: 100%;
  min-height: 300px;
  flex: 1;
  overflow-y: auto;
}
/* ä¸´æœŸç­‰çº§æ ‡ç­¾æ ·å¼ */
.expire-level {
  padding: 2px 8px;
  border-radius: 4px;
  font-size: 12px;
  font-weight: 500;
}
.expire-level.expired {
  background-color: #fff2f0;
  color: #ff4d4f;
  border: 1px solid #ffccc7;
}
.expire-level.urgent {
  background-color: #fff7e6;
  color: #fa8c16;
  border: 1px solid #ffd591;
}
.expire-level.warning {
  background-color: #f6ffed;
  color: #52c41a;
  border: 1px solid #b7eb8f;
}
.expire-level.normal {
  background-color: #e6f7ff;
  color: #1890ff;
  border: 1px solid #91d5ff;
}
.expire-level.low {
  background-color: #f0f2f5;
  color: #666666;
  border: 1px solid #d9d9d9;
}
.expire-level.default {
  background-color: #fafafa;
  color: #8c8c8c;
  border: 1px solid #e8e8e8;
}
/* å·²è¿‡æœŸæ–‡å­—红色 */
.text-red {
  color: #ff4d4f;
  font-weight: 500;
}
.chart-title,
.table-title {
@@ -814,7 +955,6 @@
  position: relative;
  letter-spacing: 0.5px;
}
.view-btn {
  font-size: 12px;
@@ -1090,10 +1230,7 @@
  animation: pulse 2.8s infinite;
}
.btn-group {
  margin-left: 10px;
}
/* ç§»é™¤åŽŸæœ‰çš„el-card__body样式穿透,因为已经替换为纯div */
</style>
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/BigGreenService/BigGreenService.cs
@@ -58,7 +58,7 @@
            //计算库位利用率
            var freeLocation = _locationInfoRepository.Db.Queryable<Dt_LocationInfo>().Where(x => x.LocationStatus == (int)LocationStatusEnum.Free).Count();
            var inStockLocation = _locationInfoRepository.Db.Queryable<Dt_LocationInfo>().Where(x => x.LocationStatus == (int)LocationStatusEnum.InStock || x.LocationStatus == (int)LocationStatusEnum.Pallet).Count();
            var inStockLocation = _locationInfoRepository.Db.Queryable<Dt_LocationInfo>().Where(x => x.LocationStatus != (int)LocationStatusEnum.Free).Count();
            int totalLocation = freeLocation + inStockLocation;
            decimal locationUtilizationRate = totalLocation == 0
                ? 0
@@ -75,7 +75,7 @@
            // 4. èŽ·å–è¿‘7日每日出入库明细(核心修改:调用上面的方法)
            var dailyInOutBoundList = Get7DaysDailyInOutBound();
            var nearExpirationList = GetMaterialsNearExpiration();
            List<StockInfoDetailExtDTO> nearExpirationList = GetMaterialsNearExpiration();
            //获取作业统计
            var completeTask = SimpleStatistics();
            //任务
@@ -239,7 +239,7 @@
            public List<SimpleStatisticsDTO> CompleteTask { get; set; }
            public NearExpirationDTO NearExpirationList { get; set; }
            public List<StockInfoDetailExtDTO> NearExpirationList { get; set; }
        }
        /// <summary>
@@ -270,82 +270,70 @@
            public int Count { get; set; }
        }
        public class NearExpirationDTO
        public class StockInfoDetailExtDTO : Dt_StockInfoDetail
        {
            public int DaysToExpiration { get; set; }
            public List<Dt_StockInfoDetail> Details { get; set; }
            public string LocationCode { get; set; }
            public string PalletCode { get; set; }
            public int DaysToExpiration { get; set; }
        }
        ///<summary>
        ///获取近30天要过期的物料
        /// </summary>
        public NearExpirationDTO GetMaterialsNearExpiration()
        public List<StockInfoDetailExtDTO> GetMaterialsNearExpiration()
        {
            // åˆå§‹åŒ–返回DTO
            var resultDTO = new NearExpirationDTO
            {
                Details = new List<Dt_StockInfoDetail>(),
                LocationCode = string.Empty,
                PalletCode = string.Empty,
                DaysToExpiration = 0 // åˆå§‹åŒ–天数
            };
            List<StockInfoDetailExtDTO> resultDTO = new List<StockInfoDetailExtDTO>();
            DateTime currentTime = DateTime.Now;
            DateTime thirtyDaysLater = currentTime.AddDays(30);
            // ç­›é€‰30天内过期的库存明细
            var nearExpirationList = _stockInfoDetailRepository.Db.Queryable<Dt_StockInfoDetail>()
                .Where(x => (x.ValidDate.Value - x.CreateDate).TotalDays <= 30)
            var nearExpirationList = _stockInfoDetailRepository.QueryData()
                .Join(
                    _stockInfoRepository.QueryData(),
                    detail => detail.StockId,
                    stock => stock.Id,
                    (detail, stock) => new
                    {
                        Detail = detail,
                        LocationCode = stock.LocationCode,
                        PalletCode = stock.PalletCode
                    }
                )
                .Where(x => x.Detail.ValidDate.HasValue
                        && (x.Detail.ValidDate.Value - x.Detail.CreateDate).TotalDays <= 30)
                .ToList();
            // æ— ç¬¦åˆæ¡ä»¶çš„æ˜Žç»†ï¼Œç›´æŽ¥è¿”回
            if (!nearExpirationList.Any())
            {
                return resultDTO;
            }
            
            var firstStockId = nearExpirationList.First().StockId;
            var stock = _stockInfoRepository.Db.Queryable<Dt_StockInfo>()
                .First(x => x.Id == firstStockId);
            if (stock == null)
            foreach (var item in nearExpirationList)
            {
                return resultDTO;
            }
                int daysToExpire = item.Detail.ValidDate.HasValue
                    ? Math.Max(0, (item.Detail.ValidDate.Value - item.Detail.CreateDate).Days)
                    : 0;
            resultDTO.LocationCode = stock.LocationCode;
            resultDTO.PalletCode = stock.PalletCode;
            int minDaysToExpiration = int.MaxValue;
            foreach (var detail in nearExpirationList)
            {
                TimeSpan totalDaysToExpiration = detail.ValidDate.Value - detail.CreateDate;
                double remainingDays = totalDaysToExpiration.TotalDays;
                int daysToExpiration = (int)Math.Ceiling(Math.Max(0, remainingDays));
                var extDetail = new StockInfoDetailExtDTO
                {
                    MaterielCode = item.Detail.MaterielCode,
                    MaterielName = item.Detail.MaterielName,
                    BatchNo = item.Detail.BatchNo,
                    SupplyCode = item.Detail.SupplyCode,
                    StockQuantity = item.Detail.StockQuantity,
                    CreateDate = item.Detail.CreateDate,
                    ValidDate = item.Detail.ValidDate,
                    LocationCode = item.LocationCode,
                    PalletCode = item.PalletCode,
                    Barcode = item.Detail.Barcode,
                    DaysToExpiration = daysToExpire
                };
               
                if (daysToExpiration < minDaysToExpiration)
                {
                    minDaysToExpiration = daysToExpiration;
                }
                resultDTO.Details.Add(detail);
                resultDTO.Add(extDetail);
            }
            resultDTO.DaysToExpiration = minDaysToExpiration;
            resultDTO = resultDTO.OrderBy(d => d.DaysToExpiration).ToList();
            return resultDTO;
        }
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_IInboundService/IInboundOrderService.cs
@@ -28,6 +28,6 @@
        WebResponseContent UnPalletGroupBarcode(string orderNo);
        WebResponseContent HandCloseOrder(List<int> orderIds);
        WebResponseContent HandCloseOrder(List<string> orderIds);
    }
}
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_InboundService/InboundOrderService.cs
@@ -47,9 +47,10 @@
        private readonly IRepository<Dt_StockInfo> _stockRepository;
        private readonly IRepository<Dt_LocationInfo> _locationInfoRepository;
        private readonly IBasicService _basicService;
        private readonly IRepository<Dt_AllocateOrder> _allocateOrderRepository;
        public IRepository<Dt_InboundOrder> Repository => BaseDal;
        public InboundOrderService(IRepository<Dt_InboundOrder> BaseDal, IMapper mapper, IUnitOfWorkManage unitOfWorkManage, IRepository<Dt_InboundOrderDetail> inboundOrderDetailRepository, IRepository<Dt_Task> taskRepository, IStockService stockService, IInboundOrderDetailService inboundOrderDetailService, IMaterialUnitService materialUnitService, IRepository<Dt_StockInfoDetail> stockDetailRepository, IRepository<Dt_InboundOrder> inboundOrderRepository, IRepository<Dt_WarehouseArea> warehouseAreaRepository, IRepository<Dt_StockInfo> stockRepository, IRepository<Dt_LocationType> locationTypeRepository, IMaterielInfoService materielInfoService, IBasicService basicService, IRepository<Dt_LocationInfo> locationInfoRepository) : base(BaseDal)
        public InboundOrderService(IRepository<Dt_InboundOrder> BaseDal, IMapper mapper, IUnitOfWorkManage unitOfWorkManage, IRepository<Dt_InboundOrderDetail> inboundOrderDetailRepository, IRepository<Dt_Task> taskRepository, IStockService stockService, IInboundOrderDetailService inboundOrderDetailService, IMaterialUnitService materialUnitService, IRepository<Dt_StockInfoDetail> stockDetailRepository, IRepository<Dt_InboundOrder> inboundOrderRepository, IRepository<Dt_WarehouseArea> warehouseAreaRepository, IRepository<Dt_StockInfo> stockRepository, IRepository<Dt_LocationType> locationTypeRepository, IMaterielInfoService materielInfoService, IBasicService basicService, IRepository<Dt_LocationInfo> locationInfoRepository, IRepository<Dt_AllocateOrder> allocateOrderRepository) : base(BaseDal)
        {
            _mapper = mapper;
            _unitOfWorkManage = unitOfWorkManage;
@@ -66,6 +67,7 @@
            _materielInfoService = materielInfoService;
            _basicService = basicService;
            _locationInfoRepository = locationInfoRepository;
            _allocateOrderRepository = allocateOrderRepository;
        }
        public async Task<WebResponseContent> ReceiveInboundOrder(List<Dt_InboundOrder> models, int operateType)
@@ -968,14 +970,18 @@
            return content.OK(data: details);
        }
        public WebResponseContent HandCloseOrder(List<int> orderIds)
        public WebResponseContent HandCloseOrder(List<string> orderNos)
        {
            try
            {
                foreach (int id in orderIds)
                foreach (var orderNo in orderNos)
                {
                    var inbound = _inboundOrderRepository.QueryFirst(x => x.Id == id);
                    if(inbound.OrderStatus !=(int)InOrderStatusEnum.未开始 && inbound.OrderStatus != (int)InOrderStatusEnum.入库中)
                    var inbound = _inboundOrderRepository.QueryFirst(x => x.InboundOrderNo == orderNo);
                    if(inbound == null)
                    {
                        return WebResponseContent.Instance.Error($"该单据不存在,无法进行关闭");
                    }
                    if (inbound.OrderStatus != (int)InOrderStatusEnum.未开始 && inbound.OrderStatus != (int)InOrderStatusEnum.入库中)
                    {
                        return WebResponseContent.Instance.Error($"该单据状态不可以关闭");
                    }
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Inbound/InboundOrderController.cs
@@ -260,7 +260,7 @@
        [HttpPost, Route("HandCloseOrder"), AllowAnonymous, MethodParamsValidate]
        public WebResponseContent HandCloseOrder(List<int> orderIds)
        public WebResponseContent HandCloseOrder(List<string> orderIds)
        {
            return Service.HandCloseOrder(orderIds);
        }
ÏîÄ¿×ÊÁÏ/½Ó¿ÚÎĵµ/~$es½Ó¿ÚÎĵµ.docx
Binary files differ