z8018
2025-12-25 664df90a747e5a97b4e1131a5f958ded3176250c
Merge branch 'htq20251215' of http://115.159.85.185:8098/r/ZhongRui/ALDbanyunxiangmu into htq20251215
已添加15个文件
已修改34个文件
5270 ■■■■ 文件已修改
项目代码/WIDESEA_WMSClient/config/buttons.js 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WIDESEA_WMSClient/package-lock.json 174 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WIDESEA_WMSClient/public/static/webconfig.js 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WIDESEA_WMSClient/src/extension/inbound/extend/OrderStockTake.vue 868 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WIDESEA_WMSClient/src/extension/inbound/extend/allocateOrderDetail.vue 276 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WIDESEA_WMSClient/src/extension/inbound/takeStockOrder.js 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WIDESEA_WMSClient/src/extension/inbound/takeStockOrderDetail.js 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WIDESEA_WMSClient/src/extension/outbound/allocateoutboundOrder.js 286 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WIDESEA_WMSClient/src/extension/outbound/extend/newAllocateOrderDetail.vue 482 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WIDESEA_WMSClient/src/extension/outbound/outboundOrder.js 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WIDESEA_WMSClient/src/extension/stock/stockView.js 172 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WIDESEA_WMSClient/src/extension/taskinfo/task.js 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WIDESEA_WMSClient/src/router/viewGird.js 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WIDESEA_WMSClient/src/views/Login.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WIDESEA_WMSClient/src/views/charts/wms-dashboard.vue 725 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WIDESEA_WMSClient/src/views/inbound/takeStockOrder.vue 291 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WIDESEA_WMSClient/src/views/inbound/takeStockOrderDetail.vue 254 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WIDESEA_WMSClient/src/views/outbound/allocateoutboundOrder.vue 122 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WIDESEA_WMSClient/src/views/outbound/outboundOrder.vue 103 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WIDESEA_WMSClient/src/views/record/stockQuantityChangeRecord.vue 456 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WIDESEA_WMSClient/src/views/stock/stockInfoDetail.vue 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WIDESEA_WMSClient/src/views/taskinfo/task.vue 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WIDESEA_WMSClient/src/views/taskinfo/task_hty.vue 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/CopilotIndices/17.14.1231.31060/CodeChunks.db 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/CopilotIndices/17.14.1231.31060/CodeChunks.db-shm 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/CopilotIndices/17.14.1231.31060/CodeChunks.db-wal 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/CopilotIndices/17.14.1231.31060/SemanticSymbols.db 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/CopilotIndices/17.14.1231.31060/SemanticSymbols.db-shm 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/CopilotIndices/17.14.1231.31060/SemanticSymbols.db-wal 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_BasicService/ESSApiService.cs 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_BasicService/MESOperation/FeedbackMesService.cs 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_DTO/Inbound/CompleteStockTakeDTO.cs 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_IInboundService/ITakeStockOrderDetailService.cs 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_IInboundService/ITakeStockOrderService.cs 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_InboundService/InboundService.cs 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_InboundService/TakeStockOrderDetailService.cs 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_InboundService/TakeStockOrderService.cs 252 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_Model/Models/Inbound/Dt_TakeStockOrderDetail.cs 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundService.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_SystemService/Sys_DictionaryService.cs 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService.cs 134 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService_Outbound.cs 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Allocate/AllocateOrderController.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Inbound/TakeStockOrderController.cs 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Inbound/TakeStockOrderDetailController.cs 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/System/Sys_MenuController.cs 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_WMSServer/Jobs/InventoryLockJob.cs 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_WMSServer/Jobs/QuartzJobMildd.cs 28 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_WMSServer/Properties/PublishProfiles/FolderProfile2.pubxml 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ÏîÄ¿´úÂë/WIDESEA_WMSClient/config/buttons.js
@@ -275,7 +275,24 @@
    type: 'primary',
    onClick: function () {
    }
}
},{
    name: "选 å®š åº“ å­˜ ç›˜ ç‚¹",
    icon: '',
    class: '',
    value: 'SelectStockTake',
    type: 'warning',
    onClick: function () {
    }
},
,{
    name: "单 æ® ç›˜ ç‚¹ æ“ ä½œ",
    icon: '',
    class: '',
    value: 'OrderStockTake',
    type: 'warning',
    onClick: function () {
    }
},
]
export default buttons
ÏîÄ¿´úÂë/WIDESEA_WMSClient/package-lock.json
@@ -3612,6 +3612,11 @@
      "dev": true,
      "optional": true
    },
    "@popperjs/core": {
      "version": "npm:@sxzz/popperjs-es@2.11.7",
      "resolved": "https://registry.npmmirror.com/@sxzz/popperjs-es/-/popperjs-es-2.11.7.tgz",
      "integrity": "sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ=="
    },
    "@soda/friendly-errors-webpack-plugin": {
      "version": "1.8.0",
      "resolved": "https://registry.npm.taobao.org/@soda/friendly-errors-webpack-plugin/download/@soda/friendly-errors-webpack-plugin-1.8.0.tgz?cache=0&sync_timestamp=1607927406873&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40soda%2Ffriendly-errors-webpack-plugin%2Fdownload%2F%40soda%2Ffriendly-errors-webpack-plugin-1.8.0.tgz",
@@ -4386,87 +4391,6 @@
        "webpack-chain": "^6.4.0",
        "webpack-dev-server": "^3.11.0",
        "webpack-merge": "^4.2.2"
      },
      "dependencies": {
        "ansi-styles": {
          "version": "4.3.0",
          "resolved": "https://mirrors.huaweicloud.com/repository/npm/ansi-styles/-/ansi-styles-4.3.0.tgz",
          "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
          "dev": true,
          "optional": true,
          "requires": {
            "color-convert": "^2.0.1"
          }
        },
        "chalk": {
          "version": "4.1.2",
          "resolved": "https://mirrors.huaweicloud.com/repository/npm/chalk/-/chalk-4.1.2.tgz",
          "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
          "dev": true,
          "optional": true,
          "requires": {
            "ansi-styles": "^4.1.0",
            "supports-color": "^7.1.0"
          }
        },
        "color-convert": {
          "version": "2.0.1",
          "resolved": "https://mirrors.huaweicloud.com/repository/npm/color-convert/-/color-convert-2.0.1.tgz",
          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
          "dev": true,
          "optional": true,
          "requires": {
            "color-name": "~1.1.4"
          }
        },
        "color-name": {
          "version": "1.1.4",
          "resolved": "https://mirrors.huaweicloud.com/repository/npm/color-name/-/color-name-1.1.4.tgz",
          "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
          "dev": true,
          "optional": true
        },
        "has-flag": {
          "version": "4.0.0",
          "resolved": "https://mirrors.huaweicloud.com/repository/npm/has-flag/-/has-flag-4.0.0.tgz",
          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
          "dev": true,
          "optional": true
        },
        "loader-utils": {
          "version": "2.0.4",
          "resolved": "https://mirrors.huaweicloud.com/repository/npm/loader-utils/-/loader-utils-2.0.4.tgz",
          "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
          "dev": true,
          "optional": true,
          "requires": {
            "big.js": "^5.2.2",
            "emojis-list": "^3.0.0",
            "json5": "^2.1.2"
          }
        },
        "supports-color": {
          "version": "7.2.0",
          "resolved": "https://mirrors.huaweicloud.com/repository/npm/supports-color/-/supports-color-7.2.0.tgz",
          "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
          "dev": true,
          "optional": true,
          "requires": {
            "has-flag": "^4.0.0"
          }
        },
        "vue-loader-v16": {
          "version": "npm:vue-loader@16.8.3",
          "resolved": "https://mirrors.huaweicloud.com/repository/npm/vue-loader/-/vue-loader-16.8.3.tgz",
          "integrity": "sha512-7vKN45IxsKxe5GcVCbc2qFU5aWzyiLrYJyUuMz4BQLKctCj/fmCa0w6fGiiQ2cLFetNcek1ppGJQDCup0c1hpA==",
          "dev": true,
          "optional": true,
          "requires": {
            "chalk": "^4.1.0",
            "hash-sum": "^2.0.0",
            "loader-utils": "^2.0.0"
          }
        }
      }
    },
    "@vue/cli-shared-utils": {
@@ -7637,13 +7561,6 @@
        "lodash-unified": "^1.0.2",
        "memoize-one": "^6.0.0",
        "normalize-wheel-es": "^1.2.0"
      },
      "dependencies": {
        "@popperjs/core": {
          "version": "npm:@sxzz/popperjs-es@2.11.7",
          "resolved": "https://mirrors.huaweicloud.com/repository/npm/@sxzz/popperjs-es/-/popperjs-es-2.11.7.tgz",
          "integrity": "sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ=="
        }
      }
    },
    "element-ui": {
@@ -15471,6 +15388,87 @@
        }
      }
    },
    "vue-loader-v16": {
      "version": "npm:vue-loader@16.8.3",
      "resolved": "https://registry.npmmirror.com/vue-loader/-/vue-loader-16.8.3.tgz",
      "integrity": "sha512-7vKN45IxsKxe5GcVCbc2qFU5aWzyiLrYJyUuMz4BQLKctCj/fmCa0w6fGiiQ2cLFetNcek1ppGJQDCup0c1hpA==",
      "dev": true,
      "optional": true,
      "requires": {
        "chalk": "^4.1.0",
        "hash-sum": "^2.0.0",
        "loader-utils": "^2.0.0"
      },
      "dependencies": {
        "ansi-styles": {
          "version": "4.3.0",
          "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz",
          "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
          "dev": true,
          "optional": true,
          "requires": {
            "color-convert": "^2.0.1"
          }
        },
        "chalk": {
          "version": "4.1.2",
          "resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz",
          "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
          "dev": true,
          "optional": true,
          "requires": {
            "ansi-styles": "^4.1.0",
            "supports-color": "^7.1.0"
          }
        },
        "color-convert": {
          "version": "2.0.1",
          "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz",
          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
          "dev": true,
          "optional": true,
          "requires": {
            "color-name": "~1.1.4"
          }
        },
        "color-name": {
          "version": "1.1.4",
          "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz",
          "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
          "dev": true,
          "optional": true
        },
        "has-flag": {
          "version": "4.0.0",
          "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz",
          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
          "dev": true,
          "optional": true
        },
        "loader-utils": {
          "version": "2.0.4",
          "resolved": "https://registry.npmmirror.com/loader-utils/-/loader-utils-2.0.4.tgz",
          "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
          "dev": true,
          "optional": true,
          "requires": {
            "big.js": "^5.2.2",
            "emojis-list": "^3.0.0",
            "json5": "^2.1.2"
          }
        },
        "supports-color": {
          "version": "7.2.0",
          "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz",
          "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
          "dev": true,
          "optional": true,
          "requires": {
            "has-flag": "^4.0.0"
          }
        }
      }
    },
    "vue-qrcode": {
      "version": "2.2.2",
      "resolved": "https://registry.npmmirror.com/vue-qrcode/-/vue-qrcode-2.2.2.tgz",
ÏîÄ¿´úÂë/WIDESEA_WMSClient/public/static/webconfig.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,7 @@
window.webConfig = {
   "webApiBaseUrl": "http://localhost:9291/",
    "webApiProduction":"http://localhost:9291/"
    //  "webApiBaseUrl": "http://172.19.69.152:9291/",
    // "webApiProduction":"http://172.19.69.152:9291/"
}
ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/extension/inbound/extend/OrderStockTake.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,868 @@
<template>
  <div>
    <vol-box
      v-model="showStockTakeBox"
      :lazy="true"
      :width="isMobile ? '95%' : '70%'"
      :padding="24"
      title="库存盘点操作"
      class="custom-vol-box"
    >
      <div class="stock-take-container">
        <div class="receipt-info">
          <el-tag type="primary" size="small" class="receipt-tag">
            å½“前盘点单据号:<span class="receipt-no">{{ orderNo }}</span>
          </el-tag>
        </div>
        <!-- æ ¸å¿ƒè¾“入表单 -->
        <el-form
          :model="formData"
          ref="formRef"
          label-width="100px"
          class="stock-take-form"
          @submit.prevent
        >
          <!-- æ–™ç®±å·è¾“入框 -->
          <el-form-item
            label="料箱号:"
            name="boxNo"
            :rules="[
              {
                required: true,
                message: '请扫描或输入料箱号',
                trigger: 'blur',
              },
              { validator: validateBoxNo, trigger: 'blur' },
            ]"
            class="form-item"
          >
            <el-input
              ref="boxNoInputRef"
              v-model="formData.boxNo"
              placeholder="请使用扫码枪扫描料箱号,或手动输入"
              clearable
              @keydown.enter="debouncedHandleBoxNoScan"
              @blur="handleBoxNoBlur"
              :disabled="loading"
              class="custom-input"
              :class="{ 'has-value': formData.boxNo.trim() }"
            >
              <template #append>
                <el-button
                  icon="Search"
                  type="primary"
                  size="small"
                  @click="handleBoxNoScan"
                  :disabled="!formData.boxNo.trim() || loading"
                  class="input-btn"
                ></el-button>
              </template>
            </el-input>
          </el-form-item>
          <!-- æ¡ç è¾“入框 -->
          <el-form-item
            label="盘点条码:"
            name="barcode"
            :rules="[
              { required: true, message: '请扫描或输入条码', trigger: 'blur' },
              { validator: validateBarcode, trigger: 'blur' },
            ]"
            class="form-item"
          >
            <el-input
              ref="barcodeInputRef"
              v-model="formData.barcode"
              placeholder="请使用扫码枪扫描条码,或手动输入"
              clearable
              @keydown.enter="debouncedHandleBarcodeScan"
              :disabled="!formData.boxNo.trim() || loading"
              class="custom-input"
              :class="{ 'has-value': formData.barcode.trim() }"
            >
              <template #append>
                <el-button
                  icon="Search"
                  type="primary"
                  size="small"
                  @click="handleBarcodeScan"
                  :disabled="
                    !formData.boxNo.trim() ||
                    !formData.barcode.trim() ||
                    loading
                  "
                  class="input-btn"
                ></el-button>
              </template>
            </el-input>
          </el-form-item>
          <!-- åº“存数量框(只读) -->
          <el-form-item
            label="库存数量:"
            name="stockQuantity"
            class="form-item"
          >
            <el-input
              v-model="formData.stockQuantity"
              placeholder="扫描条码后自动填充"
              readonly
              class="custom-input custom-readonly-input"
              :class="{ 'has-value': formData.stockQuantity }"
            ></el-input>
          </el-form-item>
          <!-- å®žé™…盘点数量 -->
          <el-form-item
            label="实际盘点数量:"
            name="actualQuantity"
            :rules="[
              {
                required: true,
                message: '请输入实际盘点数量',
                trigger: 'blur',
              },
              { type: 'number', message: '请输入有效的数字', trigger: 'blur' },
              { validator: validateActualQuantity, trigger: 'blur' },
            ]"
            class="form-item"
          >
            <el-input
              v-model.number="formData.actualQuantity"
              placeholder="请输入实际盘点数量(大于0)"
              type="number"
              clearable
              @keydown.enter="handleStockTakeComplete"
              :disabled="!formData.stockQuantity || loading"
              class="custom-input"
              :class="{ 'has-value': formData.actualQuantity }"
            ></el-input>
          </el-form-item>
        </el-form>
        <!-- æ“ä½œæŒ‰é’®åŒºåŸŸ -->
        <div class="action-buttons">
          <el-button
            type="info"
            size="small"
            @click="handleBoxReturn"
            :disabled="!formData.boxNo.trim() || loading"
            class="return-btn"
          >
            <Return /> æ–™ç®±å›žåº“
          </el-button>
          <el-button
            type="primary"
            size="small"
            @click="handleStockTakeComplete"
            :disabled="
              loading ||
              !formData.boxNo.trim() ||
              !formData.barcode.trim() ||
              !formData.stockQuantity ||
              !formData.actualQuantity
            "
            class="complete-btn"
          >
            <Check /> ç›˜ç‚¹å®Œæˆ
          </el-button>
          <el-button
            type="text"
            size="small"
            @click="handleCancel"
            :disabled="loading"
            class="cancel-btn"
          >
            å–消
          </el-button>
        </div>
      </div>
    </vol-box>
  </div>
