已添加7个文件
已修改34个文件
3701 ■■■■ 文件已修改
项目代码/WIDESEA_WMSClient/config/buttons.js 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WIDESEA_WMSClient/src/components/basic/ViewGrid/methods.js 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WIDESEA_WMSClient/src/extension/check/recheckOrder.js 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WIDESEA_WMSClient/src/extension/inbound/inboundOrder.js 847 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WIDESEA_WMSClient/src/extension/outbound/allocateoutboundOrder.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WIDESEA_WMSClient/src/extension/outbound/extend/newAllocateOrderDetail.vue 797 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WIDESEA_WMSClient/src/extension/outbound/extend/outOrderDetail.vue 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WIDESEA_WMSClient/src/extension/outbound/outboundOrder.js 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WIDESEA_WMSClient/src/extension/stock/stockInfoDetailByMaterielSum.js 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WIDESEA_WMSClient/src/router/viewGird.js 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WIDESEA_WMSClient/src/views/inbound/inboundOrder.vue 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WIDESEA_WMSClient/src/views/outbound/BatchPickingConfirm.vue 609 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WIDESEA_WMSClient/src/views/outbound/outboundOrder.vue 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WIDESEA_WMSClient/src/views/stock/stockInfoDetailByMaterielSum.vue 222 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_BasicService/ErpApiService.cs 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_BasicService/InvokeMESService.cs 309 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_BasicService/LocationInfoService.cs 19 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_Common/TaskEnum/TaskStatusEnum.cs 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_Core/BaseServices/ServiceBase.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_Core/Helper/UtilConvert.cs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_DTO/Stock/StockDetailDtO.cs 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_IStockService/IStockDetailByMaterielService.cs 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_IStockService/IStockInfoDetailService.cs 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_ITaskInfoService/ITaskService.cs 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_ITaskInfoService/ITask_HtyService.cs 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_InboundService/InboundOrderService.cs 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_Model/Models/Outbound/Dt_OutboundOrderDetail.cs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_Model/Models/Outbound/NoStockOutModel.cs 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_Model/Models/Stock/StockDetailByMateriel.cs 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundBatchPickingService.cs 54 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundPickingService.cs 147 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_OutboundService/WIDESEA_OutboundService.csproj 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_StockService/StockDetailByMaterielService.cs 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_StockService/StockInfoDetailService.cs 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_StockService/StockViewService.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService.cs 73 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_TaskInfoService/Task_HtyService.cs 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/ESSController.cs 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Inbound/InboundOrderController.cs 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Stock/StockInfoDetailController.cs 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_WMSServer/Filter/CustomProfile.cs 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ÏîÄ¿´úÂë/WIDESEA_WMSClient/config/buttons.js
@@ -208,6 +208,15 @@
    onClick: function () {
    }
},
{
    name: "分拣",
    // icon: 'el-icon-upload2',
    class: '',
    value: 'BatchOrder',
    type: 'primary',
    onClick: function () {
    }
},
]
export default buttons
ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/components/basic/ViewGrid/methods.js
@@ -874,9 +874,7 @@
    // if (_button) {
    //   _button.name = isAdd ? this.continueAddName : '保 å­˜';
    // }
    this.boxButtons.forEach(x=>{
      btn.hidden=true
    })
    this.boxButtons.forEach(x=>{})
  },
  resetAdd() {
    if (this.hasDetail) {
ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/extension/check/recheckOrder.js
@@ -8,8 +8,8 @@
//此js文件是用来自定义扩展业务代码,可以扩展一些自定义页面或者重新配置生成的代码
import gridBody from './extend/StockSelect.vue'
import http from '@/api/http.js'
import { h,createVNode, render,reactive,ref  } from 'vue';
import { ElDialog , ElForm, ElFormItem, ElInput, ElButton, ElMessage ,ElSelect ,ElOption } from 'element-plus'; // å¼•å…¥ElMessage,解决提示无反应
import { h, createVNode, render, reactive, ref } from 'vue';
import { ElDialog, ElForm, ElFormItem, ElInput, ElButton, ElMessage, ElSelect, ElOption } from 'element-plus'; // å¼•å…¥ElMessage,解决提示无反应
let extension = {
  components: {
    //查询界面扩展组件
@@ -22,36 +22,38 @@
    modelFooter: ''
  },
  tableAction: '', //指定某张表的权限(这里填写表名,默认不用填写)
  buttons: { view: [ {
          name: '组盘',
          type: 'primary',
          value: '组盘',
          onClick: function () { // ä¿®å¤1:移除无用row参数,加日志调试
            console.log('组盘按钮被点击,开始校验');
            const selectedRows = this.$refs.table.getSelected();
            // æ ¡éªŒ1:是否选中行
            if (selectedRows.length === 0) {
              console.log('校验不通过:未选中任何单据');
              ElMessage.warning('请选择一条单据');
              return;
            }
            // æ ¡éªŒ2:是否选中单行
            if (selectedRows.length > 1) {
              console.log('校验不通过:选中多行单据');
              ElMessage.warning('只能选择一条单据');
              return;
            }
            const targetRow = selectedRows[0];
            this.$emit('openPalletDialog', targetRow.orderNo);
          }
        },], box: [], detail: [] }, //扩展的按钮
  buttons: {
    view: [{
      name: '组盘',
      type: 'primary',
      value: '组盘',
      onClick: function () { // ä¿®å¤1:移除无用row参数,加日志调试
        console.log('组盘按钮被点击,开始校验');
        const selectedRows = this.$refs.table.getSelected();
        // æ ¡éªŒ1:是否选中行
        if (selectedRows.length === 0) {
          console.log('校验不通过:未选中任何单据');
          ElMessage.warning('请选择一条单据');
          return;
        }
        // æ ¡éªŒ2:是否选中单行
        if (selectedRows.length > 1) {
          console.log('校验不通过:选中多行单据');
          ElMessage.warning('只能选择一条单据');
          return;
        }
        const targetRow = selectedRows[0];
        this.$emit('openPalletDialog', targetRow.orderNo);
      }
    },], box: [], detail: []
  }, //扩展的按钮
  methods: {
     //下面这些方法可以保留也可以删除
    //下面这些方法可以保留也可以删除
    onInit() {  //框架初始化配置前,
        this.columns.push({
      this.columns.push({
        field: '操作',
        title: '操作',
        width: 90,
@@ -71,6 +73,19 @@
          this.$refs.gridBody.open(row);
        }
      });
      let EmptyTrayOutboundBtn = this.buttons.find(x => x.value == 'BatchOrder');
      if (EmptyTrayOutboundBtn) {
        EmptyTrayOutboundBtn.onClick = function () {
          let rows = this.$refs.table.getSelected();
          if (rows.length == 0) return this.$error("请选择数据!");
          if (rows.length > 1) return this.$error("请选择一条数据!");
          this.$router.push({
            path: '/outbound/picking',
            query: { orderId: rows[0].id,orderNo:rows[0].orderNo}
          })
        }
      }
    },
    onInited() {
      //框架初始化配置后
ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/extension/inbound/inboundOrder.js
@@ -1,23 +1,24 @@
//此js文件是用来自定义扩展业务代码,可以扩展一些自定义页面或者重新配置生成的代码
import http from '@/api/http.js'
import { h,createVNode, render,reactive,ref  } from 'vue';
import { ElDialog , ElForm, ElFormItem, ElInput, ElButton, ElMessage ,ElSelect ,ElOption } from 'element-plus'; // å¼•å…¥ElMessage,解决提示无反应
import { h, createVNode, render, reactive, ref } from 'vue';
import { ElDialog, ElForm, ElFormItem, ElInput, ElButton, ElMessage, ElSelect, ElOption } from 'element-plus'; // å¼•å…¥ElMessage,解决提示无反应
let extension = {
    components: {
      //查询界面扩展组件
      gridHeader: '',
      gridBody: '',
      gridFooter: '',
      //新建、编辑弹出框扩展组件
      modelHeader: '',
      modelBody: '',
      modelFooter: ''
    },
    tableAction: '', //指定某张表的权限(这里填写表名,默认不用填写)
    buttons: { view: [
       {
  components: {
    //查询界面扩展组件
    gridHeader: '',
    gridBody: '',
    gridFooter: '',
    //新建、编辑弹出框扩展组件
    modelHeader: '',
    modelBody: '',
    modelFooter: ''
  },
  tableAction: '', //指定某张表的权限(这里填写表名,默认不用填写)
  buttons: {
    view: [
      {
        name: '组盘',
        type: 'primary',
        value: '组盘',
@@ -39,417 +40,443 @@
          }
          const targetRow = selectedRows[0];
          this.$emit('openPalletDialog', targetRow.inboundOrderNo);
        }
      },
      {
                name: '撤销组盘',
                type: 'primary',
                value: '撤销组盘',
                onClick: function () {
                    console.log('撤销组盘按钮被点击');
                    const mountNode = document.createElement('div');
                    document.body.appendChild(mountNode);
        name: '撤销组盘',
        type: 'primary',
        value: '撤销组盘',
        onClick: function () {
          console.log('撤销组盘按钮被点击');
          const mountNode = document.createElement('div');
          document.body.appendChild(mountNode);
                    // å“åº”式表单数据:托盘号(必填)
                    const formData = reactive({
                        palletCode: '' // æ‰˜ç›˜å·è¾“入框
                    });
          // å“åº”式表单数据:托盘号(必填)
          const formData = reactive({
            palletCode: '' // æ‰˜ç›˜å·è¾“入框
          });
                    // æäº¤è¡¨å•的统一逻辑
                    const submitForm = async () => {
                        const formRef = vnode.component.refs.cancelPalletForm;
                        try {
                            // æ‰§è¡Œè¡¨å•校验(托盘号必填)
                            await formRef.validate();
                        } catch (err) {
                            ElMessage.warning('请输入有效的托盘号');
                            return;
                        }
          // æäº¤è¡¨å•的统一逻辑
          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());
            // å‘起撤销组盘请求
            try {
              //console.log('发起撤销组盘请求,托盘号:', formData.palletCode.trim());
              const response = await http.post('/api/InboundOrder/UndoPalletGroup?palletCode=' + formData.palletCode.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);
                    };
              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();
            }
          };
                    // åˆ›å»ºå¯¹è¯æ¡†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('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上下文
                                }, '确认撤销')
                            ])
                        ])
                    });
          // é€‰ä¸­è¾“入框文本(方便重新输入)
          const selectPalletCodeInput = () => {
            setTimeout(() => {
              const inputRef = vnode.component.refs.palletCodeInput;
              if (inputRef) {
                const targetInput = inputRef.$el?.querySelector('input') || inputRef;
                targetInput?.focus();
                targetInput?.select();
              }
            }, 100);
          };
                    vnode.appContext = this.$.appContext;
                    render(vnode, mountNode);
                }
          // åˆ›å»ºå¯¹è¯æ¡†VNode
          const vnode = createVNode(ElDialog, {
            title: '撤销组盘',
            width: '400px',
            modelValue: true,
            appendToBody: true,
            onOpened: () => {
              // å¯¹è¯æ¡†æ‰“开后自动聚焦输入框
              setTimeout(() => {
                const inputRef = vnode.component.refs.palletCodeInput;
                inputRef?.focus();
              }, 100);
            },
      {
  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.inboundOrderNo)
      .map(row => row.inboundOrderNo);
    // æ ¡éªŒ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('网络异常或接口错误,请稍后重试');
    }
  }
},
     {
  name: '空托盘入库',
  type: 'primary',
  value: '空托盘入库',
  onClick: function () {
    const mountNode = document.createElement('div');
    document.body.appendChild(mountNode);
    // å“åº”式表单数据:料箱码(必填,扫码枪/手动输入)
    const formData = reactive({
      boxCode: '',
      warehouseCode:''
    });
    const warehouses = ref([]);
    const isLoadingWarehouses = ref(false);
    const getWarehouseList = async () => {
      isLoadingWarehouses.value = true;
      try {
        const { data, status } = await http.post('/api/LocationInfo/GetLocationTypes');
        if (status && Array.isArray(data)) {
          // æ ¼å¼åŒ–仓库选项:适配ElSelect的label-value格式
          warehouses.value = data.map(item => ({
            label: item.locationTypeDesc,
            value: item.locationType
          }));
        } else {
          ElMessage.error('获取区域列表失败');
          warehouses.value = [];
        }
      } catch (err) {
        ElMessage.error('区域数据请求异常,请稍后重试');
        warehouses.value = [];
      } finally {
        isLoadingWarehouses.value = false;
      }
    };
    // æäº¤è¡¨å•的统一逻辑(供回车触发和按钮点击共用)
    const submitForm = async () => {
      const formRef = vnode.component.refs.batchInForm;
      try {
        // æ‰§è¡Œè¡¨å•校验(料箱码必填)
        await formRef.validate();
      } catch (err) {
        ElMessage.warning('请输入有效的料箱码');
        return;
      }
      http.post('/api/InboundOrder/EmptyMaterielGroup', {
        palletCode: formData.boxCode.trim(),
        warehouseCode:formData.warehouseCode
      }).then(({ data, status, message }) => {
        if (status) {
          ElMessage.success(`入库成功,料箱码:${formData.boxCode.trim()}`);
          this.refresh();
          formData.boxCode = '';
          setTimeout(() => {
            const inputRef = vnode.component.refs.boxCodeInput;
            inputRef?.focus();
          }, 100);
        } else {
          ElMessage.error(message || data?.message || '入库失败');
          selectBoxCodeInput();
        }
      }).catch(() => {
        ElMessage.error('请求失败,请稍后重试');
        selectBoxCodeInput();
      });
    };
    const selectBoxCodeInput = () => {
      setTimeout(() => {
        const inputRef = vnode.component.refs.boxCodeInput;
        if (inputRef) {
          const targetInput = inputRef.$el?.querySelector('input') || inputRef;
          targetInput?.focus();
          targetInput?.select();
        }
  }, 100);
}
    const vnode = createVNode(ElDialog, {
      title: '空托盘入库',
      width: '400px',
      modelValue: true,
      appendToBody: true,
      onOpened: async () => {
        await getWarehouseList();
        const inputRef = vnode.component.refs.boxCodeInput;
        inputRef?.focus();
      },
      'onUpdate:modelValue': (isVisible) => {
        if (!isVisible) {
          render(null, mountNode);
          document.body.removeChild(mountNode);
        }
      }
    }, {
      default: () => h(ElForm, {
        model: formData,
        rules: {
          boxCode: [
            { required: true, message: '请输入料箱码', trigger: ['blur', 'enter'] }
          ],
          warehouseCode:[
            { required: true, message: '请选择区域', trigger: ['change', 'blur'] }
          ]
        },
        ref: 'batchInForm'
      }, [
        //仓库数据
        h(ElFormItem, { label: '区域', prop: 'warehouseCode', required: true }, [
          h(ElSelect, {
            modelValue: formData.warehouseCode,
            'onUpdate:modelValue': (val) => {
              formData.warehouseCode = val;
            },
            placeholder: '请选择入库区域',
            filterable: true, // æ”¯æŒæœç´¢ä»“库
            loading: isLoadingWarehouses.value, // åŠ è½½çŠ¶æ€
            style: { width: '100%' }
          }, [
            // æ¸²æŸ“仓库下拉选项
            warehouses.value.map(item => h(ElOption, {
              label: item.label,
              value: item.value
            }))
          ])
        ]),
        // æ–™ç®±ç è¾“入项(支持聚焦、回车提交)
        h(ElFormItem, { label: '料箱码', prop: 'boxCode', required: true }, [
          h(ElInput, {
            type: 'text',
            modelValue: formData.boxCode,
            'onUpdate:modelValue': (val) => {
              formData.boxCode = val;
            },
            ref: 'boxCodeInput',
            placeholder: '扫码输入或手动输入料箱码',
            // ç›‘听回车事件(扫码枪默认会发送回车)
            onKeydown: (e) => {
              if (e.key === 'Enter') {
                e.preventDefault();
                submitForm();
            'onUpdate:modelValue': (isVisible) => {
              if (!isVisible) {
                render(null, mountNode);
                document.body.removeChild(mountNode);
              }
            }
          })
        ]),
        // åº•部按钮区
        h('div', { style: { textAlign: 'right', marginTop: '16px' } }, [
          h(ElButton, {
            type: 'text',
            onClick: () => {
              render(null, mountNode);
              document.body.removeChild(mountNode);
              ElMessage.info('取消入库任务');
          }, {
            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('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.inboundOrderNo)
            .map(row => row.inboundOrderNo);
          // æ ¡éªŒ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 || '分批入库失败');
            }
          }, '取消'),
          h(ElButton, {
            type: 'primary',
            onClick: submitForm
          }, '确定')
        ])
      ])
    });
          } catch (error) {
            console.error('分批入库请求异常:', error);
            ElMessage.error('网络异常或接口错误,请稍后重试');
          }
        }
      },
      {
        name: '空托盘入库',
        type: 'primary',
        value: '空托盘入库',
    vnode.appContext = this.$.appContext;
    render(vnode, mountNode);
  }
}
    ], box: [], detail: [] },
    methods: {
       //下面这些方法可以保留也可以删除
      onInit() {
      },
      onInited() {
        //框架初始化配置后
        //如果要配置明细表,在此方法操作
        //this.detailOptions.columns.forEach(column=>{ });
      },
      searchBefore(param) {
        //界面查询前,可以给param.wheres添加查询参数
        //返回false,则不会执行查询
      // this.searchFormFields.orderType=[0]
         let wheres = [{
            'name': 'orderType',
            'value': '0',
            'displayType': 'text'}];
        onClick: function () {
          const mountNode = document.createElement('div');
          document.body.appendChild(mountNode);
          param.wheres.push(...wheres);
        return true;
      },
      searchAfter(result) {
        //查询后,result返回的查询数据,可以在显示到表格前处理表格的值
        return true;
      },
      addBefore(formData) {
        //新建保存前formData为对象,包括明细表,可以给给表单设置值,自己输出看formData的值
        return true;
      },
      updateBefore(formData) {
        //编辑保存前formData为对象,包括明细表、删除行的Id
        return true;
      },
      rowClick({ row, column, event }) {
        //查询界面点击行事件
        this.$refs.table.$refs.table.toggleRowSelection(row); //单击行时选中当前行;
      },
      modelOpenAfter(row) {
        //点击编辑、新建按钮弹出框后,可以在此处写逻辑,如,从后台获取数据
        //(1)判断是编辑还是新建操作: this.currentAction=='Add';
        //(2)给弹出框设置默认值
        //(3)this.editFormFields.字段='xxx';
        //如果需要给下拉框设置默认值,请遍历this.editFormOptions找到字段配置对应data属性的key值
        //看不懂就把输出看:console.log(this.editFormOptions)
          // å“åº”式表单数据:料箱码(必填,扫码枪/手动输入)
          const formData = reactive({
            boxCode: '',
            warehouseCode: ''
          });
          const warehouses = ref([]);
          const isLoadingWarehouses = ref(false);
          const getWarehouseList = async () => {
            isLoadingWarehouses.value = true;
            try {
              const { data, status } = await http.post('/api/LocationInfo/GetLocationTypes');
              if (status && Array.isArray(data)) {
                // æ ¼å¼åŒ–仓库选项:适配ElSelect的label-value格式
                warehouses.value = data.map(item => ({
                  label: item.locationTypeDesc,
                  value: item.locationType
                }));
              } else {
                ElMessage.error('获取区域列表失败');
                warehouses.value = [];
              }
            } catch (err) {
              ElMessage.error('区域数据请求异常,请稍后重试');
              warehouses.value = [];
            } finally {
              isLoadingWarehouses.value = false;
            }
          };
          // æäº¤è¡¨å•的统一逻辑(供回车触发和按钮点击共用)
          const submitForm = async () => {
            const formRef = vnode.component.refs.batchInForm;
            try {
              // æ‰§è¡Œè¡¨å•校验(料箱码必填)
              await formRef.validate();
            } catch (err) {
              ElMessage.warning('请输入有效的料箱码');
              return;
            }
            http.post('/api/InboundOrder/EmptyMaterielGroup', {
              palletCode: formData.boxCode.trim(),
              warehouseCode: formData.warehouseCode
            }).then(({ data, status, message }) => {
              if (status) {
                ElMessage.success(`入库成功,料箱码:${formData.boxCode.trim()}`);
                this.refresh();
                formData.boxCode = '';
                setTimeout(() => {
                  const inputRef = vnode.component.refs.boxCodeInput;
                  inputRef?.focus();
                }, 100);
              } else {
                ElMessage.error(message || data?.message || '入库失败');
                selectBoxCodeInput();
              }
            }).catch(() => {
              ElMessage.error('请求失败,请稍后重试');
              selectBoxCodeInput();
            });
          };
          const selectBoxCodeInput = () => {
            setTimeout(() => {
              const inputRef = vnode.component.refs.boxCodeInput;
              if (inputRef) {
                const targetInput = inputRef.$el?.querySelector('input') || inputRef;
                targetInput?.focus();
                targetInput?.select();
              }
            }, 100);
          }
          const vnode = createVNode(ElDialog, {
            title: '空托盘入库',
            width: '400px',
            modelValue: true,
            appendToBody: true,
            onOpened: async () => {
              await getWarehouseList();
              const inputRef = vnode.component.refs.boxCodeInput;
              inputRef?.focus();
            },
            'onUpdate:modelValue': (isVisible) => {
              if (!isVisible) {
                render(null, mountNode);
                document.body.removeChild(mountNode);
              }
            }
          }, {
            default: () => h(ElForm, {
              model: formData,
              rules: {
                boxCode: [
                  { required: true, message: '请输入料箱码', trigger: ['blur', 'enter'] }
                ],
                warehouseCode: [
                  { required: true, message: '请选择区域', trigger: ['change', 'blur'] }
                ]
              },
              ref: 'batchInForm'
            }, [
              //仓库数据
              h(ElFormItem, { label: '区域', prop: 'warehouseCode', required: true }, [
                h(ElSelect, {
                  modelValue: formData.warehouseCode,
                  'onUpdate:modelValue': (val) => {
                    formData.warehouseCode = val;
                  },
                  placeholder: '请选择入库区域',
                  filterable: true, // æ”¯æŒæœç´¢ä»“库
                  loading: isLoadingWarehouses.value, // åŠ è½½çŠ¶æ€
                  style: { width: '100%' }
                }, [
                  // æ¸²æŸ“仓库下拉选项
                  warehouses.value.map(item => h(ElOption, {
                    label: item.label,
                    value: item.value
                  }))
                ])
              ]),
              // æ–™ç®±ç è¾“入项(支持聚焦、回车提交)
              h(ElFormItem, { label: '料箱码', prop: 'boxCode', required: true }, [
                h(ElInput, {
                  type: 'text',
                  modelValue: formData.boxCode,
                  'onUpdate:modelValue': (val) => {
                    formData.boxCode = val;
                  },
                  ref: 'boxCodeInput',
                  placeholder: '扫码输入或手动输入料箱码',
                  // ç›‘听回车事件(扫码枪默认会发送回车)
                  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
                }, '确定')
              ])
            ])
          });
          vnode.appContext = this.$.appContext;
          render(vnode, mountNode);
        }
      }
    ], box: [], detail: []
  },
  methods: {
    //下面这些方法可以保留也可以删除
    onInit() {
      this.columns.forEach(column => {
      if (column.field === 'orderStatistics') {
        column.formatter = (row) => {
          // æ ¡éªŒdetails是否存在且有数据
          if (row.details && row.details.length > 0) {
            //按materielCode分组统计orderQuantity总和
            const materielSumMap = row.details.reduce((acc, item) => {
              const materielCode = item.materielCode || '未知物料';
              const quantity = Number(item.orderQuantity) || 0;
              acc[materielCode] = (acc[materielCode] || 0) + quantity;
              return acc;
            }, {});
            //每个物料项生成独立div,跨行显示
            const displayItems = Object.entries(materielSumMap).map(([code, total]) => {
              return `<div style="line-height: 1.5; white-space: normal;">${code}:${total}个</div>`;
            });
            const displayContent = displayItems.join('');
            return `<div style="color: #F56C6C; white-space: normal; word-break: break-all;">${displayContent}</div>`;
          } else {
            return '<span style="color: #F56C6C">无入库明细</span>';
          }
        };
      }
    });
    },
    onInited() {
      //框架初始化配置后
      //如果要配置明细表,在此方法操作
      //this.detailOptions.columns.forEach(column=>{ });
    },
    searchBefore(param) {
      //界面查询前,可以给param.wheres添加查询参数
      //返回false,则不会执行查询
      // this.searchFormFields.orderType=[0]
      let wheres = [{
        'name': 'orderType',
        'value': '0',
        'displayType': 'text'
      }];
      param.wheres.push(...wheres);
      return true;
    },
    searchAfter(result) {
      //查询后,result返回的查询数据,可以在显示到表格前处理表格的值
      return true;
    },
    addBefore(formData) {
      //新建保存前formData为对象,包括明细表,可以给给表单设置值,自己输出看formData的值
      return true;
    },
    updateBefore(formData) {
      //编辑保存前formData为对象,包括明细表、删除行的Id
      return true;
    },
    rowClick({ row, column, event }) {
      //查询界面点击行事件
      this.$refs.table.$refs.table.toggleRowSelection(row); //单击行时选中当前行;
    },
    modelOpenAfter(row) {
      //点击编辑、新建按钮弹出框后,可以在此处写逻辑,如,从后台获取数据
      //(1)判断是编辑还是新建操作: this.currentAction=='Add';
      //(2)给弹出框设置默认值
      //(3)this.editFormFields.字段='xxx';
      //如果需要给下拉框设置默认值,请遍历this.editFormOptions找到字段配置对应data属性的key值
      //看不懂就把输出看:console.log(this.editFormOptions)
    }
  };
  export default extension;
  }
};
export default extension;
ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/extension/outbound/allocateoutboundOrder.js
@@ -4,7 +4,7 @@
import { h,createVNode, render,reactive ,ref } from 'vue';
import { ElDialog , ElForm, ElFormItem, ElInput, ElButton, ElMessage ,ElSelect, ElOption} from 'element-plus';
import gridBody from './extend/outOrderDetail.vue'
import gridBody from './extend/newAllocateOrderDetail.vue'
let extension = {
    components: {
      //查询界面扩展组件
ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/extension/outbound/extend/newAllocateOrderDetail.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,797 @@
<template>
  <div>
    <vol-box
      v-model="showDetialBox"
      :lazy="true"
      width="75%"
      :padding="15"
      title="单据明细信息"
    >
      <div class="box-head">
        <el-alert :closable="false" style="width: 100%">
          <el-row>
            <el-col :span="16">
              <span>已选中 {{ selection.length }} é¡¹</span>
            </el-col>
            <el-col :span="8">
          <!--     <el-link
                type="primary"
                size="small"
                style="float: right; height: 20px"
                @click="lockstocks"
                >锁定库存</el-link> -->
              <el-link
                type="primary"
                size="small"
                    v-if="isBatch === 0"
                style="float: right; height: 20px"
                @click="handleOpenPicking"
                >拣选</el-link>
                        <el-link
                type="primary"
                size="small"
                style="float: right; height: 20px; margin-right: 10px"
                  v-if="isBatch === 1"
                @click="handleOpenBatchPicking"
                >分批拣选</el-link>
              <el-link
                type="primary"
                size="small"
                   v-if="isBatch === 0"
                style="float: right; height: 20px; margin-right: 10px"
                @click="outbound"
                >直接出库</el-link
              >
               <el-link
                type="primary"
                size="small"
                 v-if="isBatch === 1"
                style="float: right; height: 20px; margin-right: 10px"
                @click="outboundbatch"
                >分批出库</el-link
              >
              <el-link
                type="primary"
                size="small"
                style="float: right; height: 20px; margin-right: 10px"
                @click="getData"
                >刷新</el-link
              ></el-col
            >
          </el-row>
        </el-alert>
      </div>
      <div class="box-table" style="margin-top: 1%">
        <el-table
          ref="singleTable"
          :data="tableData"
          style="width: 100%; height: 100%"
          highlight-current-row
          @current-change="handleCurrentChange"
          height="500px"
          @row-click="handleRowClick"
          @selection-change="handleSelectionChange"
        >
          <el-table-column type="selection" width="55"> </el-table-column>
          <el-table-column
            label="序号"
            type="index"
            fixed="left"
            width="55"
            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"
            align="center"
          >
            <template #default="scoped">
              <div v-if="item.type == 'icon'">
                <el-tooltip
                  class="item"
                  effect="dark"
                  :content="item.title"
                  placement="bottom"
                  ><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>
            </template>
          </el-table-column>
        </el-table>
      </div>
    </vol-box>
    <stock-select ref="child" @parentCall="parentCall"></stock-select>
    <selected-stock
      ref="selectedStock"
      @parentCall="parentCall"
    ></selected-stock>
    <NoStockOut ref="NoStockOut" @parentCall="parentCall"></NoStockOut>
  </div>
</template>
<script>
import VolBox from "@/components/basic/VolBox.vue";
import VolForm from "@/components/basic/VolForm.vue";
import StockSelect from "./StockSelect.vue";
import SelectedStock from "./SelectedStock.vue";
import NoStockOut from "./NoStockOut.vue";
import { h,createVNode, render,reactive  } from 'vue';
import { ElDialog , ElForm, ElFormItem, ElSelect,ElOption, ElButton, ElInput, ElMessage } from 'element-plus';
import { th } from 'element-plus/es/locale';
export default {
  components: { VolBox, VolForm, StockSelect, SelectedStock,NoStockOut},
  data() {
    return {
      row: null,
      isBatch :0,
      showDetialBox: false,
      flag: false,
      currentRow: null,
      selection: [],
      tableData: [],
      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: 150,
        },
        {
          prop: "materielName",
          title: "物料名称",
          type: "string",
          width: 150,
        },
        {
          prop: "batchNo",
          title: "批次号",
          type: "string",
          width: 90,
        },
        {
          prop: "supplyCode",
          title: "供应商编号",
          type: "string",
          width: 150,
        },
        {
          prop: "orderQuantity",
          title: "单据数量",
          type: "string",
          width: 90,
        },
        {
          prop: "lockQuantity",
          title: "锁定数量",
          type: "int",
          width: 90,
        },
        {
          prop: "overOutQuantity",
          title: "已出数量",
          type: "string",
          width: 90,
        },
        {
          prop: "overOutQuantity",
          title: "挪料数量",
          type: "string",
          width: 90,
        },
        {
          prop: "unit",
          title: "单位",
          type: "string",
          width: 90,
        },
        {
          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",
        },
      ],
      paginations: {
        sort: "id",
        order: "desc",
        Foots: "",
        total: 0,
        // 2020.08.29增加自定义分页条大小
        sizes: [30, 60, 100, 120],
        size: 30, // é»˜è®¤åˆ†é¡µå¤§å°
        Wheres: [],
        page: 1,
        rows: 30,
      },
      searchFormOptions: [
        [
          {
            title: "单据编号",
            field: "allocation_code",
            type: "like",
          },
          {
            title: "单据类型",
            field: "allocation_type",
            type: "select",
            dataKey: "OrderType",
            data: [],
          },
          {
            title: "单据状态",
            field: "allocation_state",
            type: "select",
            dataKey: "OrderState",
            data: [],
          },
        ],
      ],
      searchFormFields: {
        allocation_code: "",
        allocation_type: "",
        allocation_state: "",
      },
      dictionaryList: null,
    };
  },
  methods: {
    open(row) {
      this.row = row;
      this.showDetialBox = true;
      console.log(this.row);
      this.isBatch = row.isBatch;
      this.getDictionaryData();
      this.getData();
    },
    getData() {
      var wheres = [{ name: "orderId", value: this.row.id }];
      var param = {
        page: this.paginations.page,
        rows: this.paginations.rows,
        sort: this.paginations.sort,
        order: this.paginations.order,
        wheres: JSON.stringify(wheres), // æŸ¥è¯¢æ¡ä»¶ï¼Œæ ¼å¼ä¸º[{ name: "字段", value: "xx" }]
      };
      this.http
        .post("api/AllocateOrderDetail/GetPageData", param, "查询中")
        .then((x) => {
          this.tableData = x.rows;
        });
    },
    tableButtonClick(row, column) {
      if (column.prop == "assignStock") {
        this.$refs.child.open(row);
      } else if (column.prop == "NoStockOut") {
        this.$refs.NoStockOut.open(row);
      }else{
          //点击打开出库详情
        this.$refs.selectedStock.open(row);
      }
    },
    lockstocks() {
      if (this.selection.length === 0) {
        return this.$message.error("请选择单据明细");
      }
      var keys = this.selection.map((item) => item.id); // èŽ·å–é€‰ä¸­è¡Œçš„id
      this.http
        .post("api/OutboundOrderDetail/LockOutboundStocks", keys, "数据处理中")
        .then((x) => {
          if (!x.status) return this.$message.error(x.message);
          this.$message.success("操作成功");
          this.showDetialBox = false;
          this.$emit("parentCall", ($vue) => {
            $vue.getData();
          });
        });
    },
    // æ‰“开拣选页面
   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() {
      if (this.selection.length === 0) {
        return this.$message.error("请选择单据明细");
      }
      const platformOptions = [{label:'站台2',value:'2-1'},{label:'站台3',value:'3-1'}];
      const mountNode = document.createElement('div');
      document.body.appendChild(mountNode);
      // 2. è¡¨å•数据(默认选中站台3)
      const formData = reactive({
        selectedPlatform: platformOptions[0].value // é»˜è®¤ç»‘定「站台3」的value
      });
      // 3. åŠ¨æ€åˆ›å»ºå¼¹çª—ç»„ä»¶
      const vnode = createVNode(ElDialog, {
        title: '出库操作 - é€‰æ‹©å‡ºåº“站台',
        width: '500px',
        modelValue: true,
        appendToBody: true,
        'onUpdate:modelValue': (isVisible) => {
          if (!isVisible) {
            render(null, mountNode);
            document.body.removeChild(mountNode);
          }
        },
        style: {
          padding: '20px 0',
          borderRadius: '8px'
        }
      }, {
        default: () => h(ElForm, {
          model: formData,
          rules: {
            selectedPlatform: [
              { required: true, message: '请选择出库站台', trigger: 'change' }
            ]
          },
          ref: 'outboundForm',
          labelWidth: '100px',
          style: {
            padding: '0 30px'
          }
        }, [
          // å‡ºåº“站台选择项(核心表单项)
          h(ElFormItem, {
            label: '出库站台',
            prop: 'selectedPlatform',
            style: {
              marginBottom: '24px'
            }
          }, [
            h(ElSelect, {
              placeholder: '请选择出库站台(3-12)',
              modelValue: formData.selectedPlatform,
              'onUpdate:modelValue': (val) => {
                formData.selectedPlatform = val;
              },
              style: {
                width: '100%',
                height: '40px',
                borderRadius: '4px',
                borderColor: '#dcdfe6'
              }
            }, platformOptions.map(platform =>
              h(ElOption, { label: platform.label, value: platform.value })
            ))
          ]),
          // åº•部按钮区
          h('div', {
            style: {
              textAlign: 'right',
              marginTop: '8px',
              paddingRight: '4px'
            }
          }, [
            h(ElButton, {
              type: 'text',
              onClick: () => {
                render(null, mountNode);
                document.body.removeChild(mountNode);
                ElMessage.info('取消出库操作');
              },
              style: {
                marginRight: '8px',
                color: '#606266'
              }
            }, '取消'),
            h(ElButton, {
              type: 'primary',
              onClick: async () => {
                const formRef = vnode.component.refs.outboundForm;
                try {
                  // è¡¨å•校验
                  await formRef.validate();
                } catch (err) {
                  return;
                }
                // 4. æž„造请求参数(选中单据ID + é€‰æ‹©çš„出库站台)
                const keys = this.selection.map((item) => item.id);
                const requestParams = {
                  taskIds: keys,
                  outboundPlatform: formData.selectedPlatform // å‡ºåº“站台
                };
                // 5. è°ƒç”¨å‡ºåº“接口
                this.http
                  .post("api/Task/GenerateOutboundTasks", requestParams, "数据处理中")
                  .then((x) => {
                    if (!x.status) return ElMessage.error(x.message);
                    ElMessage.success("操作成功");
                    this.showDetialBox = false; // å…³é—­è¯¦æƒ…框
                    this.$emit("parentCall", ($vue) => {
                      $vue.getData(); // é€šçŸ¥çˆ¶ç»„件刷新
                    });
                    // å…³é—­å¼¹çª—
                    render(null, mountNode);
                    document.body.removeChild(mountNode);
                  })
                  .catch(() => {
                    ElMessage.error('请求失败,请稍后重试');
                  });
              },
              style: {
                borderRadius: '4px',
                padding: '8px 20px'
              }
            }, '确定出库')
          ])
        ])
      });
      // ç»‘定app上下文,确保El组件正常工作
      vnode.appContext = this.$.appContext;
      render(vnode, mountNode);
    },
    outboundbatch() {
  if (this.selection.length === 0) {
    return this.$message.error("请选择单据明细");
  }
    if (this.selection.length>1) {
    return this.$message.error("只能选择一条单据明细进行分批出库");
  }
  const platformOptions = [{label:'站台2',value:'2-1'},{label:'站台3',value:'3-1'}];
  const mountNode = document.createElement('div');
  document.body.appendChild(mountNode);
  // 2. è¡¨å•数据(默认选中站台3,新增小数字段)
  const formData = reactive({
    selectedPlatform: platformOptions[0].value, // é»˜è®¤ç»‘定「站台3」的value
    outboundDecimal: '' // æ–°å¢žï¼šå°æ•°è¾“入框字段
  });
  // 3. åŠ¨æ€åˆ›å»ºå¼¹çª—ç»„ä»¶
  const vnode = createVNode(ElDialog, {
    title: '出库操作 - é€‰æ‹©å‡ºåº“站台',
    width: '500px',
    modelValue: true,
    appendToBody: true,
    'onUpdate:modelValue': (isVisible) => {
      if (!isVisible) {
        render(null, mountNode);
        document.body.removeChild(mountNode);
      }
    },
    style: {
      padding: '20px 0',
      borderRadius: '8px'
    }
  }, {
    default: () => h(ElForm, {
      model: formData,
      rules: {
        selectedPlatform: [
          { required: true, message: '请选择出库站台', trigger: 'change' }
        ],
        // æ–°å¢žï¼šå°æ•°å­—段验证规则(必填 + æœ‰æ•ˆå°æ•°æ ¼å¼ï¼‰
        outboundDecimal: [
          { required: true, message: '请输入小数数值', trigger: 'blur' },
          {
            validator: (rule, value, callback) => {
              // éªŒè¯è§„则:正数、支持小数点后最多2位(可根据需求调整小数位数)
              const decimalReg = /^(([1-9]\d*)|0)(\.\d{1,2})?$/;
              if (value && !decimalReg.test(value)) {
                callback(new Error('请输入有效的小数(正数,最多2位小数)'));
              } else {
                callback();
              }
            },
            trigger: 'blur'
          }
        ]
      },
      ref: 'outboundForm',
      labelWidth: '100px',
      style: {
        padding: '0 30px'
      }
    }, [
      // å‡ºåº“站台选择项(核心表单项)
      h(ElFormItem, {
        label: '出库站台',
        prop: 'selectedPlatform',
        style: {
          marginBottom: '24px'
        }
      }, [
        h(ElSelect, {
          placeholder: '请选择出库站台(3-12)',
          modelValue: formData.selectedPlatform,
          'onUpdate:modelValue': (val) => {
            formData.selectedPlatform = val;
          },
          style: {
            width: '100%',
            height: '40px',
            borderRadius: '4px',
            borderColor: '#dcdfe6'
          }
        }, platformOptions.map(platform =>
          h(ElOption, { label: platform.label, value: platform.value })
        ))
      ]),
      // æ–°å¢žï¼šå°æ•°è¾“入框表单项
      h(ElFormItem, {
        label: '出库数', // å¯æ ¹æ®ä¸šåŠ¡éœ€æ±‚ä¿®æ”¹æ ‡ç­¾åï¼ˆå¦‚â€œå‡ºåº“æ•°é‡â€â€œé‡é‡â€ç­‰ï¼‰
        prop: 'outboundDecimal',
        style: {
          marginBottom: '24px'
        }
      }, [
        h(ElInput, {
          type: 'number', // æ•°å­—类型,原生支持小数输入
          placeholder: '请输入小数数值(最多2位小数)',
          modelValue: formData.outboundDecimal,
          'onUpdate:modelValue': (val) => {
            formData.outboundDecimal = val;
          },
          style: {
            width: '100%',
            height: '40px',
            borderRadius: '4px',
            borderColor: '#dcdfe6'
          },
          step: '0.01', // æ­¥é•¿0.01,点击上下箭头时按0.01增减
          precision: 2, // é™åˆ¶æœ€å¤šè¾“å…¥2位小数(Element Plus属性)
          min: 0.01, // å¯é€‰ï¼šé™åˆ¶æœ€å°å€¼ä¸º0.01,避免输入0或负数
        })
      ]),
      // åº•部按钮区
      h('div', {
        style: {
          textAlign: 'right',
          marginTop: '8px',
          paddingRight: '4px'
        }
      }, [
        h(ElButton, {
          type: 'text',
          onClick: () => {
            render(null, mountNode);
            document.body.removeChild(mountNode);
            ElMessage.info('取消分批出库操作');
          },
          style: {
            marginRight: '8px',
            color: '#606266'
          }
        }, '取消'),
        h(ElButton, {
          type: 'primary',
          onClick: async () => {
            const formRef = vnode.component.refs.outboundForm;
            try {
              // è¡¨å•校验(会同时校验出库站台和小数字段)
              await formRef.validate();
            } catch (err) {
              return;
            }
console.log(this.selection);
            // 4. æž„造请求参数(新增小数字段)
            const keys = this.selection.map((item) => item.id);
            const requestParams = {
              orderDetailId: keys[0], // åˆ†æ‰¹å‡ºåº“仅支持单条明细
              outboundPlatform: formData.selectedPlatform, // å‡ºåº“站台
              batchQuantity: formData.outboundDecimal // æ–°å¢žï¼šå°æ•°å­—段传给后端
            };
            // 5. è°ƒç”¨å‡ºåº“接口
            this.http
              .post("api/Task/GenerateOutboundBatchTasks", requestParams, "数据处理中")
              .then((x) => {
                if (!x.status) return ElMessage.error(x.message);
                ElMessage.success("操作成功");
                this.showDetialBox = false; // å…³é—­è¯¦æƒ…框
                this.$emit("parentCall", ($vue) => {
                  $vue.getData(); // é€šçŸ¥çˆ¶ç»„件刷新
                });
                // å…³é—­å¼¹çª—
                render(null, mountNode);
                document.body.removeChild(mountNode);
              })
              .catch(() => {
                ElMessage.error('请求失败,请稍后重试');
              });
          },
          style: {
            borderRadius: '4px',
            padding: '8px 20px'
          }
        }, '确定分批出库')
      ])
    ])
  });
  // ç»‘定app上下文,确保El组件正常工作
  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
        ) {
          return true;
        } else {
          return false;
        }
      }
      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);
        }
      });
      this.http
        .post("api/Sys_Dictionary/GetVueDictionary", param, "查询中")
        .then((x) => {
          if (x.length > 0) {
            this.dictionaryList = x;
          }
        });
    },
    getDictionary(row, column) {
      if (this.dictionaryList) {
        var item = this.dictionaryList.find((x) => x.dicNo == column.bindKey);
        if (item) {
          var dicItem = item.data.find((x) => x.key == row[column.prop]);
          console.log(dicItem);
          if (dicItem) {
            return dicItem.value;
          } else {
            return row[column.prop];
          }
        } else {
          return row[column.prop];
        }
      }
    },
  },
};
</script>
<style scoped>
.text-button {
  border: 0px;
}
</style>
<style>
.text-button:hover {
  background-color: #f0f9eb !important;
}
.el-table .warning-row {
  background: oldlace;
}
.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 {
  background: #f0f9eb;
}
.box-table .el-table {
  border: 1px solid #ebeef5;
}
</style>
ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/extension/outbound/extend/outOrderDetail.vue
@@ -201,6 +201,12 @@
          width: 90,
        },
        {
          prop: "overOutQuantity",
          title: "挪料数量",
          type: "string",
          width: 90,
        },
        {
          prop: "unit",
          title: "单位",
          type: "string",
ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/extension/outbound/outboundOrder.js
@@ -383,17 +383,6 @@
    searchBefore(param) {
      //界面查询前,可以给param.wheres添加查询参数
      //返回false,则不会执行查询
      let wheres = [{
        'name': 'orderType',
        'value': ['0','116'],
        'displayType': 'text'
      }];
      param.wheres.push(...wheres);
      return true;
      return true;
    },
    searchAfter(result) {
ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/extension/stock/stockInfoDetailByMaterielSum.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,59 @@
//此js文件是用来自定义扩展业务代码,可以扩展一些自定义页面或者重新配置生成的代码
let extension = {
    components: {
      //查询界面扩展组件
      gridHeader: '',
      gridBody: '',
      gridFooter: '',
      //新建、编辑弹出框扩展组件
      modelHeader: '',
      modelBody: '',
      modelFooter: ''
    },
    tableAction: '', //指定某张表的权限(这里填写表名,默认不用填写)
    buttons: { view: [], box: [], detail: [] }, //扩展的按钮
    methods: {
       //下面这些方法可以保留也可以删除
      onInit() {
        console.log(this)
      },
      onInited() {
        //框架初始化配置后
        //如果要配置明细表,在此方法操作
        //this.detailOptions.columns.forEach(column=>{ });
      },
      searchBefore(param) {
        //界面查询前,可以给param.wheres添加查询参数
        //返回false,则不会执行查询
        return true;
      },
      searchAfter(result) {
        //查询后,result返回的查询数据,可以在显示到表格前处理表格的值
        return true;
      },
      addBefore(formData) {
        //新建保存前formData为对象,包括明细表,可以给给表单设置值,自己输出看formData的值
        return true;
      },
      updateBefore(formData) {
        //编辑保存前formData为对象,包括明细表、删除行的Id
        return true;
      },
      rowClick({ row, column, event }) {
        //查询界面点击行事件
        this.$refs.table.$refs.table.toggleRowSelection(row); //单击行时选中当前行;
      },
      modelOpenAfter(row) {
        //点击编辑、新建按钮弹出框后,可以在此处写逻辑,如,从后台获取数据
        //(1)判断是编辑还是新建操作: this.currentAction=='Add';
        //(2)给弹出框设置默认值
        //(3)this.editFormFields.字段='xxx';
        //如果需要给下拉框设置默认值,请遍历this.editFormOptions找到字段配置对应data属性的key值
        //看不懂就把输出看:console.log(this.editFormOptions)
      }
    }
  };
  export default extension;
ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/router/viewGird.js
@@ -217,6 +217,11 @@
    path: '/reCheckOrder',
    name: 'Dt_ReCheckOrder',
    component: () => import('@/views/check/ReCheckOrder.vue')
  },
  {
    path: '/stockInfoDetailByMaterielSum',
    name: 'Dt_StockInfoDetailss',
    component: () => import('@/views/stock/stockInfoDetailByMaterielSum.vue')
  }
]
ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/views/inbound/inboundOrder.vue
@@ -79,7 +79,7 @@
    const searchFormFields = ref({
      inboundOrderNo: "",
      upperOrderNo: "",
      orderType: "0",
      orderType: "",
      orderStatus: "",
      createType: "",
      creater: "",
@@ -169,6 +169,13 @@
        bind: { key: "inboundState", data: [] },
      },
      {
        field: "orderStatistics",
        title: "单据物料统计",
        type: "string",
        width: 230,
        align: "left",
      },
      {
        field: "createType",
        title: "创建方式",
        type: "string",
ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/views/outbound/BatchPickingConfirm.vue
@@ -586,62 +586,430 @@
    },
   openSplitDialog() {
      console.log('开始打开拆包弹窗');
      if (this.isOpeningDialog) {
        console.log('正在打开弹窗,跳过');
        return;
      }
      console.log('紧急修复版:打开拆包弹窗');
      
      if (!this.scanData.palletCode) {
        this.$message.warning('请先扫描托盘码');
        return;
      }
      
      this.isOpeningDialog = true;
      // 1. å…³é—­æ‰€æœ‰Vue弹窗
      this.closeAllDialogs();
      // 2. å¼ºåˆ¶ä»ŽDOM中移除所有弹窗
      setTimeout(() => {
        const dialogs = document.querySelectorAll('.custom-dialog-overlay');
        dialogs.forEach(dialog => {
          if (dialog.parentNode) {
            dialog.parentNode.removeChild(dialog);
          }
        });
        // å¦‚果已经存在手动弹窗,先移除
        if (this.manualDialog && this.manualDialog.parentNode) {
          this.manualDialog.parentNode.removeChild(this.manualDialog);
        }
        // 3. ç­‰å¾…一帧
        requestAnimationFrame(() => {
          // 4. ç›´æŽ¥åˆ›å»ºæ–°å¼¹çª—,不依赖Vue的响应式系统
          this.createManualSplitDialog();
        });
      }, 10);
    },
    // åˆ›å»ºæ‰‹åŠ¨æ‹†åŒ…å¼¹çª—
    createManualSplitDialog() {
      const newDialog = document.createElement('div');
      newDialog.className = 'custom-dialog-overlay emergency-fix';
      // ç”ŸæˆéšæœºID用于事件绑定
      const dialogId = 'manual-dialog-' + Date.now();
      newDialog.id = dialogId;
      // å­˜å‚¨å¼•用
      this.manualDialog = newDialog;
      // å¼¹çª—内容
      newDialog.innerHTML = `
        <div class="custom-dialog-wrapper">
          <div class="custom-dialog" style="width: 500px;">
            <div class="custom-dialog-header">
              <h3 style="margin: 0; color: #303133;">拆包操作</h3>
              <button class="close-button" onclick="document.getElementById('${dialogId}').remove()" style="
                font-size: 18px;
                color: #909399;
                padding: 0;
                width: 24px;
                height: 24px;
                display: flex;
                align-items: center;
                justify-content: center;
                background: none;
                border: none;
                cursor: pointer;
              ">×</button>
            </div>
            <div class="custom-dialog-body" style="padding: 20px;">
              <div style="margin-bottom: 15px;">
                <div style="display: flex; align-items: center; margin-bottom: 5px;">
                  <span style="width: 100px; text-align: right; padding-right: 12px; color: #606266;">订单编号:</span>
                  <input type="text" value="${this.scanData.orderNo}" disabled style="
                    flex: 1;
                    padding: 8px 12px;
                    border: 1px solid #dcdfe6;
                    border-radius: 4px;
                    background-color: #f5f7fa;
                    color: #909399;
                  ">
                </div>
              </div>
              <div style="margin-bottom: 15px;">
                <div style="display: flex; align-items: center; margin-bottom: 5px;">
                  <span style="width: 100px; text-align: right; padding-right: 12px; color: #606266;">托盘编号:</span>
                  <input type="text" value="${this.scanData.palletCode}" disabled style="
                    flex: 1;
                    padding: 8px 12px;
                    border: 1px solid #dcdfe6;
                    border-radius: 4px;
                    background-color: #f5f7fa;
                    color: #909399;
                  ">
                </div>
              </div>
              <div style="margin-bottom: 15px;">
                <div style="display: flex; align-items: center; margin-bottom: 5px;">
                  <span style="width: 100px; text-align: right; padding-right: 12px; color: #606266;">原条码:</span>
                  <div style="flex: 1; display: flex; align-items: center; gap: 10px;">
                    <input type="text" id="${dialogId}-barcode" placeholder="扫描原条码" style="
                      flex: 1;
                      padding: 8px 12px;
                      border: 1px solid #dcdfe6;
                      border-radius: 4px;
                    ">
                    <button id="${dialogId}-viewChain" style="
                      padding: 8px 16px;
                      background: #409eff;
                      color: white;
                      border: none;
                      border-radius: 4px;
                      cursor: pointer;
                      white-space: nowrap;
                    ">查看拆包链</button>
                  </div>
                </div>
              </div>
              <div style="margin-bottom: 15px;">
                <div style="display: flex; align-items: center; margin-bottom: 5px;">
                  <span style="width: 100px; text-align: right; padding-right: 12px; color: #606266;">物料编码:</span>
                  <input type="text" id="${dialogId}-materiel" disabled style="
                    flex: 1;
                    padding: 8px 12px;
                    border: 1px solid #dcdfe6;
                    border-radius: 4px;
                    background-color: #f5f7fa;
                    color: #909399;
                  ">
                </div>
              </div>
              <div style="margin-bottom: 15px;">
                <div style="display: flex; align-items: center; margin-bottom: 5px;">
                  <span style="width: 100px; text-align: right; padding-right: 12px; color: #606266;">剩余数量:</span>
                  <input type="text" id="${dialogId}-remain" disabled style="
                    flex: 1;
                    padding: 8px 12px;
                    border: 1px solid #dcdfe6;
                    border-radius: 4px;
                    background-color: #f5f7fa;
                    color: #909399;
                  ">
                </div>
              </div>
              <div style="margin-bottom: 15px;">
                <div style="display: flex; align-items: center; margin-bottom: 5px;">
                  <span style="width: 100px; text-align: right; padding-right: 12px; color: #606266;">拆包数量:</span>
                  <div style="flex: 1;">
                    <input type="number" id="${dialogId}-splitQty" value="1" min="0.01" step="0.01" style="
                      width: 100%;
                      padding: 8px 12px;
                      border: 1px solid #dcdfe6;
                      border-radius: 4px;
                    ">
                  </div>
                </div>
              </div>
            </div>
            <div class="custom-dialog-footer" style="
              padding: 10px 20px 20px;
              text-align: right;
              border-top: 1px solid #ebeef5;
            ">
              <button id="${dialogId}-cancel" style="
                padding: 9px 15px;
                background: white;
                color: #606266;
                border: 1px solid #dcdfe6;
                border-radius: 4px;
                cursor: pointer;
                margin-right: 10px;
              ">取消</button>
              <button id="${dialogId}-confirm" style="
                padding: 9px 15px;
                background: #409eff;
                color: white;
                border: none;
                border-radius: 4px;
                cursor: pointer;
              ">确认拆包</button>
            </div>
          </div>
        </div>
      `;
      // æ·»åŠ æ ·å¼
      newDialog.style.cssText = `
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        background: rgba(0,0,0,0.5);
        display: flex;
        align-items: center;
        justify-content: center;
        z-index: 999999;
      `;
      // å¼¹çª—容器样式
      const wrapper = newDialog.querySelector('.custom-dialog-wrapper');
      if (wrapper) {
        wrapper.style.position = 'relative';
        wrapper.style.zIndex = '1000000';
      }
      // å¼¹çª—内容样式
      const dialog = newDialog.querySelector('.custom-dialog');
      if (dialog) {
        dialog.style.background = 'white';
        dialog.style.borderRadius = '4px';
        dialog.style.maxWidth = '90vw';
        dialog.style.maxHeight = '90vh';
        dialog.style.boxShadow = '0 2px 12px 0 rgba(0, 0, 0, 0.1)';
        dialog.style.overflow = 'auto';
      }
      // å¼¹çª—头部样式
      const header = newDialog.querySelector('.custom-dialog-header');
      if (header) {
        header.style.display = 'flex';
        header.style.justifyContent = 'space-between';
        header.style.alignItems = 'center';
        header.style.padding = '20px 20px 10px';
        header.style.borderBottom = '1px solid #ebeef5';
      }
      document.body.appendChild(newDialog);
      console.log('紧急弹窗已创建');
      // ç»‘定事件
      this.bindManualDialogEvents(dialogId);
      // è‡ªåŠ¨èšç„¦åˆ°æ¡ç è¾“å…¥æ¡†
      setTimeout(() => {
        const barcodeInput = document.getElementById(`${dialogId}-barcode`);
        if (barcodeInput) {
          barcodeInput.focus();
          // æ·»åŠ å›žè½¦é”®ç›‘å¬
          barcodeInput.addEventListener('keyup', (event) => {
            if (event.key === 'Enter') {
              this.onManualSplitBarcodeScan(dialogId);
            }
          });
        }
      }, 100);
    },
    // ç»‘定手动弹窗事件
    bindManualDialogEvents(dialogId) {
      const vm = this; // ä¿å­˜Vue实例引用
      // æŸ¥çœ‹æ‹†åŒ…链按钮
      const viewChainBtn = document.getElementById(`${dialogId}-viewChain`);
      if (viewChainBtn) {
        viewChainBtn.onclick = () => {
          const barcodeInput = document.getElementById(`${dialogId}-barcode`);
          if (barcodeInput && barcodeInput.value.trim()) {
            vm.viewSplitChainFromManualDialog(barcodeInput.value.trim(), dialogId);
          } else {
            ElMessage.warning('请先输入条码');
          }
        };
      }
      // å–消按钮
      const cancelBtn = document.getElementById(`${dialogId}-cancel`);
      if (cancelBtn) {
        cancelBtn.onclick = () => {
          const dialog = document.getElementById(dialogId);
          if (dialog && dialog.parentNode) {
            dialog.parentNode.removeChild(dialog);
          }
        };
      }
      // ç¡®è®¤æ‹†åŒ…按钮
      const confirmBtn = document.getElementById(`${dialogId}-confirm`);
      if (confirmBtn) {
        confirmBtn.onclick = () => {
          vm.handleManualSplitPackage(dialogId);
        };
      }
      // æ¡ç è¾“入框变化事件
      const barcodeInput = document.getElementById(`${dialogId}-barcode`);
      if (barcodeInput) {
        // é˜²æŠ–处理
        let timeout;
        barcodeInput.addEventListener('input', () => {
          clearTimeout(timeout);
          timeout = setTimeout(() => {
            if (barcodeInput.value.trim()) {
              vm.onManualSplitBarcodeScan(dialogId);
            }
          }, 500);
        });
      }
    },
    // æ‰‹åŠ¨å¼¹çª—çš„æ¡ç æ‰«æå¤„ç†
    async onManualSplitBarcodeScan(dialogId) {
      const barcodeInput = document.getElementById(`${dialogId}-barcode`);
      if (!barcodeInput || !barcodeInput.value.trim()) return;
      const barcode = barcodeInput.value.trim();
      
      try {
        // æ–¹æ³•1: ä½¿ç”¨ setTimeout ç¡®ä¿å¼‚步执行
        setTimeout(() => {
          console.log('执行弹窗打开逻辑');
        const res = await http.post('/api/OutboundBatchPicking/split-package-info', {
          orderNo: this.scanData.orderNo,
          palletCode: this.scanData.palletCode,
          barcode: barcode
        });
        if (res.status) {
          // æ›´æ–°ç‰©æ–™ç¼–码
          const materielInput = document.getElementById(`${dialogId}-materiel`);
          if (materielInput) {
            materielInput.value = res.data.materielCode || '';
          }
          
          // å…ˆå…³é—­æ‰€æœ‰å¼¹çª—
          this.closeAllDialogsImmediately();
          // æ›´æ–°å‰©ä½™æ•°é‡
          const remainInput = document.getElementById(`${dialogId}-remain`);
          if (remainInput) {
            remainInput.value = res.data.remainQuantity || 0;
          }
          
          // ä½¿ç”¨ requestAnimationFrame ç¡®ä¿åœ¨ä¸‹ä¸€å¸§æ‰“å¼€
          requestAnimationFrame(() => {
            console.log('设置弹窗状态为 true');
            // é‡ç½®è¡¨å•
            this.resetSplitForm();
            this.splitForm.orderNo = this.scanData.orderNo;
            this.splitForm.palletCode = this.scanData.palletCode;
            // å…³é”®ï¼šç›´æŽ¥è®¾ç½®å¼¹çª—状态
            this.showCustomSplitDialog = true;
            console.log('弹窗状态已设置,等待DOM更新');
            // ä½¿ç”¨ nextTick ç¡®ä¿DOM更新完成
            this.$nextTick(() => {
              console.log('DOM更新完成,弹窗应该显示了');
              this.isOpeningDialog = false;
              // å°è¯•聚焦到输入框
              setTimeout(() => {
                const input = this.$refs.splitFormRef?.$el?.querySelector('input');
                if (input) {
                  input.focus();
                  console.log('输入框已聚焦');
                }
              }, 100);
            });
          });
        }, 0);
          // æ›´æ–°æ‹†åŒ…数量(默认为1,不超过剩余数量)
          const splitQtyInput = document.getElementById(`${dialogId}-splitQty`);
          if (splitQtyInput) {
            const maxQty = res.data.remainQuantity || 0;
            splitQtyInput.max = maxQty;
            const currentVal = parseFloat(splitQtyInput.value) || 1;
            if (currentVal > maxQty) {
              splitQtyInput.value = Math.min(1, maxQty);
            }
          }
        } else {
          ElMessage.error(res.message || '获取拆包信息失败');
        }
      } catch (error) {
        console.error('打开拆包弹窗出错:', error);
        this.isOpeningDialog = false;
        console.error('获取拆包信息失败:', error);
        ElMessage.error('获取拆包信息失败');
      }
    },
    // ä»Žæ‰‹åŠ¨å¼¹çª—æŸ¥çœ‹æ‹†åŒ…é“¾
    viewSplitChainFromManualDialog(barcode, dialogId) {
      // å…ˆå…³é—­æ‰‹åŠ¨å¼¹çª—
      const dialog = document.getElementById(dialogId);
      if (dialog && dialog.parentNode) {
        dialog.parentNode.removeChild(dialog);
      }
      // å»¶è¿Ÿä¸€ä¸‹ï¼Œç„¶åŽæ‰“å¼€Vue的拆包链弹窗
      setTimeout(() => {
        this.viewSplitChain(barcode);
      }, 50);
    },
    // å¤„理手动弹窗的拆包操作
    async handleManualSplitPackage(dialogId) {
      const barcodeInput = document.getElementById(`${dialogId}-barcode`);
      const splitQtyInput = document.getElementById(`${dialogId}-splitQty`);
      if (!barcodeInput || !barcodeInput.value.trim()) {
        ElMessage.warning('请输入原条码');
        return;
      }
      if (!splitQtyInput || !splitQtyInput.value || parseFloat(splitQtyInput.value) <= 0) {
        ElMessage.warning('请输入有效的拆包数量');
        return;
      }
      const originalBarcode = barcodeInput.value.trim();
      const splitQuantity = parseFloat(splitQtyInput.value);
      try {
        // æ˜¾ç¤ºåŠ è½½çŠ¶æ€
        const confirmBtn = document.getElementById(`${dialogId}-confirm`);
        if (confirmBtn) {
          confirmBtn.disabled = true;
          confirmBtn.textContent = '处理中...';
        }
        const res = await http.post('/api/OutboundBatchPicking/split-package', {
          orderNo: this.scanData.orderNo,
          palletCode: this.scanData.palletCode,
          originalBarcode: originalBarcode,
          splitQuantity: splitQuantity
        });
        if (res.status) {
          ElMessage.success('拆包成功');
          // å…³é—­æ‰‹åŠ¨å¼¹çª—
          const dialog = document.getElementById(dialogId);
          if (dialog && dialog.parentNode) {
            dialog.parentNode.removeChild(dialog);
          }
          // é‡æ–°åŠ è½½æ•°æ®
          await this.loadPalletData();
        } else {
          ElMessage.error(res.message || '拆包失败');
          // æ¢å¤æŒ‰é’®çŠ¶æ€
          if (confirmBtn) {
            confirmBtn.disabled = false;
            confirmBtn.textContent = '确认拆包';
          }
        }
      } catch (error) {
        console.error('拆包失败:', error);
        ElMessage.error('拆包失败');
        // æ¢å¤æŒ‰é’®çŠ¶æ€
        const confirmBtn = document.getElementById(`${dialogId}-confirm`);
        if (confirmBtn) {
          confirmBtn.disabled = false;
          confirmBtn.textContent = '确认拆包';
        }
      }
    },
      closeAllDialogsImmediately() {
@@ -910,11 +1278,26 @@
    closeAllDialogs() {
      this.activeDialog = null;
      // ç¡®ä¿æ‰€æœ‰å¼¹çª—状态都被重置
// å…³é—­Vue弹窗
      this.showCustomSplitDialog = false;
      this.showRevertSplitDialog = false;
      this.showBatchReturnDialog = false;
      this.showEmptyPalletDialog = false;
      this.showSplitChainDialog = false;
      // å…³é—­æ‰‹åŠ¨å¼¹çª—
      if (this.manualDialog && this.manualDialog.parentNode) {
        this.manualDialog.parentNode.removeChild(this.manualDialog);
        this.manualDialog = null;
      }
      // ç§»é™¤æ‰€æœ‰ç´§æ€¥å¼¹çª—
      const emergencyDialogs = document.querySelectorAll('.emergency-fix');
      emergencyDialogs.forEach(dialog => {
        if (dialog.parentNode) {
          dialog.parentNode.removeChild(dialog);
        }
      });
    },
    // å›žåº“相关方法
@@ -1318,4 +1701,140 @@
    width: 100%;
  }
}
/* åŽŸæœ‰çš„æ ·å¼ä¿æŒä¸å˜ */
.OutboundPicking-container {
  padding: 20px;
}
.scanner-form {
  display: flex;
  gap: 10px;
  align-items: center;
  flex-wrap: wrap;
}
.scanner-form .el-input {
  width: 200px;
}
.summary-info {
  display: flex;
  gap: 20px;
  flex-wrap: wrap;
}
.table-actions {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 10px;
  padding: 0 10px;
}
.selection-count {
  font-size: 12px;
  color: #909399;
}
/* åŽŸæœ‰çš„è‡ªå®šä¹‰å¼¹çª—æ ·å¼ */
.custom-dialog-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 2000;
}
.custom-dialog-wrapper {
  position: relative;
  z-index: 2001;
}
.custom-dialog {
  background: white;
  border-radius: 4px;
  width: 500px;
  max-width: 90vw;
  max-height: 90vh;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  overflow: auto;
}
.custom-dialog-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 20px 20px 10px;
  border-bottom: 1px solid #ebeef5;
}
.custom-dialog-header h3 {
  margin: 0;
  color: #303133;
}
.close-button {
  font-size: 18px;
  color: #909399;
  padding: 0;
  width: 24px;
  height: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.close-button:hover {
  color: #409EFF;
  background-color: transparent;
}
.custom-dialog-body {
  padding: 20px;
}
.custom-dialog-footer {
  padding: 10px 20px 20px;
  text-align: right;
  border-top: 1px solid #ebeef5;
}
.custom-dialog-footer .el-button {
  margin-left: 10px;
}
@media (max-width: 768px) {
  .custom-dialog {
    width: 95vw;
    margin: 10px;
  }
  .scanner-form {
    flex-direction: column;
    align-items: stretch;
  }
  .scanner-form .el-input {
    width: 100%;
  }
}
/* æ–°å¢žï¼šæ‰‹åŠ¨å¼¹çª—çš„æŒ‰é’®æ‚¬åœæ•ˆæžœ */
:deep(button) {
  transition: all 0.3s;
}
:deep(button:hover) {
  opacity: 0.8;
}
:deep(button:active) {
  opacity: 0.6;
}
</style>
ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/views/outbound/outboundOrder.vue
@@ -168,7 +168,6 @@
        type: "string",
        width: 160,
        align: "left",
        link: true,
      },
      {
        field: "upperOrderNo",
@@ -230,6 +229,13 @@
        title: "部门名称",
        type: "string",
        width: 160,
        align: "left",
      },
      {
        field: "operator",
        title: "操作人",
        type: "string",
        width: 120,
        align: "left",
      },
      {
@@ -314,7 +320,6 @@
          width: 90,
          align: "left",
          edit: { type: "string" },
          required: true,
        },
        {
          field: "supplyCode",
@@ -323,7 +328,6 @@
          width: 90,
          align: "left",
          edit: { type: "string" },
          required: true,
        },
        {
          field: "orderQuantity",
@@ -341,6 +345,7 @@
          width: 90,
          align: "left",
          edit: { type: "number" },
          readonly:true
        },
        {
          field: "rowNo",
@@ -349,6 +354,7 @@
          width: 90,
          align: "left",
          edit: { type: "number" },
          readonly:true
        },
        {
          field: "lockQuantity",
@@ -372,7 +378,7 @@
          align: "left",
          edit: { type: "select" },
          bind: { key: "orderDetailStatusEnum", data: [] },
          required: true,
          readonly:true
        },
        {
          field: "creater",
ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/views/stock/stockInfoDetailByMaterielSum.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,222 @@
<template>
  <view-grid ref="grid" :columns="columns" :detail="detail" :editFormFields="editFormFields"
    :editFormOptions="editFormOptions" :searchFormFields="searchFormFields" :searchFormOptions="searchFormOptions"
    :table="table" :extend="extend">
  </view-grid>
</template>
<script>
import extend from "@/extension/stock/stockInfoDetailByMaterielSum.js";
import { ref, defineComponent } from "vue";
export default defineComponent({
  setup() {
    const table = ref({
      key: "id",
      footer: "Foots",
      cnName: "库存信息明细",
      name: "stockInfoDetail",
      url: "/StockInfoDetail/",
      sortName: "id",
    });
    const editFormFields = ref({
      deviceCode: "",
      deviceName: "",
      deviceType: "",
      deviceStatus: "",
      deviceIp: "",
      devicePort: "",
      devicePlcType: "",
      deviceRemark: "",
    });
    const editFormOptions = ref([
      [
        {
          title: "物料编号",
          required: true,
          field: "materielCode",
          type: "string",
        },
        {
          title: "单据编号",
          required: true,
          field: "materielName",
          type: "string",
        },
        {
          title: "批次号",
          required: true,
          field: "orderNo",
          type: "string",
        },
        {
          title: "序列号",
          required: true,
          field: "serialNumber",
          type: "string",
        },
      ],
    ]);
    const searchFormFields = ref({
      materielCode: "",
      materielName: "",
      orderNo: "",
    });
    const searchFormOptions = ref([
      [
        { title: "物料编号", field: "materielCode" ,type:'like'},
        { title: "物料名称", field: "materielName" ,type:'like'},
        { title: "单据编号", field: "orderNo" ,type:'like'},
        { title: "托盘号", field: "palletCode" ,type:'like'},
      ],
    ]);
    const columns = ref([
      {
        field: "id",
        title: "Id",
        type: "int",
        width: 90,
        hidden: true,
        readonly: true,
        require: true,
        align: "left",
      },
      {
        field: "stockId",
        title: "库存信息主键",
        type: "string",
        width: 90,
        align: "left",
      },
      {
        field: "materielCode",
        title: "物料编号",
        type: "string",
        width: 150,
        align: "left",
      },
      {
        field: "materielName",
        title: "物料名称",
        type: "string",
        width: 150,
        align: "left",
      },
      {
        field: "orderNo",
        title: "单据编号",
        type: "decimal",
        width: 90,
        align: "left",
      },
      {
        field: "batchNo",
        title: "批次号",
        type: "string",
        width: 90,
        align: "left",
      },
      {
        field: "serialNumber",
        title: "序列号",
        type: "int",
        width: 120,
        align: "left",
      },
      {
        field: "supplyCode",
        title: "供应商编号",
        type: "string",
        width: 120,
        align: "left",
      },
      {
        field: "warehouseCode",
        title: "仓库号",
        type: "string",
        width: 120,
        align: "left",
      },
      {
        field: "barcode",
        title: "条码",
        type: "string",
        width: 120,
        align: "left",
      },
      {
        field: "stockQuantity",
        title: "库存数量",
        type: "string",
        width: 200,
        align: "left",
      },
      {
        field: "outboundQuantity",
        title: "出库数量",
        type: "string",
        width: 180,
        align: "left",
      },
      {
        field: "status",
        title: "库存明细状态",
        type: "string",
        width: 120,
        align: "left",
        bind: { key: "stockStatusEmun", data: [] },
      },
      {
        field: "creater",
        title: "创建人",
        type: "string",
        width: 90,
        align: "left",
      },
      {
        field: "createDate",
        title: "创建时间",
        type: "datetime",
        width: 160,
        align: "left",
      },
      {
        field: "modifier",
        title: "修改人",
        type: "string",
        width: 100,
        align: "left",
      },
      {
        field: "modifyDate",
        title: "修改时间",
        type: "datetime",
        width: 160,
        align: "left",
      },
      {
        field: "remark",
        title: "备注",
        type: "string",
        width: 100,
        align: "left",
      },
    ]);
    const detail = ref({
      cnName: "#detailCnName",
      table: "",
      columns: [],
      sortName: "",
    });
    return {
      table,
      extend,
      editFormFields,
      editFormOptions,
      searchFormFields,
      searchFormOptions,
      columns,
      detail,
    };
  },
});
</script>
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_BasicService/ErpApiService.cs
@@ -41,7 +41,10 @@
        {
            try
            {
                var request = new TokenRequest { appId = "BG_SYSTEM", secretKey = "7e9239c1e132462a9cf03bfa342a044aMTcxODE5MzgxODI4Mw" };
                //erp æµ‹è¯•环境
                //var request = new TokenRequest { appId = "BG_SYSTEM", secretKey = "7e9239c1e132462a9cf03bfa342a044aMTcxODE5MzgxODI4Mw" };
                ////erp æ­£å¼çŽ¯å¢ƒ
                var request = new TokenRequest { appId = "BG_SYSTEM", secretKey = "9a3d0b5a37Bfc6dAM4b34ODb8ebDOSb937106d1b19DS29098" };
                var response = await PostAsync<TokenRequest, TokenResponse>("auth/getAccessToken", request, includeToken: false);
                var _token = response?.data?.access_token;
                return _token ?? "";
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_BasicService/InvokeMESService.cs
@@ -26,6 +26,7 @@
using WIDESEA_IBasicService;
using WIDESEA_IOutboundService;
using WIDESEA_Model.Models;
using WIDESEA_Model.Models.Outbound;
namespace WIDESEA_BasicService
{
@@ -45,13 +46,14 @@
        private readonly IOutboundOrderService _outboundOrderService;
        private readonly IOutboundOrderDetailService _outboundOrderDetailService;
        private readonly IOutStockLockInfoService _outStockLockInfoService;
        private readonly IRepository<Dt_InterfaceLog> _interfacelogRepository;
        // å­˜å‚¨èµ„源ID及其对应的锁对象。使用 ConcurrentDictionary ç¡®ä¿å¯¹å­—典操作本身的线程安全。
        private static readonly ConcurrentDictionary<string, object> _resourceLocks = new ConcurrentDictionary<string, object>();
        // å…¨å±€é™æ€é”ï¼šç”¨äºŽä¿æŠ¤ _resourceLocks å­—典中 GetOrAdd æˆ– TryRemove æ—¶çš„竞争
        private static readonly object _globalLocker = new object();
        public InvokeMESService(IHttpClientFactory httpClientFactory, ILogger<InvokeMESService> logger, IRepository<Dt_FeedbackToMes> feedbacktomesRepository, IRepository<Dt_StockInfoDetail> stockInfoDetailRepository, IRepository<Dt_StockInfo> stockInfoRepository, IRepository<Dt_InboundOrder> inboundOrderRepository, IOutboundOrderService outboundOrderService, IOutboundOrderDetailService outboundOrderDetailService, IOutStockLockInfoService outStockLockInfoService, IMaterialUnitService materialUnitService, IRepository<Dt_PickingRecord> pickingRecoreRepository)
        public InvokeMESService(IHttpClientFactory httpClientFactory, ILogger<InvokeMESService> logger, IRepository<Dt_FeedbackToMes> feedbacktomesRepository, IRepository<Dt_StockInfoDetail> stockInfoDetailRepository, IRepository<Dt_StockInfo> stockInfoRepository, IRepository<Dt_InboundOrder> inboundOrderRepository, IOutboundOrderService outboundOrderService, IOutboundOrderDetailService outboundOrderDetailService, IOutStockLockInfoService outStockLockInfoService, IMaterialUnitService materialUnitService, IRepository<Dt_PickingRecord> pickingRecoreRepository, IRepository<Dt_InterfaceLog> interfacelogRepository)
        {
            _httpClientFactory = httpClientFactory;
            _logger = logger;
@@ -64,6 +66,7 @@
            _outStockLockInfoService = outStockLockInfoService;
            _materialUnitService = materialUnitService;
            _pickingRecoreRepository = pickingRecoreRepository;
            _interfacelogRepository = interfacelogRepository;
        }
        /// <summary>
@@ -241,159 +244,164 @@
        /// <returns></returns>
        public async Task<WebResponseContent> BatchOrderFeedbackToMes(List<string> orderNos, int inout)
        {
            // 1. ã€å†…存锁抢占】
            if (MemoryLockManager.TryAcquireLock(orderNos[0]))
            {
                try
                {
                    if (inout == 1)
                    {
                        foreach (var orderNo in orderNos)
            try
            {             // 1. ã€å†…存锁抢占】
                //if (MemoryLockManager.TryAcquireLock(orderNos[0]))
                //{
                        if (inout == 1)
                        {
                            try
                            foreach (var orderNo in orderNos)
                            {
                                var stockinfos = _stockInfoRepository.Db.Queryable<Dt_StockInfo>("info").Where(info => info.StockStatus == 6)
                                                .Where(it => SqlFunc.Subqueryable<Dt_StockInfoDetail>().Where(s => s.StockId == it.Id && s.OrderNo == orderNo).Any())
                                                .ToList();
                                var feeds = _feedbacktomesRepository.Db.Queryable<Dt_FeedbackToMes>().Where(x => x.OrderNo == orderNo && x.ReportStatus == 1).Select(o => o.PalletCode).ToList();
                                var unreports = stockinfos.Where(x => !feeds.Contains(x.PalletCode)).ToList();
                                if (unreports != null && !unreports.Any())
                                try
                                {
                                    return WebResponseContent.Instance.Error("没有需要回传的数据");
                                }
                                foreach (var item in unreports)
                                {
                                    var lists = _stockInfoDetailRepository.Db.Queryable<Dt_StockInfoDetail>().Where(x => x.StockId == item.Id).ToList();
                                    if (lists.Any())
                                    var stockinfos = _stockInfoRepository.Db.Queryable<Dt_StockInfo>("info").Where(info => info.StockStatus == 6)
                                                    .Where(it => SqlFunc.Subqueryable<Dt_StockInfoDetail>().Where(s => s.StockId == it.Id && s.OrderNo == orderNo).Any())
                                                    .ToList();
                                    var feeds = _feedbacktomesRepository.Db.Queryable<Dt_FeedbackToMes>().Where(x => x.OrderNo == orderNo && x.ReportStatus == 1).Select(o => o.PalletCode).ToList();
                                    var unreports = stockinfos.Where(x => !feeds.Contains(x.PalletCode)).ToList();
                                    if (unreports != null && !unreports.Any())
                                    {
                                        var inboundOrder = _inboundOrderRepository.Db.Queryable<Dt_InboundOrder>().First(x => x.InboundOrderNo == lists.FirstOrDefault().OrderNo);
                                        if (inboundOrder != null)
                                        return WebResponseContent.Instance.Error("没有需要回传的数据");
                                    }
                                    foreach (var item in unreports)
                                    {
                                        var lists = _stockInfoDetailRepository.Db.Queryable<Dt_StockInfoDetail>().Where(x => x.StockId == item.Id).ToList();
                                        if (lists.Any())
                                        {
                                            if (inboundOrder.OrderType == (int)InOrderTypeEnum.AllocatInbound)//调拨入库
                                            var inboundOrder = _inboundOrderRepository.Db.Queryable<Dt_InboundOrder>().First(x => x.InboundOrderNo == lists.FirstOrDefault().OrderNo);
                                            if (inboundOrder != null)
                                            {
                                                var allocate = SqlSugarHelper.DbWMS.Queryable<Dt_AllocateOrder>().Where(x => x.OrderNo == inboundOrder.InboundOrderNo).First();
                                                var allocatefeedmodel = new AllocateDto
                                                if (inboundOrder.OrderType == (int)InOrderTypeEnum.AllocatInbound)//调拨入库
                                                {
                                                    ReqCode = Guid.NewGuid().ToString(),
                                                    ReqTime = DateTime.Now.ToString(),
                                                    BusinessType = "2",
                                                    FactoryArea = inboundOrder.FactoryArea,
                                                    OperationType = 1,
                                                    Operator = inboundOrder.Operator,
                                                    OrderNo = inboundOrder.UpperOrderNo,
                                                    fromWarehouse = allocate?.FromWarehouse ?? "",
                                                    toWarehouse = allocate?.ToWarehouse ?? "",
                                                    Details = new List<AllocateDtoDetail>()
                                                    var allocate = SqlSugarHelper.DbWMS.Queryable<Dt_AllocateOrder>().Where(x => x.OrderNo == inboundOrder.InboundOrderNo).First();
                                                    var allocatefeedmodel = new AllocateDto
                                                    {
                                                        ReqCode = Guid.NewGuid().ToString(),
                                                        ReqTime = DateTime.Now.ToString(),
                                                        BusinessType = "2",
                                                        FactoryArea = inboundOrder.FactoryArea,
                                                        OperationType = 1,
                                                        Operator = inboundOrder.Operator,
                                                        OrderNo = inboundOrder.UpperOrderNo,
                                                        fromWarehouse = allocate?.FromWarehouse ?? "",
                                                        toWarehouse = allocate?.ToWarehouse ?? "",
                                                        Details = new List<AllocateDtoDetail>()
                                                };
                                                    };
                                                var groupedData = lists.GroupBy(item => new { item.MaterielCode, item.InboundOrderRowNo, item.BarcodeUnit, item.WarehouseCode })
                                                   .Select(group => new AllocateDtoDetail
                                                   {
                                                       MaterialCode = group.Key.MaterielCode,
                                                       LineNo = group.Key.InboundOrderRowNo,
                                                       WarehouseCode = group.Key.WarehouseCode,
                                                       Qty = group.Sum(x => x.BarcodeQty),
                                                       Unit = group.Key.BarcodeUnit,
                                                       Barcodes = group.Select(row => new BarcodeInfo
                                                    var groupedData = lists.GroupBy(item => new { item.MaterielCode, item.InboundOrderRowNo, item.BarcodeUnit, item.WarehouseCode })
                                                       .Select(group => new AllocateDtoDetail
                                                       {
                                                           Barcode = row.Barcode,
                                                           Qty = row.BarcodeQty,
                                                           BatchNo = row.BatchNo,
                                                           SupplyCode = row.SupplyCode,
                                                           Unit = row.BarcodeUnit
                                                       }).ToList()
                                                   }).ToList();
                                                allocatefeedmodel.Details = groupedData;
                                                           MaterialCode = group.Key.MaterielCode,
                                                           LineNo = group.Key.InboundOrderRowNo,
                                                           WarehouseCode = group.Key.WarehouseCode,
                                                           Qty = group.Sum(x => x.BarcodeQty),
                                                           Unit = group.Key.BarcodeUnit,
                                                           Barcodes = group.Select(row => new BarcodeInfo
                                                           {
                                                               Barcode = row.Barcode,
                                                               Qty = row.BarcodeQty,
                                                               BatchNo = row.BatchNo,
                                                               SupplyCode = row.SupplyCode,
                                                               Unit = row.BarcodeUnit
                                                           }).ToList()
                                                       }).ToList();
                                                    allocatefeedmodel.Details = groupedData;
                                                var result = await FeedbackAllocate(allocatefeedmodel);
                                                if (result != null && result.code == 200)
                                                {
                                                    _feedbacktomesRepository.Db.Insertable(new Dt_FeedbackToMes { OrderNo = orderNo, PalletCode = item.PalletCode, ReportStatus = 1 }).ExecuteCommand();
                                                    var result = await FeedbackAllocate(allocatefeedmodel);
                                                    if (result != null && result.code == 200)
                                                    {
                                                        _feedbacktomesRepository.Db.Insertable(new Dt_FeedbackToMes { OrderNo = orderNo, PalletCode = item.PalletCode, ReportStatus = 1 }).ExecuteCommand();
                                                    }
                                                }
                                            }
                                            else
                                            {
                                                var feedmodel = new FeedbackInboundRequestModel
                                                else
                                                {
                                                    reqCode = Guid.NewGuid().ToString(),
                                                    reqTime = DateTime.Now.ToString(),
                                                    business_type = inboundOrder.BusinessType,
                                                    factoryArea = inboundOrder.FactoryArea,
                                                    operationType = 1,
                                                    Operator = inboundOrder.Operator,
                                                    orderNo = inboundOrder.UpperOrderNo,
                                                    status = inboundOrder.OrderStatus,
                                                    details = new List<FeedbackInboundDetailsModel>()
                                                    var feedmodel = new FeedbackInboundRequestModel
                                                    {
                                                        reqCode = Guid.NewGuid().ToString(),
                                                        reqTime = DateTime.Now.ToString(),
                                                        business_type = inboundOrder.BusinessType,
                                                        factoryArea = inboundOrder.FactoryArea,
                                                        operationType = 1,
                                                        Operator = inboundOrder.Operator,
                                                        orderNo = inboundOrder.UpperOrderNo,
                                                        status = inboundOrder.OrderStatus,
                                                        details = new List<FeedbackInboundDetailsModel>()
                                                };
                                                    };
                                                var groupedData = lists.GroupBy(item => new { item.MaterielCode, item.SupplyCode, item.BatchNo, item.InboundOrderRowNo, item.BarcodeUnit, item.WarehouseCode })
                                                   .Select(group => new FeedbackInboundDetailsModel
                                                   {
                                                       materialCode = group.Key.MaterielCode,
                                                       supplyCode = group.Key.SupplyCode,
                                                       batchNo = group.Key.BatchNo,
                                                       lineNo = group.Key.InboundOrderRowNo,
                                                       qty = group.Sum(x => x.BarcodeQty),
                                                       // warehouseCode = group.Key.WarehouseCode=="0"?"1072": group.Key.WarehouseCode,
                                                       warehouseCode = group.Key.WarehouseCode,
                                                       unit = group.Key.BarcodeUnit,
                                                       barcodes = group.Select(row => new FeedbackBarcodesModel
                                                    var groupedData = lists.GroupBy(item => new { item.MaterielCode, item.SupplyCode, item.BatchNo, item.InboundOrderRowNo, item.BarcodeUnit, item.WarehouseCode })
                                                       .Select(group => new FeedbackInboundDetailsModel
                                                       {
                                                           barcode = row.Barcode,
                                                           qty = row.BarcodeQty
                                                       }).ToList()
                                                   }).ToList();
                                                feedmodel.details = groupedData;
                                                var result = await FeedbackInbound(feedmodel);
                                                if (result != null && result.code == 200)
                                                {
                                                    _feedbacktomesRepository.Db.Insertable(new Dt_FeedbackToMes { OrderNo = orderNo, PalletCode = item.PalletCode, ReportStatus = 1 }).ExecuteCommand();
                                                           materialCode = group.Key.MaterielCode,
                                                           supplyCode = group.Key.SupplyCode,
                                                           batchNo = group.Key.BatchNo,
                                                           lineNo = group.Key.InboundOrderRowNo,
                                                           qty = group.Sum(x => x.BarcodeQty),
                                                           // warehouseCode = group.Key.WarehouseCode=="0"?"1072": group.Key.WarehouseCode,
                                                           warehouseCode = group.Key.WarehouseCode,
                                                           unit = group.Key.BarcodeUnit,
                                                           barcodes = group.Select(row => new FeedbackBarcodesModel
                                                           {
                                                               barcode = row.Barcode,
                                                               qty = row.BarcodeQty
                                                           }).ToList()
                                                       }).ToList();
                                                    feedmodel.details = groupedData;
                                                    var result = await FeedbackInbound(feedmodel);
                                                    if (result != null && result.code == 200)
                                                    {
                                                        _feedbacktomesRepository.Db.Insertable(new Dt_FeedbackToMes { OrderNo = orderNo, PalletCode = item.PalletCode, ReportStatus = 1 }).ExecuteCommand();
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                            catch (Exception ex)
                            {
                                _logger.LogInformation("InvokeMESService  BatchOrderFeedbackToMes å›žå†™MES失败:  " + ex.Message);
                                return WebResponseContent.Instance.Error(ex.Message);
                            }
                                catch (Exception ex)
                                {
                                    _logger.LogInformation("InvokeMESService  BatchOrderFeedbackToMes å›žå†™MES失败:  " + ex.Message);
                                    return WebResponseContent.Instance.Error(ex.Message);
                                }
                            }
                        }
                    }
                    else if (inout == 2)
                    {
                        foreach (var orderNo in orderNos)
                        else if (inout == 2)
                        {
                            var outboundOrder = await _outboundOrderService.Db.Queryable<Dt_OutboundOrder>().FirstAsync(x => x.OrderNo == orderNo);
                            if (outboundOrder != null && outboundOrder.IsBatch == 0)
                            foreach (var orderNo in orderNos)
                            {
                                var result = await HandleOutboundOrderToMESCompletion(outboundOrder, orderNo);
                                return result;
                                var outboundOrder = await _outboundOrderService.Db.Queryable<Dt_OutboundOrder>().FirstAsync(x => x.OrderNo == orderNo);
                                if (outboundOrder != null && outboundOrder.IsBatch == 0)
                                {
                                    var result = await HandleOutboundOrderToMESCompletion(outboundOrder, orderNo);
                                    return result;
                                }
                                else if (outboundOrder != null && outboundOrder.IsBatch == 1)
                                {
                                    var result = await HandleOutboundOrderBatchToMESCompletion(outboundOrder, orderNo);
                                    return result;
                                }
                            }
                            else if (outboundOrder != null && outboundOrder.IsBatch == 1)
                            {
                                var result = await HandleOutboundOrderBatchToMESCompletion(outboundOrder, orderNo);
                                return result;
                            }
                        }
                //}
                //else
                //{
                //    // æŠ¢é”å¤±è´¥ï¼šè¯´æ˜Žæœ‰å¦ä¸€ä¸ªçº¿ç¨‹ï¼ˆWCS回调或人工操作)正在处理
                    }
                }
                finally
                {
                    // 2. ã€é‡Šæ”¾å†…存锁】无论成功失败,必须释放
                    MemoryLockManager.ReleaseLock(orderNos[0]);
                }
                //    return WebResponseContent.Instance.Error("WMS正在处理此回传任务,请勿重复操作。");
                //}
            }
            else
            catch(Exception ex)
            {
                // æŠ¢é”å¤±è´¥ï¼šè¯´æ˜Žæœ‰å¦ä¸€ä¸ªçº¿ç¨‹ï¼ˆWCS回调或人工操作)正在处理
                return WebResponseContent.Instance.OK("WMS正在处理此回传任务,请勿重复操作。");
                _logger.LogInformation("InvokeMESService  BatchOrderFeedbackToMes :  " +ex.Message);
            }
            finally
            {
                // 2. ã€é‡Šæ”¾å†…存锁】无论成功失败,必须释放
               // MemoryLockManager.ReleaseLock(orderNos[0]);
            }
            return WebResponseContent.Instance.OK();
        }
@@ -406,10 +414,10 @@
            try
            {
                // æ ¡éªŒï¼šå·²å›žä¼ ç›´æŽ¥è¿”回错误
                if (outboundOrder.ReturnToMESStatus == 1)
                {
                    return WebResponseContent.Instance.Error("该单已经回传!");
                }
                //if (outboundOrder.ReturnToMESStatus == 1)
                //{
                //    return WebResponseContent.Instance.Error("该单已经回传!");
                //}
                // æŸ¥è¯¢è®¢å•明细(仅查询未回传成功的)
                var orderDetails = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
@@ -433,29 +441,49 @@
                var groups = pickingRecords.GroupBy(x => x.FeedBackMesDocumentNo).ToList();
                foreach (var group in groups)
                {
                    List<Dt_PickingRecord> records = group.ToList(); // è¯¥åˆ†ç»„下的所有记录
                    if (string.IsNullOrEmpty(group.Key))
                    {
                        var emptydocumentNo = UniqueValueGenerator.Generate();
                        records.ForEach(x => { x.FeedBackMesDocumentNo = emptydocumentNo; });
                        var result=   await _pickingRecoreRepository.Db.Insertable(records).ExecuteCommandAsync();
                        var result = await _pickingRecoreRepository.Db.Updateable(records).ExecuteCommandAsync();
                        var interfacelog = new Dt_InterfaceLog
                        {
                            Content = JsonConvert.SerializeObject(records),
                            DocumentNo = emptydocumentNo,
                            OrderNo = orderNo,
                            OrderType = "2",
                        };
                        _interfacelogRepository.AddData(interfacelog);
                        if (result > 0)
                        {
                            (bool _flowControl, WebResponseContent _value) = await FeedBackBatchToMes(outboundOrder, orderNo, orderDetails, pickingRecords, emptydocumentNo);
                            if (!_flowControl)
                            {
                                return _value;
                            }
                            return _value;
                        }
                    }
                    else
                    {
                        (bool _flowControl, WebResponseContent _value) = await FeedBackBatchToMes(outboundOrder, orderNo, orderDetails, pickingRecords, group.Key);
                        if (!_flowControl)
                        var ilog = _interfacelogRepository.QueryFirst(x => x.DocumentNo == group.Key);
                        if (ilog == null)
                        {
                            return _value;
                            var interfacelog = new Dt_InterfaceLog
                            {
                                Content = JsonConvert.SerializeObject(records),
                                DocumentNo = group.Key,
                                OrderNo = orderNo,
                                OrderType = "2",
                            };
                            _interfacelogRepository.AddData(interfacelog);
                        }
                        (bool _flowControl, WebResponseContent _value) = await FeedBackBatchToMes(outboundOrder, orderNo, orderDetails, pickingRecords, group.Key);
                        return _value;
                    }
                }
@@ -594,7 +622,7 @@
            //  æ›´æ–°è®¢å•状态
            int newStatus = allCompleted ? (int)OutOrderStatusEnum.出库完成 : (int)OutOrderStatusEnum.出库中;
            if (outboundOrder.OrderStatus != newStatus)
            if (allCompleted && outboundOrder.OrderStatus != newStatus)
            {
                int updateCount = await _outboundOrderService.Db.Updateable<Dt_OutboundOrder>()
@@ -637,6 +665,11 @@
                x.ReturnToMESStatus = 1;
            });
            await _pickingRecoreRepository.Db.Updateable(updates).ExecuteCommandAsync();
            await _interfacelogRepository.Db.Updateable<Dt_InterfaceLog>()
                                             .SetColumns(x => x.ReturnToMESStatus == 1)
                                             .Where(x => x.OrderNo == orderNo)
                                             .ExecuteCommandAsync();
            if (allCompleted)
            {
                //MES回传成功:更新明细为回传成功状态
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_BasicService/LocationInfoService.cs
@@ -139,15 +139,26 @@
                }
                List<string> lockLocationCodes = locationCaches.Select(x => x.LocationCode).ToList();
                //Dictionary<string, SqlSugar.OrderByType> orderBy = new Dictionary<string, OrderByType>()
                //{
                //    { nameof(Dt_LocationInfo.RoadwayNo),OrderByType.Asc },
                //    { nameof(Dt_LocationInfo.Layer),OrderByType.Asc },
                //    { nameof(Dt_LocationInfo.Column),OrderByType.Asc },
                //    { nameof(Dt_LocationInfo.Depth),OrderByType.Desc },
                //    { nameof(Dt_LocationInfo.Row),OrderByType.Asc }
                //};
                Dictionary<string, SqlSugar.OrderByType> orderBy = new Dictionary<string, OrderByType>()
                {
                    { nameof(Dt_LocationInfo.RoadwayNo),OrderByType.Asc },
                    //{ nameof(Dt_LocationInfo.RoadwayNo),OrderByType.Asc },
                    { nameof(Dt_LocationInfo.Layer),OrderByType.Asc },
                    { nameof(Dt_LocationInfo.Row),OrderByType.Asc },
                    { nameof(Dt_LocationInfo.Column),OrderByType.Asc },
                    { nameof(Dt_LocationInfo.Depth),OrderByType.Desc },
                    { nameof(Dt_LocationInfo.Row),OrderByType.Asc }
                };
                var first = BaseDal.QueryFirst(x => x.LocationType == locationType && x.LocationStatus == LocationStatusEnum.Free.ObjToInt() && x.EnableStatus != EnableStatusEnum.Disable.ObjToInt() && !lockLocationCodes.Contains(x.LocationCode), orderBy);//查询空货位信息并排除5分钟内分配的货位,根据层、列、深度、行排序
                if (first != null)
@@ -157,7 +168,7 @@
                    {
                        LocationStatus = (int)LocationStatusEnum.InStockLock,
                    }).Where(x => x.Id == first.Id).ExecuteCommand();
                }
                }
                return first;
            }
@@ -217,7 +228,7 @@
        {
            return Repository.QueryData(x => locationCodes.Contains(x.LocationCode));
        }
        public List<LocationTypeDto> GetLocationTypes()
        {
            return _locationTypeRepository.Db.Queryable<Dt_LocationType>().Select(x =>
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_Common/TaskEnum/TaskStatusEnum.cs
@@ -66,6 +66,8 @@
        [Description("AGV执行中")]
        AGV_Executing = 310,
        [Description("AGV取货中")]
        AGV_Pull = 315,
        /// <summary>
        /// AGV待继续执行
        /// </summary>
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_Core/BaseServices/ServiceBase.cs
@@ -223,7 +223,7 @@
                        if (string.IsNullOrEmpty(where))
                            where += $"{searchParametersList[i].Name} >= '{searchParametersList[i].Value}'";
                        else
                            where += $" and {searchParametersList[i].Name} {searchParametersList[i].DisplayType.GetLinqCondition()} '{searchParametersList[i].Value}'";
                            where += $" and {searchParametersList[i].Name} >= '{searchParametersList[i].Value}'";
                    }
                    else if (searchParametersList[i].DisplayType.GetLinqCondition() == LinqExpressionType.LessThanOrEqual)
                    {
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_Core/Helper/UtilConvert.cs
@@ -958,10 +958,10 @@
                case HtmlElementType.Contains:
                    linqExpression = LinqExpressionType.In;
                    break;
                case HtmlElementType.ThanOrEqual:
                case HtmlElementType.thanorequal:
                    linqExpression = LinqExpressionType.ThanOrEqual;
                    break;
                case HtmlElementType.LessOrequal:
                case HtmlElementType.lessorequal:
                    linqExpression = LinqExpressionType.LessThanOrEqual;
                    break;
                case HtmlElementType.GT:
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_DTO/Stock/StockDetailDtO.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,76 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WIDESEA_DTO.Stock
{
    public class StockDetailDtO
    {
        public int Id { get; set; }
        public int StockId { get; set; }
        public string MaterielCode { get; set; }
        public string MaterielName { get; set; }
        public string OrderNo { get; set; }
        public string BatchNo { get; set; }
        public string ProductionDate { get; set; }
        public string EffectiveDate { get; set; }
        public string SerialNumber { get; set; }
        public decimal StockQuantity { get; set; }
        public decimal OutboundQuantity { get; set; }
        public int Status { get; set; }
        public string Unit { get; set; }
        public string InboundOrderRowNo { get; set; }
        public string? SupplyCode { get; set; }
        public string FactoryArea { get; set; }
        public string? WarehouseCode { get; set; }
        public string? Barcode { get; set; }
        public string? BusinessType { get; set; }
        public decimal BarcodeQty { get; set; }
        public string BarcodeUnit { get; set; }
        public DateTime? ValidDate { get; set; }
        public string Remark { get; set; }
    }
}
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_IStockService/IStockDetailByMaterielService.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WIDESEA_Core;
using WIDESEA_Core.BaseRepository;
using WIDESEA_Core.BaseServices;
using WIDESEA_DTO.Stock;
using WIDESEA_Model.Models;
namespace WIDESEA_IStockService
{
    public interface IStockDetailByMaterielService : IService<StockDetailByMateriel>
    {
        IRepository<StockDetailByMateriel> Repository { get; }
        PageGridData<StockDetailByMateriel> GetPageData2(PageDataOptions options);
    }
}
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_IStockService/IStockInfoDetailService.cs
@@ -14,5 +14,7 @@
        bool ExistBarcodes(List<string> barcodes);
        PageGridData<StockInfoDetailWithPalletDto> GetPageData2(PageDataOptions options);
        PageGridData<StockDetailDtO> GetPageDataByMateriel(PageDataOptions options);
    }
}
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_ITaskInfoService/ITaskService.cs
@@ -23,6 +23,7 @@
using System.Text;
using System.Threading.Tasks;
using WIDESEA_Common.CommonEnum;
using WIDESEA_Common.TaskEnum;
using WIDESEA_Core;
using WIDESEA_Core.BaseRepository;
using WIDESEA_Core.BaseServices;
@@ -44,6 +45,8 @@
        Task<WebResponseContent> TaskCompleted(string taskNum);
        Task TaskStatusChange(string taskNum, TaskStatusEnum taskStatusEnum);
        Task<WebResponseContent> GenerateOutboundTasksAsync(int[] keys, string outStation);
        Task<WebResponseContent> GenerateOutboundTask(int orderDetailId, List<StockSelectViewDTO> stockSelectViews,string station=null);
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_ITaskInfoService/ITask_HtyService.cs
@@ -15,4 +15,5 @@
public interface ITask_HtyService : IService<Dt_Task_Hty>
{
    bool DeleteAndMoveIntoHty(Dt_Task task, OperateTypeEnum operateType);
}
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_InboundService/InboundOrderService.cs
@@ -689,5 +689,41 @@
            return WebResponseContent.Instance.OK("托盘撤销成功");
        }
        public override PageGridData<Dt_InboundOrder> GetPageData(PageDataOptions options)
        {
            string wheres = ValidatePageOptions(options);
            //获取排序字段
            Dictionary<string, SqlSugar.OrderByType> orderbyDic = GetPageDataSort(options, TProperties);
            List<OrderByModel> orderByModels = new List<OrderByModel>();
            foreach (var item in orderbyDic)
            {
                OrderByModel orderByModel = new()
                {
                    FieldName = item.Key,
                    OrderByType = item.Value
                };
                orderByModels.Add(orderByModel);
            }
            int totalCount = 0;
            List<SearchParameters> searchParametersList = new List<SearchParameters>();
            if (!string.IsNullOrEmpty(options.Wheres))
            {
                try
                {
                    searchParametersList = options.Wheres.DeserializeObject<List<SearchParameters>>();
                    options.Filter = searchParametersList;
                }
                catch { }
            }
            var data = BaseDal.Db.Queryable<Dt_InboundOrder>()
                .WhereIF(!wheres.IsNullOrEmpty(), wheres)
                .OrderBy(orderByModels).Includes(x=>x.Details)
                .ToPageList(options.Page, options.Rows, ref totalCount);
            return new PageGridData<Dt_InboundOrder>(totalCount, data);
        }
    }
}
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_Model/Models/Outbound/Dt_OutboundOrderDetail.cs
@@ -47,7 +47,7 @@
        /// <summary>
        /// è¡Œå·
        /// </summary>
        [SugarColumn(IsNullable = false, ColumnDescription = "行号")]
        [SugarColumn(IsNullable = false, ColumnDescription = "行号", DefaultValue = "0")]
        public int RowNo {  get; set; }
        /// <summary>
@@ -71,7 +71,7 @@
        /// <summary>
        /// è®¢å•明细状态
        /// </summary>
        [SugarColumn(IsNullable = false, ColumnDescription = "订单明细状态")]
        [SugarColumn(IsNullable = false, ColumnDescription = "订单明细状态", DefaultValue = "0")]
        public int OrderDetailStatus { get; set; }
        /// <summary>
        /// å•位
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_Model/Models/Outbound/NoStockOutModel.cs
@@ -1,5 +1,8 @@
using System;
using Newtonsoft.Json;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@@ -43,4 +46,5 @@
        public List<string> BarCodeSubmit { get; set; }
    }
}
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_Model/Models/Stock/StockDetailByMateriel.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,74 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WIDESEA_Model.Models
{
    public class StockDetailByMateriel
    {
        public int Id { get; set; }
        public int StockId { get; set; }
        public string MaterielCode { get; set; }
        public string MaterielName { get; set; }
        public string OrderNo { get; set; }
        public string BatchNo { get; set; }
        public string ProductionDate { get; set; }
        public string EffectiveDate { get; set; }
        public string SerialNumber { get; set; }
        public decimal StockQuantity { get; set; }
        public decimal OutboundQuantity { get; set; }
        public int Status { get; set; }
        public string Unit { get; set; }
        public string InboundOrderRowNo { get; set; }
        public string? SupplyCode { get; set; }
        public string FactoryArea { get; set; }
        public string? WarehouseCode { get; set; }
        public string? Barcode { get; set; }
        public string? BusinessType { get; set; }
        public decimal BarcodeQty { get; set; }
        public string BarcodeUnit { get; set; }
        public DateTime? ValidDate { get; set; }
        public string Remark { get; set; }
    }
}
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundBatchPickingService.cs
@@ -21,6 +21,7 @@
using WIDESEA_IBasicService;
using WIDESEA_IOutboundService;
using WIDESEA_IStockService;
using WIDESEA_ITaskInfoService;
using WIDESEA_Model.Models;
using WIDESEA_Model.Models.Basic;
using WIDESEA_Model.Models.Outbound;
@@ -49,6 +50,7 @@
        private readonly IDailySequenceService _dailySequenceService;
        private readonly IAllocateService _allocateService;
        private readonly IRepository<Dt_OutboundBatch> _outboundBatchRepository;
        private readonly ITask_HtyService _task_HtyService;
        private readonly ILogger<OutboundPickingService> _logger;
        private Dictionary<string, string> stations = new Dictionary<string, string>
