From 053e6028bd20e599aea103401137816c6296a9ef Mon Sep 17 00:00:00 2001
From: Junjie <540245094@qq.com>
Date: 星期五, 20 九月 2024 09:26:49 +0800
Subject: [PATCH] #

---
 zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/service/CacheSiteService.java               |    4 
 zy-asrs-wms/src/main/java/com/zy/asrs/wms/utils/Utils.java                                 |   18 
 zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/MergePreviewResultDto.java       |    2 
 zy-asrs-admin/src/components/order/order/index.vue                                         |   30 
 zy-asrs-admin/src/views/in/order/index.vue                                                 |    2 
 zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/Wave.java                            |   33 
 zy-asrs-admin/src/components/order/order/order.vue                                         |    0 
 zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/CacheSite.java                       |   14 
 zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/OrderDetl.java                       |    6 
 zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/param/OrderOutMergePreviewParam.java |    2 
 zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/controller/CacheSiteController.java         |    6 
 zy-asrs-admin/src/views/out/waveSeed/index.vue                                             |   29 
 zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/controller/LocDetlController.java           |    2 
 zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/service/impl/CacheSiteServiceImpl.java      |    6 
 zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/param/OrderOutWavePreviewParam.java  |   10 
 zy-asrs-admin/src/components/order/order/orderIn.vue                                       |    0 
 zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/timer/TaskLogTimer.java                     |   17 
 zy-asrs-admin/src/views/out/order/index.vue                                                |    2 
 zy-asrs-admin/src/components/task/showTaskDetl/index.vue                                   |   19 
 zy-asrs-admin/src/views/out/orderOut/index.txt                                             |  268 ++++++
 zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/WaveDetl.java                        |  101 +
 zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/timer/TaskWaveTimer.java                    |  149 +++
 zy-asrs-admin/src/components/order/order/edit.vue                                          |    0 
 zy-asrs-admin/src/views/out/wave/index.vue                                                 |   67 
 zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/OrderOutMergeWaveDto.java        |   32 
 zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/param/GenerateWaveParam.java         |   14 
 license.lic                                                                                |    0 
 zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/enums/OrderSettleType.java           |   11 
 zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/Order.java                           |    6 
 zy-asrs-wms/src/main/resources/license.lic                                                 |    0 
 zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/LocDetl.java                         |    6 
 zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/TaskDetl.java                        |   15 
 zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/service/impl/OrderServiceImpl.java          |   24 
 zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/controller/WaveController.java              |   24 
 zy-asrs-admin/src/views/out/orderOut/index.vue                                             |   18 
 zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/controller/OutController.java               |   60 +
 zy-asrs-admin/src/components/order/order/orderOut.vue                                      |  416 ++++++++++
 zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/service/impl/WorkServiceImpl.java           |   30 
 zy-asrs-admin/src/components/orderOut/orderOutWavePreview/index.vue                        |  360 +++++++++
 zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/enums/WaveStatusType.java            |   20 
 zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/manage/OutManage.java                       |  408 ++++++++-
 zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/mapper/CacheSiteMapper.java                 |    4 
 zy-asrs-admin/src/views/order/order/index.vue                                              |    2 
 zy-asrs-admin/src/components/orderOut/orderOutMergePreview/stockOut.vue                    |   58 +
 zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/service/impl/LocDetlServiceImpl.java        |    4 
 zy-asrs-wms/src/main/resources/mapper/asrs/CacheSiteMapper.xml                             |    4 
 46 files changed, 2,078 insertions(+), 225 deletions(-)

diff --git a/license.lic b/license.lic
index cb51cd3..f447708 100644
--- a/license.lic
+++ b/license.lic
Binary files differ
diff --git a/zy-asrs-admin/src/components/order/edit.vue b/zy-asrs-admin/src/components/order/order/edit.vue
similarity index 100%
rename from zy-asrs-admin/src/components/order/edit.vue
rename to zy-asrs-admin/src/components/order/order/edit.vue
diff --git a/zy-asrs-admin/src/components/order/order/index.vue b/zy-asrs-admin/src/components/order/order/index.vue
new file mode 100644
index 0000000..4421f16
--- /dev/null
+++ b/zy-asrs-admin/src/components/order/order/index.vue
@@ -0,0 +1,30 @@
+<script setup>
+import { defineProps } from 'vue';
+import OrderView from './order.vue'
+import OrderInView from './orderIn.vue'
+import OrderOutView from './orderOut.vue'
+
+const props = defineProps({
+  ioModel: null
+})
+</script>
+
+<script>
+export default {
+  name: '璁㈠崟'
+}
+</script>
+
+<template>
+  <div v-if="props.ioModel === 'in'">
+    <OrderInView ioModel="in" />
+  </div>
+  <div v-else-if="props.ioModel === 'out'">
+    <OrderOutView ioModel="out" />
+  </div>
+  <div v-else>
+    <OrderView />
+  </div>
+</template>
+
+<style></style>
diff --git a/zy-asrs-admin/src/components/order/index.vue b/zy-asrs-admin/src/components/order/order/order.vue
similarity index 100%
rename from zy-asrs-admin/src/components/order/index.vue
rename to zy-asrs-admin/src/components/order/order/order.vue
diff --git a/zy-asrs-admin/src/components/order/index.vue b/zy-asrs-admin/src/components/order/order/orderIn.vue
similarity index 100%
copy from zy-asrs-admin/src/components/order/index.vue
copy to zy-asrs-admin/src/components/order/order/orderIn.vue
diff --git a/zy-asrs-admin/src/components/order/order/orderOut.vue b/zy-asrs-admin/src/components/order/order/orderOut.vue
new file mode 100644
index 0000000..2e4339e
--- /dev/null
+++ b/zy-asrs-admin/src/components/order/order/orderOut.vue
@@ -0,0 +1,416 @@
+<script setup>
+import { getCurrentInstance, ref, computed, reactive, defineProps } from 'vue';
+import { useRouter } from "vue-router";
+import { get, post, postBlob } from '@/utils/request.js'
+import { message, Modal } from 'ant-design-vue';
+import { globalState, logout } from '@/config.js';
+import EditView from './edit.vue'
+import { formatMessage } from '@/utils/localeUtils.js';
+import useTableSearch from '@/utils/tableUtils.jsx';
+import ShowOrderDetlComponent from '@/components/orderDetl/show.vue';
+import {
+    DownOutlined,
+    UploadOutlined,
+    DownloadOutlined,
+} from "@ant-design/icons-vue";
+const context = getCurrentInstance()?.appContext.config.globalProperties;
+
+const emit = defineEmits(['pageReload'])
+
+const router = useRouter();
+
+const props = defineProps({
+    ioModel: null
+})
+
+const TABLE_KEY = 'table-order';
+let currentPage = 1;
+let pageSize = 10;
+const searchInput = ref("")
+const editChild = ref(null)
+const showOrderDetlChild = ref(null)
+
+const state = reactive({
+    selectedRowKeys: [],
+    loading: false,
+});
+
+let tableData = ref([]);
+getPage();
+
+const {
+    getColumnSearchProps,
+    handleResizeColumn,
+} = useTableSearch();
+
+const columns = [
+    {
+        title: formatMessage('db.man_order.order_no', '璁㈠崟缂栧彿'),
+        dataIndex: 'orderNo',
+        width: 140,
+        ellipsis: true,
+        ...getColumnSearchProps('orderNo'),
+    },
+    {
+        title: formatMessage('db.man_order.order_time', '鍗曟嵁鏃ユ湡'),
+        dataIndex: 'orderTime',
+        width: 140,
+        ellipsis: true,
+        ...getColumnSearchProps('orderTime'),
+    },
+    {
+        title: formatMessage('db.man_order.order_type', '鍗曟嵁绫诲瀷'),
+        dataIndex: 'orderType$',
+        width: 140,
+        ellipsis: true,
+        ...getColumnSearchProps('orderType$'),
+    },
+    {
+        title: formatMessage('db.man_order.order_settle', '鍗曟嵁鐘舵��'),
+        dataIndex: 'orderSettle$',
+        width: 140,
+        ellipsis: true,
+        ...getColumnSearchProps('orderSettle$'),
+    },
+    {
+        title: formatMessage('db.man_order.ioPri', '浼樺厛绾�'),
+        dataIndex: 'ioPri',
+        width: 140,
+        ellipsis: true,
+        ...getColumnSearchProps('ioPri'),
+    },
+    {
+        title: formatMessage('db.man_order.wave_no', '娉㈡缂栧彿'),
+        dataIndex: 'waveNo',
+        width: 140,
+        ellipsis: true,
+        ...getColumnSearchProps('waveNo'),
+    },
+    {
+        title: formatMessage('db.man_order.status', '鐘舵��'),
+        dataIndex: 'status$',
+        width: 140,
+        ellipsis: true,
+        ...getColumnSearchProps('status$'),
+    },
+    {
+        title: formatMessage('db.man_order.create_time', '娣诲姞鏃堕棿'),
+        dataIndex: 'createTime$',
+        width: 140,
+        ellipsis: true,
+        ...getColumnSearchProps('createTime$'),
+    },
+    {
+        title: formatMessage('db.man_order.create_by', '娣诲姞浜哄憳'),
+        dataIndex: 'createBy$',
+        width: 140,
+        ellipsis: true,
+        ...getColumnSearchProps('createBy$'),
+    },
+    {
+        title: formatMessage('db.man_order.update_time', '淇敼鏃堕棿'),
+        dataIndex: 'updateTime$',
+        width: 140,
+        ellipsis: true,
+        ...getColumnSearchProps('updateTime$'),
+    },
+    {
+        title: formatMessage('db.man_order.update_by', '淇敼浜哄憳'),
+        dataIndex: 'updateBy$',
+        width: 140,
+        ellipsis: true,
+        ...getColumnSearchProps('updateBy$'),
+    },
+    {
+        title: formatMessage('db.man_order.memo', '澶囨敞'),
+        dataIndex: 'memo',
+        width: 140,
+        ellipsis: true,
+        ...getColumnSearchProps('memo'),
+    },
+
+    {
+        title: formatMessage('common.operation', '鎿嶄綔'),
+        name: 'oper',
+        dataIndex: 'oper',
+        key: 'oper',
+        width: 240,
+    },
+];
+
+const hasSelected = computed(() => state.selectedRowKeys.length > 0);
+const start = () => {
+    state.loading = true;
+    // ajax request after empty completing
+    setTimeout(() => {
+        state.loading = false;
+        state.selectedRowKeys = [];
+    }, 1000);
+};
+const onSelectChange = selectedRowKeys => {
+    // console.log('selectedRowKeys changed: ', selectedRowKeys);
+    state.selectedRowKeys = selectedRowKeys;
+};
+
+function getPage() {
+    state.loading = true;
+
+    let apiUrl = '/api/order/page';
+    if (props.ioModel == 'in') {
+        apiUrl = '/api/order/in/page';
+    } else if (props.ioModel == 'out') {
+        apiUrl = '/api/order/out/page';
+    }
+
+    post(apiUrl, {
+        current: currentPage,
+        pageSize: pageSize,
+        condition: searchInput.value,
+    }).then((resp) => {
+        let result = resp.data;
+        if (result.code == 200) {
+            let data = result.data;
+            tableData.value = data;
+
+            state.loading = false;
+        } else if (result.code === 401) {
+            message.error(result.msg);
+            logout()
+        } else {
+            message.error(result.msg);
+        }
+    })
+}
+
+const handleEdit = (item) => {
+    editChild.value.open = true;
+    editChild.value.formData = item == null ? editChild.value.initFormData : JSON.parse(JSON.stringify(item));
+    editChild.value.isSave = item == null;
+}
+
+const handleDel = (rows) => {
+    Modal.confirm({
+        title: formatMessage('page.delete', '鍒犻櫎'),
+        content: formatMessage('page.delete.confirm', '纭畾鍒犻櫎璇ラ」鍚楋紵'),
+        maskClosable: true,
+        onOk: async () => {
+            const hide = message.loading(formatMessage('common.loading', '璇锋眰涓�'));
+            try {
+                post('/api/order/remove/' + rows.map((row) => row.id).join(','), {}).then(resp => {
+                    let result = resp.data;
+                    if (result.code === 200) {
+                        message.success(result.msg);
+                    } else {
+                        message.error(result.msg);
+                    }
+                    getPage()
+                    hide()
+                })
+            } catch (error) {
+                message.error(formatMessage('common.fail', '璇锋眰澶辫触'));
+            }
+        },
+    });
+}
+
+const showDetl = (item) => {
+    showOrderDetlChild.value.openDetl = true;
+    showOrderDetlChild.value.orderId = item.id;
+}
+
+const handleExport = async (intl) => {
+    postBlob('/api/order/export', {
+        ioModel: props.ioModel
+    }).then(result => {
+        const blob = new Blob([result.data], { type: 'application/vnd.ms-excel' });
+        window.location.href = window.URL.createObjectURL(blob);
+        return true;
+    })
+};
+
+const onSearch = () => {
+    // console.log('search');
+    getPage()
+}
+
+const onPageChange = (page, size) => {
+    currentPage = page;
+    pageSize = size;
+    getPage();
+}
+
+function handleTableReload(value) {
+    getPage()
+}
+
+const handleSyncOrderClick = (e) => {
+    if (e.key == 'import') {
+        importTemplate()
+    } else if (e.key == 'export') {
+        exportTemplate()
+    }
+}
+
+const importTemplate = () => {
+    //瀵煎叆妯℃澘
+}
+
+const exportTemplate = () => {
+    //妯℃澘瀵煎嚭
+    postBlob('/api/order/exportTemplate', {}).then(result => {
+        const blob = new Blob([result.data], { type: 'application/vnd.ms-excel' });
+        window.location.href = window.URL.createObjectURL(blob);
+        return true;
+    })
+}
+
+const fileList = ref([]);
+const handleUploadChange = info => {
+    if (info.file.status !== 'uploading') {
+        // console.log(info.file, info.fileList);
+    }
+    if (info.file.status === 'done') {
+        let result = info.file.response;
+        if (result.code == 200) {
+            message.success(`${info.file.name} ${formatMessage('page.upload.success', '涓婁紶鎴愬姛')}`);
+            getPage()
+        } else {
+            message.error(result.msg);
+        }
+    } else if (info.file.status === 'error') {
+        message.error(`${info.file.name} file upload failed.`);
+    }
+};
+
+const channel = ref(null)
+const channelList = ref(null);
+channelQuery();
+function channelQuery() {
+    post('/api/cacheSite/channel/list', {}).then(resp => {
+        let result = resp.data;
+        if (result.data == null) {
+            return
+        }
+
+        let tmp = []
+        result.data.forEach((item) => {
+            tmp.push({
+                label: item,
+                value: item
+            })
+        })
+        channelList.value = tmp;
+
+        if (tmp.length > 0) {
+            let data = tmp[0]
+            channel.value = [data.value];
+        }
+    })
+}
+
+const handleGenerateWave = () => {
+    let orderIdList = [];
+    state.selectedRowKeys.forEach((id) => {
+        orderIdList.push(id)
+    })
+
+    if (orderIdList.length == 0) {
+        message.error(formatMessage("page.orderOut.mergeOrderOut.error", "璇烽�夋嫨鑷冲皯涓�鏉¤鍗�"));
+        return;
+    }
+
+    post('/api/out/wave/generate', {
+        orderIds: orderIdList,
+        channels: channel.value
+    }).then((resp) => {
+        let result = resp.data;
+        if (result.code == 200) {
+            message.success(formatMessage('page.add.success', '鎴愬姛'));
+            emit('pageReload', 'reload')
+        } else {
+            message.error(result.msg);
+        }
+    })
+}
+
+</script>
+
+<script>
+export default {
+    name: '璁㈠崟'
+}
+</script>
+
+<template>
+    <div>
+        <EditView ref="editChild" @tableReload="handleTableReload"
+            :ioModel="ioModel == 'in' ? 1 : ioModel == 'out' ? 2 : null" />
+        <div class="table-header">
+            <div style="display: flex;">
+                <div style="margin-right: 10px;">
+                    <a-input-search v-model:value="searchInput" :placeholder="formatMessage('page.input', '璇疯緭鍏�')"
+                        style="width: 200px;" @search="onSearch" />
+                </div>
+                <div>
+                    <a-select v-model:value="channel" :options="channelList" mode="multiple"
+                        style="width: 100px;"></a-select>
+                    <a-button @click="handleGenerateWave()">{{ formatMessage('common.generateWave', '鐢熸垚娉㈡')
+                        }}</a-button>
+                </div>
+            </div>
+
+            <div class="table-header-right">
+                <a-dropdown>
+                    <template #overlay>
+                        <a-menu @click="handleSyncOrderClick">
+                            <a-menu-item key="import">
+                                <a-upload v-model:file-list="fileList" name="file" action="/api/order/upload"
+                                    @change="handleUploadChange" :showUploadList="false" :headers="{
+                                        Authorization: globalState.token
+                                    }">
+                                    <UploadOutlined />
+                                    {{ formatMessage('page.order.import', '鍗曟嵁瀵煎叆') }}
+                                </a-upload>
+                            </a-menu-item>
+
+                            <a-menu-item key="export">
+                                <DownloadOutlined />
+                                {{ formatMessage('page.order.export.template', '瀵煎嚭妯℃澘') }}
+                            </a-menu-item>
+                        </a-menu>
+                    </template>
+                    <a-button>
+                        {{ formatMessage('page.order.sync', '鍗曟嵁鍚屾') }}
+                        <DownOutlined />
+                    </a-button>
+                </a-dropdown>
+                <a-button @click="handleEdit(null)" type="primary">{{ formatMessage('page.add', '娣诲姞') }}</a-button>
+                <a-button @click="handleExport">{{ formatMessage('page.export', '瀵煎嚭') }}</a-button>
+            </div>
+        </div>
+        <a-table :row-selection="{ selectedRowKeys: state.selectedRowKeys, onChange: onSelectChange }"
+            :data-source="tableData.records" :defaultExpandAllRows="false" :key="TABLE_KEY" rowKey="id"
+            :pagination="{ total: tableData.total, onChange: onPageChange }"
+            :scroll="{ y: 768, scrollToFirstRowOnChange: true }" :columns="columns" @resizeColumn="handleResizeColumn"
+            :loading="state.loading">
+            <template #bodyCell="{ column, text, record }">
+                <template v-if="column.dataIndex === 'oper'">
+                    <div style="display: flex;justify-content: space-evenly;">
+                        <a-button type="link" primary @click="showDetl(record)">{{ formatMessage('page.order.orderDetl',
+                            '璁㈠崟鏄庣粏')
+                            }}</a-button>
+                        <a-button type="link" primary @click="handleEdit(record)">{{ formatMessage('page.edit', '缂栬緫')
+                            }}</a-button>
+                        <a-button type="link" danger @click="handleDel([record])">{{ formatMessage('page.delete', '鍒犻櫎')
+                            }}</a-button>
+                    </div>
+                </template>
+            </template>
+        </a-table>
+
+        <ShowOrderDetlComponent ref="showOrderDetlChild" />
+
+    </div>
+</template>
+
+<style></style>
diff --git a/zy-asrs-admin/src/components/orderOut/orderOutMergePreview/stockOut.vue b/zy-asrs-admin/src/components/orderOut/orderOutMergePreview/stockOut.vue
index 76722a1..480d07f 100644
--- a/zy-asrs-admin/src/components/orderOut/orderOutMergePreview/stockOut.vue
+++ b/zy-asrs-admin/src/components/orderOut/orderOutMergePreview/stockOut.vue
@@ -165,7 +165,7 @@
         list: tableData.value
     };
 