</template>
<script setup>
import { ref, reactive, onMounted, nextTick, watch, defineEmits, computed } from "vue";
import { ElMessage, ElTag, ElMessageBox } from "element-plus";
import { Search, Check, Return } from "@element-plus/icons-vue";
import VolBox from "@/components/basic/VolBox.vue";
import http from "@/api/http";
// å“åº”式变量 - å•据号
const orderNo = ref("");
// æš´éœ²äº‹ä»¶
const emit = defineEmits(["close", "refresh", "box-returned"]);
// å“åº”式数据
const showStockTakeBox = ref(false);
const formData = reactive({
  boxNo: "", // æ–™ç®±å·
  barcode: "", // ç›˜ç‚¹æ¡ç 
  stockQuantity: "", // åº“存数量(只读)
  actualQuantity: "", // å®žé™…盘点数量
});
const loading = ref(false);
const formRef = ref(null);
// æ¨¡æ¿å¼•用
const boxNoInputRef = ref(null);
const barcodeInputRef = ref(null);
// æ£€æµ‹æ˜¯å¦ä¸ºç§»åŠ¨ç«¯
const isMobile = computed(() => {
  return window.innerWidth < 768;
});
// ç»„件挂载时聚焦到料箱号输入框
onMounted(() => {
  nextTick(() => {
    boxNoInputRef.value?.focus();
  });
  // ç›‘听窗口大小变化
  window.addEventListener("resize", () => {});
});
// ç›‘听料箱号变化,清空后续相关字段
watch(
  () => formData.boxNo,
  (newVal) => {
    if (!newVal.trim()) {
      formData.barcode = "";
      formData.stockQuantity = "";
      formData.actualQuantity = "";
    }
  },
  { immediate: true }
);
// é˜²æŠ–函数
const debounce = (fn, delay = 100) => {
  let timer = null;
  return (...args) => {
    if (timer) clearTimeout(timer);
    timer = setTimeout(() => {
      fn.apply(this, args);
    }, delay);
  };
};
// æ‰“开弹窗并接收单据号
const open = (receiptNo) => {
  showStockTakeBox.value = true;
  orderNo.value = receiptNo;
  // é‡ç½®è¡¨å•
  formData.boxNo = "";
  formData.barcode = "";
  formData.stockQuantity = "";
  formData.actualQuantity = "";
  nextTick(() => {
    boxNoInputRef.value?.focus();
  });
};
// å…³é—­å¼¹çª—
const handleCancel = (e) => {
  e.stopPropagation();
  e.preventDefault();
  showStockTakeBox.value = false;
  emit("close");
  orderNo.value = "";
};
// æ–™ç®±å·éªŒè¯ï¼ˆä¼˜åŒ–:有值时仅验证长度,无值时触发必填)
const validateBoxNo = (rule, value, callback) => {
  // æœ‰å€¼æ—¶éªŒè¯é•¿åº¦
  if (value && value.trim().length < 3) {
    callback(new Error("料箱号长度不能少于3位"));
  }
  // æ— å€¼æ—¶ç”±required规则处理,这里不重复提示
  else {
    callback();
  }
};
// æ¡ç éªŒè¯ï¼ˆä¼˜åŒ–:有值时仅验证长度)
const validateBarcode = (rule, value, callback) => {
  if (value && value.trim().length < 6) {
    callback(new Error("条码长度不能少于6位"));
  } else {
    callback();
  }
};
// å®žé™…盘点数量验证(优化:有值时验证合法性)
const validateActualQuantity = (rule, value, callback) => {
  if (value === null || value === undefined) {
    callback(new Error("请输入实际盘点数量"));
  } else if (value <= 0) {
    callback(new Error("实际盘点数量必须大于0"));
  } else if (!Number.isInteger(value)) {
    callback(new Error("实际盘点数量必须是整数"));
  } else {
    callback();
  }
};
// æ–™ç®±å·å¤±ç„¦å¤„理
const handleBoxNoBlur = () => {
  if (formData.boxNo.trim() && boxNoInputRef.value?.input) {
    boxNoInputRef.value.input.select();
  }
};
// æ–™ç®±å·æ‰«æéªŒè¯ï¼ˆåŽç«¯æŽ¥å£ï¼‰
const validateBoxNoApi = async (boxNo) => {
  try {
    const res = await http.post(
      `/api/TakeStockOrder/ValidateBoxNo?orderNo=${encodeURIComponent(
        orderNo.value
      )}&boxNo=${encodeURIComponent(boxNo)}`,
      "验证料箱号中..."
    );
    if (!res.status) {
      throw new Error(res.message || "料箱号验证失败");
    }
    return res.data;
  } catch (error) {
    throw error;
  }
};
// æ–™ç®±å·æ‰«æå¤„理
const handleBoxNoScan = async () => {
  if (!formRef.value) return;
  // æ‰‹åŠ¨è§¦å‘éªŒè¯ï¼ˆä»…éªŒè¯å½“å‰å­—æ®µï¼‰
  const valid = await formRef.value.validateField("boxNo");
  if (valid !== true) return;
  const boxNo = formData.boxNo.trim();
  if (!boxNo) return;
  try {
    loading.value = true;
    await validateBoxNoApi(boxNo);
    ElMessage.success(`料箱号 ${boxNo} éªŒè¯é€šè¿‡`);
    nextTick(() => {
      barcodeInputRef.value?.focus();
    });
  } catch (error) {
    ElMessage.error(error.message);
    nextTick(() => {
      if (boxNoInputRef.value?.input) {
        boxNoInputRef.value.input.select();
      }
    });
  } finally {
    loading.value = false;
  }
};
// æ¡ç æ‰«æéªŒè¯ï¼ˆåŽç«¯æŽ¥å£ï¼‰
const validateBarcodeApi = async (boxNo, barcode) => {
  try {
    const res = await http.post(
      `/api/TakeStockOrder/ValidateBarcode?boxNo=${encodeURIComponent(
        boxNo
      )}&barcode=${encodeURIComponent(barcode)}`,
      "验证条码中..."
    );
    if (!res.status) {
      throw new Error(res.message || "条码验证失败");
    }
    if (
      res.data?.stockQuantity === undefined ||
      res.data?.stockQuantity === null
    ) {
      throw new Error("未查询到该条码的库存数量");
    }
    return res.data;
  } catch (error) {
    throw error;
  }
};
// æ¡ç æ‰«æå¤„理
const handleBarcodeScan = async () => {
  if (!formRef.value) return;
  const valid = await formRef.value.validateField("barcode");
  if (valid !== true) return;
  const boxNo = formData.boxNo.trim();
  const barcode = formData.barcode.trim();
  if (!boxNo || !barcode) return;
  try {
    loading.value = true;
    const result = await validateBarcodeApi(boxNo, barcode);
    formData.stockQuantity = result.stockQuantity;
    ElMessage.success(
      `条码 ${barcode} éªŒè¯é€šè¿‡ï¼Œåº“存数量:${result.stockQuantity}`
    );
    nextTick(() => {
      const actualQuantityInput = document.querySelector(
        ".form-item:last-child .el-input__inner"
      );
      actualQuantityInput?.focus();
    });
  } catch (error) {
    ElMessage.error(error.message);
    nextTick(() => {
      if (barcodeInputRef.value?.input) {
        barcodeInputRef.value.input.select();
      }
    });
  } finally {
    loading.value = false;
  }
};
// ç›˜ç‚¹å®Œæˆæäº¤
const handleStockTakeComplete = async () => {
  if (!formRef.value) return;
  // å…¨è¡¨å•验证
  const valid = await formRef.value.validate();
  if (!valid) return;
  const { boxNo, barcode, actualQuantity, stockQuantity } = formData;
  const receiptNo = orderNo.value;
  try {
    loading.value = true;
    const res = await http.post(
      "/api/TakeStockOrder/CompleteStockTake",
      {
        orderNo: receiptNo,
        boxNo,
        barcode,
        actualQuantity,
        stockQuantity,
      },
      {
        loadingText: "提交盘点数据中...",
      }
    );
    if (res.status) {
      ElMessage.success("盘点完成,提交成功!");
      formData.barcode = "";
      formData.stockQuantity = "";
      formData.actualQuantity = "";
      nextTick(() => {
        barcodeInputRef.value?.focus();
      });
      emit("refresh");
    } else {
      throw new Error(res.message || "盘点提交失败");
    }
  } catch (error) {
    ElMessage.error(error.message || "网络异常,提交失败");
  } finally {
    loading.value = false;
  }
};
// æ–™ç®±å›žåº“功能
const handleBoxReturn = async () => {
  const boxNo = formData.boxNo.trim();
  if (!boxNo) {
    ElMessage.warning("请先输入或扫描料箱号");
    return;
  }
  try {
    await ElMessageBox.confirm(`确定将料箱【${boxNo}】回库吗?`, "回库确认", {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
      type: "info",
      center: true,
      confirmButtonClass: "el-button--primary",
      cancelButtonClass: "el-button--text",
    });
    loading.value = true;
    const res = await http.post(
      `/api/TakeStockOrder/ReturnBox?boxNo=${encodeURIComponent(boxNo)}&orderNo=${encodeURIComponent(
        orderNo.value
      )}`,
      "料箱回库中..."
    );
    if (res.status) {
      ElMessage.success(`料箱【${boxNo}】回库成功!`);
      formData.boxNo = "";
      formData.barcode = "";
      formData.stockQuantity = "";
      formData.actualQuantity = "";
      nextTick(() => {
        boxNoInputRef.value?.focus();
      });
      emit("box-returned", boxNo);
    } else {
      throw new Error(res.message || "料箱回库失败");
    }
  } catch (error) {
    if (error.name !== "Cancel") {
      ElMessage.error(error.message);
    }
  } finally {
    loading.value = false;
  }
};
// å¸¦é˜²æŠ–的扫描处理
const debouncedHandleBoxNoScan = debounce(async (e) => {
  e.stopPropagation();
  e.preventDefault();
  await handleBoxNoScan();
}, 100);
const debouncedHandleBarcodeScan = debounce(async (e) => {
  e.stopPropagation();
  e.preventDefault();
  await handleBarcodeScan();
}, 100);
// æš´éœ²æ–¹æ³•
defineExpose({
  open,
});
</script>
<style scoped>
/* ä¸»å®¹å™¨æ ·å¼ - ä¼˜åŒ–间距和响应式 */
.stock-take-container {
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding: 8px 0;
}
/* å•据信息样式 - ä¼˜åŒ–视觉层级 */
.receipt-info {
  margin-bottom: 4px;
}
.receipt-tag {
  padding: 8px 16px;
  font-size: 14px;
  background-color: #e8f4f8 !important;
  border-color: #409eff !important;
  color: #1989fa !important;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(64, 158, 255, 0.1);
}
.receipt-no {
  font-weight: 600;
  color: #1989fa;
  margin-left: 6px;
}
/* è¡¨å•样式 - ä¼˜åŒ–阴影和内边距 */
.stock-take-form {
  width: 100%;
  background-color: #ffffff;
  padding: 20px;
  border-radius: 12px;
  box-shadow: 0 2px 12px rgba(64, 158, 255, 0.06);
  border: 1px solid #f0f8fb;
}
.form-item {
  margin-bottom: 16px;
}
/* è¾“入框核心样式 - ä¼˜åŒ–状态显示 */
.custom-input {
  width: 100%;
  position: relative;
}
/* æœ‰å€¼æ—¶éšè—å ä½ç¬¦ + ä¼˜åŒ–边框 */
.custom-input.has-value :deep(.el-input__inner) {
  --el-input-placeholder-color: transparent; /* éšè—å ä½ç¬¦ */
  border-color: #8cc5ff; /* æµ…蓝边框,区分无值状态 */
  background-color: #ffffff;
}
.custom-input :deep(.el-input__inner) {
  border-radius: 8px;
  border-color: #e5f0fa;
  transition: all 0.2s ease;
  height: 42px;
  line-height: 42px;
  font-size: 14px;
  background-color: #f8fbff;
  padding: 0 12px;
}
/* èšç„¦æ ·å¼ä¼˜åŒ– */
.custom-input :deep(.el-input__inner:focus) {
  border-color: #409eff;
  box-shadow: 0 0 0 3px rgba(64, 158, 255, 0.1);
  background-color: #ffffff;
  outline: none;
}
/* æ¸…除按钮样式优化 */
.custom-input :deep(.el-input__clear) {
  color: #91c9f7;
  width: 18px;
  height: 18px;
}
.custom-input :deep(.el-input__clear:hover) {
  color: #409eff;
}
/* åªè¯»è¾“入框样式 - å¢žå¼ºåŒºåˆ†åº¦ */
.custom-readonly-input :deep(.el-input__inner) {
  background-color: #f0f8fb;
  color: #1989fa;
  font-weight: 500;
  cursor: default;
  border-color: #d1e7fd;
  padding-right: 12px;
}
/* è¾“入框按钮样式 - ä¼˜åŒ–尺寸和hover效果 */
.input-btn {
  border-radius: 0 8px 8px 0 !important;
  height: 42px;
  width: 48px;
  background-color: #409eff;
  border-color: #409eff;
  transition: all 0.2s ease;
}
.input-btn:hover {
  background-color: #1989fa !important;
  border-color: #1989fa !important;
  box-shadow: 0 2px 8px rgba(64, 158, 255, 0.2);
  transform: translateY(-1px);
}
/* è¡¨å•验证错误样式 - å…³é”®ï¼šæœ‰å€¼æ—¶ä¸æ˜¾ç¤ºé”™è¯¯è¾¹æ¡† */
.form-item :deep(.el-form-item__error) {
  font-size: 12px;
  color: #f56c6c;
  margin-top: 4px;
  /* ä»…在输入框为空且验证失败时显示 */
  display: none;
}
/* åªæœ‰è¾“入框为空 + éªŒè¯å¤±è´¥æ—¶æ˜¾ç¤ºé”™è¯¯æç¤º */
.form-item:deep(.el-form-item--error) .custom-input:not(.has-value) + .el-form-item__error {
  display: block;
}
/* æœ‰å€¼æ—¶å³ä½¿éªŒè¯å¤±è´¥ï¼Œä¹Ÿä¸æ˜¾ç¤ºé”™è¯¯è¾¹æ¡† */
.custom-input.has-value :deep(.el-input__inner.el-input__inner--error) {
  border-color: #8cc5ff;
  box-shadow: none;
}
/* æ“ä½œæŒ‰é’®åŒºåŸŸ - ä¼˜åŒ–间距和响应式 */
.action-buttons {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 20px;
  flex-wrap: wrap;
}
/* å›žåº“按钮样式 - ä¼˜åŒ–交互 */
.return-btn {
  border-radius: 8px;
  padding: 9px 20px;
  font-size: 14px;
  font-weight: 500;
  background-color: #e8f4f8;
  border-color: #409eff;
  color: #1989fa;
  transition: all 0.2s ease;
}
.return-btn:hover {
  background-color: #d1e7fd !important;
  border-color: #1989fa !important;
  color: #1989fa !important;
  transform: translateY(-1px);
  box-shadow: 0 2px 8px rgba(64, 158, 255, 0.15);
}
.return-btn:disabled {
  background-color: #f0f8fb !important;
  border-color: #b3d8ff !important;
  color: #91c9f7 !important;
  cursor: not-allowed;
  transform: none;
  box-shadow: none;
}
/* ç›˜ç‚¹å®ŒæˆæŒ‰é’®æ ·å¼ - ä¼˜åŒ–交互 */
.complete-btn {
  border-radius: 8px;
  padding: 9px 20px;
  font-size: 14px;
  font-weight: 500;
  background-color: #409eff;
  border-color: #409eff;
  transition: all 0.2s ease;
}
.complete-btn:hover {
  background-color: #1989fa !important;
  border-color: #1989fa !important;
  transform: translateY(-1px);
  box-shadow: 0 2px 8px rgba(64, 158, 255, 0.2);
}
.complete-btn:disabled {
  background-color: #a0cfff !important;
  border-color: #a0cfff !important;
  color: #ffffff !important;
  cursor: not-allowed;
  transform: none;
  box-shadow: none;
}
/* å–消按钮样式 - ä¼˜åŒ–点击区域 */
.cancel-btn {
  color: #666666;
  font-size: 14px;
  transition: all 0.2s ease;
  padding: 9px 20px;
  border-radius: 8px;
  min-width: 80px;
}
.cancel-btn:hover {
  color: #1989fa !important;
  background-color: #f0f8fb !important;
}
/* å¼¹çª—整体样式 - ä¼˜åŒ–圆角和阴影 */
.custom-vol-box {
  border-radius: 16px !important;
  overflow: hidden;
  box-shadow: 0 8px 24px rgba(64, 158, 255, 0.12);
}
.custom-vol-box :deep(.el-dialog__header) {
  background-color: #e8f4f8;
  border-bottom: 1px solid #d1e7fd;
  padding: 16px 24px;
}
.custom-vol-box :deep(.el-dialog__title) {
  color: #1989fa;
  font-size: 18px;
  font-weight: 600;
}
.custom-vol-box :deep(.el-dialog__body) {
  padding: 16px 24px;
}
/* å“åº”式适配 - å°å±å¹•优化 */
@media (max-width: 768px) {
  .stock-take-form {
    padding: 16px;
  }
  .form-item {
    margin-bottom: 12px;
  }
  .action-buttons {
    justify-content: center;
  }
  .custom-vol-box :deep(.el-dialog__header) {
    padding: 12px 16px;
  }
  .custom-vol-box :deep(.el-dialog__body) {
    padding: 12px 16px;
  }
}
</style>
<style>
/* å…¨å±€è¡¥å……样式 - ç»Ÿä¸€ä¸»é¢˜ */
.el-tag--primary {
  --el-tag-bg-color: #e8f4f8;
  --el-tag-border-color: #409eff;
  --el-tag-text-color: #1989fa;
}
/* å ä½ç¬¦æ ·å¼ - ç»Ÿä¸€é¢œè‰² */
.el-input__inner::-webkit-input-placeholder {
  color: #b3d8ff;
  font-size: 13px;
}
.el-input__inner::-moz-placeholder {
  color: #b3d8ff;
  font-size: 13px;
}
.el-input__inner:-ms-input-placeholder {
  color: #b3d8ff;
  font-size: 13px;
}
.el-input__inner::placeholder {
  color: #b3d8ff;
  font-size: 13px;
}
/* ä¿¡æ¯æŒ‰é’®å…¨å±€æ ·å¼ */
.el-button--info {
  --el-button-bg-color: #e8f4f8;
  --el-button-border-color: #409eff;
  --el-button-text-color: #1989fa;
  --el-button-hover-bg-color: #d1e7fd;
  --el-button-hover-border-color: #1989fa;
  --el-button-hover-text-color: #1989fa;
}
/* ç¡®è®¤å¼¹çª—样式优化 */
.el-message-box {
  border-radius: 12px !important;
  box-shadow: 0 4px 20px rgba(64, 158, 255, 0.15);
}
.el-message-box__header {
  border-bottom: 1px solid #f0f8fb;
  padding: 12px 20px;
}
.el-message-box__title {
  color: #1989fa;
  font-size: 16px;
  font-weight: 600;
}
.el-message-box__content {
  color: #666666;
  font-size: 14px;
  padding: 16px 20px;
}
.el-message-box__btns {
  padding: 12px 20px;
  border-top: 1px solid #f0f8fb;
}
</style>
ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/extension/inbound/extend/allocateOrderDetail.vue
@@ -315,149 +315,149 @@
      });
    },
    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);
      // 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);
      const formData = reactive({
        selectedPlatform: platformOptions[0].value,
      });
      // const formData = reactive({
      //   selectedPlatform: platformOptions[0].value,
      // });
      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;
                      }
      // 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;
      //                 }
                      const keys = this.selection.map((item) => item.id);
                      const requestParams = {
                        detailIds: keys,
                        outboundTargetLocation: formData.selectedPlatform,
                        outboundQuantity: 1,
                        operator: "",
                        orderNo: this.row.orderNo,
                      };
      //                 const keys = this.selection.map((item) => item.id);
      //                 const requestParams = {
      //                   detailIds: keys,
      //                   outboundTargetLocation: formData.selectedPlatform,
      //                   outboundQuantity: 1,
      //                   operator: "",
      //                   orderNo: this.row.orderNo,
      //                 };
                      this.http
                        .post(
                          "api/Outbound/ProcessPickingOutbound",
                          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",
                    },
                  }, "确定出库"),
                ]),
              ]),
        }
      );
      //                 this.http
      //                   .post(
      //                     "api/Outbound/ProcessPickingOutbound",
      //                     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",
      //               },
      //             }, "确定出库"),
      //           ]),
      //         ]),
      //   }
      // );
      vnode.appContext = this.$.appContext;
      render(vnode, mountNode);
      // vnode.appContext = this.$.appContext;
      // render(vnode, mountNode);
    },
    outboundbatch() {
      if (this.selection.length === 0) {
ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/extension/inbound/takeStockOrder.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,83 @@
// è‡ªå®šä¹‰æ‰©å±•业务代码
import gridBody from "./extend/OrderStockTake.vue";
let extension = {
  components: {
    // æŸ¥è¯¢ç•Œé¢æ‰©å±•组件:将自定义弹窗注册为 gridBody ç»„ä»¶
    gridHeader: '',
    gridBody: gridBody, // å¯¹åº”你的盘点弹窗组件
    gridFooter: '',
    // æ–°å»º/编辑弹出框扩展组件(此处不用,留空)
    modelHeader: '',
    modelBody: '',
    modelFooter: ''
  },
  tableAction: '', // æ— éœ€æŒ‡å®šè¡¨åï¼ˆé»˜è®¤é€‚用当前页面表格)
  buttons: { view: [], box: [], detail: [] }, // æ‰©å±•按钮(如需额外添加可在此配置)
  methods: {
    onInit() {
      // æ‰¾åˆ° value ä¸º "OrderStockTake" çš„æŒ‰é’®ï¼ˆéœ€åœ¨æ¡†æž¶ä¸­æå‰é…ç½®è¯¥æŒ‰é’®ï¼‰
      let OrderStockTakeBtn = this.buttons.find(x => x.value === 'OrderStockTake');
      if (OrderStockTakeBtn) {
        // é‡å†™æŒ‰é’®ç‚¹å‡»äº‹ä»¶
        OrderStockTakeBtn.onClick = function () {
          // 1. èŽ·å–è¡¨æ ¼é€‰ä¸­è¡Œæ•°æ®
          let rows = this.$refs.table.getSelected();
          if (rows.length === 0) return this.$error("请选择一条盘点单据数据!");
          if (rows.length > 1) return this.$error("只能选择一条盘点单据数据!");
          const selectedReceiptNo = rows[0].orderNo;
          if (!selectedReceiptNo) return this.$error("选中的单据缺少有效的单据号!");
          // 3. è°ƒç”¨è‡ªå®šä¹‰å¼¹çª—çš„ open æ–¹æ³•,并传递单据号(核心:给弹窗传参)
          this.$refs.gridBody.open(selectedReceiptNo);
        };
      }
      // 4. ç›‘听自定义弹窗的事件(同步主页面数据)
      this.$nextTick(() => {
        const stockTakeComp = this.$refs.gridBody;
        if (stockTakeComp) {
          // ç›‘听弹窗的 "refresh" äº‹ä»¶ï¼ˆç›˜ç‚¹å®ŒæˆåŽåˆ·æ–°ä¸»é¡µé¢ï¼‰
          stockTakeComp.$on('refresh', () => {
            this.$refs.table.reload(); // åˆ·æ–°è¡¨æ ¼æ•°æ®
          });
          // ç›‘听弹窗的 "box-returned" äº‹ä»¶ï¼ˆæ–™ç®±å›žåº“后可按需处理)
          stockTakeComp.$on('box-returned', (boxNo) => {
            this.$success(`料箱【${boxNo}】回库成功,表格将刷新!`);
            this.$refs.table.reload(); // å›žåº“后也刷新表格(可选,根据业务需求)
          });
        }
      });
    },
    onInited() {
      // æ¡†æž¶åˆå§‹åŒ–完成后执行(如需配置明细表可在此操作)
    },
    searchBefore(param) {
      // æŸ¥è¯¢å‰æ‹¦æˆªï¼šå¯æ·»åŠ é¢å¤–æŸ¥è¯¢æ¡ä»¶ï¼ˆå¦‚æƒé™è¿‡æ»¤ï¼‰
      return true;
    },
    searchAfter(result) {
      // æŸ¥è¯¢åŽæ•°æ®å¤„理(如格式化日期、状态显示)
      return true;
    },
    addBefore(formData) {
      // æ–°å»ºä¿å­˜å‰å¤„理(此处不用)
      return true;
    },
    updateBefore(formData) {
      // ç¼–辑保存前处理(此处不用)
      return true;
    },
    rowClick({ row, column, event }) {
      // å•击行选中当前行(优化用户体验)
      this.$refs.table.$refs.table.toggleRowSelection(row);
    },
    modelOpenAfter(row) {
      // æ–°å»º/编辑弹窗打开后处理(此处不用)
    }
  }
};
export default extension;
ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/extension/inbound/takeStockOrderDetail.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,58 @@
//此js文件是用来自定义扩展业务代码,可以扩展一些自定义页面或者重新配置生成的代码
let extension = {
    components: {
      //查询界面扩展组件
      gridHeader: '',
      gridBody: '',
      gridFooter: '',
      //新建、编辑弹出框扩展组件
      modelHeader: '',
      modelBody: '',
      modelFooter: ''
    },
    tableAction: '', //指定某张表的权限(这里填写表名,默认不用填写)
    buttons: { view: [], box: [], detail: [] }, //扩展的按钮
    methods: {
       //下面这些方法可以保留也可以删除
      onInit() {
      },
      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/extension/outbound/allocateoutboundOrder.js
@@ -1,9 +1,5 @@
//此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';
import gridBody from './extend/newAllocateOrderDetail.vue'
let extension = {
    components: {
@@ -17,287 +13,7 @@
      modelFooter: ''
    },
    tableAction: '', //指定某张表的权限(这里填写表名,默认不用填写)
    buttons: { view: [
       /* {
        name: '出库',
        type: 'primary',
        value: '出库',
        onClick: function () { // ä¿®å¤ï¼šç”¨ElMessage替代this.$message
          const selectedRows = this.$refs.table.getSelected();
          if (selectedRows.length === 0) {
            ElMessage.warning('请先选择要生成任务的行');
            return;
          }
          if (selectedRows.length > 1) {
            ElMessage.warning('只能选择一行');
            return;
          }
          // æ‰€æœ‰æ ¡éªŒé€šè¿‡ï¼Œè§¦å‘主组件打开出库弹窗
          console.log('所有校验通过,触发openOutboundDialog事件,单据数据:', selectedRows[0]);
          this.$emit('openOutboundDialog', {
            transNo: selectedRows[0].transNo,       // å‡ºåº“单编号
            createDate: selectedRows[0].createDate || new Date().toLocaleDateString()  // å‡ºåº“日期
          });
        }
      }, */
      {
  name: '空托盘出库',
  type: 'primary',
  value: '空托盘出库',
  onClick: function () {
    const platformOptions = Array.from({ length: 1 }, (_, i) => {
      const num = 1;
      return { label: `站台${num}`, value: `1-2` };
    });
    const quantityOptions = Array.from({ length: 6 }, (_, i) => ({
      label: (i + 1).toString(),
      value: i + 1
    }));
    const warehouseOptions = 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格式
          warehouseOptions.value = data.map(item => ({
            label: item.locationTypeDesc,
            value: item.locationType
          }));
        } else {
          ElMessage.error('获取区域列表失败');
          warehouseOptions.value = [];
        }
      } catch (err) {
        ElMessage.error('区域数据请求异常,请稍后重试');
        warehouseOptions.value = [];
      } finally {
        isLoadingWarehouses.value = false;
      }
    };
    const mountNode = document.createElement('div');
    document.body.appendChild(mountNode);
    const formData = reactive({
      warehouseCode:'',
      palletCode: '',
      selectedPlatform: platformOptions[0].value,
      quantity:1
    });
    const vnode = createVNode(ElDialog, {
      title: '空托盘出库',
      width: '500px',
      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);
        }
      },
      style: {
        padding: '20px 0',
        borderRadius: '8px'
      }
    }, {
      default: () => h(ElForm, {
        model: formData,
        rules: {
          warehouseCode:[
            { required: true, message: '请选择区域', trigger: ['change', 'blur'] }
          ],
          palletCode: [
            { type: 'string', message: '料箱号必须为字符串', trigger: 'blur' }
          ],
          selectedPlatform: [
            { required: true, message: '请选择出库站台', trigger: 'change' }
          ],
          quantity:[
            { required: true, message: '请选择空箱数量', trigger: 'change'}
          ]
        },
        ref: 'batchOutForm',
        labelWidth: '100px',
        style: {
          padding: '0 30px',
        }
       },
       [
      //   h(ElFormItem, {
      //     label: '仓库区域',
      //     prop: 'warehouseCode',
      //     style: {
      //       marginBottom: '24px'
      //     }
      //   }, [
      //     h(ElSelect, {
      //       placeholder: '请选择仓库区域',
      //       modelValue: formData.warehouseCode,
      //       'onUpdate:modelValue': (val) => {
      //         formData.warehouseCode = val;
      //       },
      //       style: {
      //         width: '100%',
      //         height: '40px',
      //         borderRadius: '4px',
      //         borderColor: '#dcdfe6'
      //       }
      //     }, warehouseOptions.value.map(platform =>
      //       h(ElOption, { label: platform.label, value: platform.value })
      //     ))
      //   ]),
        h(ElFormItem, {
          label: '出库站台',
          prop: 'selectedPlatform',
          style: {
            marginBottom: '24px'
          }
        }, [
          h(ElSelect, {
            placeholder: '请选择出库站台',
            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:'quantity',
      //     style:{
      //       marginBottom:'24px'
      //     }
      //   },[h(ElSelect,{
      //     placeholder:'请选择空箱数量',
      //     modelValue:formData.quantity,
      //     'onUpdate:modelValue':(val)=>{
      //       formData.quantity=val;
      //     },
      //     style:{
      //       width:'100%',
      //       height:'40px',
      //       borderRadius:'4px',
      //       borderColor:'#dcdfe6'
      //     },
      //     filterable:false
      //   },
      //   quantityOptions.map(option=>
      //     h(ElOption,{
      //       label:option.label,
      //       value:option.value
      //     })
      //   )
      // )]),
        h(ElFormItem, {
          label: '料箱号',
          prop: 'palletCode',
          style: {
            marginBottom: '16px'
          }
        }, [
          h(ElInput, {
            type: 'text',
            placeholder: '可选输入料箱号,不填则自动分配空料箱',
            modelValue: formData.palletCode,
            'onUpdate:modelValue': (val) => {
              formData.palletCode = val;
            },
            style: {
              width: '100%',
              height: '40px',
              borderRadius: '4px',
              borderColor: '#dcdfe6'
            },
            attrs: {
              placeholderStyle: 'color: #909399;'
            }
          })
        ]),
        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.batchOutForm;
              try {
                await formRef.validate();
              } catch (err) {
                return;
              }
              http.post('/api/Task/PalletOutboundTask?palletCode='+formData.palletCode+'&endStation='+formData.selectedPlatform, {
              }).then(({ data, status, message }) => {
                if (status) {
                  ElMessage.success(`出库成功`);
                  this.refresh();
                  render(null, mountNode);
                  document.body.removeChild(mountNode);
                } else {
                  ElMessage.error(message || data?.message || '出库失败');
                }
              }).catch(() => {
                ElMessage.error('请求失败,请稍后重试');
              });
            },
            style: {
              borderRadius: '4px',
              padding: '8px 20px'
            }
          }, '确定')
        ])
      ])
    });
    vnode.appContext = this.$.appContext;
    render(vnode, mountNode);
  }
}
    ], box: [], detail: [] }, //扩展的按钮
    buttons: { view: [], box: [], detail: [] }, //扩展的按钮
    methods: {
       //下面这些方法可以保留也可以删除
      onInit() {  
ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/extension/outbound/extend/newAllocateOrderDetail.vue
@@ -55,6 +55,7 @@
    <stock-select ref="child" @parentCall="parentCall"></stock-select>
    <selected-stock ref="selectedStock" @parentCall="parentCall"></selected-stock>
    <NoStockOut ref="NoStockOut" @parentCall="parentCall"></NoStockOut>
    <DirectOutbound ref="DirectOutbound" @parentCall="parentCall"></DirectOutbound>
  </div>
</template>
@@ -64,20 +65,10 @@
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 DirectOutbound from "./DirectOutbound.vue";
export default {
  components: { VolBox, VolForm, StockSelect, SelectedStock, NoStockOut },
  components: { VolBox, VolForm, StockSelect, SelectedStock, NoStockOut, DirectOutbound },
  data() {
    return {
      row: null,
@@ -324,337 +315,166 @@
      });
    },
    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);
      // 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);
      const formData = reactive({
        selectedPlatform: platformOptions[0].value,
      });
      // const formData = reactive({
      //   selectedPlatform: platformOptions[0].value,
      // });
      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;
                      }
      // 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;
      //                 }
                      const keys = this.selection.map((item) => item.id);
                      const requestParams = {
                        detailIds: keys,
                        outboundTargetLocation: formData.selectedPlatform,
                        outboundQuantity: 1,
                        operator: "",
                        orderNo: this.row.orderNo,
                      };
      //                 const keys = this.selection.map((item) => item.id);
      //                 const requestParams = {
      //                   detailIds: keys,
      //                   outboundTargetLocation: formData.selectedPlatform,
      //                   outboundQuantity: 1,
      //                   operator: "",
      //                   orderNo: this.row.orderNo,
      //                 };
                      this.http
                        .post(
                          "api/Outbound/ProcessPickingOutbound",
                          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",
                    },
                  }, "确定出库"),
                ]),
              ]),
        }
      );
      //                 this.http
      //                   .post(
      //                     "api/Outbound/ProcessPickingOutbound",
      //                     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",
      //               },
      //             }, "确定出库"),
      //           ]),
      //         ]),
      //   }
      // );
      vnode.appContext = this.$.appContext;
      render(vnode, mountNode);
      // 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);
      const formData = reactive({
        selectedPlatform: platformOptions[0].value,
        outboundDecimal: "",
      });
      const keys = this.selection.map((item) => item.id);
      const requestParams = {
        detailIds: keys,
        outboundQuantity: this.selection[0].orderQuantity - this.selection[0].lockQuantity,
        operator: "",
        orderNo: this.row.orderNo,
        isBatch: this.isBatch
      };
      console.log(requestParams);
      this.$refs.DirectOutbound.open(requestParams);
      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) => {
                        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",
                    precision: 2,
                    min: 0.01,
                  }),
                ]),
                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;
                      }
                      const keys = this.selection.map((item) => item.id);
                      const requestParams = {
                        detailIds: keys,
                        outboundTargetLocation: formData.selectedPlatform,
                        outboundQuantity: formData.outboundDecimal,
                        operator: "",
                        orderNo: this.row.orderNo,
                      };
                      this.http
                        .post(
                          "api/Outbound/ProcessPickingOutbound",
                          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",
                    },
                  }, "确定分批出库"),
                ]),
              ]),
        }
      );
      vnode.appContext = this.$.appContext;
      render(vnode, mountNode);
    },
    setCurrent(row) {
      this.$refs.singleTable.setCurrentRow(row);
ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/extension/outbound/outboundOrder.js
@@ -385,10 +385,13 @@
    if (rows.length == 0) return this.$error("请选择数据!");
    if (rows.length > 1) return this.$error("请选择一条数据!");
    
    // ç¡®ä¿é€‰ä¸­è¡Œæœ‰id(根据实际表格数据字段调整,比如rows[0].detailId等)
    const selectedId = rows[0].id || rows[0].detailId;
    if (!selectedId) return this.$error("选中数据缺少必要ID字段!");
    if(rows[0].orderStatus!=0&&rows[0].orderStatus!=1)return this.$error("该单据已经完成");
    const platformOptions = [
      { label: "站台2", value: "2-1" },
      { label: "站台3", value: "3-1" },
ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/extension/stock/stockView.js
@@ -1,4 +1,5 @@
import { createVNode, render, h, reactive } from 'vue';
import { ElDialog, ElForm, ElFormItem, ElSelect, ElOption, ElButton, ElMessage, ElLoading } from 'element-plus';
let extension = {
  components: {
    //查询界面扩展组件
@@ -156,6 +157,175 @@
          }
        }
      })
      let SelectTake = this.buttons.find(x => x.value == 'SelectStockTake');