@@ -68,7 +70,7 @@
        public OutboundBatchPickingService(IRepository<Dt_PickingRecord> BaseDal, IUnitOfWorkManage unitOfWorkManage, IStockInfoService stockInfoService, IStockService stockService,
            IOutStockLockInfoService outStockLockInfoService, IStockInfoDetailService stockInfoDetailService, ILocationInfoService locationInfoService,
            IOutboundOrderDetailService outboundOrderDetailService, ISplitPackageService splitPackageService, IOutboundOrderService outboundOrderService,
            IRepository<Dt_Task> taskRepository, IESSApiService eSSApiService, ILogger<OutboundPickingService> logger, IInvokeMESService invokeMESService, IDailySequenceService dailySequenceService, IAllocateService allocateService, IRepository<Dt_OutboundBatch> outboundBatchRepository) : base(BaseDal)
            IRepository<Dt_Task> taskRepository, IESSApiService eSSApiService, ILogger<OutboundPickingService> logger, IInvokeMESService invokeMESService, IDailySequenceService dailySequenceService, IAllocateService allocateService, IRepository<Dt_OutboundBatch> outboundBatchRepository, ITask_HtyService task_HtyService) : base(BaseDal)
        {
            _unitOfWorkManage = unitOfWorkManage;
            _stockInfoService = stockInfoService;
@@ -86,6 +88,7 @@
            _dailySequenceService = dailySequenceService;
            _allocateService = allocateService;
            _outboundBatchRepository = outboundBatchRepository;
            _task_HtyService = task_HtyService;
        }
        // <summary>