-    post('/api/out/orderOut/merge', requestParam).then((resp) => {
+    post('/api/out/orderOut/merge/wave', requestParam).then((resp) => {
         let result = resp.data;
         if (result.code == 200) {
             message.success(formatMessage('page.add.success', '鍑哄簱鎴愬姛'));
@@ -207,21 +207,11 @@
             let idx = 0;
             let colSpan = []
             tmp.forEach((item) => {
-                item.locs.forEach((val) => {
-                    let dataTmp = JSON.parse(JSON.stringify(item));
-                    dataTmp.locId = val.locId;
-                    dataTmp.locNo = val.locNo;
-                    dataTmp.locDetlId = val.locDetlId;
-                    dataTmp.anfme = val.anfme;
-                    dataTmp.key = idx;
-                    dataTmp.operationPort = defaultOperationPort;
-
-                    tableDataTmp.push(dataTmp);
-                })
-
                 let count = item.locs.length;
-                if (item.anfme > 0) {
+
+                if (item.locs.length == 0) {
                     let dataTmp = JSON.parse(JSON.stringify(item));
+
                     dataTmp.locId = null;
                     dataTmp.locNo = null;
                     dataTmp.locDetlId = null;
@@ -231,9 +221,47 @@
 
                     tableDataTmp.push(dataTmp);
                     count++;
+                } else {
+                    let isused = item.anfme;
+                    console.log(isused);
+
+                    for (let i = 0; i < item.locs.length; i++) {
+                        if (isused == 0) {
+                            break;
+                        }
+                        const val = item.locs[i];
+                        let dataTmp = JSON.parse(JSON.stringify(item));
+                        let anfme = isused - val.anfme > 0 ? val.anfme : isused;
+                        isused -= anfme;
+
+                        dataTmp.locId = val.locId;
+                        dataTmp.locNo = val.locNo;
+                        dataTmp.locDetlId = val.locDetlId;
+                        dataTmp.anfme = anfme;
+                        dataTmp.key = idx;
+                        dataTmp.operationPort = defaultOperationPort;
+
+                        tableDataTmp.push(dataTmp);
+                    }
+
+                    console.log(tableDataTmp);
+                    
+
+                    if (isused > 0) {
+                        let dataTmp = JSON.parse(JSON.stringify(item));
+                        dataTmp.locId = null;
+                        dataTmp.locNo = null;
+                        dataTmp.locDetlId = null;
+                        dataTmp.anfme = isused;
+                        dataTmp.key = idx;
+                        dataTmp.operationPort = defaultOperationPort;
+
+                        tableDataTmp.push(dataTmp);
+                        count++;
+                    }
                 }
 
-                colSpan[idx] = count
+                colSpan[idx] = count;
                 idx += count;
             })
 
diff --git a/zy-asrs-admin/src/components/orderOut/orderOutWavePreview/index.vue b/zy-asrs-admin/src/components/orderOut/orderOutWavePreview/index.vue
new file mode 100644
index 0000000..f5c42b3
--- /dev/null
+++ b/zy-asrs-admin/src/components/orderOut/orderOutWavePreview/index.vue
@@ -0,0 +1,360 @@
+<script setup>
+import { ref, watch, reactive } from 'vue';
+import { useRouter } from "vue-router";
+import { get, post, postBlob } from '@/utils/request.js'
+import { message, Modal } from 'ant-design-vue';
+import { logout } from '@/config.js';
+import { formatMessage } from '@/utils/localeUtils.js';
+import useTableSearch from '@/utils/tableUtils.jsx';
+
+const router = useRouter();
+
+const TABLE_KEY = 'table-order-out-preview';
+
+const emit = defineEmits(['closeParent', 'reload'])
+
+const {
+    getColumnSearchProps,
+} = useTableSearch();
+
+let currentOrder = ref(null);
+let searchInput = ref(null);
+let tableData = ref([]);
+const operationPortList = ref([])
+const globalOperationPort = ref(null)
+const open = ref(false);
+const showWidth = ref("60%")
+const records = ref([])
+const waveId = ref(null)
+const loading = ref(false)
+let tableDataValue = []
+let tableDataColSpan = []
+
+const customColSpanProps = (index) => {
+    let count = tableDataColSpan[index];
+    if (count == null) {
+        count = 0;
+    }
+    return {
+        rowSpan: count,
+    };
+}
+
+let columns = [
+    {
+        title: formatMessage('db.man_order_detl.matnr', '鍟嗗搧缂栧彿'),
+        dataIndex: 'matnr',
+        width: 140,
+        ellipsis: true,
+        ...getColumnSearchProps('matnr'),
+        customCell: (_, index) => {
+            return customColSpanProps(index)
+        },
+    },
+    {
+        title: formatMessage('db.man_order_detl.batch', '鎵瑰彿'),
+        dataIndex: 'batch',
+        width: 140,
+        ellipsis: true,
+        ...getColumnSearchProps('batch'),
+        customCell: (_, index) => {
+            return customColSpanProps(index)
+        },
+    },
+];
+
+const state = reactive({
+    selectedRowKeys: [],
+});
+const onSelectChange = selectedRowKeys => {
+    // console.log('selectedRowKeys changed: ', selectedRowKeys);
+    state.selectedRowKeys = selectedRowKeys;
+};
+
+const fieldList = [];
+getColumns();
+//鍔犺浇鎵╁睍瀛楁
+async function getColumns() {
+    let fieldResp = await post('/api/matField/list', {
+        unique: 1,
+    })
+    let fieldResult = fieldResp.data;
+    let tmp = columns;
+    if (fieldResult.code == 200) {
+        let data = fieldResult.data;
+
+        data.forEach((item) => {
+            tmp.push({
+                title: formatMessage(item.language, item.describe),
+                name: item.name,
+                dataIndex: item.name,
+                key: item.name,
+                width: 140,
+                editable: true,
+                customCell: (_, index) => {
+                    return customColSpanProps(index)
+                },
+            })
+
+            fieldList.push(item.name);
+        })
+
+        tmp.push({
+            title: formatMessage('db.man_order_detl.anfme', '鏁伴噺'),
+            dataIndex: 'anfme',
+            width: 140,
+            ellipsis: true,
+            fixed: 'right',
+        })
+
+        tmp.push({
+            title: formatMessage('db.man_order_detl.locNo', '鍑哄簱搴撲綅'),
+            dataIndex: 'locNo',
+            width: 140,
+            ellipsis: true,
+            fixed: 'right',
+        })
+
+        tmp.push({
+            title: formatMessage('db.man_order_detl.operationPort', '浣滀笟鍙�'),
+            dataIndex: 'operationPort',
+            width: 140,
+            ellipsis: true,
+            fixed: 'right',
+        })
+
+        columns = tmp;
+    } else if (result.code === 401) {
+        message.error(result.msg);
+        logout()
+    } else {
+        message.error(result.msg);
+    }
+}
+
+async function getOperationPort() {
+    let resp = await post('/api/operationPort/list', {})
+    let result = resp.data;
+    if (result.code == 200) {
+        let data = result.data;
+        let tmp = []
+        data.forEach((item) => {
+            tmp.push({
+                label: item.flag,
+                value: item.id
+            })
+        })
+        operationPortList.value = tmp;
+    } else if (result.code === 401) {
+        message.error(result.msg);
+        logout()
+    } else {
+        message.error(result.msg);
+    }
+}
+
+watch(open, (newVal, oldVal) => {
+    if (newVal) {
+        handleOrderMergePreview()
+    }
+})
+
+const handleOk = () => {
+    let requestParam = {
+        waveId: waveId.value,
+        list: tableData.value
+    };
+
+    post('/api/out/orderOut/merge/wave', requestParam).then((resp) => {
+        let result = resp.data;
+        if (result.code == 200) {
+            message.success(formatMessage('page.add.success', '鍑哄簱鎴愬姛'));
+            open.value = false;
+            emit('closeParent', true)
+            emit('reload', true)
+        } else {
+            message.error(result.msg);
+        }
+    })
+}
+
+const handleOrderMergePreview = async () => {
+    loading.value = true;
+
+    await getOperationPort();
+    tableData.value = []
+    tableDataValue = []
+
+    let defaultOperationPort = "";
+    if (operationPortList.value.length > 0) {
+        defaultOperationPort = operationPortList.value[0].value;
+        globalOperationPort.value = defaultOperationPort;
+    }
+
+    post('/api/out/orderOut/wave/preview', {
+        waveId: waveId.value,
+    }).then((resp) => {
+        let result = resp.data;
+        if (result.code == 200) {
+            let tmp = result.data;
+            tableDataValue = tmp;
+
+            let tableDataTmp = []
+            let idx = 0;
+            let colSpan = []
+            tmp.forEach((item) => {
+                let count = item.locs.length;
+
+                if (item.locs.length == 0) {
+                    let dataTmp = JSON.parse(JSON.stringify(item));
+
+                    dataTmp.locId = null;
+                    dataTmp.locNo = null;
+                    dataTmp.locDetlId = null;
+                    dataTmp.anfme = item.anfme;
+                    dataTmp.key = idx;
+                    dataTmp.operationPort = defaultOperationPort;
+
+                    tableDataTmp.push(dataTmp);
+                    count++;
+                } else {
+                    let isused = item.anfme;
+
+                    for (let i = 0; i < item.locs.length; i++) {
+                        if (isused == 0) {
+                            break;
+                        }
+                        const val = item.locs[i];
+                        let dataTmp = JSON.parse(JSON.stringify(item));
+                        let anfme = isused - val.anfme > 0 ? val.anfme : isused;
+                        isused -= anfme;
+
+                        dataTmp.locId = val.locId;
+                        dataTmp.locNo = val.locNo;
+                        dataTmp.locDetlId = val.locDetlId;
+                        dataTmp.anfme = anfme;
+                        dataTmp.key = idx;
+                        dataTmp.operationPort = defaultOperationPort;
+
+                        tableDataTmp.push(dataTmp);
+                    }
+
+                    if (isused > 0) {
+                        let dataTmp = JSON.parse(JSON.stringify(item));
+                        dataTmp.locId = null;
+                        dataTmp.locNo = null;
+                        dataTmp.locDetlId = null;
+                        dataTmp.anfme = isused;
+                        dataTmp.key = idx;
+                        dataTmp.operationPort = defaultOperationPort;
+
+                        tableDataTmp.push(dataTmp);
+                        count++;
+                    }
+                }
+
+                colSpan[idx] = count;
+                idx += count;
+            })
+
+            tableDataColSpan = colSpan;
+            tableData.value = tableDataTmp;
+
+            loading.value = false;
+        } else {
+            message.error(result.msg);
+        }
+    })
+}
+
+const handleGlobalOperationPortChange = () => {
+    if (tableData.value.length > 0) {
+        tableData.value.forEach((item) => {
+            item.operationPort = globalOperationPort.value;
+        })
+    }
+}
+
+const handleOtherLocChange = (index, record) => {
+    let anfme = record.anfme;
+    record.otherLocs.forEach((item) => {
+        if (item.locId == record.locId) {
+            record.locNo = item.locNo;
+            record.locDetlId = item.locDetlId;
+            record.anfme = item.anfme;
+        }
+    })
+
+    let locDetlList = []
+    let tmp = tableData.value;
+    tmp.forEach((item) => {
+        if (item.locDetlId != null) {
+            if (!locDetlList[item.locDetlId]) {
+                locDetlList[item.locDetlId] = item.anfme;
+            }
+        }
+    })
+
+    // tmp.forEach((item) => {
+    //     if (item.locId == null) {
+    //         item.stockAlarm = true;
+    //     } else {
+    //         let stock = locDetlList[item.locDetlId]
+    //         stock = stock - item.anfme;
+    //         locDetlList[item.locDetlId] = stock;
+    //         if (stock >= 0) {
+    //             item.stockAlarm = false;
+    //         } else {
+    //             item.stockAlarm = true;
+    //         }
+    //     }
+    // })
+}
+
+defineExpose({
+    open,
+    showWidth,
+    waveId,
+})
+</script>
+
+<script>
+export default {
+    name: '棰勮娉㈡鍑哄簱'
+}
+</script>
+
+<template>
+    <div>
+        <a-modal v-model:open="open" :width="showWidth"
+            :title="formatMessage('page.orderOutPreview.preview', '棰勮鍚堝苟璁㈠崟鍑哄簱')" @ok="handleOk">
+            <div>
+                <span>浣滀笟鍙o細</span>
+                <a-select v-model:value="globalOperationPort" :options="operationPortList"
+                    @change="handleGlobalOperationPortChange"></a-select>
+            </div>
+            <a-table :data-source="tableData" :loading="loading" :defaultExpandAllRows="false" :key="TABLE_KEY"
+                rowKey="index" :scroll="{ y: 768, scrollToFirstRowOnChange: true }" :columns="columns">
+                <template #bodyCell="{ column, text, record, index }">
+                    <template v-if="column.dataIndex === 'locNo'">
+                        <div v-if="record.locId != null && record.anfme > 0">
+                            <!-- <a-tag color="green">{{ record.locNo }}</a-tag> -->
+                            <a-select v-model:value="record.locId" :options="record.otherLocs"
+                                :fieldNames="{ label: 'locNo', value: 'locId' }"
+                                @change="handleOtherLocChange(index, record)"></a-select>
+                        </div>
+                        <div v-else>
+                            <a-tag color="red">搴撳瓨涓嶈冻</a-tag>
+                        </div>
+                    </template>
+
+                    <template v-if="column.dataIndex === 'operationPort'">
+                        <a-select v-model:value="record.operationPort" :options="operationPortList"></a-select>
+                    </template>
+                </template>
+            </a-table>
+        </a-modal>
+    </div>
+</template>
+
+<style></style>
diff --git a/zy-asrs-admin/src/components/task/showTaskDetl/index.vue b/zy-asrs-admin/src/components/task/showTaskDetl/index.vue
index 59b579a..040af68 100644
--- a/zy-asrs-admin/src/components/task/showTaskDetl/index.vue
+++ b/zy-asrs-admin/src/components/task/showTaskDetl/index.vue
@@ -97,6 +97,13 @@
         ellipsis: true,
         ...getColumnSearchProps('orderNo'),
     },
+    {
+        title: formatMessage('db.man_task_detl.wave_no', '娉㈡缂栧彿'),
+        dataIndex: ['wave$', 'waveNo'],
+        width: 140,
+        ellipsis: true,
+        ...getColumnSearchProps('waveNo'),
+    },
 ];
 
 const fieldList = [];
@@ -151,6 +158,8 @@
 
 watch(taskId, (newVal, oldVal) => {
     if (newVal != null) {
+        state.loading = true;
+        tableData.value = []
         get("/api/taskDetl/taskId/" + newVal, {}).then((resp) => {
             let result = resp.data;
             let index = 1;
@@ -160,6 +169,8 @@
                 tmp.push(item)
             })
             tableData.value = tmp;
+
+            state.loading = false;
         })
 
         get("/api/task/" + newVal, {}).then((resp) => {
@@ -210,11 +221,17 @@
                 </div>
             </div>
             <a-table :data-source="tableData" :defaultExpandAllRows="false" :key="TABLE_KEY" rowKey="id"
-                :scroll="{ y: 768 }" :columns="state.columns">
+                :scroll="{ y: 768 }" :columns="state.columns" :loading="state.loading">
                 <template #bodyCell="{ column, text, record }">
                     <template v-if="column.dataIndex === 'orderNo'">
                         <a-button type="link" @click="openOrderDetl(record)">{{ text }}</a-button>
                     </template>
+
+                    <template v-if="typeof (column.dataIndex) === 'object'">
+                        <template v-if="column.dataIndex[1] === 'waveNo'">
+                            {{ text }}
+                        </template>
+                    </template>
                 </template>
             </a-table>
         </a-modal>
diff --git a/zy-asrs-admin/src/views/in/order/index.vue b/zy-asrs-admin/src/views/in/order/index.vue
index 1389dd2..df3c646 100644
--- a/zy-asrs-admin/src/views/in/order/index.vue
+++ b/zy-asrs-admin/src/views/in/order/index.vue
@@ -1,5 +1,5 @@
 <script setup>
-import OrderView from '@/components/order/index.vue';
+import OrderView from '@/components/order/order/index.vue';
 </script>
 
 <script>
diff --git a/zy-asrs-admin/src/views/order/order/index.vue b/zy-asrs-admin/src/views/order/order/index.vue
index 3ec9f48..67ac3cb 100644
--- a/zy-asrs-admin/src/views/order/order/index.vue
+++ b/zy-asrs-admin/src/views/order/order/index.vue
@@ -1,5 +1,5 @@
 <script setup>
-import OrderView from '@/components/order/index.vue';
+import OrderView from '@/components/order/order/index.vue';
 </script>
 
 <script>
diff --git a/zy-asrs-admin/src/views/out/order/index.vue b/zy-asrs-admin/src/views/out/order/index.vue
index 217c437..f39e217 100644
--- a/zy-asrs-admin/src/views/out/order/index.vue
+++ b/zy-asrs-admin/src/views/out/order/index.vue
@@ -1,5 +1,5 @@
 <script setup>
-import OrderView from '@/components/order/index.vue';
+import OrderView from '@/components/order/order/index.vue';
 </script>
 
 <script>
diff --git a/zy-asrs-admin/src/views/out/orderOut/index.txt b/zy-asrs-admin/src/views/out/orderOut/index.txt
new file mode 100644
index 0000000..ed8ded9
--- /dev/null
+++ b/zy-asrs-admin/src/views/out/orderOut/index.txt
@@ -0,0 +1,268 @@
+<script setup>
+import { ref, computed, reactive } from 'vue';
+import { useRouter } from "vue-router";
+import { get, post, postBlob } from '@/utils/request.js'
+import { message, Modal } from 'ant-design-vue';
+import { logout } from '@/config.js';
+import { formatMessage } from '@/utils/localeUtils.js';
+import useTableSearch from '@/utils/tableUtils.jsx';
+import OrderOutBatchPreviewView from '@/components/orderOut/orderOutBatchPreview/index.vue';
+import OrderOutMergePreviewView from '@/components/orderOut/orderOutMergePreview/index.vue';
+
+const router = useRouter();
+
+const emit = defineEmits(['pageReload'])
+
+const TABLE_KEY = 'table-order-detl';
+let currentPage = 1;
+let pageSize = 10;
+
+const {
+    getColumnSearchProps,
+    handleResizeColumn,
+} = useTableSearch();
+
+let currentOrder = ref(null);
+let searchInput = ref(null);
+let tableData = ref([]);
+const orderOutBatchPreviewChild = ref(null);
+const orderOutMergePreviewChild = ref(null);
+const checkedOrderKeys = ref([]);
+getPage();
+
+const columns = [
+    {
+        title: formatMessage('db.man_order_detl.order_no', '璁㈠崟缂栧彿'),
+        dataIndex: 'orderNo',
+        width: 140,
+        ellipsis: true,
+        ...getColumnSearchProps('orderNo'),
+    },
+    {
+        title: formatMessage('db.man_order_detl.anfme', '鏁伴噺'),
+        dataIndex: 'anfme',
+        width: 140,
+        ellipsis: true,
+        ...getColumnSearchProps('anfme'),
+    },
+    {
+        title: formatMessage('db.man_order_detl.qty', '宸插畬鎴愭暟閲�'),
+        dataIndex: 'qty',
+        width: 140,
+        ellipsis: true,
+        ...getColumnSearchProps('qty'),
+    },
+    {
+        title: formatMessage('db.man_order_detl.work_qty', '浣滀笟涓暟閲�'),
+        dataIndex: 'workQty',
+        width: 140,
+        ellipsis: true,
+        ...getColumnSearchProps('workQty'),
+    },
+    {
+        title: formatMessage('db.man_order_detl.matnr', '鍟嗗搧缂栧彿'),
+        dataIndex: ['mat$', 'matnr'],
+        width: 140,
+        ellipsis: true,
+        ...getColumnSearchProps('matId$'),
+    },
+    {
+        title: formatMessage('db.man_order_detl.batch', '鎵瑰彿'),
+        dataIndex: 'batch',
+        width: 140,
+        ellipsis: true,
+        ...getColumnSearchProps('batch'),
+    },
+
+    {
+        title: formatMessage('common.operation', '鎿嶄綔'),
+        name: 'oper',
+        dataIndex: 'oper',
+        key: 'oper',
+        width: 140,
+    },
+];
+
+const state = reactive({
+    selectedRowKeys: [],
+    loading: false,
+});
+const onSelectChange = selectedRowKeys => {
+    // console.log('selectedRowKeys changed: ', selectedRowKeys);
+    state.selectedRowKeys = selectedRowKeys;
+};
+
+function getPage() {
+    if (currentOrder.value != null) {
+        get('/api/orderDetl/orderId/' + currentOrder.value.id, {}).then((resp) => {
+            let result = resp.data;
+            if (result.code == 200) {
+                let data = result.data;
+                tableData.value = data;
+            } else if (result.code === 401) {
+                message.error(result.msg);
+                logout()
+            } else {
+                message.error(result.msg);
+            }
+        })
+    }
+}
+
+function handleTableReload(value) {
+    getPage()
+}
+
+let orderData = ref([]);
+let searchOrder = ref("");
+getOrderData()
+function getOrderData() {
+    post('/api/order/out/page', {
+        current: currentPage,
+        pageSize: pageSize,
+        condition: searchOrder.value,
+        orderOut: true,
+    }).then((resp) => {
+        let result = resp.data;
+        if (result.code == 200) {
+            let data = result.data.records;
+            orderData.value = data
+        } else if (result.code === 401) {
+            message.error(result.msg);
+            logout()
+        } else {
+            message.error(result.msg);
+        }
+    })
+}
+
+const handleOrderSelected = (selectedKeys, e) => {
+    currentOrder.value = e.selectedNodes[0];
+    getPage()
+}
+
+const handleSearchOrder = (e) => {
+    getOrderData()
+}
+
+const handleBatchOrderOut = () => {
+    let data = state.selectedRowKeys;
+    handleOrderOutPreview(data)
+}
+
+const handleOrderOutPreview = (data) => {
+    if (data.length == 0) {
+        message.error(formatMessage("page.orderOut.batchOrderOut.error", "璇烽�夋嫨鑷冲皯涓�鏉″嚭搴撴槑缁�"));
+        return;
+    }
+
+    orderOutBatchPreviewChild.value.open = true;
+    orderOutBatchPreviewChild.value.records = data;
+}
+
+const handleMergeOrderOut = () => {
+    let orderIdList = [];
+    checkedOrderKeys.value.forEach((idx) => {
+        let index = parseInt(idx.split("-")[1]);
+        orderIdList.push(orderData.value[index].id)
+    })
+
+    if (orderIdList.length == 0) {
+        message.error(formatMessage("page.orderOut.mergeOrderOut.error", "璇烽�夋嫨鑷冲皯涓�鏉¤鍗�"));
+        return;
+    }
+
+    orderOutMergePreviewChild.value.open = true;
+    orderOutMergePreviewChild.value.records = orderIdList;
+}
+
+const handleChildReload = () => {
+    handleTableReload()
+}
+
+const handleGenerateWave = () => {
+    let orderIdList = [];
+    checkedOrderKeys.value.forEach((idx) => {
+        let index = parseInt(idx.split("-")[1]);
+        orderIdList.push(orderData.value[index].id)
+    })
+
+    if (orderIdList.length == 0) {
+        message.error(formatMessage("page.orderOut.mergeOrderOut.error", "璇烽�夋嫨鑷冲皯涓�鏉¤鍗�"));
+        return;
+    }
+
+    post('/api/out/wave/generate', orderIdList).then((resp) => {
+        let result = resp.data;
+        if (result.code == 200) {
+            message.success(formatMessage('page.add.success', '鎴愬姛'));
+            emit('pageReload', 'reload')
+        } else {
+            message.error(result.msg);
+        }
+    })
+}
+
+</script>
+
+<script>
+export default {
+    name: '璁㈠崟鍑哄簱'
+}
+</script>
+
+<template>
+    <div style="display: flex;">
+        <a-card :title="formatMessage('common.order', '璁㈠崟')" style="flex: 4;margin-right: 30px;">
+            <div style="margin-bottom: 10px;display: flex;">
+                <!-- <div style="margin-right: 10px;">
+                    <a-button @click="handleMergeOrderOut()">
+                        {{ formatMessage('common.orderOut', '鍚堝苟璁㈠崟') }}
+                    </a-button>
+                </div> -->
+                <div style="margin-right: 10px;">
+                    <a-button @click="handleGenerateWave()">
+                        {{ formatMessage('common.generateWave', '鐢熸垚娉㈡') }}
+                    </a-button>
+                </div>
+            </div>
+            <a-input v-model:value="searchOrder" @change="handleSearchOrder"
+                :placeholder="formatMessage('page.input', '璇疯緭鍏�')" style="margin-bottom: 8px" />
+            <a-tree @select="handleOrderSelected" :tree-data="orderData" v-model:checkedKeys="checkedOrderKeys"
+                checkable blockNode>
+                <template #title="{ orderNo, createTime$ }">
+                    <div style="display: flex;justify-content: space-between">
+                        <div>{{ orderNo }}</div>
+                        <div>{{ createTime$ }}</div>
+                    </div>
+                </template>
+            </a-tree>
+        </a-card>
+
+        <a-card style="flex: 10;">
+            <div class="table-header">
+                <a-button size="small" @click="handleBatchOrderOut()">
+                    {{ formatMessage('common.orderOut', '鎵归噺鍑哄簱') }}
+                </a-button>
+            </div>
+            <a-table :row-selection="{ selectedRowKeys: state.selectedRowKeys, onChange: onSelectChange }"
+                :data-source="tableData" :defaultExpandAllRows="false" :key="TABLE_KEY" rowKey="id"
+                :scroll="{ y: 768, scrollToFirstRowOnChange: true }" :columns="columns">
+                <template #bodyCell="{ column, text, record }">
+                    <template v-if="column.dataIndex === 'oper'">
+                        <div style="display: flex;justify-content: space-evenly;">
+                            <a-button size="small" @click="handleOrderOutPreview([record.id])">
+                                {{ formatMessage('common.orderOut', '鍑哄簱') }}
+                            </a-button>
+                        </div>
+                    </template>
+                </template>
+            </a-table>
+        </a-card>
+
+        <OrderOutBatchPreviewView ref="orderOutBatchPreviewChild" @reload="handleChildReload" />
+        <OrderOutMergePreviewView ref="orderOutMergePreviewChild" @reload="handleChildReload" />
+    </div>
+</template>
+
+<style></style>
diff --git a/zy-asrs-admin/src/views/out/orderOut/index.vue b/zy-asrs-admin/src/views/out/orderOut/index.vue
index ed8ded9..e362c5f 100644
--- a/zy-asrs-admin/src/views/out/orderOut/index.vue
+++ b/zy-asrs-admin/src/views/out/orderOut/index.vue
@@ -74,13 +74,13 @@
         ...getColumnSearchProps('batch'),
     },
 
-    {
-        title: formatMessage('common.operation', '鎿嶄綔'),
-        name: 'oper',
-        dataIndex: 'oper',
-        key: 'oper',
-        width: 140,
-    },
+    // {
+    //     title: formatMessage('common.operation', '鎿嶄綔'),
+    //     name: 'oper',
+    //     dataIndex: 'oper',
+    //     key: 'oper',
+    //     width: 140,
+    // },
 ];
 
 const state = reactive({
@@ -241,9 +241,9 @@
 
         <a-card style="flex: 10;">
             <div class="table-header">
-                <a-button size="small" @click="handleBatchOrderOut()">
+                <!-- <a-button size="small" @click="handleBatchOrderOut()">
                     {{ formatMessage('common.orderOut', '鎵归噺鍑哄簱') }}
-                </a-button>
+                </a-button> -->
             </div>
             <a-table :row-selection="{ selectedRowKeys: state.selectedRowKeys, onChange: onSelectChange }"
                 :data-source="tableData" :defaultExpandAllRows="false" :key="TABLE_KEY" rowKey="id"
diff --git a/zy-asrs-admin/src/views/out/wave/index.vue b/zy-asrs-admin/src/views/out/wave/index.vue
index f0c760e..aac8b81 100644
--- a/zy-asrs-admin/src/views/out/wave/index.vue
+++ b/zy-asrs-admin/src/views/out/wave/index.vue
@@ -7,7 +7,7 @@
 import EditView from './edit.vue'
 import { formatMessage } from '@/utils/localeUtils.js';
 import useTableSearch from '@/utils/tableUtils.jsx';
-import OrderOutMergePreviewView from '@/components/orderOut/orderOutMergePreview/index.vue';
+import OrderOutWavePreviewView from '@/components/orderOut/orderOutWavePreview/index.vue';
 const context = getCurrentInstance()?.appContext.config.globalProperties;
 
 const router = useRouter();
@@ -17,7 +17,7 @@
 let pageSize = 10;
 const searchInput = ref("")
 const editChild = ref(null)
-const orderOutMergePreviewChild = ref(null);
+const orderOutWavePreviewChild = ref(null);
 
 const state = reactive({
   selectedRowKeys: [],
@@ -66,11 +66,14 @@
     },
   },
   {
-    title: formatMessage('db.man_wave.orderNo', '璁㈠崟鍙�'),
-    dataIndex: ['orderNo'],
+    title: formatMessage('db.man_wave.waveStatus$', '鐘舵��'),
+    dataIndex: 'waveStatus$',
     width: 140,
     ellipsis: true,
-    ...getColumnSearchProps('waveType$'),
+    ...getColumnSearchProps('waveStatus$'),
+    customCell: (_, index) => {
+      return customColSpanProps(index)
+    },
   },
   {
     title: formatMessage('db.man_wave.matnr', '鍟嗗搧缂栧彿'),
@@ -88,7 +91,7 @@
   },
   {
     title: formatMessage('db.man_wave.batch', '鎵瑰彿'),
-    dataIndex: ['mat$', 'batch'],
+    dataIndex: ['batch'],
     width: 140,
     ellipsis: true,
     ...getColumnSearchProps('batch'),
@@ -99,6 +102,13 @@
     width: 140,
     ellipsis: true,
     ...getColumnSearchProps('anfme'),
+  },
+  {
+    title: formatMessage('db.man_wave.work_qty', '宸ヤ綔鏁伴噺'),
+    dataIndex: ['workQty'],
+    width: 140,
+    ellipsis: true,
+    ...getColumnSearchProps('workQty'),
   },
 
 ];
@@ -135,17 +145,14 @@
       data.forEach((item) => {
         let count = 0;
 
-        item.waveDetlList.forEach((val) => {
-          count += val.orderDetl$.length;
-          val.orderDetl$.forEach((detl) => {
-            detl.key = idx;
-            detl.waveNo = item.waveNo;
-            detl.waveId = item.id;
-            detl.waveType = item.waveType;
-            detl.waveType$ = item.waveType$;
-            detl.generateTask = item.generateTask;
-            tmp.push(detl)
-          })
+        item.waveDetlList.forEach((detl) => {
+          detl.waveStatus = item.waveStatus;
+          detl.waveStatus$ = item.waveStatus$;
+          detl.waveType = item.waveType;
+          detl.waveType$ = item.waveType$;
+
+          count++;
+          tmp.push(detl)
         })
 
         colSpan[idx] = count;
@@ -219,25 +226,15 @@
 //   editChild.value.isSave = item == null;
 // }
 
-const handleGenerateOut = (item) => {
-  get('/api/wave/list/' + item.waveId, {}).then(resp => {
-    let result = resp.data;
-    let data = result.data;
-    let orderIds = []
-    data.forEach((item) => {
-      orderIds.push(item.orderId)
-    })
-
-    orderOutMergePreviewChild.value.open = true;
-    orderOutMergePreviewChild.value.records = orderIds;
-    orderOutMergePreviewChild.value.waveId = item.waveId;
-  })
+const handleGenerateOut = (waveId) => {
+  orderOutWavePreviewChild.value.open = true;
+  orderOutWavePreviewChild.value.waveId = waveId;
 }
 
 const handleDel = (rows) => {
   Modal.confirm({
-    title: formatMessage('page.delete', '鍒犻櫎'),
-    content: formatMessage('page.delete.confirm', '纭畾鍒犻櫎璇ラ」鍚楋紵'),
+    title: formatMessage('page.cancel', '鍙栨秷'),
+    content: formatMessage('page.cancel.confirm', '纭畾鍙栨秷璇ラ」鍚楋紵'),
     maskClosable: true,
     onOk: async () => {
       const hide = message.loading(formatMessage('common.loading', '璇锋眰涓�'));
@@ -316,18 +313,18 @@
       <template #bodyCell="{ column, text, record }">
         <template v-if="column.dataIndex === 'oper'">
           <div style="display: flex;justify-content: space-evenly;">
-            <a-button type="link" primary @click="handleGenerateOut(record)" :disabled="record.generateTask">{{
+            <a-button type="link" primary @click="handleGenerateOut(record.waveId)">{{
               formatMessage('page.generateOut',
                 '鐢熸垚鍑哄簱浠诲姟')
             }}</a-button>
-            <a-button type="link" danger @click="handleDel([record])">{{ formatMessage('page.delete', '鍒犻櫎')
+            <a-button type="link" danger @click="handleDel([record])">{{ formatMessage('page.cancel', '鍙栨秷')
               }}</a-button>
           </div>
         </template>
       </template>
     </a-table>
 
-    <OrderOutMergePreviewView ref="orderOutMergePreviewChild" @reload="handleChildReload" />
+    <OrderOutWavePreviewView ref="orderOutWavePreviewChild" @reload="handleChildReload" />
   </div>
 </template>
 
diff --git a/zy-asrs-admin/src/views/out/waveSeed/index.vue b/zy-asrs-admin/src/views/out/waveSeed/index.vue
index 799963d..3429c34 100644
--- a/zy-asrs-admin/src/views/out/waveSeed/index.vue
+++ b/zy-asrs-admin/src/views/out/waveSeed/index.vue
@@ -22,6 +22,12 @@
   loading: false,
 });
 
+const reviewState = reactive({
+  open: false,
+  record: null,
+  reviewNum: null
+});
+
 let tableData = ref([]);
 getPage();
 
@@ -209,6 +215,16 @@
   getPage()
 }
 
+const handleReview = (record) => {
+  reviewState.open = true;
+  reviewState.record = record;
+  reviewState.reviewNum = 0;
+}
+
+const handleReviewOk = () => {
+
+}
+
 </script>
 
 <script>
@@ -236,13 +252,24 @@
       <template #bodyCell="{ column, text, record }">
         <template v-if="column.dataIndex === 'oper'">
           <div style="display: flex;justify-content: space-evenly;">
-            <a-button type="link" primary @click="handleEdit(record)">{{ formatMessage('page.edit', '缂栬緫') }}</a-button>
+            <!-- <a-button type="link" primary @click="handleEdit(record)">{{ formatMessage('page.edit', '缂栬緫') }}</a-button> -->
+            <a-button type="link" primary @click="handleReview(record)">{{ formatMessage('page.review', '澶嶆牳')
+              }}</a-button>
             <a-button type="link" danger @click="handleDel([record])">{{ formatMessage('page.delete', '鍒犻櫎')
               }}</a-button>
           </div>
         </template>
       </template>
     </a-table>
+
+    <a-modal v-model:open="reviewState.open" :title="formatMessage('page.review', '澶嶆牳')" @ok="handleReviewOk">
+      <div>
+        鎾鏁伴噺锛歿{ reviewState.record.anfme }}
+      </div>
+      <div>
+        瀹為檯鏁伴噺锛�<a-input v-model:value="reviewState.reviewNum" />
+      </div>
+    </a-modal>
   </div>
 </template>
 
diff --git a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/controller/CacheSiteController.java b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/controller/CacheSiteController.java
index 5bec197..14aa1a8 100644
--- a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/controller/CacheSiteController.java
+++ b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/controller/CacheSiteController.java
@@ -99,4 +99,10 @@
         ExcelUtil.build(ExcelUtil.create(cacheSiteService.list(), CacheSite.class), response);
     }
 
+    @PreAuthorize("hasAuthority('asrs:cacheSite:list')")
+    @PostMapping("/cacheSite/channel/list")
+    public R channelList() {
+        return R.ok().add(cacheSiteService.getChannelList());
+    }
+
 }
diff --git a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/controller/LocDetlController.java b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/controller/LocDetlController.java
index 3549007..fe4f715 100644
--- a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/controller/LocDetlController.java
+++ b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/controller/LocDetlController.java
@@ -9,7 +9,6 @@
 import com.zy.asrs.framework.common.R;
 import com.zy.asrs.wms.asrs.entity.*;
 import com.zy.asrs.wms.asrs.entity.enums.LocStsType;
-import com.zy.asrs.wms.asrs.mapper.LocDetlMapper;
 import com.zy.asrs.wms.asrs.service.LocDetlFieldService;
 import com.zy.asrs.wms.asrs.service.LocService;
 import com.zy.asrs.wms.asrs.service.MatFieldService;
@@ -131,7 +130,6 @@
             locDetlField.setName(matField.getName());
             locDetlFieldService.save(locDetlField);
         }
-
         return R.ok("娣诲姞鎴愬姛");
     }
 
diff --git a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/controller/OutController.java b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/controller/OutController.java
index 7532179..e8f5c1b 100644
--- a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/controller/OutController.java
+++ b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/controller/OutController.java
@@ -1,11 +1,18 @@
 package com.zy.asrs.wms.asrs.controller;
 
+import com.alibaba.fastjson.JSON;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.zy.asrs.framework.common.R;
+import com.zy.asrs.framework.exception.CoolException;
+import com.zy.asrs.wms.asrs.entity.Order;
+import com.zy.asrs.wms.asrs.entity.WaveDetl;
 import com.zy.asrs.wms.asrs.entity.dto.MergePreviewDto;
 import com.zy.asrs.wms.asrs.entity.dto.MergePreviewResultDto;
 import com.zy.asrs.wms.asrs.entity.dto.OrderOutBatchPreviewDto;
 import com.zy.asrs.wms.asrs.entity.param.*;
 import com.zy.asrs.wms.asrs.manage.OutManage;
+import com.zy.asrs.wms.asrs.service.OrderService;
+import com.zy.asrs.wms.asrs.service.WaveDetlService;
 import com.zy.asrs.wms.common.annotation.OperationLog;
 import com.zy.asrs.wms.system.controller.BaseController;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -15,6 +22,7 @@
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
+import java.util.ArrayList;
 import java.util.List;
 
 
@@ -24,6 +32,10 @@
 
     @Autowired
     private OutManage outManage;
+    @Autowired
+    private OrderService orderService;
+    @Autowired
+    private WaveDetlService waveDetlService;
 
     /**
      * 鍑哄簱
@@ -68,19 +80,57 @@
         return R.ok().add(dtos);
     }
 
-    @PostMapping("/out/orderOut/merge")
-    @OperationLog("鍚堝苟璁㈠崟鍑哄簱")
+    @PostMapping("/out/orderOut/wave/preview")
+    @OperationLog("棰勮娉㈡鍑哄簱")
+    @Transactional
+    public R orderOutWavePreview(@RequestBody OrderOutWavePreviewParam param) {
+        if (param == null) {
+            throw new CoolException("鍙傛暟涓嶈兘涓虹┖");
+        }
+
+        Long waveId = param.getWaveId();
+        if (waveId == null) {
+            throw new CoolException("娉㈡涓嶈兘涓虹┖");
+        }
+
+        List<Long> orderIds = new ArrayList<>();
+        List<Order> orders = orderService.list(new LambdaQueryWrapper<Order>().eq(Order::getWaveId, waveId));
+        for (Order order : orders) {
+            orderIds.add(order.getId());
+        }
+
+        List<MergePreviewDto> dtos = new ArrayList<>();
+        List<WaveDetl> waveDetls = waveDetlService.list(new LambdaQueryWrapper<WaveDetl>().eq(WaveDetl::getWaveId, waveId));
+        for (WaveDetl waveDetl : waveDetls) {
+            MergePreviewDto dto = new MergePreviewDto();
+            dtos.add(dto);
+
+            double anfme = waveDetl.getAnfme() - waveDetl.getWorkQty();
+            dto.setMatnr(waveDetl.getMatnr());
+            dto.setBatch(waveDetl.getBatch());
+            dto.setAnfme(anfme);
+            dto.setOrderIds(orderIds);
+            dto.setFieldParams(JSON.parseArray(waveDetl.getFieldParams(), FieldParam.class));
+            dto.setFieldParamsEncode(waveDetl.getFieldParams());
+        }
+
+        List<MergePreviewResultDto> resultDtos = outManage.orderOutMergeLocPreview(dtos);
+        return R.ok().add(resultDtos);
+    }
+
+    @PostMapping("/out/orderOut/merge/wave")
+    @OperationLog("娉㈡鍚堝苟璁㈠崟鍑哄簱")
     @Transactional
     public R orderOutMerge(@RequestBody OrderOutMergeParamDto param) {
-        outManage.orderOutMerge(param);
+        outManage.orderOutMergeWave(param);
         return R.ok();
     }
 
     @PostMapping("/out/wave/generate")
     @OperationLog("鐢熸垚娉㈡")
     @Transactional
-    public R generateWave(@RequestBody List<Long> orderIds) {
-        outManage.generateWave(orderIds);
+    public R generateWave(@RequestBody GenerateWaveParam param) {
+        outManage.generateWave(param);
         return R.ok();
     }
 
diff --git a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/controller/WaveController.java b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/controller/WaveController.java
index c7944ed..06b68e4 100644
--- a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/controller/WaveController.java
+++ b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/controller/WaveController.java
@@ -4,9 +4,7 @@
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.zy.asrs.framework.common.Cools;
 import com.zy.asrs.framework.common.R;
-import com.zy.asrs.wms.asrs.entity.TaskDetl;
 import com.zy.asrs.wms.asrs.entity.WaveDetl;
-import com.zy.asrs.wms.asrs.service.TaskDetlService;
 import com.zy.asrs.wms.asrs.service.WaveDetlService;
 import com.zy.asrs.wms.common.annotation.OperationLog;
 import com.zy.asrs.wms.common.domain.BaseParam;
@@ -21,10 +19,7 @@
 import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletResponse;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 
 @RestController
 @RequestMapping("/api")
@@ -34,8 +29,6 @@
     private WaveService waveService;
     @Autowired
     private WaveDetlService waveDetlService;
-    @Autowired
-    private TaskDetlService taskDetlService;
 
     @PreAuthorize("hasAuthority('asrs:wave:list')")
     @PostMapping("/wave/page")
@@ -43,21 +36,6 @@
         BaseParam baseParam = buildParam(map, BaseParam.class);
         PageParam<Wave, BaseParam> pageParam = new PageParam<>(baseParam, Wave.class);
         PageParam<Wave, BaseParam> page = waveService.page(pageParam, pageParam.buildWrapper(true));
-
-        List<Wave> records = page.getRecords();
-        for (Wave record : records) {
-            ArrayList<Long> orderDetlIds = new ArrayList<>();
-            for (WaveDetl waveDetl : record.getWaveDetlList()) {
-                orderDetlIds.add(waveDetl.getOrderId());
-            }
-
-            List<TaskDetl> taskDetls = taskDetlService.list(new LambdaQueryWrapper<TaskDetl>().in(TaskDetl::getOrderId, orderDetlIds));
-            if (taskDetls.isEmpty()) {
-                record.setGenerateTask(false);
-            }else {
-                record.setGenerateTask(true);
-            }
-        }
         return R.ok().add(page);
     }
 
diff --git a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/CacheSite.java b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/CacheSite.java
index 68f3ca0..e241e4f 100644
--- a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/CacheSite.java
+++ b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/CacheSite.java
@@ -1,6 +1,7 @@
 package com.zy.asrs.wms.asrs.entity;
 
-import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.baomidou.mybatisplus.annotation.*;
+
 import java.text.SimpleDateFormat;
 import java.util.Date;
 
@@ -11,10 +12,7 @@
 import java.text.SimpleDateFormat;
 import java.util.Date;
 
-import com.baomidou.mybatisplus.annotation.IdType;
-import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableLogic;
-import com.baomidou.mybatisplus.annotation.TableName;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
@@ -56,12 +54,14 @@
      * 璁㈠崟ID
      */
     @ApiModelProperty(value= "璁㈠崟ID")
+    @TableField(updateStrategy = FieldStrategy.IGNORED)
     private Long orderId;
 
     /**
      * 璁㈠崟缂栧彿
      */
     @ApiModelProperty(value= "璁㈠崟缂栧彿")
+    @TableField(updateStrategy = FieldStrategy.IGNORED)
     private String orderNo;
 
     /**
@@ -115,6 +115,12 @@
     @ApiModelProperty(value= "澶囨敞")
     private String memo;
 
+    /**
+     * 閫氶亾
+     */
+    @ApiModelProperty(value= "閫氶亾")
+    private String channel;
+
     public CacheSite() {}
 
     public CacheSite(String siteNo,Integer siteStatus,Long orderId,String orderNo,Long hostId,Integer status,Integer deleted,Date createTime,Long createBy,Date updateTime,Long updateBy,String memo) {
diff --git a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/LocDetl.java b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/LocDetl.java
index 7040908..6596b8a 100644
--- a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/LocDetl.java
+++ b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/LocDetl.java
@@ -1,7 +1,5 @@
 package com.zy.asrs.wms.asrs.entity;
 
-import com.baomidou.mybatisplus.annotation.TableLogic;
-
 import java.lang.reflect.Field;
 import java.text.SimpleDateFormat;
 import java.util.*;
@@ -15,14 +13,11 @@
 import com.zy.asrs.wms.system.entity.Host;
 import com.zy.asrs.wms.system.entity.User;
 import org.springframework.format.annotation.DateTimeFormat;
-import java.text.SimpleDateFormat;
 import java.util.Date;
 
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableLogic;
 import com.baomidou.mybatisplus.annotation.TableName;
-import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 import com.zy.asrs.framework.common.Cools;
@@ -31,7 +26,6 @@
 import com.zy.asrs.wms.system.service.HostService;
 
 import java.io.Serializable;
-import java.util.Date;
 
 @Data
 @TableName("man_loc_detl")
diff --git a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/Order.java b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/Order.java
index e2923fd..8b291ac 100644
--- a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/Order.java
+++ b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/Order.java
@@ -132,6 +132,12 @@
     @TableField(updateStrategy = FieldStrategy.IGNORED)
     private String waveNo;
 
+    /**
+     * 鏄惁鐢熸垚娉㈡ 1: 鏄�  0: 鍚�
+     */
+    @ApiModelProperty(value= "鏄惁鐢熸垚娉㈡ 1: 鏄�  0: 鍚�  ")
+    private Integer hasWave;
+
     public Order() {}
 
     public Order(String orderNo,String orderTime,Long orderType,Long orderSettle,Long hostId,Integer status,Integer deleted,Date createTime,Long createBy,Date updateTime,Long updateBy,String memo) {
diff --git a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/OrderDetl.java b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/OrderDetl.java
index 78bc22b..75e005c 100644
--- a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/OrderDetl.java
+++ b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/OrderDetl.java
@@ -136,6 +136,12 @@
     @ApiModelProperty(value= "澶囨敞")
     private String memo;
 
+    /**
+     * 鍟嗗搧搴撳瓨绱㈠紩
+     */
+    @ApiModelProperty(value= "鍟嗗搧搴撳瓨绱㈠紩")
+    private String stockIndex;
+
     public OrderDetl() {}
 
     public OrderDetl(Long orderId,String orderNo,Double anfme,Double qty,Double workQty,Long matId,String batch,Long hostId,Integer status,Integer deleted,Date createTime,Long createBy,Date updateTime,Long updateBy,String memo) {
diff --git a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/TaskDetl.java b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/TaskDetl.java
index 0f0bb1e..09768bb 100644
--- a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/TaskDetl.java
+++ b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/TaskDetl.java
@@ -157,6 +157,12 @@
     @ApiModelProperty(value= "澶囨敞")
     private String memo;
 
+    /**
+     * 娉㈡ID
+     */
+    @ApiModelProperty(value= "娉㈡ID")
+    private Long waveId;
+
     public TaskDetl() {}
 
     public TaskDetl(Long taskId,String taskNo,Double anfme,String batch,String barcode,Long orderId,String orderNo,Long detlId,Long matId,Long hostId,Integer status,Integer deleted,Date createTime,Long createBy,Date updateTime,Long updateBy,String memo) {
@@ -262,6 +268,15 @@
         return null;
     }
 
+    public Wave getWave$(){
+        WaveService service = SpringUtils.getBean(WaveService.class);
+        Wave wave = service.getById(this.waveId);
+        if (!Cools.isEmpty(wave)){
+            return wave;
+        }
+        return null;
+    }
+
     public String getHostId$(){
         HostService service = SpringUtils.getBean(HostService.class);
         Host host = service.getById(this.hostId);
diff --git a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/Wave.java b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/Wave.java
index 7c43c8f..073733d 100644
--- a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/Wave.java
+++ b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/Wave.java
@@ -1,14 +1,17 @@
 package com.zy.asrs.wms.asrs.entity;
 
+import com.alibaba.fastjson.JSON;
 import com.baomidou.mybatisplus.annotation.*;
 
 import java.text.SimpleDateFormat;
-import java.util.Date;
+import java.util.*;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.zy.asrs.wms.asrs.entity.param.FieldParam;
 import com.zy.asrs.wms.asrs.service.WaveDetlService;
 import com.zy.asrs.wms.system.entity.Host;
 import com.zy.asrs.wms.system.entity.User;
+import com.zy.asrs.wms.utils.Utils;
 import org.springframework.format.annotation.DateTimeFormat;
 import java.text.SimpleDateFormat;
 import java.util.Date;
@@ -25,7 +28,6 @@
 
 import java.io.Serializable;
 import java.util.Date;
-import java.util.List;
 
 @Data
 @TableName("man_wave")
@@ -51,6 +53,12 @@
      */
     @ApiModelProperty(value= "娉㈡绫诲瀷 0: 鎵嬪姩  1: 鑷姩  ")
     private Integer waveType;
+
+    /**
+     * 娉㈡鐘舵�� 0: 鍒濆鍖�  1: 鐢熸垚浠诲姟  2: 浠诲姟鎾  3: 瀹屾垚
+     */
+    @ApiModelProperty(value= "娉㈡鐘舵�� 0: 鍒濆鍖�  1: 鐢熸垚浠诲姟  2: 浠诲姟鎾  3: 瀹屾垚  ")
+    private Integer waveStatus;
 
     /**
      * 鎵�灞炴満鏋�
@@ -145,6 +153,22 @@
         }
     }
 
+    public String getWaveStatus$(){
+        if (null == this.waveStatus){ return null; }
+        switch (this.waveStatus){
+            case 0:
+                return "鍒濆鍖�";
+            case 1:
+                return "鐢熸垚浠诲姟";
+            case 2:
+                return "浠诲姟鎾";
+            case 3:
+                return "瀹屾垚";
+            default:
+                return String.valueOf(this.waveStatus);
+        }
+    }
+
     public List<WaveDetl> getWaveDetlList(){
         if (null == this.id){ return null; }
         WaveDetlService service = SpringUtils.getBean(WaveDetlService.class);
@@ -152,6 +176,11 @@
         if (waveDetls.isEmpty()) {
             return null;
         }
+        for (WaveDetl waveDetl : waveDetls) {
+            String fieldParams = waveDetl.getFieldParams();
+            List<FieldParam> list = JSON.parseArray(fieldParams, FieldParam.class);
+            waveDetl.setDynamicFields(list);
+        }
         return waveDetls;
     }
 
diff --git a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/WaveDetl.java b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/WaveDetl.java
index 1c4799f..3e6c2c9 100644
--- a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/WaveDetl.java
+++ b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/WaveDetl.java
@@ -2,9 +2,12 @@
 
 import com.baomidou.mybatisplus.annotation.TableLogic;
 import java.text.SimpleDateFormat;
-import java.util.Date;
+import java.util.*;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.zy.asrs.wms.asrs.entity.param.FieldParam;
+import com.zy.asrs.wms.asrs.service.MatService;
 import com.zy.asrs.wms.asrs.service.OrderDetlService;
 import com.zy.asrs.wms.asrs.service.OrderService;
 import com.zy.asrs.wms.asrs.service.WaveService;
@@ -29,7 +32,6 @@
 
 import java.io.Serializable;
 import java.util.Date;
-import java.util.List;
 
 @Data
 @TableName("man_wave_detl")
@@ -57,16 +59,40 @@
     private String waveNo;
 
     /**
-     * 璁㈠崟ID
+     * 鍟嗗搧ID
      */
-    @ApiModelProperty(value= "璁㈠崟ID")
-    private Long orderId;
+    @ApiModelProperty(value= "鍟嗗搧ID")
+    private Long matId;
 
     /**
-     * 璁㈠崟鍙�
+     * 鍟嗗搧缂栧彿
      */
-    @ApiModelProperty(value= "璁㈠崟鍙�")
-    private String orderNo;
+    @ApiModelProperty(value= "鍟嗗搧缂栧彿")
+    private String matnr;
+
+    /**
+     * 鎵瑰彿
+     */
+    @ApiModelProperty(value= "鎵瑰彿")
+    private String batch;
+
+    /**
+     * 鍟嗗搧搴撳瓨绱㈠紩
+     */
+    @ApiModelProperty(value= "鍟嗗搧搴撳瓨绱㈠紩")
+    private String stockIndex;
+
+    /**
+     * 鏁伴噺
+     */
+    @ApiModelProperty(value= "鏁伴噺")
+    private Double anfme;
+
+    /**
+     * 宸ヤ綔鏁伴噺
+     */
+    @ApiModelProperty(value= "宸ヤ綔鏁伴噺")
+    private Double workQty;
 
     /**
      * 鎵�灞炴満鏋�
@@ -118,13 +144,22 @@
     @ApiModelProperty(value= "澶囨敞")
     private String memo;
 
+    /**
+     * 绱㈠紩瀛楁
+     */
+    @ApiModelProperty(value= "绱㈠紩瀛楁")
+    private String fieldParams;
+
     public WaveDetl() {}
 
-    public WaveDetl(Long waveId,String waveNo,Long orderId,String orderNo,Long hostId,Integer status,Integer deleted,Date createTime,Long createBy,Date updateTime,Long updateBy,String memo) {
+    public WaveDetl(Long waveId, String waveNo, String matnr, String batch, String stockIndex, Double anfme, Double workQty, Long hostId, Integer status, Integer deleted, Date createTime, Long createBy, Date updateTime, Long updateBy, String memo) {
         this.waveId = waveId;
         this.waveNo = waveNo;
-        this.orderId = orderId;
-        this.orderNo = orderNo;
+        this.matnr = matnr;
+        this.batch = batch;
+        this.stockIndex = stockIndex;
+        this.anfme = anfme;
+        this.workQty = workQty;
         this.hostId = hostId;
         this.status = status;
         this.deleted = deleted;
@@ -135,7 +170,7 @@
         this.memo = memo;
     }
 
-//    WaveDetl waveDetl = new WaveDetl(
+    //    WaveDetl waveDetl = new WaveDetl(
 //            null,    // 娉㈡ID
 //            null,    // 娉㈡鍙�
 //            null,    // 璁㈠崟ID
@@ -159,29 +194,11 @@
         return null;
     }
 
-    public String getOrderId$(){
-        OrderService service = SpringUtils.getBean(OrderService.class);
-        Order order = service.getById(this.orderId);
-        if (!Cools.isEmpty(order)){
-            return String.valueOf(order.getId());
-        }
-        return null;
-    }
-
-    public Order getOrder$(){
-        OrderService service = SpringUtils.getBean(OrderService.class);
-        Order order = service.getById(this.orderId);
-        if (!Cools.isEmpty(order)){
-            return order;
-        }
-        return null;
-    }
-
-    public List<OrderDetl> getOrderDetl$(){
-        OrderDetlService service = SpringUtils.getBean(OrderDetlService.class);
-        List<OrderDetl> orderDetls = service.list(new LambdaQueryWrapper<OrderDetl>().eq(OrderDetl::getOrderId, this.orderId));
-        if (!orderDetls.isEmpty()){
-            return service.parseDetl(orderDetls);
+    public Mat getMat$(){
+        MatService service = SpringUtils.getBean(MatService.class);
+        Mat mat = service.getById(this.matId);
+        if (!Cools.isEmpty(mat)){
+            return mat;
         }
         return null;
     }
@@ -256,4 +273,18 @@
     public void sync(Object source) {
         Synchro.Copy(source, this);
     }
+
+    //鍔ㄦ�佹墿灞曞瓧娈�
+    public transient Map<String, Object> dynamicFields = new HashMap<>();
+
+    @JsonAnyGetter
+    public Map<String,Object> getDynamicFields() {
+        return dynamicFields;
+    }
+
+    public void setDynamicFields(List<FieldParam> list) {
+        for (FieldParam param : list) {
+            dynamicFields.put(param.getName(), param.getValue());
+        }
+    }
 }
diff --git a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/MergePreviewResultDto.java b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/MergePreviewResultDto.java
index 3c701e9..bad9f05 100644
--- a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/MergePreviewResultDto.java
+++ b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/MergePreviewResultDto.java
@@ -22,6 +22,8 @@
 
     private List<MergePreviewResultLocDto> locs;
 
+    private List<MergePreviewResultLocDto> otherLocs;
+
     private List<FieldParam> fieldParams;
 
     private String fieldParamsEncode;
diff --git a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/OrderOutMergeWaveDto.java b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/OrderOutMergeWaveDto.java
new file mode 100644
index 0000000..002bdf7
--- /dev/null
+++ b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/OrderOutMergeWaveDto.java
@@ -0,0 +1,32 @@
+package com.zy.asrs.wms.asrs.entity.dto;
+
+import com.zy.asrs.common.utils.Synchro;
+import com.zy.asrs.wms.asrs.entity.param.FieldParam;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class OrderOutMergeWaveDto {
+
+    private Long locId;
+
+    private String locNo;
+
+    private Long locDetlId;
+
+    private String matnr;
+
+    private String batch;
+
+    private Double anfme;
+
+    private Long operationPort;
+
+    private List<FieldParam> fieldParams;
+
+    public void sync(Object source) {
+        Synchro.Copy(source, this);
+    }
+
+}
diff --git a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/enums/OrderSettleType.java b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/enums/OrderSettleType.java
index 3efe1c5..15d38b7 100644
--- a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/enums/OrderSettleType.java
+++ b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/enums/OrderSettleType.java
@@ -12,11 +12,12 @@
 
     INIT(0, "鍒濆鍖�"),
     WAIT(1, "寰呭鐞�"),
-    WORKING(2, "浣滀笟涓�"),
-    CANCEL(3, "宸插彇娑�"),
-    COMPLETE(4, "宸插畬鎴�"),
-    WAIT_CANCEL(5, "鍑嗗鍙栨秷"),
-    REPORT_COMPLETE(6, "涓婃姤瀹屾垚"),
+    WAVE(2, "娉㈡鐢熸垚"),
+    WORKING(3, "浣滀笟涓�"),
+    CANCEL(4, "宸插彇娑�"),
+    COMPLETE(5, "宸插畬鎴�"),
+    WAIT_CANCEL(6, "鍑嗗鍙栨秷"),
+    REPORT_COMPLETE(7, "涓婃姤瀹屾垚"),
     ;
 
 
diff --git a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/enums/WaveStatusType.java b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/enums/WaveStatusType.java
new file mode 100644
index 0000000..607aa3f
--- /dev/null
+++ b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/enums/WaveStatusType.java
@@ -0,0 +1,20 @@
+package com.zy.asrs.wms.asrs.entity.enums;
+
+public enum WaveStatusType {
+
+    INIT(0, "鍒濆鍖�"),
+    GENERATE(1, "鐢熸垚浠诲姟"),
+    SEED(2, "浠诲姟鎾"),
+    COMPLETE(3, "瀹屾垚"),
+    ;
+
+
+    public Integer id;
+    public String desc;
+
+    WaveStatusType(Integer id, String desc) {
+        this.id = id;
+        this.desc = desc;
+    }
+
+}
diff --git a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/param/GenerateWaveParam.java b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/param/GenerateWaveParam.java
new file mode 100644
index 0000000..9d461e3
--- /dev/null
+++ b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/param/GenerateWaveParam.java
@@ -0,0 +1,14 @@
+package com.zy.asrs.wms.asrs.entity.param;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class GenerateWaveParam {
+
+    private List<String> channels;
+
+    private List<Long> orderIds;
+
+}
diff --git a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/param/OrderOutMergePreviewParam.java b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/param/OrderOutMergePreviewParam.java
index 2ec8afb..d2b78d4 100644
--- a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/param/OrderOutMergePreviewParam.java
+++ b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/param/OrderOutMergePreviewParam.java
@@ -7,6 +7,8 @@
 @Data
 public class OrderOutMergePreviewParam {
 
+    private Long waveId;
+
     private List<Long> orderIds;
 
 }
diff --git a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/param/OrderOutWavePreviewParam.java b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/param/OrderOutWavePreviewParam.java
new file mode 100644
index 0000000..df7b07a
--- /dev/null
+++ b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/param/OrderOutWavePreviewParam.java
@@ -0,0 +1,10 @@
+package com.zy.asrs.wms.asrs.entity.param;
+
+import lombok.Data;
+
+@Data
+public class OrderOutWavePreviewParam {
+
+    private Long waveId;
+
+}
diff --git a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/manage/OutManage.java b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/manage/OutManage.java
index d6be710..34c43e9 100644
--- a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/manage/OutManage.java
+++ b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/manage/OutManage.java
@@ -7,6 +7,8 @@
 import com.zy.asrs.wms.asrs.entity.dto.OrderOutMergeDto;
 import com.zy.asrs.wms.asrs.entity.enums.CacheSiteStatusType;
 import com.zy.asrs.wms.asrs.entity.enums.LocStsType;
+import com.zy.asrs.wms.asrs.entity.enums.OrderSettleType;
+import com.zy.asrs.wms.asrs.entity.enums.WaveStatusType;
 import com.zy.asrs.wms.asrs.entity.param.*;
 import com.zy.asrs.wms.asrs.entity.*;
 import com.zy.asrs.wms.asrs.service.*;
@@ -112,6 +114,7 @@
                 TaskDetl taskDetl = new TaskDetl();
                 taskDetl.sync(locDetl);
                 taskDetl.setTaskId(task.getId());
+                taskDetl.setTaskNo(task.getTaskNo());
                 taskDetl.setAnfme(detl.getAnfme());
                 taskDetl.setStock(detl.getStock());
                 taskDetl.setOrderId(null);
@@ -389,6 +392,7 @@
                 taskDetl.sync(locDetl);
                 taskDetl.setId(null);
                 taskDetl.setTaskId(task.getId());
+                taskDetl.setTaskNo(task.getTaskNo());
                 taskDetl.setAnfme(dto.getAnfme());
                 taskDetl.setStock(locDetl.getAnfme());
                 taskDetl.setOrderId(orderDetl.getOrderId());
@@ -506,6 +510,12 @@
         for (MergePreviewDto dto : param) {
             List<LocDetl> locDetls = locDetlService.queryStock(dto.getMatnr(), dto.getBatch(), dto.getFieldParams(), sortParams);
             if(locDetls.isEmpty()){
+                MergePreviewResultDto resultDto = new MergePreviewResultDto();
+                resultDto.sync(dto);
+                resultDto.setLocs(new ArrayList<>());
+                resultDto.setOrderIds(dto.getOrderIds());
+                resultDto.setAnfme(dto.getAnfme());
+                resultDtos.add(resultDto);
                 continue;
             }
 
@@ -518,6 +528,15 @@
 
             Double anfme = dto.getAnfme();
             for (LocDetl locDetl : locDetls) {
+                Loc loc = locService.getById(locDetl.getLocId());
+                if (loc == null) {
+                    throw new CoolException("搴撲綅鏁版嵁涓嶅瓨鍦�");
+                }
+
+                if (loc.getLocStsId() != LocStsType.F.val()) {
+                    continue;
+                }
+
                 MergePreviewResultLocDto locDto = new MergePreviewResultLocDto();
                 locDto.setLocId(locDetl.getLocId());
                 locDto.setLocNo(locDetl.getLocNo());
@@ -531,7 +550,28 @@
                 locDto.setAnfme(locDetl.getAnfme());
                 anfme -= locDetl.getAnfme();
             }
-            resultDto.setAnfme(anfme < 0 ? 0 : anfme);
+
+            List<MergePreviewResultLocDto> otherLocDtos = new ArrayList<>();
+            for (LocDetl locDetl : locDetls) {
+                Loc loc = locService.getById(locDetl.getLocId());
+                if (loc == null) {
+                    throw new CoolException("搴撲綅鏁版嵁涓嶅瓨鍦�");
+                }
+
+                if (loc.getLocStsId() != LocStsType.F.val()) {
+                    continue;
+                }
+
+                MergePreviewResultLocDto locDto = new MergePreviewResultLocDto();
+                locDto.setLocId(locDetl.getLocId());
+                locDto.setLocNo(locDetl.getLocNo());
+                locDto.setLocDetlId(locDetl.getId());
+                locDto.setAnfme(locDetl.getAnfme());
+                otherLocDtos.add(locDto);
+            }
+            resultDto.setOtherLocs(otherLocDtos);
+
+            resultDto.setAnfme(dto.getAnfme());
 
             resultDtos.add(resultDto);
         }
@@ -704,6 +744,7 @@
                 taskDetl.sync(locDetl);
                 taskDetl.setId(null);
                 taskDetl.setTaskId(task.getId());
+                taskDetl.setTaskNo(task.getTaskNo());
                 taskDetl.setAnfme(merge.getAnfme());
                 taskDetl.setStock(locDetl.getAnfme());
                 taskDetl.setOrderId(orderDetl.getOrderId());
@@ -738,73 +779,220 @@
 
         }
 
-        if (dto.getWaveId() != null) {
-            HashMap<Long, List<TaskDetl>> orderMap = new HashMap<>();
-            for (TaskDetl taskDetl : taskDetls) {
-                Long orderId = taskDetl.getOrderId();
-
-                List<TaskDetl> list = orderMap.get(orderId);
-                if (list == null) {
-                    list = new ArrayList<>();
-                }
-
-                list.add(taskDetl);
-                orderMap.put(orderId, list);
-            }
-
-            for (Map.Entry<Long, List<TaskDetl>> entry : orderMap.entrySet()) {
-                List<TaskDetl> list = entry.getValue();
-
-                List<CacheSite> cacheSites = cacheSiteService.list(new LambdaQueryWrapper<CacheSite>().eq(CacheSite::getSiteStatus, CacheSiteStatusType.O.id));
-                if (cacheSites.isEmpty()) {
-                    throw new CoolException("缂撳瓨绔欑┖闂翠笉瓒筹紝璇风◢鍚庡啀璇�");
-                }
-                CacheSite cacheSite = cacheSites.get(0);
-
-                Long orderId = null;
-                String orderNo = null;
-                for (TaskDetl taskDetl : list) {
-                    orderId = taskDetl.getOrderId();
-                    orderNo = taskDetl.getOrderNo();
-                    Long orderDetlId = taskDetl.getDetlId();
-
-                    WaveSeed waveSeed = new WaveSeed();
-                    waveSeed.setSiteId(cacheSite.getId());
-                    waveSeed.setSiteNo(cacheSite.getSiteNo());
-                    waveSeed.setOrderDetlId(orderDetlId);
-                    waveSeed.setTaskDetlId(taskDetl.getId());
-                    waveSeed.setAnfme(taskDetl.getAnfme());
-                    waveSeed.setWorkQty(0D);
-                    if (!waveSeedService.save(waveSeed)) {
-                        throw new CoolException("娉㈡鎾鍒涘缓澶辫触");
-                    }
-                }
-
-                if(orderId == null){
-                    continue;
-                }
-
-                cacheSite.setOrderId(orderId);
-                cacheSite.setOrderNo(orderNo);
-                cacheSite.setSiteStatus(CacheSiteStatusType.R.id);
-                cacheSite.setUpdateTime(new Date());
-                if (!cacheSiteService.updateById(cacheSite)) {
-                    throw new CoolException("缂撳瓨绔欐洿鏂板け璐�");
-                }
-
-            }
-        }
-
     }
 
     @Transactional
-    public void generateWave(List<Long> orderIds) {
-        if (orderIds == null) {
+    public void orderOutMergeWave(OrderOutMergeParamDto dto) {
+        if(dto == null){
             throw new CoolException("鍙傛暟涓嶈兘涓虹┖");
         }
 
-        if (orderIds.isEmpty()) {
+        if (dto.getWaveId() == null) {
+            throw new CoolException("鏈敓鎴愭尝娆�");
+        }
+
+        List<OrderOutMergeParam> params = dto.getList();
+
+        if (params.isEmpty()) {
             throw new CoolException("鍙傛暟涓嶈兘涓虹┖");
+        }
+
+        Long waveId = dto.getWaveId();
+
+        List<Long> filterParamsList = new ArrayList<>();
+        List<OrderOutMergeParam> filterParams = new ArrayList<>();
+        for (OrderOutMergeParam param : params) {
+            if (param.getLocId() == null) {
+                continue;
+            }
+
+            if(!filterParamsList.contains(param.getLocId())){
+                filterParamsList.add(param.getLocId());
+                filterParams.add(param);
+            }
+        }
+
+        HashMap<String, Double> stockMap = new HashMap<>();
+        for (OrderOutMergeParam param : filterParams) {
+            String matUniqueKey = Utils.getMatUniqueKey(param.getMatnr(), param.getBatch(), param.getFieldParams());
+            WaveDetl waveDetl = waveDetlService.getOne(new LambdaQueryWrapper<WaveDetl>().eq(WaveDetl::getStockIndex, matUniqueKey).eq(WaveDetl::getWaveId, waveId));
+            if(waveDetl == null){
+                throw new CoolException("娉㈡鏁版嵁涓嶅瓨鍦�");
+            }
+
+            double issued = Optional.of(waveDetl.getAnfme() - waveDetl.getWorkQty()).orElse(0.0D);
+            if(!stockMap.containsKey(matUniqueKey)){
+                stockMap.put(matUniqueKey, issued);
+            }
+        }
+
+        HashMap<Long, List<OrderOutMergeDto>> map = new HashMap<>();
+        for (OrderOutMergeParam param : filterParams) {
+            LocDetl locDetl = locDetlService.getById(param.getLocDetlId());
+            if(locDetl == null) {
+                continue;
+            }
+
+            if (locDetl.getAnfme() - param.getAnfme() < 0) {
+                continue;
+            }
+
+            OrderOutMergeDto orderOutMergeDto = new OrderOutMergeDto();
+            orderOutMergeDto.sync(param);
+
+            String matUniqueKey = Utils.getMatUniqueKey(param.getMatnr(), param.getBatch(), param.getFieldParams());
+            Double issued = stockMap.get(matUniqueKey);
+            if (issued - orderOutMergeDto.getAnfme() < 0) {
+                orderOutMergeDto.setAnfme(issued);
+                issued = 0D;
+            }else {
+                issued -= orderOutMergeDto.getAnfme();
+            }
+            stockMap.put(matUniqueKey, issued);
+
+            List<OrderOutMergeDto> list = null;
+            if (map.containsKey(orderOutMergeDto.getLocId())) {
+                list = map.get(orderOutMergeDto.getLocId());
+            }else {
+                list = new ArrayList<>();
+            }
+            list.add(orderOutMergeDto);
+            map.put(orderOutMergeDto.getLocId(), list);
+        }
+
+        for (Map.Entry<Long, List<OrderOutMergeDto>> entry : map.entrySet()) {
+            Long locId = entry.getKey();
+            List<OrderOutMergeDto> list = entry.getValue();
+            Boolean all = outUtils.isAllForMerge(locId, list);
+            OrderOutMergeDto param = list.get(0);
+            Long operationPortId = param.getOperationPort();
+
+            Loc loc = locService.getById(locId);
+            if (loc == null) {
+                throw new CoolException("搴撲綅涓嶅瓨鍦�");
+            }
+
+            if (!loc.getLocStsId().equals(LocStsType.F.val())) {
+                throw new CoolException(loc.getLocNo() + "搴撲綅鐘舵�佸紓甯�");
+            }
+
+            OperationPort operationPort = operationPortService.getById(operationPortId);
+            if (operationPort == null) {
+                throw new CoolException("浣滀笟鍙d笉瀛樺湪");
+            }
+
+            long taskType = all ? 101L : 103L;
+
+            Task task = new Task();
+            task.setTaskNo(workService.generateTaskNo(taskType));
+            task.setTaskSts(101L);
+            task.setTaskType(taskType);
+            task.setIoPri(workService.generateIoPri(taskType));
+            task.setOriginLoc(loc.getLocNo());
+            task.setTargetSite(operationPort.getFlag());
+            task.setBarcode(loc.getBarcode());
+            boolean res = taskService.save(task);
+            if (!res) {
+                throw new CoolException("淇濆瓨宸ヤ綔妗eけ璐�");
+            }
+
+            for (OrderOutMergeDto merge : list) {
+                LocDetl locDetl = locDetlService.getById(merge.getLocDetlId());
+                if(locDetl == null) {
+                    throw new CoolException("鏄庣粏涓嶅瓨鍦�");
+                }
+
+                TaskDetl taskDetl = new TaskDetl();
+                taskDetl.sync(locDetl);
+                taskDetl.setId(null);
+                taskDetl.setTaskId(task.getId());
+                taskDetl.setTaskNo(task.getTaskNo());
+                taskDetl.setAnfme(merge.getAnfme());
+                taskDetl.setStock(locDetl.getAnfme());
+                taskDetl.setWaveId(waveId);
+                taskDetl.setOrderId(null);
+                taskDetl.setOrderNo(null);
+                if (!taskDetlService.save(taskDetl)) {
+                    throw new CoolException("淇濆瓨宸ヤ綔妗f槑缁嗗け璐�");
+                }
+
+                List<LocDetlField> locDetlFields = locDetlFieldService.list(new LambdaQueryWrapper<LocDetlField>().eq(LocDetlField::getDetlId, locDetl.getId()));
+                for (LocDetlField locDetlField : locDetlFields) {
+                    TaskDetlField taskDetlField = new TaskDetlField();
+                    taskDetlField.sync(locDetlField);
+                    taskDetlField.setId(null);
+                    taskDetlField.setDetlId(taskDetl.getId());
+                    boolean taskDetlFieldSave = taskDetlFieldService.save(taskDetlField);
+                    if(!taskDetlFieldSave){
+                        throw new CoolException("鏄庣粏鎵╁睍鐢熸垚澶辫触");
+                    }
+                }
+
+                String matUniqueKey = Utils.getMatUniqueKey(taskDetl.getMatnr(), taskDetl.getBatch(), taskDetl.getUniqueField());
+                WaveDetl waveDetl = waveDetlService.getOne(new LambdaQueryWrapper<WaveDetl>().eq(WaveDetl::getStockIndex, matUniqueKey).eq(WaveDetl::getWaveId, waveId));
+                if (waveDetl == null) {
+                    throw new CoolException("娉㈡鏁版嵁涓嶅瓨鍦�");
+                }
+                waveDetl.setWorkQty(waveDetl.getWorkQty() + taskDetl.getAnfme());
+                waveDetl.setUpdateTime(new Date());
+                if (!waveDetlService.updateById(waveDetl)) {
+                    throw new CoolException("娉㈡鏁版嵁鏇存柊澶辫触");
+                }
+
+            }
+
+            //搴撲綅F => R
+            loc.setLocStsId(LocStsType.R.val());
+            loc.setUpdateTime(new Date());
+            boolean locUpdate = locService.updateById(loc);
+            if(!locUpdate){
+                throw new CoolException("搴撲綅鐘舵�佹洿鏂板け璐�");
+            }
+
+        }
+
+        Wave wave = waveService.getById(waveId);
+        if (wave == null) {
+            throw new CoolException("娉㈡涓嶅瓨鍦�");
+        }
+
+        wave.setWaveStatus(WaveStatusType.GENERATE.id);
+        wave.setUpdateTime(new Date());
+        if (!waveService.updateById(wave)) {
+            throw new CoolException("娉㈡鏇存柊澶辫触");
+        }
+    }
+
+    @Transactional
+    public void generateWave(GenerateWaveParam param) {
+        if (param == null) {
+            throw new CoolException("鍙傛暟涓嶈兘涓虹┖");
+        }
+
+        List<String> channels = param.getChannels();
+        if (channels == null) {
+            throw new CoolException("閫氶亾鍙傛暟涓嶈兘涓虹┖");
+        }
+
+        if (channels.isEmpty()) {
+            throw new CoolException("閫氶亾鍙傛暟涓嶈兘涓虹┖");
+        }
+
+        for (String channel : channels) {
+            long count = cacheSiteService.count(new LambdaQueryWrapper<CacheSite>().eq(CacheSite::getChannel, channel).ne(CacheSite::getSiteStatus, 0));
+            if (count > 0) {
+                throw new CoolException(channel + "閫氶亾宸茬粡鍒嗛厤娉㈡");
+            }
+        }
+
+
+        List<Long> orderIds = param.getOrderIds();
+        if (orderIds == null) {
+            throw new CoolException("璁㈠崟鍙傛暟涓嶈兘涓虹┖");
+        }
+
+        if (orderIds.isEmpty()) {
+            throw new CoolException("璁㈠崟鍙傛暟涓嶈兘涓虹┖");
         }
 
         List<Order> orderList = orderService.listByIds(orderIds);
@@ -822,26 +1010,77 @@
         Wave wave = new Wave();
         wave.setWaveNo(waveNo);
         wave.setWaveType(0);
+        wave.setWaveStatus(WaveStatusType.INIT.id);
         if (!waveService.save(wave)) {
             throw new CoolException("娉㈡鐢熸垚澶辫触");
         }
 
+        HashMap<String, List<OrderDetl>> map = new HashMap<>();
         for (Order order : orderList) {
-            WaveDetl waveDetl = new WaveDetl();
-            waveDetl.setWaveNo(waveNo);
-            waveDetl.setWaveId(wave.getId());
-            waveDetl.setOrderId(order.getId());
-            waveDetl.setOrderNo(order.getOrderNo());
-            if (!waveDetlService.save(waveDetl)) {
-                throw new CoolException("娉㈡鏄庣粏鐢熸垚澶辫触");
+            List<OrderDetl> orderDetls = orderDetlService.list(new LambdaQueryWrapper<OrderDetl>().eq(OrderDetl::getOrderId, order.getId()));
+            for (OrderDetl orderDetl : orderDetls) {
+                List<OrderDetl> list = map.get(orderDetl.getStockIndex());
+                if (list == null) {
+                    list = new ArrayList<>();
+                }
+                list.add(orderDetl);
+                map.put(orderDetl.getStockIndex(), list);
             }
 
+            order.setOrderSettle(OrderSettleType.WAVE.val());
             order.setWaveId(wave.getId());
             order.setWaveNo(waveNo);
+            order.setHasWave(1);
             order.setUpdateTime(new Date());
             if (!orderService.updateById(order)) {
                 throw new CoolException("璁㈠崟鍙嶅啓娉㈡澶辫触");
             }
+
+            List<CacheSite> cacheSites = cacheSiteService.list(new LambdaQueryWrapper<CacheSite>().eq(CacheSite::getSiteStatus, CacheSiteStatusType.O.id).in(CacheSite::getChannel, channels).orderBy(true, true, CacheSite::getChannel));
+            if (cacheSites.isEmpty()) {
+                throw new CoolException("缂撳瓨绔欑┖闂翠笉瓒筹紝璇风◢鍚庡啀璇�");
+            }
+
+            CacheSite cacheSite = cacheSites.get(0);
+            cacheSite.setOrderId(order.getId());
+            cacheSite.setOrderNo(order.getOrderNo());
+            cacheSite.setSiteStatus(CacheSiteStatusType.R.id);
+            cacheSite.setUpdateTime(new Date());
+            if (!cacheSiteService.updateById(cacheSite)) {
+                throw new CoolException("缂撳瓨绔欐洿鏂板け璐�");
+            }
+        }
+
+        for (Map.Entry<String, List<OrderDetl>> entry : map.entrySet()) {
+            String stockIndex = entry.getKey();
+            List<OrderDetl> orderDetls = entry.getValue();
+            Double anfme = 0D;
+            Long matId = null;
+            String matnr = null;
+            String batch = null;
+            List<FieldParam> uniqueField = null;
+            for (OrderDetl orderDetl : orderDetls) {
+                anfme += orderDetl.getAnfme();
+                matId = orderDetl.getMatId();
+                matnr = orderDetl.getMat$().getMatnr();
+                batch = orderDetl.getBatch();
+                uniqueField = orderDetl.getUniqueField();
+            }
+
+            WaveDetl waveDetl = new WaveDetl();
+            waveDetl.setWaveNo(waveNo);
+            waveDetl.setWaveId(wave.getId());
+            waveDetl.setStockIndex(stockIndex);
+            waveDetl.setMatId(matId);
+            waveDetl.setMatnr(matnr);
+            waveDetl.setBatch(batch);
+            waveDetl.setAnfme(anfme);
+            waveDetl.setWorkQty(0D);
+            waveDetl.setFieldParams(JSON.toJSONString(uniqueField));
+            if (!waveDetlService.save(waveDetl)) {
+                throw new CoolException("娉㈡鏄庣粏鐢熸垚澶辫触");
+            }
+
         }
 
     }
@@ -864,11 +1103,34 @@
         for (Wave wave : waves) {
             List<WaveDetl> waveDetls = waveDetlService.list(new LambdaQueryWrapper<WaveDetl>().eq(WaveDetl::getWaveId, wave.getId()));
             for (WaveDetl waveDetl : waveDetls) {
-                Order order = orderService.getById(waveDetl.getOrderId());
-                order.setWaveId(null);
-                order.setWaveNo(null);
-                if (!orderService.updateById(order)) {
-                    throw new CoolException("璁㈠崟鍙嶅啓澶辫触");
+                long count = taskDetlService.count(new LambdaQueryWrapper<TaskDetl>().eq(TaskDetl::getWaveId, wave.getId()));
+                if (count > 0) {
+                    throw new CoolException("宸插瓨鍦ㄤ换鍔★紝绂佹鍙栨秷娉㈡");
+                }
+
+                List<Order> orders = orderService.list(new LambdaQueryWrapper<Order>().eq(Order::getWaveId, wave.getId()));
+                for (Order order : orders) {
+                    order.setWaveId(null);
+                    order.setWaveNo(null);
+                    order.setHasWave(0);
+                    if(order.getOrderSettle().equals(OrderSettleType.WAVE.val())){
+                        order.setOrderSettle(OrderSettleType.WAIT.val());
+                    }
+                    if (!orderService.updateById(order)) {
+                        throw new CoolException("璁㈠崟鍙嶅啓澶辫触");
+                    }
+
+                    CacheSite cacheSite = cacheSiteService.getOne(new LambdaQueryWrapper<CacheSite>().eq(CacheSite::getOrderId, order.getId()));
+                    if (cacheSite == null) {
+                        throw new CoolException("缂撳瓨绔欎笉瀛樺湪");
+                    }
+                    cacheSite.setSiteStatus(CacheSiteStatusType.O.id);
+                    cacheSite.setOrderId(null);
+                    cacheSite.setOrderNo(null);
+                    cacheSite.setUpdateTime(new Date());
+                    if (!cacheSiteService.updateById(cacheSite)) {
+                        throw new CoolException("缂撳瓨绔欐竻绌哄け璐�");
+                    }
                 }
 
                 waveDetlService.removeById(waveDetl.getId());
diff --git a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/mapper/CacheSiteMapper.java b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/mapper/CacheSiteMapper.java
index 06d6257..389eb29 100644
--- a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/mapper/CacheSiteMapper.java
+++ b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/mapper/CacheSiteMapper.java
@@ -5,8 +5,12 @@
 import org.apache.ibatis.annotations.Mapper;
 import org.springframework.stereotype.Repository;
 
+import java.util.List;
+
 @Mapper
 @Repository
 public interface CacheSiteMapper extends BaseMapper<CacheSite> {
 
+    List<String> getChannelList();
+
 }
diff --git a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/service/CacheSiteService.java b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/service/CacheSiteService.java
index 059a5b5..d65c686 100644
--- a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/service/CacheSiteService.java
+++ b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/service/CacheSiteService.java
@@ -3,6 +3,10 @@
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.zy.asrs.wms.asrs.entity.CacheSite;
 
+import java.util.List;
+
 public interface CacheSiteService extends IService<CacheSite> {
 
+    List<String> getChannelList();
+
 }
diff --git a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/service/impl/CacheSiteServiceImpl.java b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/service/impl/CacheSiteServiceImpl.java
index a4b8fa1..67e213a 100644
--- a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/service/impl/CacheSiteServiceImpl.java
+++ b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/service/impl/CacheSiteServiceImpl.java
@@ -6,7 +6,13 @@
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import org.springframework.stereotype.Service;
 
+import java.util.List;
+
 @Service("cacheSiteService")
 public class CacheSiteServiceImpl extends ServiceImpl<CacheSiteMapper, CacheSite> implements CacheSiteService {
 
+    @Override
+    public List<String> getChannelList() {
+        return this.baseMapper.getChannelList();
+    }
 }
diff --git a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/service/impl/LocDetlServiceImpl.java b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/service/impl/LocDetlServiceImpl.java
index d477f27..fbd7893 100644
--- a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/service/impl/LocDetlServiceImpl.java
+++ b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/service/impl/LocDetlServiceImpl.java
@@ -160,7 +160,9 @@
                     continue;
                 }
 
-                sortDirctLoc.add(one.getId());
+                if (!sortDirctLoc.contains(one.getId())) {
+                    sortDirctLoc.add(one.getId());
+                }
             }
         }
 
diff --git a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/service/impl/OrderServiceImpl.java b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/service/impl/OrderServiceImpl.java
index e050386..6defe8e 100644
--- a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/service/impl/OrderServiceImpl.java
+++ b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/service/impl/OrderServiceImpl.java
@@ -10,6 +10,7 @@
 import com.zy.asrs.wms.asrs.service.*;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.zy.asrs.wms.utils.OrderUtils;
+import com.zy.asrs.wms.utils.Utils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -122,6 +123,11 @@
                 }
             }
 
+            orderDetl.setStockIndex(Utils.getMatUniqueKey(matnr, batch, orderDetl.getUniqueField()));
+            if (!orderDetlService.updateById(orderDetl)) {
+                throw new CoolException("鏇存柊鏄庣粏绱㈠紩澶辫触");
+            }
+
         }
 
         return true;
@@ -130,6 +136,14 @@
     @Override
     public boolean updateOrder(UpdateOrderParam param) {
         Order order = this.getOne(new LambdaQueryWrapper<Order>().eq(Order::getId, param.getOrderId()));
+        if (order == null) {
+            throw new CoolException("璁㈠崟涓嶅瓨鍦�");
+        }
+
+        if (order.getHasWave() == 1) {
+            throw new CoolException("璁㈠崟宸茬粡鐢熸垚娉㈡锛屾棤娉曚慨鏀�");
+        }
+
         order.setOrderType(param.getOrderType());
         order.setOrderSettle(param.getOrderSettle());
         order.setUpdateTime(new Date());
@@ -207,6 +221,11 @@
                 }
             }
 
+            orderDetl.setStockIndex(Utils.getMatUniqueKey(matnr, batch, orderDetl.getUniqueField()));
+            if (!orderDetlService.updateById(orderDetl)) {
+                throw new CoolException("鏇存柊鏄庣粏绱㈠紩澶辫触");
+            }
+
         }
 
         List<Long> deleteDetlId = param.getDeleteDetlId();
@@ -224,6 +243,11 @@
 
     @Override
     public boolean deleteOrder(Long orderId) {
+        Order order = this.getById(orderId);
+        if (order.getHasWave() == 1) {
+            throw new CoolException("璁㈠崟宸茬粡鐢熸垚娉㈡锛屽垹闄ゅけ璐�");
+        }
+
         //鍒犻櫎璁㈠崟
         this.removeById(orderId);
         //鍒犻櫎鏄庣粏
diff --git a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/service/impl/WorkServiceImpl.java b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/service/impl/WorkServiceImpl.java
index 92c9b51..f65dc93 100644
--- a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/service/impl/WorkServiceImpl.java
+++ b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/service/impl/WorkServiceImpl.java
@@ -9,6 +9,7 @@
 import com.zy.asrs.wms.asrs.service.*;
 import com.zy.asrs.wms.utils.LocUtils;
 import com.zy.asrs.wms.utils.OrderUtils;
+import com.zy.asrs.wms.utils.Utils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -60,6 +61,8 @@
     private MatService matService;
     @Autowired
     private OrderUtils orderUtils;
+    @Autowired
+    private WaveDetlService waveDetlService;
 
     @Override
     public String generateTaskNo(Long taskType) {
@@ -416,7 +419,12 @@
             task.setTaskSts(99L);//99.鍏ュ簱瀹屾垚
         }else {
             //鍑哄簱
-            task.setTaskSts(199L);//199.鍑哄簱瀹屾垚
+            TaskDetl taskDetl = taskDetls.get(0);
+            if (taskDetl.getWaveId() == null) {
+                task.setTaskSts(199L);//199.鍑哄簱瀹屾垚
+            }else {
+                task.setTaskSts(198L);//198.鎾涓�
+            }
         }
 
         task.setUpdateTime(new Date());
@@ -473,6 +481,26 @@
                 if(!locService.updateById(loc)){
                     throw new CoolException("搴撲綅鐘舵�佸彉鏇村け璐�");
                 }
+
+                List<TaskDetl> taskDetls = taskDetlService.getTaskDetlByTaskId(taskId);
+                for (TaskDetl taskDetl : taskDetls) {
+                    if (taskDetl.getWaveId() == null) {
+                        continue;
+                    }
+
+                    String matUniqueKey = Utils.getMatUniqueKey(taskDetl.getMatnr(), taskDetl.getBatch(), taskDetl.getUniqueField());
+                    WaveDetl waveDetl = waveDetlService.getOne(new LambdaQueryWrapper<WaveDetl>().eq(WaveDetl::getStockIndex, matUniqueKey).eq(WaveDetl::getWaveId, taskDetl.getWaveId()));
+                    if(waveDetl == null){
+                        continue;
+                    }
+                    waveDetl.setWorkQty(waveDetl.getWorkQty() - taskDetl.getAnfme());
+                    waveDetl.setUpdateTime(new Date());
+                    if (!waveDetlService.updateById(waveDetl)) {
+                        throw new CoolException("娉㈡鏄庣粏鏇存柊澶辫触");
+                    }
+                }
+
+
                 break;
         }
 
diff --git a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/timer/TaskLogTimer.java b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/timer/TaskLogTimer.java
index cde400b..456e4d9 100644
--- a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/timer/TaskLogTimer.java
+++ b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/timer/TaskLogTimer.java
@@ -3,10 +3,13 @@
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.plugins.IgnoreStrategy;
 import com.baomidou.mybatisplus.core.plugins.InterceptorIgnoreHelper;
+import com.zy.asrs.framework.common.DateUtils;
 import com.zy.asrs.framework.exception.CoolException;
 import com.zy.asrs.wms.asrs.entity.*;
 import com.zy.asrs.wms.asrs.entity.enums.OrderSettleType;
 import com.zy.asrs.wms.asrs.service.*;
+import com.zy.asrs.wms.system.entity.Dict;
+import com.zy.asrs.wms.system.service.DictService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Component;
@@ -35,6 +38,8 @@
     private OrderService orderService;
     @Autowired
     private OrderDetlService orderDetlService;
+    @Autowired
+    private DictService dictService;
 
     @Scheduled(cron = "0/3 * * * * ? ")
     @Transactional
@@ -154,7 +159,7 @@
     public void outExecute() {
         InterceptorIgnoreHelper.handle(IgnoreStrategy.builder().tenantLine(true).build());
         try {
-            //鑾峰彇鍏ュ簱瀹屾垚浠诲姟
+            //鑾峰彇鍑哄簱瀹屾垚浠诲姟
             List<Task> list = taskService.list(new LambdaQueryWrapper<Task>()
                     .eq(Task::getTaskSts, 200)
                     .in(Task::getTaskType, 101, 53, 57));
@@ -162,7 +167,17 @@
                 return;
             }
 
+            Dict dict = dictService.getOne(new LambdaQueryWrapper<Dict>().eq(Dict::getFlag, "taskLogDiffDays").eq(Dict::getStatus, 1));
+            if(dict == null) {
+                return;
+            }
             for (Task task : list) {
+                int diff = DateUtils.diff(task.getCreateTime(), new Date());
+                int taskLogDiffDays = Integer.parseInt(dict.getValue());
+                if (diff < taskLogDiffDays) {
+                    continue;
+                }
+
                 Long hostId = task.getHostId();
 
                 //淇濆瓨浠诲姟鍘嗗彶妗�
diff --git a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/timer/TaskWaveTimer.java b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/timer/TaskWaveTimer.java
new file mode 100644
index 0000000..ea48026
--- /dev/null
+++ b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/timer/TaskWaveTimer.java
@@ -0,0 +1,149 @@
+package com.zy.asrs.wms.asrs.timer;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.plugins.IgnoreStrategy;
+import com.baomidou.mybatisplus.core.plugins.InterceptorIgnoreHelper;
+import com.zy.asrs.framework.exception.CoolException;
+import com.zy.asrs.wms.asrs.entity.*;
+import com.zy.asrs.wms.asrs.entity.enums.CacheSiteStatusType;
+import com.zy.asrs.wms.asrs.service.*;
+import com.zy.asrs.wms.system.entity.Dict;
+import com.zy.asrs.wms.system.service.DictService;
+import com.zy.asrs.wms.utils.OrderUtils;
+import com.zy.asrs.wms.utils.Utils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.transaction.interceptor.TransactionAspectSupport;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Optional;
+
+@Component
+public class TaskWaveTimer {
+
+    @Autowired
+    private TaskService taskService;
+    @Autowired
+    private TaskDetlService taskDetlService;
+    @Autowired
+    private OrderService orderService;
+    @Autowired
+    private OrderDetlService orderDetlService;
+    @Autowired
+    private OrderUtils orderUtils;
+    @Autowired
+    private CacheSiteService cacheSiteService;
+    @Autowired
+    private WaveSeedService waveSeedService;
+    @Autowired
+    private DictService dictService;
+
+    @Scheduled(cron = "0/3 * * * * ? ")
+    @Transactional
+    public void taskWave() {
+        InterceptorIgnoreHelper.handle(IgnoreStrategy.builder().tenantLine(true).build());
+        try {
+            Dict dict = dictService.getOne(new LambdaQueryWrapper<Dict>().eq(Dict::getFlag, "autoCreateWaveSeed").eq(Dict::getStatus, 1));
+            if (dict == null) {
+                return;
+            }
+            String autoCreateWaveSeed = dict.getValue();
+            if (!autoCreateWaveSeed.equals("true")) {
+                return;
+            }
+
+            List<Task> taskList = taskService.list(new LambdaQueryWrapper<Task>().eq(Task::getTaskSts, 198));
+            for (Task task : taskList) {
+                Long hostId = task.getHostId();
+
+                List<TaskDetl> taskDetls = taskDetlService.list(new LambdaQueryWrapper<TaskDetl>().eq(TaskDetl::getTaskId, task.getId()).eq(TaskDetl::getHostId, hostId));
+                if (taskDetls.isEmpty()) {
+                    continue;
+                }
+
+                for (TaskDetl taskDetl : taskDetls) {
+                    //鍒嗛厤璁㈠崟
+                    Long waveId = taskDetl.getWaveId();
+                    List<Order> list = orderService.list(new LambdaQueryWrapper<Order>().eq(Order::getWaveId, waveId));
+                    if (list.isEmpty()) {
+                        continue;
+                    }
+
+                    ArrayList<Long> orderIds = new ArrayList<>();
+                    for (Order order : list) {
+                        orderIds.add(order.getId());
+                    }
+
+                    String matUniqueKey = Utils.getMatUniqueKey(taskDetl.getMatnr(), taskDetl.getBatch(), taskDetl.getUniqueField());
+                    List<OrderDetl> orderDetls = orderDetlService.list(new LambdaQueryWrapper<OrderDetl>()
+                            .in(OrderDetl::getOrderId, orderIds)
+                            .eq(OrderDetl::getStockIndex, matUniqueKey)
+                            .eq(OrderDetl::getHostId, hostId));
+                    if(orderDetls.isEmpty()){
+                        throw new CoolException("璁㈠崟鏄庣粏涓嶅瓨鍦�");
+                    }
+
+                    Double anfme = taskDetl.getAnfme();
+                    for (OrderDetl orderDetl : orderDetls) {
+                        double issued = Optional.of(orderDetl.getAnfme() - orderDetl.getQty() - orderDetl.getWorkQty()).orElse(0.0D);
+                        if (issued <= 0.0D) { continue; }
+                        if (anfme <= 0.0D) { break; }
+
+                        double workQty = issued;
+                        if(anfme - issued < 0){
+                            workQty = anfme;
+                        }
+                        anfme -= workQty;
+
+                        orderUtils.updateWorkQty(orderDetl.getId(), workQty, true);
+
+
+                        List<CacheSite> cacheSites = cacheSiteService.list(new LambdaQueryWrapper<CacheSite>().eq(CacheSite::getSiteStatus, CacheSiteStatusType.O.id).eq(CacheSite::getHostId, hostId));
+                        if (cacheSites.isEmpty()) {
+                            throw new CoolException("缂撳瓨绔欑┖闂翠笉瓒筹紝璇风◢鍚庡啀璇�");
+                        }
+                        CacheSite cacheSite = cacheSites.get(0);
+
+                        WaveSeed waveSeed = new WaveSeed();
+                        waveSeed.setSiteId(cacheSite.getId());
+                        waveSeed.setSiteNo(cacheSite.getSiteNo());
+                        waveSeed.setOrderDetlId(orderDetl.getId());
+                        waveSeed.setTaskDetlId(taskDetl.getId());
+                        waveSeed.setAnfme(taskDetl.getAnfme());
+                        waveSeed.setWorkQty(0D);
+                        waveSeed.setHostId(hostId);
+                        if (!waveSeedService.save(waveSeed)) {
+                            throw new CoolException("娉㈡鎾鍒涘缓澶辫触");
+                        }
+
+                        cacheSite.setOrderId(orderDetl.getOrderId());
+                        cacheSite.setOrderNo(orderDetl.getOrderNo());
+                        cacheSite.setSiteStatus(CacheSiteStatusType.R.id);
+                        cacheSite.setUpdateTime(new Date());
+                        if (!cacheSiteService.updateById(cacheSite)) {
+                            throw new CoolException("缂撳瓨绔欐洿鏂板け璐�");
+                        }
+
+                    }
+
+                }
+
+                task.setTaskSts(199L);
+                task.setUpdateTime(new Date());
+                if (!taskService.updateById(task)) {
+                    throw new CoolException("浠诲姟鏇存柊澶辫触");
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
+        }finally {
+            InterceptorIgnoreHelper.clearIgnoreStrategy();
+        }
+    }
+
+}
diff --git a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/utils/Utils.java b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/utils/Utils.java
index 998116d..5d947dd 100644
--- a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/utils/Utils.java
+++ b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/utils/Utils.java
@@ -19,14 +19,26 @@
 
     public static final String _LINK = "-";
 
-    public static final String _KEY_LINK = "_";
-
     public static String getMatUniqueKey(String matnr, String batch, List<FieldParam> params) {
         MatUniqueObjDto dto = new MatUniqueObjDto();
         dto.setMatnr(matnr);
         dto.setBatch(batch);
-        dto.setParams(params);
 
+        ArrayList<FieldParam> list = new ArrayList<>();
+        for (FieldParam param : params) {
+            FieldParam fieldParam = new FieldParam();
+            list.add(fieldParam);
+
+            String value = "";
+            if (!Cools.isEmpty(param.getValue())) {
+                value = param.getValue().toString();
+            }
+
+            fieldParam.setName(param.getName());
+            fieldParam.setType(param.getType());
+            fieldParam.setValue(value);
+        }
+        dto.setParams(list);
         String encode = Base64.getEncoder().encodeToString(JSON.toJSONString(dto).getBytes());
         return encode;
     }
diff --git a/zy-asrs-wms/src/main/resources/license.lic b/zy-asrs-wms/src/main/resources/license.lic
index cb51cd3..f447708 100644
--- a/zy-asrs-wms/src/main/resources/license.lic
+++ b/zy-asrs-wms/src/main/resources/license.lic
Binary files differ
diff --git a/zy-asrs-wms/src/main/resources/mapper/asrs/CacheSiteMapper.xml b/zy-asrs-wms/src/main/resources/mapper/asrs/CacheSiteMapper.xml
index 5449c13..7d9448c 100644
--- a/zy-asrs-wms/src/main/resources/mapper/asrs/CacheSiteMapper.xml
+++ b/zy-asrs-wms/src/main/resources/mapper/asrs/CacheSiteMapper.xml
@@ -2,4 +2,8 @@
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.zy.asrs.wms.asrs.mapper.CacheSiteMapper">
 
+    <select id="getChannelList" resultType="string">
+        select distinct channel from man_cache_site
+    </select>
+
 </mapper>

--
Gitblit v1.9.1