if (SelectTake) {
  // æ”¹ä¸ºç®­å¤´å‡½æ•°ç¡®ä¿this指向Vue组件实例
  SelectTake.onClick = async () => {
    // èŽ·å–é€‰ä¸­æ•°æ®ï¼ˆä¸ŽåŽŸé€»è¾‘ä¸€è‡´ï¼Œç¡®ä¿æ˜¯æ•°ç»„æ ¼å¼ï¼‰
    let stockViews = this.$refs.table.getSelected();
    // æ•°æ®æ ¡éªŒï¼šè‡³å°‘选择一条数据
    if (stockViews.length === 0) return ElMessage.error("请选择需要操作的数据!");
    // ç«™å°é€‰é¡¹ï¼ˆå¯æ ¹æ®å®žé™…业务调整选项值)
    const stationOptions = [
      { label: "站台2", value: "2-1" },
      { label: "站台3", value: "3-1" },
      { label: "站台4", value: "4-1" },
    ];
    // åˆ›å»ºå¼¹çª—挂载节点
    const mountNode = document.createElement("div");
    document.body.appendChild(mountNode);
    // è¡¨å•数据(绑定选中的站台)
    const formData = reactive({
      outStation: stationOptions[0].value, // é»˜è®¤é€‰ä¸­ç¬¬ä¸€ä¸ªç«™å°
    });
    // åˆ›å»ºå¼¹çª—VNode
    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: {
                outStation: [
                  { required: true, message: "请选择出库站台", trigger: "change" },
                ],
              },
              ref: "stockTakeForm", // è¡¨å•ref标识
              labelWidth: "100px",
              style: {
                padding: "0 30px",
              },
            },
            [
              // ç«™å°é€‰æ‹©ä¸‹æ‹‰æ¡†
              h(ElFormItem, {
                label: "出库站台",
                prop: "outStation",
                style: { marginBottom: "24px" },
              }, [
                h(ElSelect, {
                  placeholder: "请选择出库站台",
                  modelValue: formData.outStation,
                  "onUpdate:modelValue": (val) => {
                    formData.outStation = val;
                  },
                  style: {
                    width: "100%",
                    height: "40px",
                    borderRadius: "4px",
                    borderColor: "#dcdfe6",
                  },
                }, stationOptions.map((station) =>
                  h(ElOption, { label: station.label, value: station.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 () => {
                    // ç¡®ä¿è¡¨å•ref已挂载
                    await this.$nextTick();
                    const formRef = vnode.component.refs.stockTakeForm;
                    if (!formRef) {
                      ElMessage.error("表单初始化失败,请重试");
                      return;
                    }
                    // è¡¨å•验证
                    try {
                      await formRef.validate();
                    } catch (err) {
                      return;
                    }
                    // æž„造请求参数:
                    // 1. è¯·æ±‚体:直接传递stockViews数组(对应后端List<StockViewDTO>)
                    // 2. outStation:通过查询参数传递(因后端未指定[FromBody]接收该参数)
                    const requestBody = stockViews; // ç›´æŽ¥ä¼ é€’选中数组(确保数组内对象结构与StockViewDTO一致)
                    const outStation = formData.outStation;
                    // æŽ¥å£è¯·æ±‚:Post方式,请求体传stockViews数组,outStation拼到URL查询参数
                    try {
                      // æ‹¼æŽ¥æŸ¥è¯¢å‚数(如果outStation有特殊字符,可使用encodeURIComponent处理)
                      const url = `api/Task/TakeOutbound?outStation=${encodeURIComponent(outStation)}`;
                      const x = await this.http.post(
                        url, // å¸¦æŸ¥è¯¢å‚æ•°çš„URL
                        requestBody, // è¯·æ±‚体:stockViews数组
                        "数据处理中"
                      );
                      if (!x.status) {
                        ElMessage.error(x.message || "库存操作失败");
                        return;
                      }
                      ElMessage.success("操作成功");
                      this.refresh(); // åŽŸåˆ·æ–°é€»è¾‘ä¿ç•™
                    } catch (error) {
                      console.error("库存接口请求失败:", error);
                      ElMessage.error("请求失败,请稍后重试");
                    } finally {
                      // æ— è®ºæˆåŠŸå¤±è´¥ï¼Œå…³é—­å¼¹çª—
                      render(null, mountNode);
                      document.body.removeChild(mountNode);
                    }
                  },
                  style: { borderRadius: "4px", padding: "8px 20px" },
                }, "确定操作"),
              ]),
            ]),
      }
    );
    // ç»‘定app上下文(确保弹窗内组件正常工作)
    vnode.appContext = this.$.appContext;
    render(vnode, mountNode);
  };
}
    },
    onInited() {
      //框架初始化配置后
ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/extension/taskinfo/task.js
@@ -15,31 +15,7 @@
      modelFooter: ''
    },
    tableAction: '', //指定某张表的权限(这里填写表名,默认不用填写)
    buttons: { view: [
      {
        name: '重下任务',
        type: 'primary',
        value: '重下任务',
        onClick: async function () {
          const selectRows = this.$refs.table.getSelected();
          if (selectRows.length == 0) return ElMessage.warning('请选择一条任务');
          if (selectRows.length > 1) return ElMessage.warning('只能选择一条任务');
          const taskNum = selectRows[0].taskId;
          try{
            const response = await http.post('api/Task/RecreateTasks?taskNums='+taskNum, '任务重下中...');
            const { status, message ,data} = response;
            if (status) {
              ElMessage.success(`重下任务成功`);
              this.refresh();
            }else{
              ElMessage.error(`重下任务失败:${message}`);
            }
          }catch(err){
            ElMessage.error(`重下任务异常:${err.message}`);
          }
        }
      }
    ], box: [], detail: [] }, //扩展的按钮
    buttons: { view: [ ], box: [], detail: [] }, //扩展的按钮
    methods: {
       //下面这些方法可以保留也可以删除
      onInit() {  
ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/router/viewGird.js
@@ -239,6 +239,18 @@
    component: () => import('@/views/system/Log.vue'),
    meta: {
    }
  }, {
    path: '/takeStockOrder',
    name: 'takeStockOrder',
    component: () => import('@/views/inbound/takeStockOrder.vue')
  }, {
    path: '/takeStockOrderDetail',
    name: 'takeStockOrderDetail',
    component: () => import('@/views/inbound/takeStockOrderDetail.vue')
  }, {
    path: '/dashboard',
    name: 'dashboard',
    component: () => import('@/views/charts/wms-dashboard.vue')
  }
]
ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/views/Login.vue
@@ -68,8 +68,8 @@
    const codeImgSrc = ref("");
    const value = ref("");
    const userInfo = reactive({
      userName: "admin",
      password: "123456",
      userName: "",
      password: "",
      verificationCode: "1234",
      UUID: undefined,
    });
ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/views/charts/wms-dashboard.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,725 @@
<template>
  <div class="wms-dashboard">
    <!-- é¡¶éƒ¨æ ‡é¢˜æ  -->
    <div class="header">
      <h1>WMS仓储可视化图表看板</h1>
      <div class="header-right">
        <span>2025-12-24 16:11:44</span>
        <el-select v-model="month" placeholder="本月" style="margin-left: 10px; width: 80px;">
          <el-option label="本月" value="month"></el-option>
          <el-option label="上月" value="lastMonth"></el-option>
        </el-select>
        <el-button type="primary" style="margin-left: 10px;" @click="refreshCharts">刷新</el-button>
      </div>
    </div>
    <!-- ç»Ÿè®¡å¡ç‰‡åŒºåŸŸ -->
    <el-row :gutter="20" class="stats-card-row">
      <el-col :span="6">
        <el-card class="stats-card">
          <div class="card-title">总库存(件)</div>
          <div class="card-value">269,225</div>
          <div class="card-change"><el-tag type="success">↑ 2.1% è¾ƒæ˜¨æ—¥</el-tag></div>
        </el-card>
      </el-col>
      <el-col :span="6">
        <el-card class="stats-card">
          <div class="card-title">待出库订单</div>
          <div class="card-value">425</div>
          <div class="card-change"><el-tag type="warning">↑ 5.3% è¾ƒ1小时前</el-tag></div>
        </el-card>
      </el-col>
      <el-col :span="6">
        <el-card class="stats-card">
          <div class="card-title">今日作业完成率</div>
          <div class="card-value">93.9%</div>
          <div class="card-change"><el-tag type="success">↑ 1.8% è¾ƒæ˜¨æ—¥</el-tag></div>
        </el-card>
      </el-col>
      <el-col :span="6">
        <el-card class="stats-card">
          <div class="card-title">未处理异常</div>
          <div class="card-value">7</div>
          <div class="card-change"><el-tag type="danger">↑ 1 è¾ƒ30分钟前</el-tag></div>
        </el-card>
      </el-col>
    </el-row>
    <!-- å›¾è¡¨åŒºåŸŸï¼ˆç¬¬ä¸€è¡Œï¼‰ -->
    <el-row :gutter="20" class="chart-row">
      <el-col :span="12">
        <el-card class="chart-card">
          <div class="chart-title">库存库位分布(图像化占比)<el-button type="text" class="view-btn">切换视图</el-button></div>
          <div ref="inventoryPieRef" class="chart-container"></div>
        </el-card>
      </el-col>
      <el-col :span="12">
        <el-card class="chart-card">
          <div class="chart-title">近7日出入库趋势(图像化走势)
            <el-button-group class="btn-group">
              <el-button type="primary" size="small">全部</el-button>
              <el-button type="default" size="small">入库</el-button>
              <el-button type="default" size="small">出库</el-button>
            </el-button-group>
          </div>
          <div ref="stockTrendRef" class="chart-container"></div>
        </el-card>
      </el-col>
    </el-row>
    <!-- å›¾è¡¨åŒºåŸŸï¼ˆç¬¬äºŒè¡Œï¼‰ -->
    <el-row :gutter="20" class="chart-row">
      <el-col :span="8">
        <el-card class="chart-card">
          <div class="chart-title">库位利用率</div>
          <div ref="locationRateRef" class="chart-container"></div>
        </el-card>
      </el-col>
      <el-col :span="8">
        <el-card class="chart-card">
          <div class="chart-title">作业类型分布<el-button type="text" class="view-btn">查看详情</el-button></div>
          <div ref="operationRadarRef" class="chart-container"></div>
        </el-card>
      </el-col>
      <el-col :span="8">
        <el-card class="chart-card">
          <div class="chart-title">异常类型统计趋势<el-button type="text" class="view-btn">筛选</el-button></div>
          <div ref="exceptionTrendRef" class="chart-container"></div>
        </el-card>
      </el-col>
    </el-row>
    <!-- è¡¨æ ¼åŒºåŸŸ -->
    <el-row :gutter="20" class="table-row">
      <el-col :span="12">
        <el-card class="table-card">
          <div class="table-title">订单处理进度<el-select v-model="orderType" placeholder="退货入库"
              style="width: 100px; margin-left: 10px;">
              <el-option label="退货入库" value="return"></el-option>
              <el-option label="普通出库" value="normal"></el-option>
            </el-select></div>
          <el-table :data="orderList" border style="width: 100%;">
            <el-table-column prop="orderNo" label="订单号" />
            <el-table-column prop="type" label="类型" />
            <el-table-column prop="priority" label="优先级">
              <template #default="scope">
                <el-tag
                  :type="scope.row.priority === '紧急' ? 'danger' : scope.row.priority === '加急' ? 'warning' : 'success'">
                  {{ scope.row.priority }}
                </el-tag>
              </template>
            </el-table-column>
            <el-table-column prop="progress" label="进度">
              <template #default="scope">
                <el-progress :percentage="scope.row.progress" :color="scope.row.progressColor" />
              </template>
            </el-table-column>
          </el-table>
          <div class="table-pagination">
            <el-button type="text">加载更多订单</el-button>
            <el-pagination layout="prev, pager, next, jumper" :current-page="1" :total="50" />
          </div>
        </el-card>
      </el-col>
      <el-col :span="12">
        <el-card class="table-card">
          <div class="table-title">实时作业监控
            <el-button-group class="btn-group">
              <el-button type="primary" size="small">全部作业</el-button>
              <el-button type="default" size="small">入库</el-button>
              <el-button type="default" size="small">出库</el-button>
              <el-button type="default" size="small">盘点</el-button>
            </el-button-group>
          </div>
          <el-table :data="operationList" border style="width: 100%;">
            <el-table-column prop="opNo" label="作业单号" />
            <el-table-column prop="opType" label="作业类型" />
            <el-table-column prop="operator" label="操作人员" />
            <el-table-column prop="startTime" label="开始时间" />
            <el-table-column prop="status" label="当前状态">
              <template #default="scope">
                <el-tag :type="scope.row.status === '处理中' ? 'info' : scope.row.status === '已完成' ? 'success' : 'danger'">
                  {{ scope.row.status }}
                </el-tag>
              </template>
            </el-table-column>
            <el-table-column label="操作"><el-button type="text">详情</el-button></el-table-column>
          </el-table>
          <div class="table-pagination">
            <el-pagination layout="prev, pager, next, jumper" :current-page="1" :total="50" />
          </div>
        </el-card>
      </el-col>
    </el-row>
  </div>