@@ -1798,7 +1801,7 @@
                // æ›´æ–°é”å®šè®°å½•状态为已回库
                lockInfo.Status = (int)OutLockStockStatusEnum.已回库;
                lockInfo.Operator = App.User.UserName;
                lockInfo.Operator = App.User.UserName;
                await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync();
@@ -1854,7 +1857,7 @@
                    // æ›´æ–°é”å®šè®°å½•状态为已回库
                    lockInfo.Status = (int)OutLockStockStatusEnum.已回库;
                    lockInfo.Operator = App.User.UserName;
                    lockInfo.Operator = App.User.UserName;
                    await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync();
@@ -1945,11 +1948,33 @@
                    PalletType = stockInfo.PalletType,
                    WarehouseId = currentTask.WarehouseId
                };
                var targetAddress = currentTask.TargetAddress;
                await _taskRepository.Db.Insertable(returnTask).ExecuteCommandAsync();
                try
                {
                    await _taskRepository.Db.Insertable(returnTask).ExecuteCommandAsync();
                    _logger.LogInformation($"CreateReturnTaskAndHandleESS  åˆ†æ‰¹åˆ é™¤åŽ†å²ä»»åŠ¡: {orderNo} ï¼Œ {currentTask.TaskNum}");
                    // åˆ é™¤åŽŸå§‹å‡ºåº“ä»»åŠ¡
                    //_taskRepository.DeleteAndMoveIntoHty(originalTask, OperateTypeEnum.自动完成);
                    var result = _task_HtyService.DeleteAndMoveIntoHty(currentTask, OperateTypeEnum.人工删除);
                    await _taskRepository.Db.Deleteable(currentTask).ExecuteCommandAsync();
                    if (!result)
                    {
                        await _taskRepository.Db.Deleteable(currentTask).ExecuteCommandAsync();
                    }
                    _logger.LogInformation($"CreateReturnTaskAndHandleESS  åˆ†æ‰¹åˆ é™¤åŽ†å²ä»»åŠ¡: {orderNo} ï¼Œ {currentTask.TaskNum},影响行  {result}");
                }
                catch (Exception ex)
                {
                    _logger.LogInformation($"创建回库任务失败 - è®¢å•: {orderNo}, æ‰˜ç›˜: {palletCode}");
                    throw new Exception($"创建回库任务失败 - è®¢å•: {orderNo}, æ‰˜ç›˜: {palletCode}");
                }
                // å‘送ESS命令
                await SendESSCommands(palletCode, currentTask.TargetAddress, returnTask);
                await SendESSCommands(palletCode, targetAddress, returnTask);
                _logger.LogInformation($"创建回库任务成功 - è®¢å•: {orderNo}, æ‰˜ç›˜: {palletCode}");
            }