</template>
<script setup>
import { ref, onMounted, onUnmounted, nextTick } from 'vue';
import * as echarts from 'echarts';
// å“åº”式数据
const month = ref('month');
const orderType = ref('return');
// æ¨¡æ‹Ÿæ•°æ®
const orderList = ref([
  { orderNo: 'OD20251224001', type: '普通出库', priority: '紧急', progress: 60, progressColor: '#ff4d4f' },
  { orderNo: 'OD20251224002', type: '退货入库', priority: '普通', progress: 80, progressColor: '#1890ff' },
  { orderNo: 'OD20251224003', type: '调拨订单', priority: '加急', progress: 40, progressColor: '#faad14' },
  { orderNo: 'OD20251224004', type: '普通出库', priority: '常规', progress: 100, progressColor: '#52c41a' }
]);
const operationList = ref([
  { opNo: 'JW251224001', opType: '入库', operator: '张三', startTime: '15:30:22', status: '处理中' },
  { opNo: 'CK251224002', opType: '出库', operator: '李四', startTime: '15:25:10', status: '已完成' },
  { opNo: 'PD251224003', opType: '盘点', operator: '王五', startTime: '15:20:05', status: '待确认' },
  { opNo: 'SC251224005', opType: '上架', operator: '孙七', startTime: '15:10:18', status: '异常' }
]);
// å›¾è¡¨å®¹å™¨
const inventoryPieRef = ref(null);
const stockTrendRef = ref(null);
const locationRateRef = ref(null);
const operationRadarRef = ref(null);
const exceptionTrendRef = ref(null);
// å›¾è¡¨å®žä¾‹
let inventoryPieChart = null;
let stockTrendChart = null;
let locationRateChart = null;
let operationRadarChart = null;
let exceptionTrendChart = null;
// åˆå§‹åŒ–库存库位分布饼图
const initInventoryPie = () => {
  if (!inventoryPieRef.value) return;
  if (inventoryPieChart) {
    inventoryPieChart.dispose();
  }
  inventoryPieChart = echarts.init(inventoryPieRef.value);
  const option = {
    tooltip: {
      trigger: 'item',
      formatter: '{a} <br/>{b}: {c}%'
    },
    legend: {
      bottom: 0,
      left: 'center',
      data: ['常温区A区', '冷藏区B区', '保税区C区', '残次品区D区']
    },
    series: [{
      name: '库存库位分布',
      type: 'pie',
      radius: ['40%', '70%'],
      center: ['50%', '40%'],
      avoidLabelOverlap: false,
      itemStyle: {
        borderRadius: 10,
        borderColor: '#fff',
        borderWidth: 2
      },
      label: {
        show: false,
        position: 'center'
      },
      emphasis: {
        label: {
          show: true,
          fontSize: 20,
          fontWeight: 'bold'
        }
      },
      labelLine: {
        show: false
      },
      data: [
        { value: 48.7, name: '常温区A区', itemStyle: { color: '#5470c6' } },
        { value: 29.2, name: '冷藏区B区', itemStyle: { color: '#91cc75' } },
        { value: 21.9, name: '保税区C区', itemStyle: { color: '#fac858' } },
        { value: 2.2, name: '残次品区D区', itemStyle: { color: '#ee6666' } }
      ]
    }]
  };
  inventoryPieChart.setOption(option);
  return inventoryPieChart;
};
// åˆå§‹åŒ–è¿‘7日出入库趋势图
const initStockTrend = () => {
  if (!stockTrendRef.value) return;
  if (stockTrendChart) {
    stockTrendChart.dispose();
  }
  stockTrendChart = echarts.init(stockTrendRef.value);
  const option = {
    tooltip: {
      trigger: 'axis',
      axisPointer: {
        type: 'cross'
      }
    },
    legend: {
      data: ['入库量', '出库量'],
      top: 10
    },
    grid: {
      left: '3%',
      right: '4%',
      bottom: '3%',
      top: '15%',
      containLabel: true
    },
    xAxis: {
      type: 'category',
      boundaryGap: true,
      data: ['12-18', '12-19', '12-20', '12-21', '12-22', '12-23', '12-24']
    },
    yAxis: {
      type: 'value',
      name: '数量(千件)',
      max: 25
    },
    series: [
      {
        name: '入库量',
        type: 'bar',
        barWidth: '30%',
        data: [10, 12, 10, 12, 10, 12, 12],
        itemStyle: { color: '#52c41a' }
      },
      {
        name: '出库量',
        type: 'bar',
        barWidth: '30%',
        data: [16, 18, 14, 18, 16, 18, 20],
        itemStyle: { color: '#1890ff' }
      }
    ]
  };
  stockTrendChart.setOption(option);
  return stockTrendChart;
};
// åˆå§‹åŒ–库位利用率环形图
const initLocationRate = () => {
  if (!locationRateRef.value) return;
  if (locationRateChart) {
    locationRateChart.dispose();
  }
  locationRateChart = echarts.init(locationRateRef.value);
  const option = {
    tooltip: {
      formatter: '{a} <br/>{b} : {c}%'
    },
    series: [{
      name: '库位利用率',
      type: 'gauge',
      min: 0,
      max: 100,
      splitNumber: 10,
      radius: '90%',
      center: ['50%', '55%'],
      startAngle: 180,
      endAngle: 0,
      progress: {
        show: true,
        width: 20,
        itemStyle: {
          color: '#1890ff'
        }
      },
      axisLine: {
        lineStyle: {
          width: 20,
          color: [[1, 'rgba(200,200,200,0.3)']]
        }
      },
      axisTick: {
        distance: -30,
        splitNumber: 5,
        lineStyle: {
          width: 2,
          color: '#999'
        }
      },
      splitLine: {
        distance: -30,
        length: 14,
        lineStyle: {
          width: 3,
          color: '#999'
        }
      },
      axisLabel: {
        distance: -20,
        color: '#999',
        fontSize: 12
      },
      anchor: {
        show: false
      },
      title: {
        show: true,
        offsetCenter: [0, '30%'],
        fontSize: 16,
        fontWeight: 'bold'
      },
      detail: {
        valueAnimation: true,
        formatter: '{value}%',
        fontSize: 20,
        fontWeight: 'bold',
        offsetCenter: [0, '70%']
      },
      data: [{
        value: 86.2,
        name: '库位利用率'
      }]
    }]
  };
  locationRateChart.setOption(option);
  return locationRateChart;
};
// åˆå§‹åŒ–作业类型雷达图
const initOperationRadar = () => {
  if (!operationRadarRef.value) return;
  if (operationRadarChart) {
    operationRadarChart.dispose();
  }
  operationRadarChart = echarts.init(operationRadarRef.value);
  const option = {
    tooltip: {
      trigger: 'item'
    },
    legend: {
      show: false
    },
    radar: {
      indicator: [
        { name: '出库作业', max: 100 },
        { name: '入库作业', max: 100 },
        { name: '调拨作业', max: 100 },
        { name: '盘点作业', max: 100 }
      ],
      shape: 'circle',
      splitNumber: 5,
      axisName: {
        color: '#666'
      },
      splitLine: {
        lineStyle: {
          color: 'rgba(0,0,0,0.1)'
        }
      },
      splitArea: {
        show: true,
        areaStyle: {
          color: ['rgba(255,255,255,0.8)', 'rgba(200,200,200,0.2)']
        }
      }
    },
    series: [{
      name: '作业类型分布',
      type: 'radar',
      symbolSize: 8,
      areaStyle: {
        color: 'rgba(24,144,255,0.3)'
      },
      lineStyle: {
        width: 2
      },
      itemStyle: {
        color: '#1890ff'
      },
      data: [{
        value: [45, 30, 15, 10],
        name: '作业占比',
        label: {
          show: true,
          formatter: function (params) {
            return params.value + '%';
          }
        }
      }]
    }]
  };
  operationRadarChart.setOption(option);
  return operationRadarChart;
};
// åˆå§‹åŒ–异常趋势折线图
const initExceptionTrend = () => {
  if (!exceptionTrendRef.value) return;
  if (exceptionTrendChart) {
    exceptionTrendChart.dispose();
  }
  exceptionTrendChart = echarts.init(exceptionTrendRef.value);
  const option = {
    tooltip: {
      trigger: 'axis',
      axisPointer: {
        type: 'cross'
      }
    },
    legend: {
      data: ['库存不足', '订单超时', '库位异常', '盘点差异'],
      top: 10
    },
    grid: {
      left: '3%',
      right: '4%',
      bottom: '3%',
      top: '15%',
      containLabel: true
    },
    xAxis: {
      type: 'category',
      boundaryGap: false,
      data: ['12-18', '12-19', '12-20', '12-21', '12-22', '12-23', '12-24']
    },
    yAxis: {
      type: 'value',
      name: '异常数量'
    },
    series: [
      {
        name: '库存不足',
        type: 'line',
        smooth: true,
        symbol: 'circle',
        symbolSize: 8,
        data: [10, 11, 9, 12, 10, 13, 12],
        itemStyle: { color: '#ff4d4f' },
        lineStyle: {
          width: 3
        }
      },
      {
        name: '订单超时',
        type: 'line',
        smooth: true,
        symbol: 'circle',
        symbolSize: 8,
        data: [8, 9, 7, 8, 7, 9, 8],
        itemStyle: { color: '#faad14' },
        lineStyle: {
          width: 3
        }
      },
      {
        name: '库位异常',
        type: 'line',
        smooth: true,
        symbol: 'circle',
        symbolSize: 8,
        data: [4, 5, 2, 4, 3, 5, 4],
        itemStyle: { color: '#722ed1' },
        lineStyle: {
          width: 3
        }
      },
      {
        name: '盘点差异',
        type: 'line',
        smooth: true,
        symbol: 'circle',
        symbolSize: 8,
        data: [2, 3, 1, 2, 1, 3, 2],
        itemStyle: { color: '#13c2c2' },
        lineStyle: {
          width: 3
        }
      }
    ]
  };
  exceptionTrendChart.setOption(option);
  return exceptionTrendChart;
};
// åˆ·æ–°æ‰€æœ‰å›¾è¡¨
const refreshCharts = () => {
  const charts = [
    initInventoryPie,
    initStockTrend,
    initLocationRate,
    initOperationRadar,
    initExceptionTrend
  ];
  charts.forEach(initFunc => {
    const chart = initFunc();
    if (chart) {
      chart.resize();
    }
  });
};
// ç›‘听窗口大小变化
const handleResize = () => {
  const charts = [
    inventoryPieChart,
    stockTrendChart,
    locationRateChart,
    operationRadarChart,
    exceptionTrendChart
  ];
  charts.forEach(chart => {
    if (chart) {
      chart.resize();
    }
  });
};
// æŒ‚载后初始化图表
onMounted(() => {
  nextTick(() => {
    initInventoryPie();
    initStockTrend();
    initLocationRate();
    initOperationRadar();
    initExceptionTrend();
    window.addEventListener('resize', handleResize);
  });
});
// ç»„件卸载时清理
onUnmounted(() => {
  const charts = [
    inventoryPieChart,
    stockTrendChart,
    locationRateChart,
    operationRadarChart,
    exceptionTrendChart
  ];
  charts.forEach(chart => {
    if (chart) {
      chart.dispose();
    }
  });
  window.removeEventListener('resize', handleResize);
});
</script>
<style scoped>
.wms-dashboard {
  padding: 20px;
  background: #f5f7fa;
  min-height: 100vh;
  box-sizing: border-box;
}
.header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
  background: white;
  padding: 15px 20px;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
}
.stats-card-row,
.chart-row,
.table-row {
  margin-bottom: 20px;
}
.stats-card {
  height: 120px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 0 20px;
  transition: all 0.3s ease;
}
.stats-card:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
.card-title {
  font-size: 14px;
  color: #666;
  margin-bottom: 8px;
}
.card-value {
  font-size: 28px;
  font-weight: bold;
  margin: 8px 0 4px;
  color: #333;
}
.card-change {
  margin-top: 8px;
}
.chart-card {
  height: 320px;
  padding: 15px;
  display: flex;
  flex-direction: column;
}
.chart-container {
  width: 100%;
  height: 100%;
  min-height: 250px;
  flex: 1;
}
.chart-title,
.table-title {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 15px;
  font-size: 16px;
  font-weight: bold;
  color: #333;
}
.view-btn {
  font-size: 12px;
}
.table-pagination {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 15px;
}
.btn-group {
  margin-left: 10px;
}
/* ç¡®ä¿å›¾è¡¨å®¹å™¨æœ‰æ˜Žç¡®å°ºå¯¸ */
:deep(.el-card__body) {
  height: 100%;
  display: flex;
  flex-direction: column;
}
</style>
ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/views/inbound/takeStockOrder.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,291 @@
<template>
    <!-- <div>
      <assemble-dist></assemble-dist>
    </div> -->
    <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/inbound/takeStockOrder.js";
  import { ref, defineComponent } from "vue";
  // import AssembleDistVue from '../charts/AssembleDist.vue';
  export default defineComponent({
    // components: {
    //   'assemble-dist': AssembleDistVue,
    // },
    setup() {
      //使用组件AssembleDist
      const table = ref({
        key: "id",
        footer: "Foots",
        cnName: "盘点单",
        name: "takeStockOrder",
        url: "/TakeStockOrder/",
        sortName: "id",
      });
      const searchFormFields = ref({
        orderNo:""
      });
      const searchFormOptions = ref([
        [
        { title: "单据编号", field: "orderNo", type: "like" },
        ]
      ]);
      const editFormFields = ref({
        orderNo:"",
        warehouseId: "",
        remark:""
      });
      const editFormOptions = ref([
      [
        {
          field: "orderNo",
          title: "单据编号",
          type: "string",
          readonly: "true",
        },
        {
          title: "仓库",
          field: "warehouseId",
          type: "select",
          dataKey: "warehouses",
          data: [],
          required: true,
        },
        {
          field: "remark",
          title: "备注",
          type: "string",
        }
      ]
      ]);
      const columns = ref([
        {
          field: "id",
          title: "Id",
          type: "int",
          width: 90,
          hidden: true,
          readonly: true,
          require: true,
          align: "left",
        },
        {
          field: "orderNo",
          title: "盘点单号",
          type: "string",
          width: 150,
          align: "left",
        },
        {
          field: "takeStockStatus",
          title: "盘点状态",
          type: "string",
          width: 120,
          align: "left",
          bind: { key: "takeStockStatusEnum", data: [] },
        },
        {
          field: "allPalletCode",
          title: "单据盘点托盘",
          type: "string",
          width: 600,
          align: "left",
        },
        {
          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: "盘点明细",
        table: "Dt_TakeStockOrderDetail",
        columns: [
          {
            field: "id",
            title: "Id",
            type: "int",
            width: 90,
            hidden: true,
            readonly: true,
            require: true,
            align: "left",
          },
          {
            field: "takeStockId",
            title: "盘点单主键",
            type: "string",
            width: 90,
            align: "left",
            hidden: true,
          },
          {
            field: "takePalletCode",
            title: "盘点托盘",
            type: "string",
            width: 150,
            align: "left",
            required: true,
          },
          {
            field: "takeDetalStatus",
            title: "盘点明细状态",
            type: "int",
            width: 130,
            align: "left",
            bind: { key: "takeStockDetailStatusEnum", data: [] },
          },
          {
            field: "materielCode",
            title: "物料编码",
            type: "string",
            width: 110,
            align: "left",
            required: true,
          },
          {
            field: "materielName",
            title: "物料名称",
            type: "string",
            width: 120,
            align: "left",
            required: true,
          },
          {
            field: "batchNo",
            title: "批次号",
            type: "string",
            width: 130,
            align: "left",
            required: true,
          },
          {
            field: "materielSpec",
            title: "物料名称",
            type: "string",
            width: 120,
            align: "left",
            required: true,
          },
          {
            field: "sysQty",
            title: "账面数量",
            type: "decimal",
            width: 90,
            align: "left",
            required: true,
            edit: { type: "decimal" }
          },
          {
            field: "qty",
            title: "实盘数量",
            type: "decimal",
            width: 90,
            align: "left",
            required: true,
            edit: { type: "decimal" }
          },
          {
            field: "unit",
            title: "单位",
            type: "string",
            width: 90,
            align: "left",
          },
          {
            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",
          },
        ],
        sortName: "id",
        key: "id",
      });
      return {
        table,
        extend,
        editFormFields,
        editFormOptions,
        searchFormFields,
        searchFormOptions,
        columns,
        detail,
      };
    },
  });
  </script>
ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/views/inbound/takeStockOrderDetail.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,254 @@
<template>
    <!-- <div>
      <assemble-dist></assemble-dist>
    </div> -->
    <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/inbound/takeStockOrderDetail.js";
  import { ref, defineComponent } from "vue";
  // import AssembleDistVue from '../charts/AssembleDist.vue';
  export default defineComponent({
    // components: {
    //   'assemble-dist': AssembleDistVue,
    // },
    setup() {
      //使用组件AssembleDist
      const table = ref({
        key: "id",
        footer: "Foots",
        cnName: "盘点单",
        name: "TakeStockOrderDetail",
        url: "/TakeStockOrderDetail/",
        sortName: "id",
      });
      const searchFormFields = ref({
        orderNo:""
      });
      const searchFormOptions = ref([
        [
        { title: "盘点单据", field: "takeStockNo", type: "like" },
        { title: "盘点料箱", field: "takePalletCode", type: "like" },
        { title: "物料编号", field: "materielCode", type: "like" },
        { title: "批次号", field: "batchNo", type: "like" },
        ],
        [
        { title: "条码", field: "barcode", type: "like" },
        { title: "仓库", field: "warehouseCode", type: "like" },
        { title: "厂区", field: "factoryArea", type: "like" },
        { title: "供应商编号", field: "supplyCode", type: "like" },
        ],
        [
        { title: "创建人", field: "creater", type: "like" },
        { title: "创建时间", field: "createDate", type: "datetime" },
        ]
      ]);
      const editFormFields = ref({
        orderNo:"",
        warehouseId: "",
        remark:""
      });
      const editFormOptions = ref([
      [
        {
          field: "orderNo",
          title: "单据编号",
          type: "string",
          readonly: "true",
        },
        {
          title: "仓库",
          field: "warehouseId",
          type: "select",
          dataKey: "warehouses",
          data: [],
          required: true,
        },
        {
          field: "remark",
          title: "备注",
          type: "string",
        }
      ]
      ]);
      const columns = ref([
        {
            field: "id",
            title: "Id",
            type: "int",
            width: 90,
            hidden: true,
            readonly: true,
            require: true,
            align: "left",
          },
          {
            field: "takeStockId",
            title: "盘点单主键",
            type: "string",
            width: 90,
            align: "left",
            hidden: true,
          },
          {
            field: "takeStockNo",
            title: "盘点单据",
            type: "string",
            width: 145,
            align: "left",
          },
          {
            field: "takePalletCode",
            title: "盘点料箱",
            type: "string",
            width: 110,
            align: "left",
            required: true,
          },
          {
            field: "materielCode",
            title: "物料编码",
            type: "string",
            width: 130,
            align: "left",
            required: true,
          },
          {
            field: "materielName",
            title: "物料名称",
            type: "string",
            width: 120,
            align: "left",
            required: true,
          },
          {
            field: "batchNo",
            title: "批次号",
            type: "string",
            width: 130,
            align: "left",
            required: true,
          },
          {
            field: "barcode",
            title: "条码",
            type: "string",
            width: 120,
            align: "left",
            required: true,
          },
          {
            field: "sysQty",
            title: "账面数量",
            type: "decimal",
            width: 90,
            align: "left",
            required: true,
            edit: { type: "decimal" }
          },
          {
            field: "qty",
            title: "实盘数量",
            type: "decimal",
            width: 90,
            align: "left",
            required: true,
            edit: { type: "decimal" }
          },
          {
            field: "unit",
            title: "单位",
            type: "string",
            width: 90,
            align: "left",
          },
          {
            field: "takeDetalStatus",
            title: "盘点明细状态",
            type: "int",
            width: 130,
            align: "left",
            bind: { key: "takeStockDetailStatusEnum", data: [] },
          },
          {
            field: "warehouseCode",
            title: "仓库编号",
            type: "string",
            width: 90,
            align: "left",
          },
          {
            field: "factoryArea",
            title: "厂区",
            type: "string",
            width: 90,
            align: "left",
          },
          {
            field: "supplyCode",
            title: "供应商编号",
            type: "string",
            width: 90,
            align: "left",
          },
          {
            field: "creater",
            title: "创建人",
            type: "string",
            width: 90,
            align: "left",
          },
          {
            field: "createDate",
            title: "创建时间",
            type: "datetime",
            width: 160,
            align: "left",
          },
          {
            field: "remark",
            title: "备注",
            type: "string",
            width: 100,
            align: "left",
          },
      ]);
      const detail = ref({
        cnName: "盘点明细",
        table: "Dt_TakeStockOrderDetail",
        columns: [
        ],
        sortName: "id",
        key: "id",
      });
      return {
        table,
        extend,
        editFormFields,
        editFormOptions,
        searchFormFields,
        searchFormOptions,
        columns,
        detail,
      };
    },
  });
  </script>
ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/views/outbound/allocateoutboundOrder.vue
@@ -1,39 +1,15 @@
<template>
  <view-grid
    ref="grid"
        @openOutboundDialog="handleOpenOutboundDialog"
    :columns="columns"
    :detail="detail"
    :editFormFields="editFormFields"
    :editFormOptions="editFormOptions"
    :searchFormFields="searchFormFields"
    :searchFormOptions="searchFormOptions"
    :table="table"
    :extend="extend"
  >
  <view-grid ref="grid" @openOutboundDialog="handleOpenOutboundDialog" :columns="columns" :detail="detail"
    :editFormFields="editFormFields" :editFormOptions="editFormOptions" :searchFormFields="searchFormFields"
    :searchFormOptions="searchFormOptions" :table="table" :extend="extend">
  </view-grid>
      <!-- å‡ºåº“操作弹窗 -->
    <OutboundDialog
      v-model:visible="outboundVisible"
      :selected-document="selectedOutboundDocument"
      @outbound-success="handleOutboundSuccess"
    ></OutboundDialog>
</template>
    <script>
<script>
import extend from "@/extension/outbound/allocateoutboundOrder.js";
import ViewGrid from '@/components/basic/ViewGrid/ViewGrid.vue';
import { ref, defineComponent } from "vue";
import { ElMessage } from "element-plus";
import OutboundDialog from "@/extension/outbound/extend/OutBound.vue";  // å¼•入出库弹窗组件
export default defineComponent({
   components: {
    // å…³é”®ä¿®å¤2:组件注册名与模板标签名适配(kebab-case对应view-grid)
    viewGrid: ViewGrid,  // æ³¨å†Œä¸ºkebab-case,模板用<view-grid>
    OutboundDialog  // æ³¨å†Œå‡ºåº“弹窗组件
  },
  setup() {
    const table = ref({
      key: "id",
@@ -45,11 +21,11 @@
    });
    const editFormFields = ref({
      orderType: "",
      orderNo:"",
      orderNo: "",
      upperOrderNo: "",
      orderStatus: "",
      remark: "",
      warehouseId:""
      warehouseId: ""
    });
    const editFormOptions = ref([
      [
@@ -62,11 +38,11 @@
          data: [],
        },
        {
        field: "orderNo",
        title: "单据编号",
        type: "string",
        readonly:true
      },
          field: "orderNo",
          title: "单据编号",
          type: "string",
          readonly: true
        },
        {
          title: "上游单据编号",
          field: "upperOrderNo",
@@ -220,7 +196,7 @@
        type: "string",
        width: 120,
        align: "left",
        hidden:true
        hidden: true
      },
      {
        field: "departmentName",
@@ -401,41 +377,41 @@
      sortName: "id",
      key: "id",
    });
      // è°ƒæ‹¨å¼¹çª—相关
    const outboundVisible = ref(false);
    const selectedOutboundDocument = ref({});  // å­˜å‚¨é€‰ä¸­çš„调拨单数据
    // è°ƒæ‹¨å¼¹çª—相关
    // const outboundVisible = ref(false);
    // const selectedOutboundDocument = ref({});  // å­˜å‚¨é€‰ä¸­çš„调拨单数据
    // æ‰“开调拨弹窗(从扩展配置的按钮事件触发)
    const handleOpenOutboundDialog = (docData) => {
      selectedOutboundDocument.value = docData;  // ä¿å­˜é€‰ä¸­çš„单据数据
      outboundVisible.value = true;  // æ˜¾ç¤ºå¼¹çª—
    };
    // // æ‰“开调拨弹窗(从扩展配置的按钮事件触发)
    // const handleOpenOutboundDialog = (docData) => {
    //   selectedOutboundDocument.value = docData;  // ä¿å­˜é€‰ä¸­çš„单据数据
    //   outboundVisible.value = true;  // æ˜¾ç¤ºå¼¹çª—
    // };
    // è°ƒæ‹¨æˆåŠŸåŽçš„å›žè°ƒ
    const handleOutboundSuccess = (docNo) => {
      ElMessage.success(`单据 ${docNo} è°ƒæ‹¨æˆåŠŸ`);
      gridRef.value?.refresh();  // åˆ·æ–°è¡¨æ ¼æ•°æ®
    };
    // // è°ƒæ‹¨æˆåŠŸåŽçš„å›žè°ƒ
    // const handleOutboundSuccess = (docNo) => {
    //   ElMessage.success(`单据 ${docNo} è°ƒæ‹¨æˆåŠŸ`);
    //   gridRef.value?.refresh();  // åˆ·æ–°è¡¨æ ¼æ•°æ®
    // };
    // åˆå§‹åŒ–扩展配置:为调拨按钮添加事件触发逻辑
    const initExtension = () => {
      // æ‰¾åˆ°"调拨"按钮并绑定打开弹窗的逻辑
      const outboundBtn = extend.buttons.view.find(btn => btn.name === '出库');
      if (outboundBtn) {
        const originalOnClick = outboundBtn.onClick;
        outboundBtn.onClick = function() {
          // å…ˆæ‰§è¡ŒåŽŸæœ‰æ ¡éªŒé€»è¾‘
          const selectedRows = this.$refs.table.getSelected();
          if (selectedRows.length === 1) {
            // æ ¡éªŒé€šè¿‡åŽï¼Œè§¦å‘主组件的出库弹窗事件
            this.$emit('openOutboundDialog', selectedRows[0]);
          } else {
            // åŽŸæœ‰é€»è¾‘å·²å¤„ç†æç¤ºï¼Œæ— éœ€é‡å¤
            originalOnClick.call(this);
          }
        };
      }
    };
    // // åˆå§‹åŒ–扩展配置:为调拨按钮添加事件触发逻辑
    // const initExtension = () => {
    //   // æ‰¾åˆ°"调拨"按钮并绑定打开弹窗的逻辑
    //   const outboundBtn = extend.buttons.view.find(btn => btn.name === '出库');
    //   if (outboundBtn) {
    //     const originalOnClick = outboundBtn.onClick;
    //     outboundBtn.onClick = function () {
    //       // å…ˆæ‰§è¡ŒåŽŸæœ‰æ ¡éªŒé€»è¾‘
    //       const selectedRows = this.$refs.table.getSelected();
    //       if (selectedRows.length === 1) {
    //         // æ ¡éªŒé€šè¿‡åŽï¼Œè§¦å‘主组件的出库弹窗事件
    //         this.$emit('openOutboundDialog', selectedRows[0]);
    //       } else {
    //         // åŽŸæœ‰é€»è¾‘å·²å¤„ç†æç¤ºï¼Œæ— éœ€é‡å¤
    //         originalOnClick.call(this);
    //       }
    //     };
    //   }
    // };
    return {
      table,
      extend,
@@ -445,11 +421,11 @@
      searchFormOptions,
      columns,
      detail,
       // å‡ºåº“相关
      outboundVisible,
      selectedOutboundDocument,
      handleOpenOutboundDialog,
      handleOutboundSuccess
      // å‡ºåº“相关
      // outboundVisible,
      // selectedOutboundDocument,
      // handleOpenOutboundDialog,
      // handleOutboundSuccess
    };
  },
});
ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/views/outbound/outboundOrder.vue
@@ -1,39 +1,16 @@
<template>
  <view-grid
    ref="grid"
        @openOutboundDialog="handleOpenOutboundDialog"
    :columns="columns"
    :detail="detail"
    :editFormFields="editFormFields"
    :editFormOptions="editFormOptions"
    :searchFormFields="searchFormFields"
    :searchFormOptions="searchFormOptions"
    :table="table"
    :extend="extend"
  >
  <view-grid ref="grid" @openOutboundDialog="handleOpenOutboundDialog" :columns="columns" :detail="detail"
    :editFormFields="editFormFields" :editFormOptions="editFormOptions" :searchFormFields="searchFormFields"
    :searchFormOptions="searchFormOptions" :table="table" :extend="extend">
  </view-grid>
      <!-- å‡ºåº“操作弹窗 -->
    <OutboundDialog
      v-model:visible="outboundVisible"
      :selected-document="selectedOutboundDocument"
      @outbound-success="handleOutboundSuccess"
    ></OutboundDialog>
</template>
    <script>
<script>
import extend from "@/extension/outbound/outboundOrder.js";
import ViewGrid from '@/components/basic/ViewGrid/ViewGrid.vue';
import { ref, defineComponent } from "vue";
import { ElMessage } from "element-plus";
import OutboundDialog from "@/extension/outbound/extend/OutBound.vue";  // å¼•入出库弹窗组件
export default defineComponent({
   components: {
    // å…³é”®ä¿®å¤2:组件注册名与模板标签名适配(kebab-case对应view-grid)
    viewGrid: ViewGrid,  // æ³¨å†Œä¸ºkebab-case,模板用<view-grid>
    OutboundDialog  // æ³¨å†Œå‡ºåº“弹窗组件
  },
  setup() {
    const table = ref({
      key: "id",
@@ -45,20 +22,20 @@
    });
    const editFormFields = ref({
      orderType: "",
      orderNo:"",
      orderNo: "",
      upperOrderNo: "",
      orderStatus: "",
      remark: "",
      warehouseId:""
      warehouseId: ""
    });
    const editFormOptions = ref([
      [
        {
        field: "orderNo",
        title: "单据编号",
        type: "string",
        readonly:true
      },
          field: "orderNo",
          title: "单据编号",
          type: "string",
          readonly: true
        },
        {
          title: "上游单据编号",
          field: "upperOrderNo",
@@ -104,9 +81,9 @@
          title: "操作者",
          field: "operator",
          type: "string",
          hidden:true,
          hidden: true,
          readonly: true,
        },
      ],
    ]);
@@ -182,7 +159,7 @@
        width: 150,
        align: "left",
        bind: { key: "outOrderType", data: [] },
        hidden:true
        hidden: true
      },
      {
        field: "businessType",
@@ -219,7 +196,7 @@
        field: "returnToMESStatus",
        title: "回传MES状态",
        width: 120,
        bind: { key: "createType", data:[{key:0, value:"未回传"},{key:1, value:"已回传成功"},{key:2, value:"回传失败"}]},
        bind: { key: "createType", data: [{ key: 0, value: "未回传" }, { key: 1, value: "已回传成功" }, { key: 2, value: "回传失败" }] },
      },
      {
        field: "factoryArea",
@@ -234,7 +211,7 @@
        type: "string",
        width: 120,
        align: "left",
        hidden:true
        hidden: true
      },
      {
        field: "departmentName",
@@ -350,7 +327,7 @@
          width: 90,
          align: "left",
          edit: { type: "number" },
          readonly:true
          readonly: true
        },
        {
          field: "rowNo",
@@ -359,7 +336,7 @@
          width: 90,
          align: "left",
          edit: { type: "number" },
          readonly:true
          readonly: true
        },
        {
          field: "lockQuantity",
@@ -383,7 +360,7 @@
          align: "left",
          edit: { type: "select" },
          bind: { key: "orderDetailStatusEnum", data: [] },
          readonly:true
          readonly: true
        },
        {
          field: "creater",
@@ -424,41 +401,6 @@
      sortName: "id",
      key: "id",
    });
      // å‡ºåº“弹窗相关
    const outboundVisible = ref(false);
    const selectedOutboundDocument = ref({});  // å­˜å‚¨é€‰ä¸­çš„出库单数据
    // æ‰“开出库弹窗(从扩展配置的按钮事件触发)
    const handleOpenOutboundDialog = (docData) => {
      selectedOutboundDocument.value = docData;  // ä¿å­˜é€‰ä¸­çš„单据数据
      outboundVisible.value = true;  // æ˜¾ç¤ºå¼¹çª—
    };
    // å‡ºåº“成功后的回调
    const handleOutboundSuccess = (docNo) => {
      ElMessage.success(`单据 ${docNo} å‡ºåº“成功`);
      gridRef.value?.refresh();  // åˆ·æ–°è¡¨æ ¼æ•°æ®
    };
    // åˆå§‹åŒ–扩展配置:为出库按钮添加事件触发逻辑
    const initExtension = () => {
      // æ‰¾åˆ°"出库"按钮并绑定打开弹窗的逻辑
      const outboundBtn = extend.buttons.view.find(btn => btn.name === '出库');
      if (outboundBtn) {
        const originalOnClick = outboundBtn.onClick;
        outboundBtn.onClick = function() {
          // å…ˆæ‰§è¡ŒåŽŸæœ‰æ ¡éªŒé€»è¾‘
          const selectedRows = this.$refs.table.getSelected();
          if (selectedRows.length === 1) {
            // æ ¡éªŒé€šè¿‡åŽï¼Œè§¦å‘主组件的出库弹窗事件
            this.$emit('openOutboundDialog', selectedRows[0]);
          } else {
            // åŽŸæœ‰é€»è¾‘å·²å¤„ç†æç¤ºï¼Œæ— éœ€é‡å¤
            originalOnClick.call(this);
          }
        };
      }
    };
    return {
      table,
      extend,
@@ -468,11 +410,6 @@
      searchFormOptions,
      columns,
      detail,
       // å‡ºåº“相关
      outboundVisible,
      selectedOutboundDocument,
      handleOpenOutboundDialog,
      handleOutboundSuccess
    };
  },
});
ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/views/record/stockQuantityChangeRecord.vue
@@ -1,225 +1,237 @@
<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/record/stockQuantityChangeRecord.js";
  import { ref, defineComponent } from "vue";
  export default defineComponent({
    setup() {
      const table = ref({
        key: "id",
        footer: "Foots",
        cnName: "库存变动信息记录",
        name: "stockQuantityChangeRecord",
        url: "/StockQuantityChangeRecord/",
        sortName: "id",
      });
      const editFormFields = ref({
      });
      const editFormOptions = ref([
      ]);
      const searchFormFields = ref({
        palleCode: "",
        materielCode: "",
        orderNo: "",
      });
      const searchFormOptions = ref([
        [
          { title: "托盘号", field: "palleCode" ,type:"like"},
          { title: "物料编号", field: "materielCode",type:"like" },
          { title: "单据编号", field: "orderNo" ,type:"like"},
          { title: "变动类型", field: "changeType" ,type: "selectList",dataKey: "stockChangeType",data: [],},
        ],
        [
          { title: "批次号", field: "batchNo" ,type:"like"},
          { title: "任务号", field: "taskNum" ,type:"like"},
          { title: "序列号", field: "serilNumber" ,type:"like"},
        ],
      ]);
      const columns = ref([
        {
          field: "id",
          title: "Id",
          type: "int",
          width: 90,
          hidden: true,
          readonly: true,
          require: true,
          align: "left",
        },
        {
          field: "stockDetailId",
          title: "库存明细ID",
          type: "string",
          width: 90,
          align: "left",
        },
        {
          field: "palleCode",
          title: "托盘编号",
          type: "string",
          width: 150,
          align: "left",
        },
        {
          field: "materielCode",
          title: "物料编号",
          type: "string",
          width: 150,
          align: "left",
        },
        {
          field: "materielName",
          title: "物料名称",
          type: "decimal",
          width: 90,
          align: "left",
        },
        {
          field: "barcode",
          title: "条码",
          type: "string",
          width: 150,
          align: "left",
        },
        {
          field: "batchNo",
          title: "批次号",
          type: "string",
          width: 90,
          align: "left",
        },
        {
          field: "serilNumber",
          title: "序列号",
          type: "int",
          width: 280,
          align: "left",
        },
        {
          field: "orderNo",
          title: "单据编号",
          type: "string",
          width: 150,
          align: "left",
        },
        {
          field: "taskNum",
          title: "任务号",
          type: "string",
          width: 90,
          align: "left",
        },
        {
          field: "changeType",
          title: "变动类型",
          type: "int",
          width: 120,
          align: "left",
          bind: { key: "stockChangeType", data: [] },
        },
        {
          field: "changeQuantity",
          title: "变动数量",
          type: "string",
          width: 100,
          align: "left",
        },
        {
          field: "beforeQuantity",
          title: "变动前库存量",
          type: "string",
          width: 100,
          align: "left",
        },
        {
          field: "afterQuantity",
          title: "变动后库存量",
          type: "string",
          width: 100,
          align: "left",
        },
        {
          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: "orderId",
          title: "单据主键",
          type: "string",
          width: 180,
          align: "left",
        },
        {
          field: "orderDetailId",
          title: "单据明细主键",
          type: "string",
          width: 120,
          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>
  <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/record/stockQuantityChangeRecord.js";
import { ref, defineComponent } from "vue";
export default defineComponent({
  setup() {
    const table = ref({
      key: "id",
      footer: "Foots",
      cnName: "库存变动信息记录",
      name: "stockQuantityChangeRecord",
      url: "/StockQuantityChangeRecord/",
      sortName: "id",
    });
    const editFormFields = ref({
    });
    const editFormOptions = ref([
    ]);
    const searchFormFields = ref({
      palleCode: "",
      materielCode: "",
      orderNo: "",
    });
    const searchFormOptions = ref([
      [
        { title: "托盘号", field: "palleCode", type: "like" },
        { title: "物料编号", field: "materielCode", type: "like" },
        { title: "单据编号", field: "orderNo", type: "like" },
        // { title: "变动类型", field: "changeType", type: "selectList", dataKey: "stockChangeType", data: [], },
      ],
      [
        { title: "原条码", field: "originalSerilNumber", type: "like" },
        { title: "任务号", field: "taskNum", type: "like" },
        { title: "批次号", field: "batchNo", type: "like" },
      ],
    ]);
    const columns = ref([
      {
        field: "id",
        title: "Id",
        type: "int",
        width: 90,
        hidden: true,
        readonly: true,
        require: true,
        align: "left",
      },
      {
        field: "stockDetailId",
        title: "库存明细ID",
        type: "string",
        width: 90,
        align: "left",
      }, {
        field: "taskNum",
        title: "任务号",
        type: "string",
        width: 70,
        align: "left",
      },
      {
        field: "palleCode",
        title: "托盘编号",
        type: "string",
        width: 120,
        align: "left",
      },
      {
        field: "materielCode",
        title: "物料编号",
        type: "string",
        width: 150,
        align: "left",
      },
      // {
      //   field: "materielName",
      //   title: "物料名称",
      //   type: "decimal",
      //   width: 90,
      //   align: "left",
      // },
      {
        field: "originalSerilNumber",
        title: "原条码",
        type: "string",
        width: 180,
        align: "left",
      },
      {
        field: "newSerilNumber",
        title: "新条码",
        type: "string",
        width: 180,
        align: "left",
      },
      // {
      //   field: "serilNumber",
      //   title: "序列号",
      //   type: "int",
      //   width: 280,
      //   align: "left",
      // },
      {
        field: "remark",
        title: "备注",
        type: "string",
        width: 280,
        align: "left",
      },
      {
        field: "batchNo",
        title: "批次号",
        type: "string",
        width: 150,
        align: "left",
      },
      {
        field: "orderNo",
        title: "单据编号",
        type: "string",
        width: 150,
        align: "left",
      },
      // {
      //   field: "changeType",
      //   title: "变动类型",
      //   type: "int",
      //   width: 120,
      //   align: "left",
      //   bind: { key: "stockChangeType", data: [] },
      // },
      {
        field: "changeQuantity",
        title: "变动数量",
        type: "string",
        width: 100,
        align: "left",
      },
      {
        field: "beforeQuantity",
        title: "变动前库存量",
        type: "string",
        width: 100,
        align: "left",
      },
      {
        field: "afterQuantity",
        title: "变动后库存量",
        type: "string",
        width: 100,
        align: "left",
      },
      {
        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",
        hidden: true,
      },
      {
        field: "modifyDate",
        title: "修改时间",
        type: "datetime",
        width: 160,
        align: "left",
        hidden: true,
      },
      {
        field: "orderId",
        title: "单据主键",
        type: "string",
        width: 180,
        align: "left",
        hidden: true,
      },
      {
        field: "orderDetailId",
        title: "单据明细主键",
        type: "string",
        width: 120,
        align: "left",
        hidden: true,
      },
      {
        field: "remark",
        title: "备注",
        type: "string",
        width: 100,
        align: "left",
        hidden: true,
      },
    ]);
    const detail = ref({
      cnName: "#detailCnName",
      table: "",
      columns: [],
      sortName: "",
    });
    return {
      table,
      extend,
      editFormFields,
      editFormOptions,
      searchFormFields,
      searchFormOptions,
      columns,
      detail,
    };
  },
});
</script>
    
ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/views/stock/stockInfoDetail.vue
@@ -114,14 +114,14 @@
        field: "orderNo",
        title: "单据编号",
        type: "decimal",
        width: 90,
        width: 150,
        align: "left",
      },
      {
        field: "batchNo",
        title: "批次号",
        type: "string",
        width: 90,
        width: 150,
        align: "left",
      },
      {
@@ -130,6 +130,7 @@
        type: "int",
        width: 120,
        align: "left",
        hidden: true,
      },
      {
        field: "supplyCode",
@@ -163,7 +164,7 @@
        field: "outboundQuantity",
        title: "出库数量",
        type: "string",
        width: 180,
        width: 120,
        align: "left",
      },
      {
@@ -208,6 +209,7 @@
        type: "string",
        width: 100,
        align: "left",
        hidden: true,
      },
    ]);
    const detail = ref({
ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/views/taskinfo/task.vue
@@ -1,19 +1,11 @@
<template>
  <view-grid
    ref="grid"
    :columns="columns"
    :detail="detail"
    :editFormFields="editFormFields"
    :editFormOptions="editFormOptions"
    :searchFormFields="searchFormFields"
    :searchFormOptions="searchFormOptions"
    :table="table"
    :extend="extend"
  >
  <view-grid ref="grid" :columns="columns" :detail="detail" :editFormFields="editFormFields"
    :editFormOptions="editFormOptions" :searchFormFields="searchFormFields" :searchFormOptions="searchFormOptions"
    :table="table" :extend="extend">
  </view-grid>
</template>
    <script>
<script>
import extend from "@/extension/taskinfo/task.js";
import { ref, defineComponent } from "vue";
export default defineComponent({
@@ -45,17 +37,16 @@
      [
        { title: "任务号", field: "taskNum", type: "int" },
        { title: "托盘编号", field: "palletCode", type: "like" },
        { title: "创建人", field: "creater", type: "like" },
        // { title: "创建人", field: "creater", type: "like" },
      ],
      [
        //{ title: "任务类型",field: "taskType",type: "selectList",dataKey: "taskType",data: [],},
        { title: "任务状态",field: "taskStatus",type: "selectList",dataKey: "taskStatusEnum",data: [],},
        { title: "巷道号", field: "roadway", type: "like" },
        { title: "任务类型", field: "taskType", type: "selectList", dataKey: "taskType", data: [], },
        { title: "任务状态", field: "taskStatus", type: "selectList", dataKey: "taskStatusEnum", data: [], },
      ],
      [
        { title: "起始地址", field: "sourceAddress", type: "like" },
        { title: "目标地址", field: "targetAddress", type: "like" },
        { title: "创建时间", field: "createDate", type: "datetime" },
        // { title: "创建时间", field: "createDate", type: "datetime" },
      ],
    ]);
    const columns = ref([
@@ -89,6 +80,7 @@
        type: "string",
        width: 120,
        align: "left",
        hidden: true,
      },
      {
        field: "taskType",
@@ -161,7 +153,7 @@
        type: "datetime",
        width: 160,
        align: "left",
        hidden:true,
        hidden: true,
      },
      {
        field: "wMSId",
ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/views/taskinfo/task_hty.vue
@@ -1,19 +1,11 @@
<template>
  <view-grid
    ref="grid"
    :columns="columns"
    :detail="detail"
    :editFormFields="editFormFields"
    :editFormOptions="editFormOptions"
    :searchFormFields="searchFormFields"
    :searchFormOptions="searchFormOptions"
    :table="table"
    :extend="extend"
  >
  <view-grid ref="grid" :columns="columns" :detail="detail" :editFormFields="editFormFields"
    :editFormOptions="editFormOptions" :searchFormFields="searchFormFields" :searchFormOptions="searchFormOptions"
    :table="table" :extend="extend">
  </view-grid>
</template>
    <script>
<script>
import extend from "@/extension/taskinfo/task_hty.js";
import { ref, defineComponent } from "vue";
export default defineComponent({
@@ -42,20 +34,20 @@
      createDate: "",
    });
    const searchFormOptions = ref([
    [
      [
        { title: "任务号", field: "taskNum", type: "int" },
        { title: "托盘编号", field: "palletCode", type: "like" },
        { title: "创建人", field: "creater", type: "like" },
        // { title: "创建人", field: "creater", type: "like" },
      ],
      [
        //{ title: "任务类型",field: "taskType",type: "selectList",dataKey: "taskType",data: [],},
        { title: "任务状态",field: "taskStatus",type: "selectList",dataKey: "taskStatusEnum",data: [],},
        { title: "巷道号", field: "roadway", type: "like" },
        { title: "任务类型", field: "taskType", type: "selectList", dataKey: "taskType", data: [], },
        { title: "任务状态", field: "taskStatus", type: "selectList", dataKey: "taskStatusEnum", data: [], },
        // { title: "巷道号", field: "roadway", type: "like" },
      ],
      [
        { title: "起始地址", field: "sourceAddress", type: "like" },
        { title: "目标地址", field: "targetAddress", type: "like" },
        { title: "创建时间", field: "createDate", type: "datetime" },
        // { title: "创建时间", field: "createDate", type: "datetime" },
      ],
    ]);
    const columns = ref([
@@ -89,15 +81,16 @@
        type: "string",
        width: 120,
        align: "left",
        hidden: true,
      },
      // {
      //   field: "taskType",
      //   title: "任务类型",
      //   type: "int",
      //   width: 120,
      //   align: "left",
      //   bind: { key: "taskType", data: [] },
      // },
      {
        field: "taskType",
        title: "任务类型",
        type: "int",
        width: 120,
        align: "left",
        bind: { key: "taskType", data: [] },
      },
      {
        field: "taskStatus",
        title: "任务状态",
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/CopilotIndices/17.14.1231.31060/CodeChunks.db
Binary files differ
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/CopilotIndices/17.14.1231.31060/CodeChunks.db-shm
Binary files differ
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/CopilotIndices/17.14.1231.31060/CodeChunks.db-wal
Binary files differ
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/CopilotIndices/17.14.1231.31060/SemanticSymbols.db
Binary files differ
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/CopilotIndices/17.14.1231.31060/SemanticSymbols.db-shm
Binary files differ
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/CopilotIndices/17.14.1231.31060/SemanticSymbols.db-wal
Binary files differ
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_BasicService/ESSApiService.cs
@@ -8,6 +8,8 @@
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using WIDESEA_Core.Helper;
using WIDESEA_Core.LogHelper;
using WIDESEA_DTO.Basic;
using WIDESEA_IBasicService;
@@ -66,6 +68,8 @@
                var result = await PostAsync<TaskModel, ApiResponse<TasksData>>(url, request);
                if (result != null && result.Code == 0)
                {
                    _logger.LogInformation(result.Serialize());
                    return true;
                }
                return false;
@@ -76,31 +80,45 @@
                return false;
            }
        }
        private async Task<TResponse> PostAsync<TRequest, TResponse>(string url, TRequest request)
        {
            string json = JsonConvert.SerializeObject(request, new JsonSerializerSettings
            TResponse response1 = (TResponse)Activator.CreateInstance(typeof(TResponse));
            try
            {
                ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver()
            });
            var content = new StringContent(json, Encoding.UTF8, "application/json");
            var _client = _httpClientFactory.CreateClient("ESSUrl");
            _client.DefaultRequestHeaders.Clear();
                string json = JsonConvert.SerializeObject(request, new JsonSerializerSettings
                {
                    ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver()
                });
                var content = new StringContent(json, Encoding.UTF8, "application/json");
                var _client = _httpClientFactory.CreateClient("ESSUrl");
                _client.DefaultRequestHeaders.Clear();
            _client.DefaultRequestHeaders.Add("Accept", "application/json");
                _client.DefaultRequestHeaders.Add("Accept", "application/json");
            using var response = await _client.PostAsync(url, content);
            string body = await response.Content.ReadAsStringAsync();
            _logger.LogInformation($"ESSAPI post :  {_client.BaseAddress}  {url}   {body}");
            if (!response.IsSuccessStatusCode)
            {
                throw new HttpRequestException(body);
                using var response = await _client.PostAsync(url, content);
                string body = await response.Content.ReadAsStringAsync();
                _logger.LogInformation($"ESSAPI post :  {_client.BaseAddress}  {url}   {body}");
                if (!response.IsSuccessStatusCode)
                {
                    throw new HttpRequestException(body);
                }
                response1 = JsonConvert.DeserializeObject<TResponse>(body);
                return response1;
            }
            return JsonConvert.DeserializeObject<TResponse>(body);
            catch (Exception ex)
            {
                Logger.Add(request == null ? "" : JsonConvert.SerializeObject(request), response1 == null ? ex.ToString() : JsonConvert.SerializeObject(response1));
                throw new Exception(ex.Message);
            }
            finally
            {
                Logger.Add(request == null ? "" : JsonConvert.SerializeObject(request), response1 == null ? "" : JsonConvert.SerializeObject(response1));
            }
        }
    }
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_BasicService/MESOperation/FeedbackMesService.cs
@@ -12,6 +12,7 @@
using WIDESEA_Core.BaseServices;
using WIDESEA_Core.Helper;
using WIDESEA_Core.HttpContextUser;
using WIDESEA_Core.LogHelper;
using WIDESEA_Core.Util;
using WIDESEA_DTO.Base;
using WIDESEA_DTO.ReturnMES;
@@ -42,12 +43,13 @@
        public WebResponseContent OutboundFeedback(string orderNo)
        {
            WebResponseContent webResponse = new WebResponseContent();
            try
            {
                Dt_OutboundOrder outboundOrder = _outboundOrderRepository.Db.Queryable<Dt_OutboundOrder>().Where(x => x.OrderNo == orderNo).Includes(x => x.Details).First();
                if (outboundOrder == null)
                {
                    return WebResponseContent.Instance.Error($"未找到对应的出库单信息");
                    return webResponse = WebResponseContent.Instance.Error($"未找到对应的出库单信息");
                }
                List<Dt_MesReturnRecord> returnRecords = BaseDal.QueryData(x => x.OrderNo == orderNo && x.OrderId == outboundOrder.Id && x.ReturnStatus == 2);
@@ -91,12 +93,12 @@
                    MaterialOutboundReturnDTO? returnDTO = BuildOutboundFeedbackData(outboundOrder);
                    if (returnDTO == null)
                    {
                        return WebResponseContent.Instance.Error($"构建回调对象失败");
                        return webResponse = WebResponseContent.Instance.Error($"构建回调对象失败");
                    }
                    if (returnDTO.Details.Count <= 0)
                    {
                        return WebResponseContent.Instance.Error($"该单据无明细可回传");
                        return webResponse = WebResponseContent.Instance.Error($"该单据无明细可回传");
                    }
                    string apiUrl = AppSettings.GetValue("MaterialOutboundFeedbackUrl");
@@ -116,18 +118,18 @@
                    Dt_AllocateOrder allocateOrder = _allocateRepository.QueryFirst(x => x.OrderNo == outboundOrder.OrderNo);
                    if (allocateOrder == null)
                    {
                        return WebResponseContent.Instance.Error($"未找到对应的调拨单");
                        return webResponse = WebResponseContent.Instance.Error($"未找到对应的调拨单");
                    }
                    AllocationReturnDTO? returnDTO = BuildAllocationFeedbackData(outboundOrder, allocateOrder.FromWarehouse, allocateOrder.ToWarehouse);
                    if (returnDTO == null)
                    {
                        return WebResponseContent.Instance.Error($"构建回调对象失败");
                        return webResponse = WebResponseContent.Instance.Error($"构建回调对象失败");
                    }
                    if (returnDTO.Details.Count <= 0)
                    {
                        return WebResponseContent.Instance.Error($"该单据无明细可回传");
                        return webResponse = WebResponseContent.Instance.Error($"该单据无明细可回传");
                    }
                    string apiUrl = AppSettings.GetValue("AllocationFeedbackUrl"); ;
@@ -141,6 +143,8 @@
                    lineNos = returnDTO.Details.Select(x => x.LineNo).ToList();
                    httpResponseResult = _httpClientHelper.Post<MesResponseDTO>(apiUrl, requestData);
                    httpResponseResult.ApiUrl = apiUrl;
                    Logger.Add(requestData, httpResponseResult.Serialize());
                }
                bool isSuccess = httpResponseResult.IsSuccess && httpResponseResult.Data.Code == "200";
@@ -210,14 +214,19 @@
                _unitOfWorkManage.CommitTran();
                int successCount = returnRecords.Where(x => x.ReturnStatus == 1).Count() + (isSuccess ? 1 : 0);
                int failCount = returnRecords.Where(x => x.ReturnStatus == 2).Count() + (isSuccess ? 1 : 0);
                WebResponseContent responseContent = new WebResponseContent();
                responseContent.Status = true;
                responseContent.Message = $"回调成功条数:{successCount},回调失败条数:{failCount}";
                return responseContent;
                webResponse.Status = true;
                webResponse.Message = $"回调成功条数:{successCount},回调失败条数:{failCount}";
                return webResponse;
            }
            catch (Exception ex)
            {
                return WebResponseContent.Instance.Error(ex.Message);
                return webResponse = WebResponseContent.Instance.Error(ex.Message);
            }
            finally
            {
                Logger.Add(orderNo, webResponse.Serialize());
            }
        }
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_DTO/Inbound/CompleteStockTakeDTO.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WIDESEA_Core.Attributes;
namespace WIDESEA_DTO.Inbound
{
    public class CompleteStockTakeDTO
    {
        public string orderNo { get; set; }
        public string boxNo { get; set; }
        public string barcode { get; set; }
        public decimal actualQuantity { get; set; }
        public decimal stockQuantity { get; set; }
    }
}
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_IInboundService/ITakeStockOrderDetailService.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WIDESEA_Core.BaseServices;
using WIDESEA_Model.Models;
namespace WIDESEA_IInboundService
{
    public interface ITakeStockOrderDetailService:IService<Dt_TakeStockOrderDetail>
    {
    }
}
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_IInboundService/ITakeStockOrderService.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,24 @@
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WIDESEA_Core;
using WIDESEA_Core.BaseServices;
using WIDESEA_DTO.Inbound;
using WIDESEA_Model.Models;
namespace WIDESEA_IInboundService
{
    public interface ITakeStockOrderService : IService<Dt_TakeStockOrder>
    {
        WebResponseContent ValidateBoxNo(string orderNo, string boxNo);
        WebResponseContent ValidateBarcode(string boxNo, string barcode);
        WebResponseContent CompleteStockTake([FromBody] CompleteStockTakeDTO completeStockTakeDTO);
        WebResponseContent ReturnBox(string orderNo, string boxNo);
    }
}
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_InboundService/InboundService.cs
@@ -120,6 +120,7 @@
                        StockId = stockInfo == null ? 0 : stockInfo.Id,
                        Barcode = item.Barcode,
                        MaterielCode = item.MaterielCode,
                        MaterielName = item.MaterielName,
                        BatchNo = item.BatchNo,
                        Unit = item.Unit,
                        InboundOrderRowNo = item.lineNo,
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_InboundService/TakeStockOrderDetailService.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WIDESEA_Core.BaseRepository;
using WIDESEA_Core.BaseServices;
using WIDESEA_IInboundService;
using WIDESEA_Model.Models;
namespace WIDESEA_InboundService
{
    public class TakeStockOrderDetailService : ServiceBase<Dt_TakeStockOrderDetail, IRepository<Dt_TakeStockOrderDetail>>, ITakeStockOrderDetailService
    {
        public IRepository<Dt_TakeStockOrderDetail> Repository => BaseDal;
        public TakeStockOrderDetailService(IRepository<Dt_TakeStockOrderDetail> BaseDal) : base(BaseDal)
        {
        }
    }
}
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_InboundService/TakeStockOrderService.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,252 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WIDESEA_Core.BaseServices;
using WIDESEA_Core;
using WIDESEA_IInboundService;
using WIDESEA_Model.Models;
using WIDESEA_Common.OrderEnum;
using WIDESEA_Core.Helper;
using Microsoft.AspNetCore.Mvc.RazorPages;
using WIDESEA_Core.Enums;
using SqlSugar;
using WIDESEA_Core.BaseRepository;
using WIDESEA_Common.StockEnum;
using Microsoft.AspNetCore.Mvc;
using WIDESEA_DTO.Inbound;
using WIDESEA_DTO.ReturnMES;
using MailKit.Search;
using static System.Collections.Specialized.BitVector32;
using WIDESEA_Common.CommonEnum;
using WIDESEA_Common.TaskEnum;
using WIDESEA_IBasicService;
namespace WIDESEA_InboundService
{
    public class TakeStockOrderService : ServiceBase<Dt_TakeStockOrder, IRepository<Dt_TakeStockOrder>>, ITakeStockOrderService
    {
        public IRepository<Dt_TakeStockOrder> Repository => BaseDal;
        private readonly IUnitOfWorkManage _unitOfWorkManage;
        private readonly IRepository<Dt_TakeStockOrder> _takeStockOrder;
        private readonly IRepository<Dt_StockInfo> _stockInfoRepository;
        private readonly IRepository<Dt_TakeStockOrderDetail> _takeStockOrderDetail;
        private readonly IRepository<Dt_Task> _taskRepository;
        private readonly ILocationInfoService _locationInfoService;
        public TakeStockOrderService(IRepository<Dt_TakeStockOrder> BaseDal, IUnitOfWorkManage unitOfWorkManage,IRepository<Dt_TakeStockOrder> takeStockOrder,IRepository<Dt_StockInfo> stockInfoRepository,IRepository<Dt_TakeStockOrderDetail> takeStockOrderDetail,IRepository<Dt_Task> taskRepository,ILocationInfoService locationInfoService) : base(BaseDal)
        {
            _unitOfWorkManage = unitOfWorkManage;
            _takeStockOrder = takeStockOrder;
            _stockInfoRepository = stockInfoRepository;
            _takeStockOrderDetail = takeStockOrderDetail;
            _taskRepository = taskRepository;
            _locationInfoService = locationInfoService;
        }
        public WebResponseContent ValidateBoxNo(string orderNo, string boxNo)
        {
            try
            {
                Dt_StockInfo stockInfo = _stockInfoRepository.QueryFirst(x => x.PalletCode == boxNo);
                if (stockInfo == null) {
                    return WebResponseContent.Instance.Error("未找到该托盘库存");
                }
                if(stockInfo.StockStatus != StockStatusEmun.盘点出库完成.ObjToInt())
                {
                    return WebResponseContent.Instance.Error("该托盘处于非盘点状态,请检查盘点任务");
                }
                Dt_TakeStockOrder takeStockOrder = _takeStockOrder.QueryFirst(x=>x.OrderNo == orderNo);
                if (takeStockOrder == null)
                {
                    return WebResponseContent.Instance.Error("未找到该盘点单据");
                }
                if (takeStockOrder.AllPalletCode.Contains(","))
                {
                    var remarkValues = takeStockOrder.AllPalletCode
                        .Split(',')
                        .Select(s => s.Trim())
                        .Where(s => !string.IsNullOrWhiteSpace(s))
                        .ToList();
                    if (remarkValues.Count == 0)
                    {
                        return WebResponseContent.Instance.Error("盘点单箱号仅包含逗号,无有效箱号数据");
                    }
                    bool isMatch = remarkValues.Any(val => val.Equals(boxNo, StringComparison.OrdinalIgnoreCase));
                    if (!isMatch)
                    {
                        return WebResponseContent.Instance.Error($"箱号【{boxNo}】未在盘点单箱号【{takeStockOrder.Remark}】中找到匹配项");
                    }
                }
                else
                {
                    bool isMatch = takeStockOrder.Remark.Trim().Equals(boxNo, StringComparison.OrdinalIgnoreCase);
                    if (!isMatch)
                    {
                        return WebResponseContent.Instance.Error($"箱号【{boxNo}】与盘点单箱号【{takeStockOrder.Remark}】不匹配");
                    }
                }
                return WebResponseContent.Instance.OK();
            }
            catch(Exception ex)
            {
                return WebResponseContent.Instance.Error(ex.Message);
            }
        }
        public WebResponseContent ValidateBarcode(string boxNo, string barcode)
        {
            try
            {
                Dt_StockInfo stockInfo = _stockInfoRepository.Db.Queryable<Dt_StockInfo>().Where(x => x.PalletCode == boxNo).Includes(x => x.Details).First();
                if(stockInfo == null)
                {
                    return WebResponseContent.Instance.Error("未找到该料箱库存信息");
                }
                if(stockInfo.Details == null)
                {
                    return WebResponseContent.Instance.Error("未找到该料箱库存");
                }
                List<string> barcodes = stockInfo.Details.Select(x => x.Barcode).ToList();
                bool isMatch = barcodes.Any(val => val.Equals(barcode, StringComparison.OrdinalIgnoreCase));
                if (!isMatch)
                {
                    return WebResponseContent.Instance.Error($"条码【{barcode}】未在【{boxNo}】料箱条码中找到匹配项");
                }
                var stockDetail = stockInfo.Details.FirstOrDefault(x=>x.Barcode == barcode);
                var resultData = new { stockQuantity = stockDetail.StockQuantity };
                return WebResponseContent.Instance.OK(data:resultData);
            }
            catch(Exception ex)
            {
                return WebResponseContent.Instance.Error(ex.Message);
            }
        }
        public WebResponseContent CompleteStockTake([FromBody] CompleteStockTakeDTO completeStockTakeDTO)
        {
            try
            {
                Dt_TakeStockOrder takeStockOrder = _takeStockOrder.QueryFirst(x=>x.OrderNo == completeStockTakeDTO.orderNo);
                if (takeStockOrder == null)
                {
                    return WebResponseContent.Instance.Error("未找到该盘点单据");
                }
                Dt_StockInfo stockInfo = _stockInfoRepository.Db.Queryable<Dt_StockInfo>().Where(x => x.PalletCode == completeStockTakeDTO.boxNo).Includes(x=>x.Details).First();
                if(stockInfo == null)
                {
                    return WebResponseContent.Instance.Error("未找到该托盘库存");
                }
                Dt_StockInfoDetail stockInfoDetail = stockInfo.Details.FirstOrDefault(x => x.Barcode == completeStockTakeDTO.barcode);
                if(stockInfoDetail == null)
                {
                    return WebResponseContent.Instance.Error("条码库存数据未找到匹配数据");
                }
                Dt_TakeStockOrderDetail takeStockOrderDetail = new Dt_TakeStockOrderDetail()
                {
                    TakeStockId = takeStockOrder.Id,
                    MaterielCode = stockInfoDetail.MaterielCode,
                    MaterielName = stockInfoDetail.MaterielName??"",
                    BatchNo = stockInfoDetail.BatchNo,
                    TakePalletCode = completeStockTakeDTO.boxNo,
                    TakeDetalStatus = TakeStockDetailStatusEnum.盘点完成.ObjToInt(),
                    Unit = stockInfoDetail.Unit,
                    SysQty = completeStockTakeDTO.stockQuantity,
                    Qty =completeStockTakeDTO.actualQuantity,
                    Remark = completeStockTakeDTO.stockQuantity-completeStockTakeDTO.actualQuantity>=0 ?"盘亏":"盘盈",
                    barcode = completeStockTakeDTO.barcode,
                    WarehouseCode = stockInfoDetail.WarehouseCode??"",
                    FactoryArea = stockInfoDetail.FactoryArea,
                    SupplyCode = stockInfoDetail.SupplyCode??"",
                    TakeStockNo = takeStockOrder.OrderNo,
                };
                _unitOfWorkManage.BeginTran();
                _takeStockOrderDetail.AddData(takeStockOrderDetail);
                _unitOfWorkManage.CommitTran();
                return WebResponseContent.Instance.OK();
            }
            catch (Exception ex)
            {
                _unitOfWorkManage.RollbackTran();
                return WebResponseContent.Instance.Error(ex.Message);
            }
        }
        public WebResponseContent ReturnBox(string orderNo, string boxNo)
        {
            WebResponseContent content = new WebResponseContent();
            try
            {
                Dt_TakeStockOrder takeStockOrder = _takeStockOrder.QueryFirst(x=>x.OrderNo == orderNo);
                if(takeStockOrder == null)
                {
                    return content.Error("未找到该盘点单据");
                }
                var stock = _stockInfoRepository.QueryFirst(x => x.PalletCode == boxNo);
                if (stock == null)
                {
                    return content.Error($"未找到托盘{boxNo}库存信息不允许回库");
                }
                var task = _taskRepository.QueryFirst(x => x.PalletCode == boxNo);
                if (task != null)
                {
                    return content.Error($"托盘{boxNo}存在任务回库失败!");
                }
                if(stock.StockStatus != StockStatusEmun.盘点出库完成.ObjToInt())
                {
                    return content.Error("该托盘状态不对,不允许盘点入库");
                }
                stock.StockStatus = StockStatusEmun.入库确认.ObjToInt();
                takeStockOrder.TakeStockStatus = TakeStockStatusEnum.盘点完成.ObjToInt();
                // åˆ†é…æ–°è´§ä½
                var newLocation = _locationInfoService.AssignLocation(stock.LocationType);
                var newTask = new Dt_Task()
                {
                    CurrentAddress = takeStockOrder.Remark,
                    Grade = 0,
                    PalletCode = boxNo,
                    NextAddress = "",
                    OrderNo = takeStockOrder.OrderNo,
                    Roadway = newLocation.RoadwayNo,
                    SourceAddress = takeStockOrder.Remark,
                    TargetAddress = newLocation.LocationCode,
                    TaskStatus = (int)TaskStatusEnum.New,
                    TaskType = TaskTypeEnum.InInventory.ObjToInt(),
                    PalletType = stock.PalletType,
                    WarehouseId = stock.WarehouseId
                };
                _unitOfWorkManage.BeginTran();
                _stockInfoRepository.UpdateData(stock);
                _takeStockOrder.UpdateData(takeStockOrder);
                _taskRepository.AddData(newTask);
                _unitOfWorkManage.CommitTran();
                //var moveResult = await _eSSApiService.MoveContainerAsync(new MoveContainerRequest
                //{
                //    slotCode = movestations[station],
                //    containerCode = palletCode
                //});
                return content.OK();
            }
            catch (Exception ex)
            {
                _unitOfWorkManage.RollbackTran();
                return content.Error(ex.Message);
            }
        }
    }
}
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_Model/Models/Inbound/Dt_TakeStockOrderDetail.cs
@@ -1,4 +1,5 @@
using SqlSugar;
using Magicodes.ExporterAndImporter.Core;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -18,108 +19,126 @@
        /// ä¸»é”®
        /// </summary>
        [SugarColumn(IsPrimaryKey = true, IsIdentity = true, ColumnDescription = "主键")]
        [ExporterHeader(DisplayName = "主键")]
        public int Id { get; set; }
        /// <summary>
        /// ç›˜ç‚¹å•主键
        /// </summary>
        [SugarColumn(IsNullable = false, ColumnDescription = "盘点单主键")]
        [ExporterHeader(DisplayName = "盘点单主键")]
        public int TakeStockId { get; set; }
        /// <summary>
        /// ç‰©æ–™ç¼–码
        /// </summary>
        [SugarColumn(IsNullable = false, Length = 50, ColumnDescription = "物料编码")]
        [ExporterHeader(DisplayName = "物料编码")]
        public string MaterielCode { get; set; }
        /// <summary>
        /// ç‰©æ–™åç§°
        /// </summary>
        [SugarColumn(IsNullable = false, Length = 200, ColumnDescription = "物料名称")]
        [ExporterHeader(DisplayName = "物料名称")]
        public string MaterielName { get; set; }
        /// <summary>
        /// æ‰¹æ¬¡å·
        /// </summary>
        [SugarColumn(IsNullable = false, Length = 50, ColumnDescription = "批次号")]
        [ExporterHeader(DisplayName = "批次号")]
        public string BatchNo { get; set; }
        /// <summary>
        /// ç‰©æ–™è§„æ ¼
        /// </summary>
        [SugarColumn(IsNullable = true, Length = 200, ColumnDescription = "物料规格")]
        [ExporterHeader(DisplayName = "物料规格")]
        public string MaterielSpec { get; set; }
        /// <summary>
        /// åŽŸä»“ä½
        /// </summary>
        [SugarColumn(IsNullable = true, Length = 50, ColumnDescription = "原仓位")]
        [ExporterHeader(DisplayName = "原仓位")]
        public string LocationCode { get; set; }
        /// <summary>
        /// ç›˜ç‚¹æ‰˜ç›˜
        /// </summary>
        [SugarColumn(IsNullable = true, Length = 50, ColumnDescription = "盘点托盘")]
        [ExporterHeader(DisplayName = "盘点托盘")]
        public string TakePalletCode { get; set; }
        /// <summary>
        /// ç›˜ç‚¹æ˜Žç»†çŠ¶æ€
        /// </summary>
        [SugarColumn(IsNullable = true, ColumnDescription = "盘点明细状态")]
        [ExporterHeader(DisplayName = "盘点明细状态")]
        public int TakeDetalStatus { get; set; }
        /// <summary>
        /// å•位
        /// </summary>
        [SugarColumn(IsNullable = true, Length = 50, ColumnDescription = "单位")]
        [ExporterHeader(DisplayName = "单位")]
        public string Unit { get; set; }
        /// <summary>
        /// è´¦é¢æ•°é‡
        /// </summary>
        [SugarColumn(IsNullable = true, ColumnDescription = "账面数量")]
        [ExporterHeader(DisplayName = "账面数量")]
        public decimal SysQty { get; set; }
        /// <summary>
        /// å®žç›˜æ•°é‡
        /// </summary>
        [SugarColumn(IsNullable = true, ColumnDescription = "实盘数量")]
        [ExporterHeader(DisplayName = "实盘数量")]
        public decimal Qty { get; set; }
        /// <summary>
        /// å¤‡æ³¨
        /// </summary>
        [SugarColumn(IsNullable = true, Length = 500, ColumnDescription = "备注")]
        [ExporterHeader(DisplayName = "备注")]
        public string Remark { get; set; }
        /// <summary>
        /// æ¡ç 
        /// </summary>
        [SugarColumn(IsNullable = true, Length = 50, ColumnDescription = "条码")]
        [ExporterHeader(DisplayName = "条码")]
        public string barcode { get; set; }
        /// <summary>
        /// ç‰©æ–™ä»“库
        /// </summary>
        [SugarColumn(IsNullable = true, Length = 20, ColumnDescription = "物料仓库")]
        [ExporterHeader(DisplayName = "物料仓库")]
        public string WarehouseCode { get; set; }
        /// <summary>
        /// åŽ‚åŒº
        /// </summary>
        [SugarColumn(IsNullable = true, Length = 10, ColumnDescription = "厂区")]
        [ExporterHeader(DisplayName = "厂区")]
        public string FactoryArea { get; set; }
        /// <summary>
        /// ä¾›åº”商编号
        /// </summary>
        [SugarColumn(IsNullable = true, Length = 20, ColumnDescription = "供应商编号")]
        [ExporterHeader(DisplayName = "供应商编号")]
        public string SupplyCode { get; set; }
        /// <summary>
        /// ç›˜ç‚¹å•单据
        /// </summary>
        [SugarColumn(IsNullable = true, Length = 50, ColumnDescription = "盘点单单据")]
        [ExporterHeader(DisplayName = "盘点单单据")]
        public string TakeStockNo { get; set; }
    }
}
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundService.cs
@@ -1435,7 +1435,7 @@
                        List<Barcodes> barcodesList = new List<Barcodes>();
                        Barcodes barcodes = new Barcodes
                        {
                            Barcode = newBarcode,
                            Barcode = isUnpacked ? newBarcode : stockDetail?.Barcode,
                            Qty = barcodeQuantity,
                            SupplyCode = stockDetail?.SupplyCode ?? "",
                            BatchNo = stockDetail?.BatchNo ?? "",
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_SystemService/Sys_DictionaryService.cs
@@ -295,6 +295,54 @@
                            result = new VueDictionaryDTO { DicNo = key, Config = "", Data = data };
                        }
                        break;
                    case "takeStockStatusEnum":
                        {
                            List<object> data = new List<object>();
                            Type type = typeof(TakeStockStatusEnum);
                            List<int> enums = Enum.GetValues(typeof(TakeStockStatusEnum)).Cast<int>().ToList();
                            int index = 0;
                            foreach (var item in enums)
                            {
                                FieldInfo? fieldInfo = typeof(TakeStockStatusEnum).GetField(((TakeStockStatusEnum)item).ToString());
                                DescriptionAttribute? description = fieldInfo.GetCustomAttribute<DescriptionAttribute>();
                                if (description != null)
                                {
                                    data.Add(new { key = item.ToString(), value = description.Description });
                                }
                                else
                                {
                                    data.Add(new { key = item.ToString(), value = item.ToString() });
                                }
                                index++;
                            }
                            result = new VueDictionaryDTO { DicNo = key, Config = "", Data = data };
                        }
                        break;
                    case "takeStockDetailStatusEnum":
                        {
                            List<object> data = new List<object>();
                            Type type = typeof(TakeStockDetailStatusEnum);
                            List<int> enums = Enum.GetValues(typeof(TakeStockDetailStatusEnum)).Cast<int>().ToList();
                            int index = 0;
                            foreach (var item in enums)
                            {
                                FieldInfo? fieldInfo = typeof(TakeStockDetailStatusEnum).GetField(((TakeStockDetailStatusEnum)item).ToString());
                                DescriptionAttribute? description = fieldInfo.GetCustomAttribute<DescriptionAttribute>();
                                if (description != null)
                                {
                                    data.Add(new { key = item.ToString(), value = description.Description });
                                }
                                else
                                {
                                    data.Add(new { key = item.ToString(), value = item.ToString() });
                                }
                                index++;
                            }
                            result = new VueDictionaryDTO { DicNo = key, Config = "", Data = data };
                        }
                        break;
                }
                return result;
            }
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService.cs
@@ -94,6 +94,7 @@
        private readonly IRepository<Dt_AllocateMaterialInfo_Hty> _allocateMaterialInfo_Hty;
        private readonly HttpClientHelper _httpClientHelper;
        private readonly IBasicService _basicService;
        private readonly IRepository<Dt_TakeStockOrder> _takeStockOrder;
        public IRepository<Dt_Task> Repository => BaseDal;
        private Dictionary<string, SqlSugar.OrderByType> _taskOrderBy = new()
@@ -113,7 +114,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, ITask_HtyService task_HtyService, IRepository<Dt_AllocateMaterialInfo> allocateMaterialInfo, IRepository<Dt_AllocateMaterialInfo_Hty> allocateMaterialInfo_Hty, HttpClientHelper httpClientHelper, IBasicService basicService) : 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, IRepository<Dt_AllocateMaterialInfo> allocateMaterialInfo, IRepository<Dt_AllocateMaterialInfo_Hty> allocateMaterialInfo_Hty, HttpClientHelper httpClientHelper, IBasicService basicService,IRepository<Dt_TakeStockOrder> takeStockOrder) : base(BaseDal)
        {
            _mapper = mapper;
            _unitOfWorkManage = unitOfWorkManage;
@@ -141,6 +142,7 @@
            _allocateMaterialInfo_Hty = allocateMaterialInfo_Hty;
            _httpClientHelper = httpClientHelper;
            _basicService = basicService;
            _takeStockOrder = takeStockOrder;
        }
        public async Task TaskStatusChange(string taskNum, TaskStatusEnum taskStatusEnum)
@@ -591,6 +593,7 @@
            _stockService.StockInfoService.Db.UpdateNav(stock).IncludesAllFirstLayer().ExecuteCommand();
            task.TaskStatus = (int)TaskStatusEnum.Finish;
            var result = _task_HtyService.DeleteAndMoveIntoHty(task, OperateTypeEnum.自动完成);
            if (!result)
            {
@@ -1849,5 +1852,134 @@
            return TaskCompleted(TaskNum);
        }
        /// <summary>
        /// ç›˜ç‚¹å‡ºåº“完成
        /// </summary>
        public WebResponseContent OutInventoryTaskCompleted(Dt_Task task)
        {
            WebResponseContent content = new WebResponseContent();
            try
            {
                task = BaseDal.QueryFirst(x => x.TaskNum == task.TaskNum);
                if (task == null)
                {
                    return WebResponseContent.Instance.Error("未找到任务信息");
                }
                var SourceAddress = task.SourceAddress;
                Dt_StockInfo stockInfo = _stockService.StockInfoService.Repository.QueryFirst(x=>x.PalletCode == task.PalletCode);
                Dt_LocationInfo locationInfo = _basicService.LocationInfoService.Repository.QueryFirst(x => x.LocationCode == SourceAddress);
                if (stockInfo == null) return WebResponseContent.Instance.Error("未找到库存信息");
                if (locationInfo == null) return WebResponseContent.Instance.Error("未找到货位信息");
                //获取对应盘点单
                Dt_TakeStockOrder takeStockOrder = _takeStockOrder.Db.Queryable<Dt_TakeStockOrder>().Where(x => x.OrderNo == task.OrderNo).Includes(x => x.Details).First();
                if (takeStockOrder == null)
                {
                    return content.Error($"盘点单{task.OrderNo}不存在");
                }
                if (takeStockOrder.TakeStockStatus != TakeStockStatusEnum.盘点中.ObjToInt())
                {
                    return content.Error($"盘点单{task.OrderNo}盘点已完成或未开始");
                }
                if (stockInfo.StockStatus != StockStatusEmun.出库锁定.ObjToInt())
                {
                    return content.Error($"{stockInfo.PalletCode}库存状态不正确");
                }
                if (locationInfo.LocationStatus != LocationStatusEnum.Lock.ObjToInt())
                {
                    return content.Error($"{locationInfo.LocationCode}货位状态不正确");
                }
                stockInfo.StockStatus = StockStatusEmun.盘点出库完成.ObjToInt();
                stockInfo.LocationCode = "";
                task.TaskStatus = TaskStatusEnum.Finish.ObjToInt();
                int beforeStatus = locationInfo.LocationStatus;
                locationInfo.LocationStatus = LocationStatusEnum.Free.ObjToInt();
                _unitOfWorkManage.BeginTran();
                //货位变动记录
                _basicService.LocationInfoService.UpdateData(locationInfo);
                _recordService.LocationStatusChangeRecordSetvice.AddLocationStatusChangeRecord(locationInfo, beforeStatus, LocationStatusEnum.Free.ObjToInt(),  takeStockOrder?.OrderNo ?? "", task.TaskNum);
                _stockRepository.UpdateData(stockInfo);
                BaseDal.DeleteAndMoveIntoHty(task, App.User.UserId == 0 ? OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成);
                _unitOfWorkManage.CommitTran();
                content.OK();
            }
            catch (Exception ex)
            {
                _unitOfWorkManage.RollbackTran();
                content.Error(ex.Message);
            }
            return content;
        }
        /// <summary>
        /// ç›˜ç‚¹å…¥åº“完成
        /// </summary>
        /// <param name="task"></param>
        /// <returns></returns>
        public async Task<WebResponseContent> InInventoryTaskCompleted(Dt_Task task)
        {
            WebResponseContent content = new WebResponseContent();
            try
            {
                Dt_LocationInfo locationInfo = _locationInfoService.Repository.QueryFirst(x => x.LocationCode == task.TargetAddress);
                if (locationInfo == null)
                {
                    return content.Error($"未找到对应的终点货位信息");
                }
                Dt_StockInfo stockInfo = _stockRepository.Db.Queryable<Dt_StockInfo>().Where(x => x.PalletCode == task.PalletCode && x.WarehouseId == task.WarehouseId).First();
                if (stockInfo == null)
                {
                    return WebResponseContent.Instance.Error($"未找到托盘对应的组盘信息");
                }
                if (!string.IsNullOrEmpty(stockInfo.LocationCode))
                {
                    return WebResponseContent.Instance.Error($"该托盘已绑定货位");
                }
                if (locationInfo.LocationStatus == LocationStatusEnum.InStock.ObjToInt())
                {
                    return WebResponseContent.Instance.Error($"货位状态不正确");
                }
                var beforelocationStatus = locationInfo.LocationStatus;
                locationInfo.LocationStatus = LocationStatusEnum.InStock.ObjToInt();
                stockInfo.LocationCode = locationInfo.LocationCode;
                stockInfo.PalletCode = task.PalletCode;
                stockInfo.LocationCode = task.TargetAddress;
                stockInfo.StockStatus = StockStatusEmun.入库完成.ObjToInt();
                task.TaskStatus = TaskStatusEnum.Finish.ObjToInt();
                _unitOfWorkManage.BeginTran();
                _locationInfoService.Repository.UpdateData(locationInfo);
                _stockRepository.UpdateData(stockInfo);
                var result = _task_HtyService.DeleteAndMoveIntoHty(task, OperateTypeEnum.人工删除);
                _unitOfWorkManage.CommitTran();
                if (!result)
                {
                    await Db.Deleteable(task).ExecuteCommandAsync();
                }
                try
                {
                    _locationStatusChangeRecordService.AddLocationStatusChangeRecord(locationInfo, beforelocationStatus, StockChangeType.Inbound.ObjToInt(), "", task.TaskNum);
                }
                catch (Exception ex)
                {
                    _logger.LogInformation($"InEmptyTaskCompleted AddLocationStatusChangeRecord : {ex.Message} ");
                }
                return content;
            }
            catch (Exception ex)
            {
                _unitOfWorkManage.RollbackTran();
                return await Task.FromResult(WebResponseContent.Instance.Error(ex.Message));
            }
        }
    }
}
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService_Outbound.cs
@@ -393,7 +393,7 @@
                            TargetAddress = outStation,
                            TaskStatus = TaskStatusEnum.New.ObjToInt(),
                            TaskType = taskType.ObjToInt(),
                            // TaskNum = BaseDal.GetTaskNum(nameof(SequenceEnum.SeqTaskNum)),
                            //TaskNum = BaseDal.GetTaskNum(nameof(SequenceEnum.SeqTaskNum)),
                            PalletType = stockInfo.PalletType,
                            WarehouseId = stockInfo.WarehouseId,
                        };