@@ -2223,7 +2248,7 @@
                    // åˆ†é…æ•°é‡åœ¨è®¢å•明细层面统一处理
                    var originalStatus = lockInfo.Status;
                    lockInfo.Status = (int)OutLockStockStatusEnum.已回库;
                    lockInfo.Operator = App.User.UserName;
                    lockInfo.Operator = App.User.UserName;
                    await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync();
@@ -2550,7 +2575,7 @@
        /// <summary>
        /// å¤„理未分拣的锁定记录回库
        /// </summary>
        /// <summary>
        /// å¤„理托盘上的库存货物回库
@@ -3478,13 +3503,24 @@
            };
            // ä¿å­˜å›žåº“任务
            await _taskRepository.Db.Insertable(returnTask).ExecuteCommandAsync();
            var insertcount = await _taskRepository.Db.Insertable(returnTask).ExecuteCommandAsync();
            if (insertcount <= 0)
            {
                throw new Exception("创建任务失败!");
            }
            var targetAddress = originalTask.TargetAddress;
            _logger.LogInformation($"CreateReturnTaskAndHandleESS  åˆ†æ‰¹åˆ é™¤åŽ†å²ä»»åŠ¡: {orderNo} ï¼Œ {originalTask.TaskNum}");
            // åˆ é™¤åŽŸå§‹å‡ºåº“ä»»åŠ¡
            _taskRepository.DeleteAndMoveIntoHty(originalTask, OperateTypeEnum.自动完成);
            //_taskRepository.DeleteAndMoveIntoHty(originalTask, OperateTypeEnum.自动完成);
           var result= _task_HtyService.DeleteAndMoveIntoHty(originalTask, OperateTypeEnum.人工删除);
            await _taskRepository.Db.Deleteable(originalTask).ExecuteCommandAsync();
            if (!result)
            {
                await _taskRepository.Db.Deleteable(originalTask).ExecuteCommandAsync();
            }
            _logger.LogInformation($"CreateReturnTaskAndHandleESS  åˆ†æ‰¹åˆ é™¤åŽ†å²ä»»åŠ¡: {orderNo} ï¼Œ {originalTask.TaskNum},影响行  {result}");
            // ç»™ ESS å‘送流动信号和创建任务
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundPickingService.cs
@@ -7,6 +7,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection.Metadata;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
@@ -32,9 +33,11 @@
using WIDESEA_IInboundService;
using WIDESEA_IOutboundService;
using WIDESEA_IStockService;
using WIDESEA_ITaskInfoService;
using WIDESEA_Model.Models;
using WIDESEA_Model.Models.Basic;
using WIDESEA_Model.Models.Check;
using WIDESEA_Model.Models.Outbound;
namespace WIDESEA_OutboundService
{
@@ -63,7 +66,9 @@
        private readonly IInboundOrderDetailService _inboundOrderDetailService;
        private readonly IRepository<Dt_WarehouseArea> _warehouseAreaRepository;
        private readonly IReCheckOrderService _reCheckOrderService;
        private readonly ITask_HtyService _task_HtyService;
        private readonly ILogger<OutboundPickingService> _logger;
        private readonly IRepository<Dt_InterfaceLog> _interfaceLog;
        private Dictionary<string, string> stations = new Dictionary<string, string>
        {
@@ -82,7 +87,7 @@
        public OutboundPickingService(IRepository<Dt_PickingRecord> BaseDal, IUnitOfWorkManage unitOfWorkManage, IStockInfoService stockInfoService, IStockService stockService,
            IOutStockLockInfoService outStockLockInfoService, IStockInfoDetailService stockInfoDetailService, ILocationInfoService locationInfoService,
            IOutboundOrderDetailService outboundOrderDetailService, ISplitPackageService splitPackageService, IOutboundOrderService outboundOrderService,
            IRepository<Dt_Task> taskRepository, IESSApiService eSSApiService, ILogger<OutboundPickingService> logger, IInvokeMESService invokeMESService, IDailySequenceService dailySequenceService, IAllocateService allocateService, IRepository<Dt_InboundOrder> inboundOrderRepository, IInboundOrderDetailService inboundOrderDetailService, IRepository<Dt_WarehouseArea> warehouseAreaRepository, IReCheckOrderService reCheckOrderService) : base(BaseDal)
            IRepository<Dt_Task> taskRepository, IESSApiService eSSApiService, ILogger<OutboundPickingService> logger, IInvokeMESService invokeMESService, IDailySequenceService dailySequenceService, IAllocateService allocateService, IRepository<Dt_InboundOrder> inboundOrderRepository, IInboundOrderDetailService inboundOrderDetailService, IRepository<Dt_WarehouseArea> warehouseAreaRepository, IReCheckOrderService reCheckOrderService, ITask_HtyService task_HtyService,IRepository<Dt_InterfaceLog> interfaceLog) : base(BaseDal)
        {
            _unitOfWorkManage = unitOfWorkManage;
            _stockInfoService = stockInfoService;
@@ -103,6 +108,8 @@
            _inboundOrderDetailService = inboundOrderDetailService;
            _warehouseAreaRepository = warehouseAreaRepository;
            _reCheckOrderService = reCheckOrderService;
            _task_HtyService = task_HtyService;
            _interfaceLog = interfaceLog;
        }
@@ -1684,15 +1691,31 @@
                WarehouseId = originalTask.WarehouseId
            };
            // ä¿å­˜å›žåº“任务
            await _taskRepository.Db.Insertable(returnTask).ExecuteCommandAsync();
            try
            {
                // ä¿å­˜å›žåº“任务
                var insertcount = await _taskRepository.Db.Insertable(returnTask).ExecuteCommandAsync();
                if (insertcount <= 0)
                {
                    throw new Exception("创建任务失败!");
                }
            }
            catch (Exception ex)
            {
                _logger.LogInformation($"CreateReturnTaskAndHandleESS åˆ›å»ºä»»åŠ¡å¤±è´¥: {orderNo} ï¼Œ {palletCode}");
                throw new Exception("创建任务失败!");
            }
            var targetAddress = originalTask.TargetAddress;
            _logger.LogInformation($"CreateReturnTaskAndHandleESS åˆ é™¤åŽ†å²ä»»åŠ¡: {orderNo} ï¼Œ {originalTask.TaskNum}");
            // åˆ é™¤åŽŸå§‹å‡ºåº“ä»»åŠ¡
            _taskRepository.DeleteAndMoveIntoHty(originalTask, OperateTypeEnum.自动完成);
            await _taskRepository.Db.Deleteable(originalTask).ExecuteCommandAsync();
            // _taskRepository.DeleteAndMoveIntoHty(originalTask, OperateTypeEnum.自动完成);
            var result = _task_HtyService.DeleteAndMoveIntoHty(originalTask, OperateTypeEnum.人工删除);
            if (!result)
            {
                await _taskRepository.Db.Deleteable(originalTask).ExecuteCommandAsync();
            }
            _logger.LogInformation($"CreateReturnTaskAndHandleESS åˆ é™¤åŽ†å²ä»»åŠ¡: {orderNo} ï¼Œ {originalTask.TaskNum},影响行  {result}");
            // ç»™ ESS å‘送流动信号和创建任务
            await SendESSCommands(palletCode, targetAddress, returnTask);