@@ -1127,7 +1127,7 @@
                }
                //获取货位
                List<string> locStrs = stockInfos.Select(x => x.LocationCode).ToList();
                List<Dt_LocationInfo> locationInfos = (List<Dt_LocationInfo>)_locationInfoService.Db.Queryable<Dt_LocationInfo>().Where(x => locStrs.Contains(x.LocationCode));
                List<Dt_LocationInfo> locationInfos =_locationInfoService.Db.Queryable<Dt_LocationInfo>().Where(x => locStrs.Contains(x.LocationCode)).ToList();
                if (stockInfos.Count != locationInfos.Count)
                {
                    string? locStr = locStrs.FirstOrDefault(x => !locationInfos.Select(x => x.LocationCode).ToList().Contains(x));
@@ -1138,7 +1138,9 @@
                    WarehouseId = stockInfos.FirstOrDefault().WarehouseId,
                    TakeStockStatus = TakeStockStatusEnum.盘点中.ObjToInt(),
                    OrderNo = CreateCodeByRule(nameof(RuleCodeEnum.PDCodeRule)),
                    Details = new List<Dt_TakeStockOrderDetail>()
                    AllPalletCode = string.Join(",", stockInfos.Select(item => item.PalletCode).Where(palletCode => !string.IsNullOrEmpty(palletCode))),
                    Remark = outStation
                };
                foreach (var item in stockInfos)
                {
@@ -1172,7 +1174,7 @@
                _unitOfWorkManage.BeginTran();
                //更新库存状态
                _stockRepository.UpdateData(stockInfos);
                BaseDal.Db.InsertNav(takeStockOrder);
                _takeStockOrder.AddData(takeStockOrder);
                //新建任务
                BaseDal.AddData(tasks);
                _locationInfoService.UpdateData(locationInfos);
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Allocate/AllocateOrderController.cs
@@ -71,7 +71,7 @@
                {
                    return WebResponseContent.Instance.Error($"条码不能为空");
                }
                var materialName = _materialInfoRepository.QueryFirst(x => x.MaterielCode == detailDto.materialCode).MaterielName;
                var materialName = _materialInfoRepository.QueryFirst(x => x.MaterielCode == detailDto.MaterialCode).MaterielName;
                if (detailDto.Barcodes != null && detailDto.Barcodes.Any())
                {
                    foreach (var barcodeDto in detailDto.Barcodes)
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Inbound/TakeStockOrderController.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,57 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using WIDESEA_Core;
using WIDESEA_Core.BaseController;
using WIDESEA_DTO.Inbound;
using WIDESEA_IInboundService;
using WIDESEA_Model.Models;
namespace WIDESEA_WMSServer.Controllers.Inbound
{
    /// <summary>
    /// ç›˜ç‚¹å•
    /// </summary>
    [Route("api/TakeStockOrder")]
    [ApiController]
    public class TakeStockOrderController : ApiBaseController<ITakeStockOrderService, Dt_TakeStockOrder>
    {
        public TakeStockOrderController(ITakeStockOrderService service) : base(service)
        {
        }
        /// <summary>
        /// æ–™ç®±éªŒè¯
        /// </summary>
        [HttpPost,HttpGet, Route("ValidateBoxNo"), AllowAnonymous]
        public WebResponseContent ValidateBoxNo(string orderNo , string boxNo)
        {
            return Service.ValidateBoxNo(orderNo,boxNo);
        }
        /// <summary>
        /// æ¡ç éªŒè¯
        /// </summary>
        [HttpPost, HttpGet, Route("ValidateBarcode"), AllowAnonymous]
        public WebResponseContent ValidateBarcode( string boxNo,string barcode)
        {
            return Service.ValidateBarcode(boxNo, barcode);
        }
        /// <summary>
        /// ç›˜ç‚¹å®Œæˆè®°å½•
        /// </summary>
        [HttpPost, HttpGet, Route("CompleteStockTake"), AllowAnonymous]
        public WebResponseContent CompleteStockTake([FromBody] CompleteStockTakeDTO completeStockTakeDTO)
        {
            return Service.CompleteStockTake(completeStockTakeDTO);
        }
        /// <summary>
        /// ç›˜ç‚¹æ–™ç®±å›žåº“
        /// </summary>
        [HttpPost, HttpGet, Route("ReturnBox"), AllowAnonymous]
        public WebResponseContent ReturnBox(string orderNo, string boxNo)
        {
            return Service.ReturnBox(orderNo, boxNo);
        }
    }
}
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Inbound/TakeStockOrderDetailController.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,16 @@
using Microsoft.AspNetCore.Mvc;
using WIDESEA_Core.BaseController;
using WIDESEA_IInboundService;
using WIDESEA_Model.Models;
namespace WIDESEA_WMSServer.Controllers.Inbound
{
    [Route("api/TakeStockOrderDetail")]
    [ApiController]
    public class TakeStockOrderDetailController : ApiBaseController<ITakeStockOrderDetailService, Dt_TakeStockOrderDetail>
    {
        public TakeStockOrderDetailController(ITakeStockOrderDetailService service) : base(service)
        {
        }
    }
}
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/System/Sys_MenuController.cs
@@ -39,7 +39,8 @@
        [HttpPost, Route("save")]
        public ActionResult Save([FromBody] Sys_Menu menu)
        {
            if (App.User.UserId == 1)
            //超级管理员也能修改菜单
            if (App.User.RoleId == 1)
            {
                return Json(Service.Save(menu));
            }
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_WMSServer/Jobs/InventoryLockJob.cs
@@ -22,13 +22,13 @@
        {
            // ç¬¬ä¸€æ­¥ï¼šæ›´æ–°ValidDate的原生SQL(SQL Server)
            string updateSql = @"
    UPDATE s
    SET s.ValidDate = DATEADD(DAY, m.ValidityDays, s.CreateDate)
    FROM Dt_StockInfoDetail s
    INNER JOIN Dt_MaterialExpirationDate m ON SUBSTRING(s.MaterielCode, 1, 6) = m.MaterialCode
    WHERE s.ValidDate IS NULL";
            int updateValidDateResult = _db.Ado.ExecuteCommand(updateSql);
    //        string updateSql = @"
    //UPDATE s
    //SET s.ValidDate = DATEADD(DAY, m.ValidityDays, s.CreateDate)
    //FROM Dt_StockInfoDetail s
    //INNER JOIN Dt_MaterialExpirationDate m ON SUBSTRING(s.MaterielCode, 1, 6) = m.MaterialCode
    //WHERE s.ValidDate IS NULL";
    //        int updateValidDateResult = _db.Ado.ExecuteCommand(updateSql);
            // ç¬¬äºŒæ­¥ï¼šæ›´æ–°è¿‡æœŸçŠ¶æ€çš„åŽŸç”ŸSQL
            string updateStatusSql = @"
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_WMSServer/Jobs/QuartzJobMildd.cs
@@ -21,20 +21,20 @@
            {
                var allQzServices = new List<TasksQz>()
                {
                    //new TasksQz()
                    //{
                    //     Id = 1,
                    //     AssemblyName = "WIDESEA_WMSServer",
                    //     ClassName = "AgvTaskJob",
                    //     CreateTime = DateTime.Now,
                    //     IntervalSecond = 3,
                    //     IsDeleted = false,
                    //     IsStart = false,
                    //     JobGroup = "WIDESEA_WMSServer",
                    //     Name = "AgvTaskJob",
                    //     TriggerType = 0
                    //},
                    new TasksQz()
                    {
                         Id = 1,
                         AssemblyName = "WIDESEA_WMSServer",
                         ClassName = "AgvTaskJob",
                         CreateTime = DateTime.Now,
                         IntervalSecond = 3,
                         IsDeleted = false,
                         IsStart = false,
                         JobGroup = "WIDESEA_WMSServer",
                         Name = "AgvTaskJob",
                         TriggerType = 0
                    },
                };
                foreach (var item in allQzServices)
                {
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_WMSServer/Properties/PublishProfiles/FolderProfile2.pubxml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- https://go.microsoft.com/fwlink/?LinkID=208121. -->
<Project>
  <PropertyGroup>
    <DeleteExistingFiles>false</DeleteExistingFiles>
    <ExcludeApp_Data>false</ExcludeApp_Data>
    <LaunchSiteAfterPublish>true</LaunchSiteAfterPublish>
    <LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
    <LastUsedPlatform>Any CPU</LastUsedPlatform>
    <PublishProvider>FileSystem</PublishProvider>
    <PublishUrl>bin\Release\net6.0\publish\</PublishUrl>
    <WebPublishMethod>FileSystem</WebPublishMethod>
    <_TargetId>Folder</_TargetId>
  </PropertyGroup>
</Project>