@@ -2752,15 +2775,15 @@
                        TaskNum = 0,
                        Status = (int)OutLockStockStatusEnum.拣选完成,
                        Unit = outboundOrderDetail.Unit,
                        SupplyCode = outboundOrderDetail.SupplyCode?? "无",
                        SupplyCode = outboundOrderDetail.SupplyCode ?? "无",
                        OrderType = outboundOrder.OrderType,
                        CurrentBarcode = inboundOrderDetail.Barcode,
                        IsSplitted = 1,
                        Operator = App.User.UserName,
                        lineNo= outboundOrderDetail.lineNo,
                        lineNo = outboundOrderDetail.lineNo,
                        WarehouseCode = outboundOrderDetail.WarehouseCode ?? "无",
                        BarcodeQty=outboundOrderDetail.NoStockOutQty,
                        BarcodeUnit =outboundOrderDetail.BarcodeUnit,
                        BarcodeQty = outboundOrderDetail.NoStockOutQty,
                        BarcodeUnit = outboundOrderDetail.BarcodeUnit,
                        BatchNo = outboundOrderDetail.BatchNo
                    };
                    _outStockLockInfoService.AddData(newLockInfo);
@@ -2832,29 +2855,30 @@
                var result1 = await _invokeMESService.FeedbackInbound(infeedmodel);
                if (result1 != null && result1.code == 200)
                {
                    var orderIds = inboundOrderDetails.Select(x => x.Id).Distinct().ToList();
                    _inboundOrderRepository.Db.Updateable<Dt_InboundOrder>().SetColumns(it => new Dt_InboundOrder { ReturnToMESStatus = 1 })
                    .Where(it => it.Id == inboundOrder.Id).ExecuteCommand();
                    _inboundOrderDetailService.Db.Updateable<Dt_InboundOrderDetail>().SetColumns(it => new Dt_InboundOrderDetail { ReturnToMESStatus = 1 })
                    .Where(it => it.OrderId == inboundOrder.Id).ExecuteCommand();
                    .Where(it => orderIds.Contains(it.Id)).ExecuteCommand();
                }
                //出库回传MES
                var documentNo = UniqueValueGenerator.Generate();
                var outfeedmodel = new FeedbackOutboundRequestModel
                    {
                        reqCode = Guid.NewGuid().ToString(),
                        reqTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                        business_type = outboundOrder.BusinessType,
                        factoryArea = outboundOrder.FactoryArea,
                        operationType = 1,
                        Operator = App.User.UserName,
                        orderNo = outboundOrder.UpperOrderNo,
                        documentsNO = documentNo,
                        status = outboundOrder.OrderStatus,
                        details = new List<FeedbackOutboundDetailsModel>()
                    };
                foreach (var detail in outboundOrder.Details)
                {
                    reqCode = Guid.NewGuid().ToString(),
                    reqTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                    business_type = outboundOrder.BusinessType,
                    factoryArea = outboundOrder.FactoryArea,
                    operationType = 1,
                    Operator = App.User.UserName,
                    orderNo = outboundOrder.UpperOrderNo,
                    documentsNO = documentNo,
                    status = outboundOrder.OrderStatus,
                    details = new List<FeedbackOutboundDetailsModel>()
                };
                foreach (var detail in outboundOrderDetails)
                {
                    // èŽ·å–è¯¥æ˜Žç»†å¯¹åº”çš„æ¡ç ä¿¡æ¯ï¼ˆä»Žé”å®šè®°å½•ï¼‰
                    var detailLocks = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
@@ -2863,39 +2887,58 @@
                                        (x.Status == (int)OutLockStockStatusEnum.拣选完成 || x.Status == (int)OutLockStockStatusEnum.已回库))
                        .ToListAsync();
                        var groupdata = detailLocks.GroupBy(item => new { item.MaterielCode, item.lineNo, item.BarcodeUnit, item.WarehouseCode })
                              .Select(group => new FeedbackOutboundDetailsModel
                              {
                    var groupdata = detailLocks.GroupBy(item => new { item.MaterielCode, item.lineNo, item.BarcodeUnit, item.WarehouseCode })
                          .Select(group => new FeedbackOutboundDetailsModel
                          {
                                  materialCode = group.Key.MaterielCode,
                                  lineNo = group.Key.lineNo,
                                  warehouseCode = group.Key.WarehouseCode,
                                  qty = group.Sum(x => x.PickedQty),
                                  currentDeliveryQty = group.Sum(x => x.PickedQty),
                                  unit = group.Key.BarcodeUnit,
                                  barcodes = group.Select(lockInfo => new WIDESEA_DTO.Outbound.BarcodesModel
                                  {
                                      barcode = lockInfo.CurrentBarcode,
                                      supplyCode = lockInfo.SupplyCode,
                                      batchNo = lockInfo.BatchNo,
                                      unit = lockInfo.BarcodeUnit,
                                      qty = lockInfo.PickedQty
                                  }).ToList()
                              }).ToList();
                        outfeedmodel.details.AddRange(groupdata);
                    }
                    var result = await _invokeMESService.FeedbackOutbound(outfeedmodel);
                    if (result != null && result.code == 200)
                    {
                        await _outboundOrderDetailService.Db.Updateable<Dt_OutboundOrderDetail>()
                            .SetColumns(x => x.ReturnToMESStatus == 1)
                            .Where(x => x.OrderId == outboundOrder.Id)
                            .ExecuteCommandAsync();
                              materialCode = group.Key.MaterielCode,
                              lineNo = group.Key.lineNo,
                              warehouseCode = group.Key.WarehouseCode,
                              qty = group.Sum(x => x.PickedQty),
                              currentDeliveryQty = group.Sum(x => x.PickedQty),
                              unit = group.Key.BarcodeUnit,
                              barcodes = group.Select(lockInfo => new WIDESEA_DTO.Outbound.BarcodesModel
                              {
                                  barcode = lockInfo.CurrentBarcode,
                                  supplyCode = lockInfo.SupplyCode,
                                  batchNo = lockInfo.BatchNo,
                                  unit = lockInfo.BarcodeUnit,
                                  qty = lockInfo.PickedQty
                              }).ToList()
                          }).ToList();
                    outfeedmodel.details.AddRange(groupdata);
                }
                //存储回传参数,保证异常手动回传
                Dt_InterfaceLog interfaceLog = new Dt_InterfaceLog
                {
                    OrderNo = outboundOrder.UpperOrderNo,
                    DocumentNo = documentNo,
                    OrderType = "虚拟出入库",
                    Content = outfeedmodel.ToJson(),
                    ReturnToMESStatus = 0,
                    IsDeleted = false
                };
                _interfaceLog.AddData(interfaceLog);
                var result = await _invokeMESService.FeedbackOutbound(outfeedmodel);
                if (result != null && result.code == 200)
                {
                    var orderIds = outboundOrderDetails.Select(x => x.Id).Distinct().ToList();
                    await _outboundOrderDetailService.Db.Updateable<Dt_OutboundOrderDetail>()
                        .SetColumns(x => x.ReturnToMESStatus == 1)
                        .Where(x => orderIds.Contains(x.Id))
                        .ExecuteCommandAsync();
                    await _outboundOrderService.Db.Updateable<Dt_OutboundOrder>()
                        .SetColumns(x => x.ReturnToMESStatus == 1)
                        .Where(x => x.Id == outboundOrder.Id)
                        .ExecuteCommandAsync();
                    await _interfaceLog.Db.Updateable<Dt_InterfaceLog>()
                        .SetColumns(x => x.ReturnToMESStatus == 1)
                        .Where(x=>x.DocumentNo == documentNo)
                        .ExecuteCommandAsync();
                }
                return WebResponseContent.Instance.OK();
            }
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_OutboundService/WIDESEA_OutboundService.csproj
@@ -15,6 +15,7 @@
    <ProjectReference Include="..\WIDESEA_IOutboundService\WIDESEA_IOutboundService.csproj" />
    <ProjectReference Include="..\WIDESEA_IRecordService\WIDESEA_IRecordService.csproj" />
    <ProjectReference Include="..\WIDESEA_IStockService\WIDESEA_IStockService.csproj" />
    <ProjectReference Include="..\WIDESEA_ITaskInfoService\WIDESEA_ITaskInfoService.csproj" />
  </ItemGroup>
</Project>
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_StockService/StockDetailByMaterielService.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WIDESEA_StockService
{
    internal class StockDetailByMaterielService
    {
    }
}
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_StockService/StockInfoDetailService.cs
@@ -72,6 +72,42 @@
            return new PageGridData<StockInfoDetailWithPalletDto> { Rows = dtoList, Total = lists.Total, Summary = lists.Summary  };
        }
        public PageGridData<StockDetailDtO> GetPageDataByMateriel(PageDataOptions options)
        {
            PageGridData<Dt_StockInfoDetail> lists = base.GetPageData(options);
            List<StockDetailDtO> dtoList = lists.Rows.GroupBy(detail => new { detail.MaterielCode, detail.BatchNo, detail.SupplyCode }).Select(group =>
            {
                var firstItem = group.First();
                return new StockDetailDtO
                {
                    Id = firstItem.Id,
                    StockId = firstItem.StockId,
                    MaterielCode = group.Key.MaterielCode,
                    MaterielName = firstItem.MaterielName,
                    OrderNo = firstItem.OrderNo,
                    BatchNo = group.Key.BatchNo,
                    ProductionDate = firstItem.ProductionDate,
                    EffectiveDate = firstItem.EffectiveDate,
                    SerialNumber = firstItem.SerialNumber,
                    // æ ¸å¿ƒï¼šå¯¹å½“前分组的StockQuantity求和
                    StockQuantity = group.Sum(item => item.StockQuantity),
                    OutboundQuantity = firstItem.OutboundQuantity,
                    Status = firstItem.Status,
                    Unit = firstItem.Unit,
                    InboundOrderRowNo = firstItem.InboundOrderRowNo,
                    SupplyCode = group.Key.SupplyCode,
                    WarehouseCode = firstItem.WarehouseCode,
                    Barcode = firstItem.Barcode,
                    BusinessType = firstItem.BusinessType,
                    Remark = firstItem.Remark
                };
            }).ToList();
            return new PageGridData<StockDetailDtO> { Rows = dtoList, Total = lists.Total, Summary = lists.Summary };
        }
    }
 }
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_StockService/StockViewService.cs
@@ -42,7 +42,7 @@
            //}
            int totalCount = 0;
            ISugarQueryable<Dt_StockInfo> sugarQueryable1 = _dbBase.Queryable<Dt_StockInfo>();
            ISugarQueryable<Dt_StockInfo> sugarQueryable1 = _dbBase.Queryable<Dt_StockInfo>().Includes(x=>x.Details);
            ISugarQueryable<Dt_LocationInfo> sugarQueryable = _dbBase.Queryable<Dt_LocationInfo>();
            ISugarQueryable<Dt_StockInfoDetail> sugarQueryable2 = _dbBase.Queryable<Dt_StockInfoDetail>();
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService.cs
@@ -84,6 +84,7 @@
        private readonly IRecordService _recordService;
        private readonly IAllocateService _allocateService;
        private readonly IInvokeMESService _invokeMESService;
        private readonly ITask_HtyService _task_HtyService;
        public IRepository<Dt_Task> Repository => BaseDal;
        private Dictionary<string, SqlSugar.OrderByType> _taskOrderBy = new()
@@ -103,7 +104,7 @@
        public List<int> TaskOutboundTypes => typeof(TaskTypeEnum).GetEnumIndexList();
        public TaskService(IRepository<Dt_Task> BaseDal, IMapper mapper, IUnitOfWorkManage unitOfWorkManage, IRepository<Dt_StockInfo> stockRepository, ILocationInfoService locationInfoService, IInboundOrderService inboundOrderService, ILocationStatusChangeRecordService locationStatusChangeRecordService, IESSApiService eSSApiService, ILogger<TaskService> logger, IStockService stockService, IRecordService recordService, IInboundOrderDetailService inboundOrderDetailService, IOutboundOrderService outboundOrderService, IOutboundOrderDetailService outboundOrderDetailService, IInvokeMESService invokeMESService, IOutStockLockInfoService outStockLockInfoService, IAllocateService allocateService, IRepository<Dt_OutboundBatch> outboundBatchRepository, IRepository<Dt_ReCheckOrder> reCheckOrderRepository, IRepository<Dt_AllocateOrderDetail> allocateOrderDetailRepository, IRepository<Dt_AllocateOrder> allocateOrderRepository, IMaterialUnitService materialUnitService) : base(BaseDal)
        public TaskService(IRepository<Dt_Task> BaseDal, IMapper mapper, IUnitOfWorkManage unitOfWorkManage, IRepository<Dt_StockInfo> stockRepository, ILocationInfoService locationInfoService, IInboundOrderService inboundOrderService, ILocationStatusChangeRecordService locationStatusChangeRecordService, IESSApiService eSSApiService, ILogger<TaskService> logger, IStockService stockService, IRecordService recordService, IInboundOrderDetailService inboundOrderDetailService, IOutboundOrderService outboundOrderService, IOutboundOrderDetailService outboundOrderDetailService, IInvokeMESService invokeMESService, IOutStockLockInfoService outStockLockInfoService, IAllocateService allocateService, IRepository<Dt_OutboundBatch> outboundBatchRepository, IRepository<Dt_ReCheckOrder> reCheckOrderRepository, IRepository<Dt_AllocateOrderDetail> allocateOrderDetailRepository, IRepository<Dt_AllocateOrder> allocateOrderRepository, IMaterialUnitService materialUnitService, ITask_HtyService task_HtyService) : base(BaseDal)
        {
            _mapper = mapper;
            _unitOfWorkManage = unitOfWorkManage;
@@ -126,8 +127,21 @@
            _allocateOrderDetailRepository = allocateOrderDetailRepository;
            _allocateOrderRepository = allocateOrderRepository;
            _materialUnitService = materialUnitService;
            _task_HtyService = task_HtyService;
        }
        public async Task TaskStatusChange(string taskNum,TaskStatusEnum taskStatusEnum)
        {
            if (int.TryParse(taskNum, out var newTaskNum))
            {
                await Db.Updateable<Dt_Task>().SetColumns(it => new Dt_Task {
                        TaskStatus = taskStatusEnum.ObjToInt()
                    })
                    .Where(it => it.TaskNum == newTaskNum)
                    .ExecuteCommandAsync();
            }
        }
        /// <summary>
        /// 
@@ -276,8 +290,12 @@
            task.TaskStatus = TaskStatusEnum.Finish.ObjToInt();
            BaseDal.DeleteAndMoveIntoHty(task, App.User.UserId == 0 ? OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成);
            //  BaseDal.DeleteAndMoveIntoHty(task, App.User.UserId == 0 ? OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成);
            var result = _task_HtyService.DeleteAndMoveIntoHty(task, OperateTypeEnum.人工删除);
            if (!result)
            {
                await Db.Deleteable(task).ExecuteCommandAsync();
            }
            _locationStatusChangeRecordService.AddLocationStatusChangeRecord(locationInfo, beforeStatus, StockChangeType.Inbound.ObjToInt(), "", task.TaskNum);
            _recordService.StockQuantityChangeRecordService.AddStockChangeRecord(stockInfo, stockInfo.Details, beforeQuantity, stockInfo.Details.Sum(x => x.StockQuantity) + beforeQuantity, WIDESEA_Common.StockEnum.StockChangeType.MaterielGroup);
@@ -325,8 +343,8 @@
                               }).ToList();
                            allocatefeedmodel.Details = groupedData;
                            var result = await _invokeMESService.FeedbackAllocate(allocatefeedmodel);
                            if (result != null && result.code == 200)
                            var feedbackresult = await _invokeMESService.FeedbackAllocate(allocatefeedmodel);
                            if (feedbackresult != null && feedbackresult.code == 200)
                            {
                                _inboundOrderService.Db.Updateable<Dt_InboundOrder>().SetColumns(it => new Dt_InboundOrder { ReturnToMESStatus = 1 })
                                .Where(it => it.Id == inboundOrder.Id).ExecuteCommand();
@@ -381,8 +399,8 @@
                               }).ToList();
                            allocatefeedmodel.Details = groupedData;
                            var result = await _invokeMESService.FeedbackAllocate(allocatefeedmodel);
                            if (result != null && result.code == 200)
                            var feedbackresult = await _invokeMESService.FeedbackAllocate(allocatefeedmodel);
                            if (feedbackresult != null && feedbackresult.code == 200)
                            {
                                _inboundOrderService.Db.Updateable<Dt_InboundOrder>().SetColumns(it => new Dt_InboundOrder { ReturnToMESStatus = 1 })
                                .Where(it => it.Id == inboundOrder.Id).ExecuteCommand();
@@ -429,8 +447,8 @@
                               }).ToList();
                            feedmodel.details = groupedData;
                            var result = await _invokeMESService.FeedbackInbound(feedmodel);
                            if (result != null && result.code == 200)
                            var feedbackresult = await _invokeMESService.FeedbackInbound(feedmodel);
                            if (feedbackresult != null && feedbackresult.code == 200)
                            {
                                _inboundOrderService.Db.Updateable<Dt_InboundOrder>().SetColumns(it => new Dt_InboundOrder { ReturnToMESStatus = 1 })
                                .Where(it => it.Id == inboundOrder.Id).ExecuteCommand();
@@ -536,8 +554,12 @@
                var outboundOrder = _outboundOrderService.Db.Queryable<Dt_OutboundOrder>().First(x => x.OrderNo == task.OrderNo);
                task.TaskStatus = TaskStatusEnum.Finish.ObjToInt();
                BaseDal.DeleteAndMoveIntoHty(task, App.User.UserId == 0 ? WIDESEA_Core.Enums.OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成);
                // BaseDal.DeleteAndMoveIntoHty(task, App.User.UserId == 0 ? WIDESEA_Core.Enums.OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成);
                var result = _task_HtyService.DeleteAndMoveIntoHty(task, OperateTypeEnum.人工删除);
                if (!result)
                {
                    await Db.Deleteable(task).ExecuteCommandAsync();
                }
                _locationStatusChangeRecordService.AddLocationStatusChangeRecord(locationInfo, beforelocationStatus, StockChangeType.Inbound.ObjToInt(), "", task.TaskNum);
@@ -650,9 +672,13 @@
                task.TaskStatus = TaskStatusEnum.Finish.ObjToInt();
                // åˆ é™¤ä»»åŠ¡è®°å½•
                BaseDal.DeleteAndMoveIntoHty(task, App.User.UserId == 0 ? OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成);
                BaseDal.DeleteData(task);
                //BaseDal.DeleteAndMoveIntoHty(task, App.User.UserId == 0 ? OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成);
                //BaseDal.DeleteData(task);
                var result = _task_HtyService.DeleteAndMoveIntoHty(task, OperateTypeEnum.人工删除);
                if (!result)
                {
                    await Db.Deleteable(task).ExecuteCommandAsync();
                }
                // è®°å½•货位状态变更
                _locationStatusChangeRecordService.AddLocationStatusChangeRecord(
                    locationInfo,
@@ -1105,7 +1131,7 @@
                        //不用回传
                    }
                    else
                    {
                    {
                        if (outboundOrder != null && outboundOrder.IsBatch == 0)
                        {
                            var feedmodel = new FeedbackOutboundRequestModel
@@ -1187,7 +1213,7 @@
                        }
                        else if (outboundOrder != null && outboundOrder.IsBatch == 1)
                        {
                           await  _invokeMESService.BatchOrderFeedbackToMes(new List<string>(){outboundOrder.OrderNo },2);
                            await _invokeMESService.BatchOrderFeedbackToMes(new List<string>() { outboundOrder.OrderNo }, 2);
                        }
                    }
@@ -1227,9 +1253,18 @@
                task.TaskStatus = TaskStatusEnum.Finish.ObjToInt();
                BaseDal.DeleteAndMoveIntoHty(task, App.User.UserId == 0 ? OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成);
                _stockService.StockInfoService.Repository.DeleteAndMoveIntoHty(stockInfo, App.User.UserId == 0 ? OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成);
                //_stockRepository.Db.Deleteable(stockInfo).ExecuteCommand();
                // BaseDal.DeleteAndMoveIntoHty(task, App.User.UserId == 0 ? OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成);
                var result = _task_HtyService.DeleteAndMoveIntoHty(task, OperateTypeEnum.人工删除);
                if (!result)
                {
                    await Db.Deleteable(task).ExecuteCommandAsync();
                }
                var stockresult = _stockService.StockInfoService.Repository.DeleteAndMoveIntoHty(stockInfo, App.User.UserId == 0 ? OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成);
                if (!stockresult)
                {
                    _stockRepository.Db.Deleteable(stockInfo).ExecuteCommand();
                }
                _stockService.StockInfoService.DeleteData(stockInfo);
                _locationStatusChangeRecordService.AddLocationStatusChangeRecord(locationInfo, beforeStatus, StockChangeType.Outbound.ObjToInt(), stockInfo.Details.FirstOrDefault()?.OrderNo ?? "", task.TaskNum);
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_TaskInfoService/Task_HtyService.cs
@@ -1,5 +1,10 @@
using WIDESEA_Core.BaseRepository;
using AutoMapper;
using Microsoft.Extensions.Logging;
using System.Transactions;
using WIDESEA_Core;
using WIDESEA_Core.BaseRepository;
using WIDESEA_Core.BaseServices;
using WIDESEA_Core.Enums;
using WIDESEA_ITaskInfoService;
using WIDESEA_Model.Models;
@@ -7,7 +12,58 @@
public class Task_HtyService : ServiceBase<Dt_Task_Hty, IRepository<Dt_Task_Hty>>, ITask_HtyService
{
    public Task_HtyService(IRepository<Dt_Task_Hty> BaseDal) : base(BaseDal)
    private readonly ILogger<Task_HtyService> _logger;
    private readonly IMapper _mapper; // AutoMapper实例
    public Task_HtyService(IRepository<Dt_Task_Hty> BaseDal, IMapper mapper, ILogger<Task_HtyService> logger) : base(BaseDal)
    {
        _mapper = mapper;
        _logger = logger;
    }
    public bool DeleteAndMoveIntoHty(Dt_Task task, OperateTypeEnum operateType)
    {
       // using var transaction = Db.Ado.UseTran();
        try
        {
           var historyEntity = _mapper.Map<Dt_Task_Hty>(task);
            // 2. å¡«å……历史实体核心字段
            historyEntity.SourceId = task.TaskId;
            historyEntity.OperateType =  App.User?.UserName != null ? OperateTypeEnum.自动完成.ToString() : OperateTypeEnum.人工完成.ToString();
            historyEntity.Creater = App.User?.UserName != null ? App.User.UserName : "System";
            // è¦†ç›–修改人/修改时间(优先级高于映射)
           // historyEntity.Modifier = App.User?.UserId > 0 ? App.User?.UserName : "System";
           // historyEntity.ModifyDate = DateTime.Now;
            // 3. æ’入历史表(类型安全,无反射拼接表名)
            int insertCount = Db.Insertable(historyEntity).ExecuteCommand();
            if (insertCount <= 0)
            {
                _logger.LogError($"任务历史表Dt_Task_Hty [{task.TaskNum}]插入失败,影响行数为0");
               // transaction.RollbackTran();
                return false;
            }
            // 4. åˆ é™¤åŽŸå®žä½“ï¼ˆç±»åž‹å®‰å…¨ï¼‰
            int deleteCount = Db.Deleteable(task).ExecuteCommand();
            if (deleteCount <= 0)
            {
                _logger.LogError("任务业务实体[{0}]删除失败,影响行数为0", task.TaskNum);
              //  transaction.RollbackTran();
                return false;
            }
            //transaction.CommitTran();
            _logger.LogInformation("任务实体[{0}]已成功移入历史表[{1}]并删除原数据", task.TaskNum);
            return true;
        }
        catch (Exception ex)
        {
           // transaction.RollbackTran();
            _logger.LogError(ex, "任务删除实体[{0}]并移入历史表失败", task.TaskNum);
            return false;
        }
    }
}
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/ESSController.cs
@@ -287,8 +287,7 @@
        /// </summary>
        private async Task HandleTaskSuspended(StatusCallbackRequest request)
        {
            _logger.LogWarning("任务挂起: TaskCode={TaskCode}, ç³»ç»Ÿä»»åŠ¡ç ={SysTaskCode}, åŽŸå› ={Message}",
                request.TaskCode, request.SysTaskCode, request.Message);
            _logger.LogWarning("任务挂起: TaskCode={TaskCode}, ç³»ç»Ÿä»»åŠ¡ç ={SysTaskCode}, åŽŸå› ={Message}",request.TaskCode, request.SysTaskCode, request.Message);
            // è¿™é‡Œæ·»åŠ æ‚¨çš„æŒ‚èµ·å¤„ç†é€»è¾‘
            await Task.CompletedTask;
@@ -299,8 +298,7 @@
        /// </summary>
        private async Task HandleTaskAllocated(StatusCallbackRequest request)
        {
            _logger.LogInformation("任务分配: TaskCode={TaskCode}, Robot={Robot}",
                request.TaskCode, request.RobotCode);
            _logger.LogInformation("任务分配: TaskCode={TaskCode}, Robot={Robot}",request.TaskCode, request.RobotCode);
            // è¿™é‡Œæ·»åŠ æ‚¨çš„ä»»åŠ¡åˆ†é…å¤„ç†é€»è¾‘
            await Task.CompletedTask;
@@ -313,8 +311,9 @@
        {
            if (request.Status == WIDESEA_DTO.Basic.TaskStatus.success)
            {
                _logger.LogInformation("取箱完成: Container={Container}, Location={Location}",
                    request.ContainerCode, request.LocationCode);
                _logger.LogInformation("取箱完成: Container={Container}, Location={Location}", request.ContainerCode, request.LocationCode);
                await _taskService.TaskStatusChange(request.TaskCode, WIDESEA_Common.TaskEnum.TaskStatusEnum.AGV_Pull);
            }
            else
            {
@@ -333,8 +332,8 @@
        {
            if (request.Status == WIDESEA_DTO.Basic.TaskStatus.success)
            {
                _logger.LogInformation("放箱完成: Container={Container}, Location={Location}",
                    request.ContainerCode, request.LocationCode);
                _logger.LogInformation("放箱完成: Container={Container}, Location={Location}", request.ContainerCode, request.LocationCode);
                await _taskService.TaskStatusChange(request.TaskCode, WIDESEA_Common.TaskEnum.TaskStatusEnum.AGV_Puting);
            }
            else
            {
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Inbound/InboundOrderController.cs
@@ -22,6 +22,7 @@
using WIDESEA_IInboundService;
using WIDESEA_InboundService;
using WIDESEA_IOutboundService;
using WIDESEA_ITaskInfoService;
using WIDESEA_Model.Models;
using WIDESEA_OutboundService;
@@ -45,8 +46,9 @@
        private readonly IOutStockLockInfoService _outStockLockInfoService;
        private readonly IOutboundOrderDetailService _outboundOrderDetailService;
        private readonly IRepository<Dt_Task> _taskRepository;
        private readonly ITask_HtyService _task_HtyService;
        private readonly ILogger<InboundOrderController> _logger;
        public InboundOrderController(IInboundOrderService service, WIDESEA_IBasicService.IErpApiService erpApiService, WIDESEA_IBasicService.IInvokeMESService invokeMESService, IESSApiService eSSApiService, IDailySequenceService dailySequenceService, ILocationInfoService locationInfoService, ILogger<InboundOrderController> logger, IMaterialUnitService materialUnitService, IInboundService inboundService, IOutStockLockInfoService outStockLockInfoService, IOutboundOrderDetailService outboundOrderDetailService, IRepository<Dt_Task> taskRepository) : base(service)
        public InboundOrderController(IInboundOrderService service, WIDESEA_IBasicService.IErpApiService erpApiService, WIDESEA_IBasicService.IInvokeMESService invokeMESService, IESSApiService eSSApiService, IDailySequenceService dailySequenceService, ILocationInfoService locationInfoService, ILogger<InboundOrderController> logger, IMaterialUnitService materialUnitService, IInboundService inboundService, IOutStockLockInfoService outStockLockInfoService, IOutboundOrderDetailService outboundOrderDetailService, IRepository<Dt_Task> taskRepository, ITask_HtyService task_HtyService) : base(service)
        {
            this.erpApiService = erpApiService;
            _invokeMESService = invokeMESService;
@@ -59,13 +61,22 @@
            _outStockLockInfoService = outStockLockInfoService;
            _outboundOrderDetailService = outboundOrderDetailService;
            _taskRepository = taskRepository;
            _task_HtyService = task_HtyService;
        }
        [HttpPost, Route("Test"), AllowAnonymous, MethodParamsValidate]
        public async Task<WebResponseContent> Test()
        {
            var originalTask = _taskRepository.Db.Queryable<Dt_Task>().First();
            _taskRepository.DeleteAndMoveIntoHty(originalTask, OperateTypeEnum.自动完成);
            //var originalTask = _taskRepository.Db.Queryable<Dt_Task>().First();
            //var result = _task_HtyService.DeleteAndMoveIntoHty(originalTask, OperateTypeEnum.人工删除);
            //if (result)
            //{
            //    var sddd = "trueee";
            //}
            //var originalTask = _taskRepository.Db.Queryable<Dt_Task>().First();
            //_taskRepository.DeleteAndMoveIntoHty(originalTask, OperateTypeEnum.自动完成);
            // Service.Db.Deleteable<Dt_InboundOrder>().Where(x=>x.UpperOrderNo== "12020251100040").ExecuteCommand();
            //_inboundService.InboundOrderDetailService.Db.Deleteable<Dt_InboundOrderDetail>()
            // .Where(p => SqlFunc.Subqueryable<Dt_InboundOrder>().Where(s => s.Id == p.OrderId && s.UpperOrderNo == "12020251100040").Any()).ExecuteCommand();
@@ -74,28 +85,29 @@
            //var pdddurchaseToStockResult = await _materialUnitService.ConvertFromToStockAsync("100513-00303", "W013", 1);
            //var sddd = _locationInfoService.AssignLocation();
            //var sddd = _locationInfoService.AssignLocation(1);
            //var code = sddd.LocationCode;
            //var ssss=await _dailySequenceService.GetNextSequenceAsync();
            //var  ddddssss = "WSLOT" + DateTime.Now.ToString("yyyyMMddHHmmss") + ssss.ToString().PadLeft(5, '0');
            //erpApiService.GetSuppliersAsync();
            //erpApiService.GetMaterialUnitAsync();
            //var sss=await  _invokeMESService.NewMaterielToMes(new WIDESEA_DTO.Basic.MaterielToMesDTO
            //  {
            //      reqTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
            //      reqCode = Guid.NewGuid().ToString(),
            //      oldmaterialCode = "b001",
            //      newmaterialCode = "Bar01",
            //      unit = "A01",
            //      operationType = 1,
            //      supplyCode = "A0001",
            //      batchNo = "A0002",
            //      materialCode = "FC00001",
            //      warehouseCode = "",
            //      factoryArea = "A01",
            //      qty = "20.0",
            //  });
            erpApiService.GetMaterialUnitAsync();
            var sss = await _invokeMESService.NewMaterielToMes(new WIDESEA_DTO.Basic.MaterielToMesDTO
            {
                reqTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                reqCode = Guid.NewGuid().ToString(),
                oldmaterialCode = "b001",
                newmaterialCode = "Bar01",
                unit = "A01",
                operationType = 1,
                supplyCode = "A0001",
                batchNo = "A0002",
                materialCode = "FC00001",
                warehouseCode = "",
                factoryArea = "A01",
                qty =20,
            });
            //await _eSSApiService.MoveContainerAsync(new WIDESEA_DTO.Basic.MoveContainerRequest
            //{
@@ -108,7 +120,7 @@
            //await  erpApiService.GetMaterialInfoAsync(new WIDESEA_DTO.Basic.MaterialRequest());
            return WebResponseContent.Instance.OK();
            return WebResponseContent.Instance.OK( );
        }
        /// <summary>
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Stock/StockInfoDetailController.cs
@@ -1,10 +1,12 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using WIDESEA_Core;
using WIDESEA_Core.BaseController;
using WIDESEA_DTO.Stock;
using WIDESEA_IStockService;
using WIDESEA_Model.Models;
using WIDESEA_StockService;
namespace WIDESEA_WMSServer.Controllers.Stock
{
@@ -28,5 +30,11 @@
            return Json(result);
        }
        [HttpPost, Route("GetPageDataByMateriel"),AllowAnonymous]
        public PageGridData<StockDetailDtO> GetPageDataByMateriel([FromBody] PageDataOptions options)
        {
            return Service.GetPageDataByMateriel(options);
        }
    }
}
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_WMSServer/Filter/CustomProfile.cs
@@ -7,6 +7,7 @@
using System.Threading.Tasks;
using WIDESEA_Common.OrderEnum;
using WIDESEA_Core.Helper;
using WIDESEA_Core.HttpContextUser;
using WIDESEA_DTO;
using WIDESEA_DTO.Inbound;
using WIDESEA_DTO.Outbound;
@@ -33,6 +34,10 @@
            CreateMap<Dt_ReceiveOrderDetail, Dt_CheckOrder>().ForMember(a => a.ReceivedQuantity, b => b.MapFrom(x => x.ReceivedQuantity)).ForMember(a => a.MaterielCode, b => b.MapFrom(x => x.MaterielCode)).ForMember(a => a.CheckOrderStatus, b => b.MapFrom(x => CheckOrderStatusEnum.NotCheck.ObjToInt()));
            CreateMap<Dt_Task, WMSTaskDTO>();
            CreateMap<Dt_Task, Dt_Task_Hty>()
         .ForMember(dest => dest.SourceId, opt => opt.Ignore()) // æ‰‹åŠ¨å¡«å……ï¼Œå¿½ç•¥æ˜ å°„
         .ForMember(dest => dest.OperateType, opt => opt.Ignore()); // æ‰‹åŠ¨å¡«å……ï¼Œå¿½ç•¥æ˜ å°„
        }
    }
}