From 11b3ac7e9f6bc9144ddd7a5261cf69796f38d7b3 Mon Sep 17 00:00:00 2001
From: Junjie <540245094@qq.com>
Date: 星期六, 07 九月 2024 13:51:31 +0800
Subject: [PATCH] #

---
 zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/mapper/ViewLocDetlMapper.java               |    3 
 zy-asrs-wms/src/main/java/com/zy/asrs/wms/utils/Utils.java                                 |   68 +
 zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/OrderOutMergeDto.java            |   34 
 zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/MergePreviewResultDto.java       |   49 +
 zy-asrs-admin/src/components/orderOut/orderOutMergePreview/index.vue                       |  180 ++++
 zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/OrderDetl.java                       |    2 
 zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/MatUniqueObjDto.java             |   17 
 zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/param/OrderOutMergePreviewParam.java |   12 
 zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/param/FieldSortParam.java            |    7 
 zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/param/OrderOutBatchPreviewParam.java |   12 
 zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/BatchPreviewOtherLocDto.java     |   16 
 zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/service/impl/OrderDetlServiceImpl.java      |   10 
 zy-asrs-wms/src/main/java/com/zy/asrs/wms/utils/OrderUtils.java                            |   57 +
 zy-asrs-admin/src/components/orderOut/orderOutBatchPreview/index.vue                       |  237 ++++++
 zy-asrs-wms/src/main/resources/mapper/asrs/ViewLocDetlMapper.xml                           |    5 
 zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/service/LocDetlService.java                 |    5 
 zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/OutDetlDto.java                  |    2 
 zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/LocDetl.java                         |    1 
 zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/MergePreviewResultLocDto.java    |   16 
 zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/service/OrderDetlService.java               |    2 
 zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/OrderOutBatchPreviewDto.java     |   54 +
 zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/param/OrderOutMergeParam.java        |   28 
 zy-asrs-wms/src/main/java/com/zy/asrs/wms/utils/LocUtils.java                              |    3 
 zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/MergePreviewDto.java             |   42 +
 zy-asrs-admin/src/views/out/orderOut/index.vue                                             |  232 ++++++
 zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/controller/OutController.java               |   45 +
 zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/manage/OutManage.java                       |  601 ++++++++++++++++
 zy-asrs-wms/src/main/java/com/zy/asrs/wms/utils/OutUtils.java                              |   59 +
 zy-asrs-admin/src/components/orderOut/orderOutMergePreview/stockOut.vue                    |  279 +++++++
 zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/service/impl/LocDetlServiceImpl.java        |  110 ++
 30 files changed, 2,139 insertions(+), 49 deletions(-)

diff --git a/zy-asrs-admin/src/components/orderOut/orderOutBatchPreview/index.vue b/zy-asrs-admin/src/components/orderOut/orderOutBatchPreview/index.vue
new file mode 100644
index 0000000..301cca5
--- /dev/null
+++ b/zy-asrs-admin/src/components/orderOut/orderOutBatchPreview/index.vue
@@ -0,0 +1,237 @@
+<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(['reload'])
+
+const {
+    getColumnSearchProps,
+} = useTableSearch();
+
+let currentOrder = ref(null);
+let searchInput = ref(null);
+let tableData = ref([]);
+const open = ref(false);
+const showWidth = ref("60%")
+const records = ref([])
+const loading = ref(false)
+
+let columns = [
+    {
+        title: formatMessage('db.man_order_detl.order_no', '璁㈠崟缂栧彿'),
+        dataIndex: ['orderDetl$', 'orderNo'],
+        width: 140,
+        ellipsis: true,
+        ...getColumnSearchProps('orderNo'),
+    },
+    {
+        title: formatMessage('db.man_order_detl.matnr', '鍟嗗搧缂栧彿'),
+        dataIndex: ['orderDetl$', 'mat$', 'matnr'],
+        width: 140,
+        ellipsis: true,
+        ...getColumnSearchProps('matnr'),
+    },
+    {
+        title: formatMessage('db.man_order_detl.batch', '鎵瑰彿'),
+        dataIndex: ['orderDetl$', 'batch'],
+        width: 140,
+        ellipsis: true,
+        ...getColumnSearchProps('batch'),
+    },
+    {
+        title: formatMessage('db.man_order_detl.anfme', '鏁伴噺'),
+        dataIndex: 'anfme',
+        width: 140,
+        ellipsis: true,
+        ...getColumnSearchProps('anfme'),
+    },
+    {
+        title: formatMessage('db.man_order_detl.stock', '搴撳瓨'),
+        dataIndex: 'stock',
+        width: 140,
+        ellipsis: true,
+        ...getColumnSearchProps('stock'),
+    },
+];
+
+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,
+            })
+
+            fieldList.push(item.name);
+        })
+
+        tmp.push({
+            title: formatMessage('db.man_order_detl.locNo', '鍑哄簱搴撲綅'),
+            dataIndex: 'locNo',
+            width: 140,
+            ellipsis: true,
+            fixed: 'right',
+        })
+
+        tmp.push({
+            title: '',
+            dataIndex: 'handleStatus',
+            width: 100,
+            ellipsis: true,
+            fixed: 'right',
+        })
+
+        columns = tmp;
+    } else if (result.code === 401) {
+        message.error(result.msg);
+        logout()
+    } else {
+        message.error(result.msg);
+    }
+}
+
+watch(open, (newVal, oldVal) => {
+    if (newVal) {
+        handleOrderOutPreview()
+    }
+})
+
+const handleOk = () => {
+    post('/api/out/orderOut/batch', tableData.value).then((resp) => {
+        let result = resp.data;
+        if (result.code == 200) {
+            message.success(formatMessage('page.add.success', '鍑哄簱鎴愬姛'));
+            open.value = false;
+            emit('reload', true)
+        } else {
+            message.error(result.msg);
+        }
+    })
+}
+
+const handleOrderOutPreview = () => {
+    loading.value = true;
+    tableData.value = []
+
+    post('/api/out/orderOut/batch/preview', {
+        orderDetlIds: records.value,
+    }).then((resp) => {
+        let result = resp.data;
+        if (result.code == 200) {
+            tableData.value = result.data;
+            loading.value = false;
+        }
+    })
+}
+
+const handleOtherLocChange = (index, record) => {
+    let stock = record.stock;
+    record.otherLoc.forEach((item) => {
+        if (item.locId == record.locId) {
+            record.locNo = item.locNo;
+            record.locDetlId = item.locDetlId;
+            record.stock = item.stock;
+        }
+    })
+
+    let locDetlList = []
+    let tmp = tableData.value;
+    tmp.forEach((item) => {
+        if (!locDetlList[item.locDetlId]) {
+            locDetlList[item.locDetlId] = item.stock;
+        }
+    })
+
+    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,
+    records,
+})
+
+</script>
+
+<script>
+export default {
+    name: '棰勮璁㈠崟鍑哄簱'
+}
+</script>
+
+<template>
+    <div>
+        <a-modal v-model:open="open" :width="showWidth" :title="formatMessage('page.orderOutPreview.preview', '棰勮璁㈠崟鍑哄簱')"
+            @ok="handleOk">
+            <a-table :data-source="tableData" :loading="loading" :defaultExpandAllRows="false" :key="TABLE_KEY"
+                rowKey="id" :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">
+                            <a-select v-model:value="record.locId" :options="record.otherLoc"
+                                :fieldNames="{ label: 'locNo', value: 'locId' }"
+                                @change="handleOtherLocChange(index, record)"></a-select>
+                        </div>
+                    </template>
+
+                    <template v-if="column.dataIndex === 'handleStatus'">
+                        <div v-if="record.locId == null">
+                            <a-tag color="error">搴撳瓨涓嶈冻</a-tag>
+                        </div>
+                        <div v-else>
+                            <div v-if="record.stockAlarm != null && record.stockAlarm">
+                                <a-tag color="error">搴撳瓨涓嶈冻</a-tag>
+                            </div>
+                        </div>
+                    </template>
+                </template>
+            </a-table>
+        </a-modal>
+    </div>
+</template>
+
+<style></style>
diff --git a/zy-asrs-admin/src/components/orderOut/orderOutMergePreview/index.vue b/zy-asrs-admin/src/components/orderOut/orderOutMergePreview/index.vue
new file mode 100644
index 0000000..7edcf19
--- /dev/null
+++ b/zy-asrs-admin/src/components/orderOut/orderOutMergePreview/index.vue
@@ -0,0 +1,180 @@
+<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';
+import StockOutView from './stockOut.vue';
+
+const router = useRouter();
+
+const TABLE_KEY = 'table-order-out-preview';
+
+const emit = defineEmits(['reload'])
+
+const {
+    getColumnSearchProps,
+} = useTableSearch();
+
+let currentOrder = ref(null);
+let searchInput = ref(null);
+let tableData = ref([]);
+const open = ref(false);
+const showWidth = ref("60%")
+const records = ref([])
+const loading = ref(false)
+const stockOutChild = ref(null)
+
+let columns = [
+    {
+        title: formatMessage('db.man_order_detl.matnr', '鍟嗗搧缂栧彿'),
+        dataIndex: 'matnr',
+        width: 140,
+        ellipsis: true,
+        ...getColumnSearchProps('matnr'),
+    },
+    {
+        title: formatMessage('db.man_order_detl.batch', '鎵瑰彿'),
+        dataIndex: 'batch',
+        width: 140,
+        ellipsis: true,
+        ...getColumnSearchProps('batch'),
+    },
+    {
+        title: formatMessage('db.man_order_detl.anfme', '鏁伴噺'),
+        dataIndex: 'anfme',
+        width: 140,
+        ellipsis: true,
+        ...getColumnSearchProps('anfme'),
+    },
+];
+
+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,
+            })
+
+            fieldList.push(item.name);
+        })
+
+        columns = 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 = () => {
+    if (state.selectedRowKeys.length == 0) {
+        message.error(formatMessage("page.orderOut.mergeOrderOut.checkedError", "璇烽�夋嫨鑷冲皯涓�鏉℃暟鎹�"));
+        return;
+    }
+
+    let param = []
+    state.selectedRowKeys.forEach((idx) => {
+        let tmp = tableData.value[idx];
+        if (tmp != null) {
+            param.push(tmp)
+        }
+    })
+
+    stockOutChild.value.open = true;
+    stockOutChild.value.records = param;
+    stockOutChild.value.showWidth = '55%'
+
+    emit('reload', true)
+}
+
+const handleOrderMergePreview = () => {
+    loading.value = true;
+    tableData.value = []
+    state.selectedRowKeys = []
+
+    post('/api/out/orderOut/merge/preview', {
+        orderIds: records.value,
+    }).then((resp) => {
+        let result = resp.data;
+        if (result.code == 200) {
+            let tmp = result.data;
+            let index = 0;
+            tmp.forEach((item) => {
+                item.index = index++;
+            })
+            tableData.value = tmp;
+            loading.value = false;
+        }
+    })
+}
+
+const handleCloseParent = () => {
+    open.value = false;
+}
+
+defineExpose({
+    open,
+    showWidth,
+    records,
+})
+
+</script>
+
+<script>
+export default {
+    name: '棰勮鍚堝苟璁㈠崟'
+}
+</script>
+
+<template>
+    <div>
+        <a-modal v-model:open="open" :width="showWidth" :title="formatMessage('page.orderOutPreview.preview', '棰勮鍚堝苟璁㈠崟')"
+            @ok="handleOk">
+            <a-table :data-source="tableData"
+                :row-selection="{ selectedRowKeys: state.selectedRowKeys, onChange: onSelectChange }" :loading="loading"
+                :defaultExpandAllRows="false" :key="TABLE_KEY" rowKey="index"
+                :scroll="{ y: 768, scrollToFirstRowOnChange: true }" :columns="columns">
+                <template #bodyCell="{ column, text, record, index }">
+
+                </template>
+            </a-table>
+        </a-modal>
+
+        <StockOutView ref="stockOutChild" @closeParent="handleCloseParent" />
+    </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
new file mode 100644
index 0000000..bf83378
--- /dev/null
+++ b/zy-asrs-admin/src/components/orderOut/orderOutMergePreview/stockOut.vue
@@ -0,0 +1,279 @@
+<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'])
+
+const {
+    getColumnSearchProps,
+} = useTableSearch();
+
+let currentOrder = ref(null);
+let searchInput = ref(null);
+let tableData = ref([]);
+const operationPortList = ref([])
+const open = ref(false);
+const showWidth = ref("60%")
+const records = ref([])
+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 = () => {
+    post('/api/out/orderOut/merge', tableData.value).then((resp) => {
+        let result = resp.data;
+        if (result.code == 200) {
+            message.success(formatMessage('page.add.success', '鍑哄簱鎴愬姛'));
+            open.value = false;
+            emit('closeParent', true)
+        } else {
+            message.error(result.msg);
+        }
+    })
+}
+
+const handleOrderMergePreview = async () => {
+    let data = records.value;
+    if (data.length == 0) {
+        message.error(formatMessage("page.orderOut.mergeOrderOut.checkedError", "璇烽�夋嫨鑷冲皯涓�鏉℃暟鎹�"));
+        return;
+    }
+
+    loading.value = true;
+
+    await getOperationPort();
+    tableData.value = []
+    tableDataValue = []
+
+    let defaultOperationPort = "";
+    if (operationPortList.value.length > 0) {
+        defaultOperationPort = operationPortList.value[0].value;
+    }
+
+    post('/api/out/orderOut/merge/loc/preview', data).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) => {
+                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) {
+                    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++;
+                }
+
+                colSpan[idx] = count
+                idx += count;
+            })
+
+            tableDataColSpan = colSpan;
+            tableData.value = tableDataTmp;
+
+            loading.value = false;
+        } else {
+            message.error(result.msg);
+        }
+    })
+}
+
+defineExpose({
+    open,
+    showWidth,
+    records,
+})
+</script>
+
+<script>
+export default {
+    name: '棰勮鍚堝苟璁㈠崟鍑哄簱'
+}
+</script>
+
+<template>
+    <div>
+        <a-modal v-model:open="open" :width="showWidth"
+            :title="formatMessage('page.orderOutPreview.preview', '棰勮鍚堝苟璁㈠崟鍑哄簱')" @ok="handleOk">
+            <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">
+                            <a-tag color="green">{{ record.locNo }}</a-tag>
+                        </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/views/out/orderOut/index.vue b/zy-asrs-admin/src/views/out/orderOut/index.vue
new file mode 100644
index 0000000..74da6d9
--- /dev/null
+++ b/zy-asrs-admin/src/views/out/orderOut/index.vue
@@ -0,0 +1,232 @@
+<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 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
+    }).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()
+}
+
+</script>
+
+<script>
+export default {
+    name: '璁㈠崟鍑哄簱'
+}
+</script>
+
+<template>
+    <div style="display: flex;">
+        <a-card :title="formatMessage('common.order', '璁㈠崟')" style="flex: 4;margin-right: 30px;">
+            <a-button @click="handleMergeOrderOut()">
+                {{ formatMessage('common.orderOut', '鍚堝苟璁㈠崟') }}
+            </a-button>
+            <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-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 d3d6558..248a3cc 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,14 +1,23 @@
 package com.zy.asrs.wms.asrs.controller;
 
 import com.zy.asrs.framework.common.R;
+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.OrderOutBatchPreviewParam;
+import com.zy.asrs.wms.asrs.entity.param.OrderOutMergeParam;
+import com.zy.asrs.wms.asrs.entity.param.OrderOutMergePreviewParam;
 import com.zy.asrs.wms.asrs.entity.param.OutParam;
 import com.zy.asrs.wms.asrs.manage.OutManage;
 import com.zy.asrs.wms.system.controller.BaseController;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
 
 
 @RestController
@@ -22,8 +31,44 @@
      * 鍑哄簱
      */
     @PostMapping("/out/start")
+    @Transactional
     public R start(@RequestBody OutParam param) {
         outManage.out(param);
         return R.ok();
     }
+
+    @PostMapping("/out/orderOut/batch/preview")
+    @Transactional
+    public R orderOutBatchPreview(@RequestBody OrderOutBatchPreviewParam param) {
+        List<OrderOutBatchPreviewDto> previewDtos = outManage.orderOutBatchPreview(param);
+        return R.ok().add(previewDtos);
+    }
+
+    @PostMapping("/out/orderOut/batch")
+    @Transactional
+    public R orderOutBatch(@RequestBody List<OrderOutBatchPreviewDto> param) {
+        outManage.orderOutBatch(param);
+        return R.ok();
+    }
+
+    @PostMapping("/out/orderOut/merge/preview")
+    @Transactional
+    public R orderOutMergePreview(@RequestBody OrderOutMergePreviewParam param) {
+        List<MergePreviewDto> dtos = outManage.orderOutMergePreview(param);
+        return R.ok().add(dtos);
+    }
+
+    @PostMapping("/out/orderOut/merge/loc/preview")
+    @Transactional
+    public R orderOutMergeLocPreview(@RequestBody List<MergePreviewDto> param) {
+        List<MergePreviewResultDto> dtos = outManage.orderOutMergeLocPreview(param);
+        return R.ok().add(dtos);
+    }
+
+    @PostMapping("/out/orderOut/merge")
+    @Transactional
+    public R orderOutMerge(@RequestBody List<OrderOutMergeParam> param) {
+        outManage.orderOutMerge(param);
+        return R.ok();
+    }
 }
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 f7cb142..7040908 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
@@ -104,7 +104,6 @@
      * 鏄惁鍒犻櫎 1: 鏄�  0: 鍚�  
      */
     @ApiModelProperty(value= "鏄惁鍒犻櫎 1: 鏄�  0: 鍚�  ")
-    @TableLogic
     private Integer deleted;
 
     /**
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 06b1630..34c63ad 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
@@ -343,7 +343,7 @@
         for (MatField matField : service.list(new LambdaQueryWrapper<MatField>().eq(MatField::getUnique, 1))) {
             FieldParam param = new FieldParam();
             param.setName(matField.getName());
-            param.setValue(dynamicFields.get(matField.getName()));
+            param.setValue(dynamicFields.getOrDefault(matField.getName(), ""));
             list.add(param);
         }
         return list;
diff --git a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/BatchPreviewOtherLocDto.java b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/BatchPreviewOtherLocDto.java
new file mode 100644
index 0000000..3317530
--- /dev/null
+++ b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/BatchPreviewOtherLocDto.java
@@ -0,0 +1,16 @@
+package com.zy.asrs.wms.asrs.entity.dto;
+
+import lombok.Data;
+
+@Data
+public class BatchPreviewOtherLocDto {
+
+    private Long locId;
+
+    private String locNo;
+
+    private Double stock;
+
+    private Long locDetlId;
+
+}
diff --git a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/MatUniqueObjDto.java b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/MatUniqueObjDto.java
new file mode 100644
index 0000000..89a3bcf
--- /dev/null
+++ b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/MatUniqueObjDto.java
@@ -0,0 +1,17 @@
+package com.zy.asrs.wms.asrs.entity.dto;
+
+import com.zy.asrs.wms.asrs.entity.param.FieldParam;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class MatUniqueObjDto {
+
+    private String matnr;
+
+    private String batch;
+
+    private List<FieldParam> params;
+
+}
diff --git a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/MergePreviewDto.java b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/MergePreviewDto.java
new file mode 100644
index 0000000..586beef
--- /dev/null
+++ b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/MergePreviewDto.java
@@ -0,0 +1,42 @@
+package com.zy.asrs.wms.asrs.entity.dto;
+
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.zy.asrs.wms.asrs.entity.param.FieldParam;
+import lombok.Data;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Data
+public class MergePreviewDto {
+
+    private String matnr;
+
+    private String batch;
+
+    private Double anfme;
+
+    private List<Long> orderIds;
+
+    private List<FieldParam> fieldParams;
+
+    private String fieldParamsEncode;
+
+    //鍔ㄦ�佹墿灞曞瓧娈�
+    public transient Map<String, Object> dynamicFields = new HashMap<>();
+
+    @JsonAnyGetter
+    public Map<String,Object> getDynamicFields() {
+        return dynamicFields;
+    }
+
+    public String getFieldString(String key) {
+        return dynamicFields.get(key).toString();
+    }
+
+    public void setField(String key, Object value) {
+        dynamicFields.put(key, value);
+    }
+
+}
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
new file mode 100644
index 0000000..3c701e9
--- /dev/null
+++ b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/MergePreviewResultDto.java
@@ -0,0 +1,49 @@
+package com.zy.asrs.wms.asrs.entity.dto;
+
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.zy.asrs.common.utils.Synchro;
+import com.zy.asrs.wms.asrs.entity.param.FieldParam;
+import lombok.Data;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Data
+public class MergePreviewResultDto {
+
+    private String matnr;
+
+    private String batch;
+
+    private Double anfme;
+
+    private List<Long> orderIds;
+
+    private List<MergePreviewResultLocDto> locs;
+
+    private List<FieldParam> fieldParams;
+
+    private String fieldParamsEncode;
+
+    //鍔ㄦ�佹墿灞曞瓧娈�
+    public transient Map<String, Object> dynamicFields = new HashMap<>();
+
+    @JsonAnyGetter
+    public Map<String,Object> getDynamicFields() {
+        return dynamicFields;
+    }
+
+    public String getFieldString(String key) {
+        return dynamicFields.get(key).toString();
+    }
+
+    public void setField(String key, Object value) {
+        dynamicFields.put(key, value);
+    }
+
+    public void sync(Object source) {
+        Synchro.Copy(source, this);
+    }
+
+}
diff --git a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/MergePreviewResultLocDto.java b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/MergePreviewResultLocDto.java
new file mode 100644
index 0000000..500b82c
--- /dev/null
+++ b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/MergePreviewResultLocDto.java
@@ -0,0 +1,16 @@
+package com.zy.asrs.wms.asrs.entity.dto;
+
+import lombok.Data;
+
+@Data
+public class MergePreviewResultLocDto {
+
+    private Long locId;
+
+    private String locNo;
+
+    private Long locDetlId;
+
+    private Double anfme;
+
+}
diff --git a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/OrderOutBatchPreviewDto.java b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/OrderOutBatchPreviewDto.java
new file mode 100644
index 0000000..e4f3316
--- /dev/null
+++ b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/OrderOutBatchPreviewDto.java
@@ -0,0 +1,54 @@
+package com.zy.asrs.wms.asrs.entity.dto;
+
+import com.zy.asrs.framework.common.Cools;
+import com.zy.asrs.framework.common.SpringUtils;
+import com.zy.asrs.wms.asrs.entity.LocDetl;
+import com.zy.asrs.wms.asrs.entity.OrderDetl;
+import com.zy.asrs.wms.asrs.service.LocDetlService;
+import com.zy.asrs.wms.asrs.service.OrderDetlService;
+import lombok.Data;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Data
+public class OrderOutBatchPreviewDto {
+
+    private Long locId;
+
+    private String locNo;
+
+    private Long locDetlId;
+
+    private Boolean all;
+
+    private Double anfme;
+
+    private Double stock;
+
+    private Long orderDetlId;
+
+    private List<BatchPreviewOtherLocDto> otherLoc;
+
+    public LocDetl getLocDetl$() {
+        LocDetlService service = SpringUtils.getBean(LocDetlService.class);
+        LocDetl locDetl = service.getById(locDetlId);
+        if (!Cools.isEmpty(locDetl)){
+            return locDetl;
+        }
+        return null;
+    }
+
+    public OrderDetl getOrderDetl$() {
+        OrderDetlService service = SpringUtils.getBean(OrderDetlService.class);
+        OrderDetl orderDetl = service.getById(orderDetlId);
+        if (!Cools.isEmpty(orderDetl)){
+            List<OrderDetl> orderDetls = new ArrayList<>();
+            orderDetls.add(orderDetl);
+            List<OrderDetl> list = service.parseDetl(orderDetls);
+            return list.get(0);
+        }
+        return null;
+    }
+
+}
diff --git a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/OrderOutMergeDto.java b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/OrderOutMergeDto.java
new file mode 100644
index 0000000..a1cac57
--- /dev/null
+++ b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/OrderOutMergeDto.java
@@ -0,0 +1,34 @@
+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 OrderOutMergeDto {
+
+    private Long locId;
+
+    private String locNo;
+
+    private Long locDetlId;
+
+    private Long orderDetlId;
+
+    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/dto/OutDetlDto.java b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/OutDetlDto.java
index 7b7a10a..d00e951 100644
--- a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/OutDetlDto.java
+++ b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/OutDetlDto.java
@@ -20,4 +20,6 @@
      */
     private Double stock;
 
+    private Long orderDetlId;
+
 }
diff --git a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/param/FieldSortParam.java b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/param/FieldSortParam.java
index 9638885..251b82a 100644
--- a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/param/FieldSortParam.java
+++ b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/param/FieldSortParam.java
@@ -13,4 +13,11 @@
      */
     private String value;
 
+    public FieldSortParam() {
+    }
+
+    public FieldSortParam(String name, String value) {
+        this.name = name;
+        this.value = value;
+    }
 }
diff --git a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/param/OrderOutBatchPreviewParam.java b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/param/OrderOutBatchPreviewParam.java
new file mode 100644
index 0000000..88a3281
--- /dev/null
+++ b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/param/OrderOutBatchPreviewParam.java
@@ -0,0 +1,12 @@
+package com.zy.asrs.wms.asrs.entity.param;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class OrderOutBatchPreviewParam {
+
+    private List<Long> orderDetlIds;
+
+}
diff --git a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/param/OrderOutMergeParam.java b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/param/OrderOutMergeParam.java
new file mode 100644
index 0000000..e3fbaba
--- /dev/null
+++ b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/param/OrderOutMergeParam.java
@@ -0,0 +1,28 @@
+package com.zy.asrs.wms.asrs.entity.param;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class OrderOutMergeParam {
+
+    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;
+
+    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
new file mode 100644
index 0000000..2ec8afb
--- /dev/null
+++ b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/param/OrderOutMergePreviewParam.java
@@ -0,0 +1,12 @@
+package com.zy.asrs.wms.asrs.entity.param;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class OrderOutMergePreviewParam {
+
+    private List<Long> orderIds;
+
+}
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 8e65e8a..295462d 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
@@ -1,23 +1,24 @@
 package com.zy.asrs.wms.asrs.manage;
 
+import com.alibaba.fastjson.JSON;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.zy.asrs.framework.exception.CoolException;
-import com.zy.asrs.wms.asrs.entity.dto.OutDetlDto;
-import com.zy.asrs.wms.asrs.entity.dto.OutLocDto;
+import com.zy.asrs.wms.asrs.entity.dto.*;
 import com.zy.asrs.wms.asrs.entity.enums.LocStsType;
-import com.zy.asrs.wms.asrs.entity.param.OutParam;
+import com.zy.asrs.wms.asrs.entity.enums.OrderSettleType;
+import com.zy.asrs.wms.asrs.entity.param.*;
 import com.zy.asrs.wms.asrs.entity.*;
 import com.zy.asrs.wms.asrs.service.*;
+import com.zy.asrs.wms.utils.OrderUtils;
 import com.zy.asrs.wms.utils.OutUtils;
+import com.zy.asrs.wms.utils.Utils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
+import java.util.*;
 
 /**
  * 鍑哄簱绠$悊
@@ -47,6 +48,10 @@
     private OrderDetlService orderDetlService;
     @Autowired
     private OutUtils outUtils;
+    @Autowired
+    private OperationPortService operationPortService;
+    @Autowired
+    private OrderUtils orderUtils;
 
 
     /**
@@ -126,4 +131,588 @@
             }
         }
     }
+
+    public List<OrderOutBatchPreviewDto> orderOutBatchPreview(OrderOutBatchPreviewParam param) {
+        List<Long> orderDetlIds = param.getOrderDetlIds();
+        if (orderDetlIds.isEmpty()) {
+            throw new CoolException("璁㈠崟鏄庣粏涓嶈兘涓虹┖");
+        }
+
+        List<OrderDetl> orderDetls = orderDetlService.list(new LambdaQueryWrapper<OrderDetl>().in(OrderDetl::getId, orderDetlIds).orderByAsc(OrderDetl::getOrderNo, OrderDetl::getCreateTime));
+        if (orderDetls.isEmpty()) {
+            throw new CoolException("璁㈠崟鏄庣粏涓嶅瓨鍦�");
+        }
+        orderDetls = orderDetlService.parseDetl(orderDetls);
+
+        HashMap<Long, List<LocDetl>> orderDetlLocMap = new HashMap<>();
+        List<OutDetlDto> detlDtos = new ArrayList<>();
+
+        for (OrderDetl orderDetl : orderDetls) {
+            double issued = Optional.of(orderDetl.getAnfme() - orderDetl.getQty() - orderDetl.getWorkQty()).orElse(0.0D);
+            if (issued <= 0.0D) { continue; }
+            List<LocDetl> locDetls = locDetlService.queryStock(orderDetl.getMat$().getMatnr(), orderDetl.getBatch(), orderDetl.getUniqueField());
+            orderDetlLocMap.put(orderDetl.getId(), locDetls);
+            for (LocDetl locDetl : locDetls) {
+                if (issued > 0) {
+                    OutDetlDto outDetlDto = new OutDetlDto();
+                    outDetlDto.setDetlId(locDetl.getId());
+                    outDetlDto.setAnfme(issued >= locDetl.getAnfme() ? locDetl.getAnfme() : issued);
+                    outDetlDto.setStock(locDetl.getAnfme());
+                    outDetlDto.setOrderDetlId(orderDetl.getId());
+                    detlDtos.add(outDetlDto);
+                    issued = issued - outDetlDto.getAnfme();
+                }else {
+                    break;
+                }
+            }
+        }
+
+        HashMap<Long, List<OutDetlDto>> map = new HashMap<>();
+        for (OutDetlDto detlDto : detlDtos) {
+            LocDetl locDetl = locDetlService.getById(detlDto.getDetlId());
+            List<OutDetlDto> dtos = map.get(locDetl.getLocId());
+            if (dtos == null) {
+                dtos = new ArrayList<>();
+                dtos.add(detlDto);
+            }else {
+                dtos.add(detlDto);
+            }
+            map.put(locDetl.getLocId(), dtos);
+        }
+
+        List<Long> orderDetlIdsTmp = param.getOrderDetlIds();
+        List<OrderOutBatchPreviewDto> previewDtos = new ArrayList<>();
+        for (Map.Entry<Long, List<OutDetlDto>> entry : map.entrySet()) {
+            Long locId = entry.getKey();
+            Loc loc = locService.getById(locId);
+
+            List<OutDetlDto> outDetlDtos = entry.getValue();
+            for (OutDetlDto outDetlDto : outDetlDtos) {
+                orderDetlIdsTmp.remove(outDetlDto.getOrderDetlId());
+            }
+            Boolean all = outUtils.isAllForOut(locId, outDetlDtos);
+
+            for (OutDetlDto outDetlDto : outDetlDtos) {
+                OrderOutBatchPreviewDto previewDto = new OrderOutBatchPreviewDto();
+                previewDto.setLocId(locId);
+                previewDto.setLocNo(loc.getLocNo());
+                previewDto.setLocDetlId(outDetlDto.getDetlId());
+                previewDto.setAll(all);
+                previewDto.setAnfme(outDetlDto.getAnfme());
+                previewDto.setStock(outDetlDto.getStock());
+                previewDto.setOrderDetlId(outDetlDto.getOrderDetlId());
+                previewDtos.add(previewDto);
+
+
+                List<BatchPreviewOtherLocDto> otherLocs = new ArrayList<>();
+                previewDto.setOtherLoc(otherLocs);
+
+                List<LocDetl> locDetls = orderDetlLocMap.get(outDetlDto.getOrderDetlId());
+                for (LocDetl locDetl : locDetls) {
+                    BatchPreviewOtherLocDto otherLocDto = new BatchPreviewOtherLocDto();
+                    otherLocDto.setLocId(locDetl.getLocId());
+                    otherLocDto.setLocNo(locDetl.getLocNo());
+                    otherLocDto.setStock(locDetl.getAnfme());
+                    otherLocDto.setLocDetlId(locDetl.getId());
+
+                    if (locDetl.getLocId().equals(locId)) {
+                        otherLocs.add(0, otherLocDto);
+                        continue;
+                    }
+
+                    if (otherLocs.isEmpty()) {
+                        otherLocs.add(otherLocDto);
+                    }
+
+                    for (int i = 0; i < otherLocs.size(); i++) {
+                        BatchPreviewOtherLocDto locDto = otherLocs.get(i);
+                        if (locDto.getLocId().equals(locDetl.getLocId())) {
+                            break;
+                        }
+                        otherLocs.add(otherLocDto);
+                    }
+                }
+            }
+
+        }
+
+        for (Long id : orderDetlIdsTmp) {
+            OrderDetl orderDetl = orderDetlService.getById(id);
+            double issued = Optional.of(orderDetl.getAnfme() - orderDetl.getQty() - orderDetl.getWorkQty()).orElse(0.0D);
+
+            OrderOutBatchPreviewDto previewDto = new OrderOutBatchPreviewDto();
+            previewDto.setLocId(null);
+            previewDto.setLocNo(null);
+            previewDto.setLocDetlId(null);
+            previewDto.setAll(null);
+            previewDto.setAnfme(issued);
+            previewDto.setStock(0D);
+            previewDto.setOrderDetlId(orderDetl.getId());
+
+            previewDtos.add(previewDto);
+        }
+
+        return previewDtos;
+    }
+
+    @Transactional
+    public void orderOutBatch(List<OrderOutBatchPreviewDto> param) {
+        if (param == null) {
+            throw new CoolException("鍙傛暟涓嶈兘涓虹┖");
+        }
+
+        if (param.isEmpty()) {
+            throw new CoolException("鍙傛暟涓嶈兘涓虹┖");
+        }
+
+        boolean noStock = true;
+        for (OrderOutBatchPreviewDto dto : param) {
+            if (dto.getStock() > 0) {
+                noStock = false;
+                break;
+            }
+        }
+        if (noStock) {
+            throw new CoolException("搴撳瓨涓嶈冻");
+        }
+
+
+        HashMap<Long, List<OrderOutBatchPreviewDto>> detlMap = new HashMap<>();
+        for (OrderOutBatchPreviewDto previewDto : param) {
+            if (previewDto.getLocId() == null) {
+                continue;
+            }
+
+            if(detlMap.containsKey(previewDto.getLocDetlId())) {
+                List<OrderOutBatchPreviewDto> previewDtos = detlMap.get(previewDto.getLocDetlId());
+                previewDtos.add(previewDto);
+                detlMap.put(previewDto.getLocDetlId(), previewDtos);
+            }else {
+                List<OrderOutBatchPreviewDto> previewDtos = new ArrayList<>();
+                previewDtos.add(previewDto);
+                detlMap.put(previewDto.getLocDetlId(), previewDtos);
+            }
+        }
+
+        List<OrderOutBatchPreviewDto> dtos = new ArrayList<>();
+        for (Map.Entry<Long, List<OrderOutBatchPreviewDto>> entry : detlMap.entrySet()) {
+            Long locDetlId = entry.getKey();
+            LocDetl locDetl = locDetlService.getById(locDetlId);
+            if (locDetl == null) {
+                continue;
+            }
+
+            Double stock = locDetl.getAnfme();
+            for (OrderOutBatchPreviewDto dto : entry.getValue()) {
+                stock = stock - dto.getAnfme();
+                if (stock >= 0) {
+                    dtos.add(dto);
+                }
+            }
+        }
+
+
+        HashMap<Long, List<OrderOutBatchPreviewDto>> map = new HashMap<>();
+
+        for (OrderOutBatchPreviewDto previewDto : dtos) {
+            if(map.containsKey(previewDto.getLocId())) {
+                List<OrderOutBatchPreviewDto> previewDtos = map.get(previewDto.getLocId());
+                previewDtos.add(previewDto);
+                map.put(previewDto.getLocId(), previewDtos);
+            }else {
+                List<OrderOutBatchPreviewDto> previewDtos = new ArrayList<>();
+                previewDtos.add(previewDto);
+                map.put(previewDto.getLocId(), previewDtos);
+            }
+        }
+
+        for (Map.Entry<Long, List<OrderOutBatchPreviewDto>> entry : map.entrySet()) {
+            Long locId = entry.getKey();
+            List<OrderOutBatchPreviewDto> previewDtos = entry.getValue();
+            Boolean all = outUtils.isAllForPreview(locId, previewDtos);
+
+            Loc loc = locService.getById(locId);
+            if (loc == null) {
+                continue;
+            }
+
+            if (!loc.getLocStsId().equals(LocStsType.F.val())) {
+                continue;
+            }
+
+
+            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("A");
+            task.setBarcode(loc.getBarcode());
+            boolean res = taskService.save(task);
+            if (!res) {
+                throw new CoolException("淇濆瓨宸ヤ綔妗eけ璐�");
+            }
+
+            for (OrderOutBatchPreviewDto dto : previewDtos) {
+                LocDetl locDetl = locDetlService.getById(dto.getLocDetlId());
+                if(locDetl == null) {
+                    throw new CoolException("鏄庣粏涓嶅瓨鍦�");
+                }
+
+                OrderDetl orderDetl = orderDetlService.getById(dto.getOrderDetlId());
+                if(orderDetl == null) {
+                    throw new CoolException("璁㈠崟鏄庣粏涓嶅瓨鍦�");
+                }
+                orderUtils.updateWorkQty(dto.getOrderDetlId(), dto.getAnfme());
+
+                TaskDetl taskDetl = new TaskDetl();
+                taskDetl.sync(locDetl);
+                taskDetl.setTaskId(task.getId());
+                taskDetl.setAnfme(dto.getAnfme());
+                taskDetl.setStock(locDetl.getAnfme());
+                taskDetl.setOrderId(orderDetl.getOrderId());
+                taskDetl.setOrderNo(orderDetl.getOrderNo());
+                taskDetl.setDetlId(orderDetl.getId());
+                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.setDetlId(taskDetl.getId());
+                    boolean taskDetlFieldSave = taskDetlFieldService.save(taskDetlField);
+                    if(!taskDetlFieldSave){
+                        throw new CoolException("鏄庣粏鎵╁睍鐢熸垚澶辫触");
+                    }
+                }
+            }
+
+            //搴撲綅F => R
+            loc.setLocStsId(LocStsType.R.val());
+            loc.setUpdateTime(new Date());
+            boolean locUpdate = locService.updateById(loc);
+            if(!locUpdate){
+                throw new CoolException("搴撲綅鐘舵�佹洿鏂板け璐�");
+            }
+
+        }
+
+    }
+
+    @Transactional
+    public List<MergePreviewDto> orderOutMergePreview(OrderOutMergePreviewParam param) {
+        if (param == null) {
+            throw new CoolException("鍙傛暟涓嶈兘涓虹┖");
+        }
+
+        List<Long> orderIds = param.getOrderIds();
+        if (orderIds.isEmpty()) {
+            throw new CoolException("璁㈠崟涓嶈兘涓虹┖");
+        }
+
+        List<Order> orders = orderService.list(new LambdaQueryWrapper<Order>().in(Order::getId, orderIds));
+        if (orders.isEmpty()) {
+            throw new CoolException("璁㈠崟涓嶅瓨鍦�");
+        }
+
+        List<OrderDetl> orderDetls = orderDetlService.list(new LambdaQueryWrapper<OrderDetl>().in(OrderDetl::getOrderId, orderIds));
+        if(orderDetls.isEmpty()){
+            throw new CoolException("璁㈠崟鏄庣粏涓嶅瓨鍦�");
+        }
+        orderDetls = orderDetlService.parseDetl(orderDetls);
+
+        HashMap<String, Double> locDetlStockMap = new HashMap<>();
+        for (OrderDetl orderDetl : orderDetls) {
+            String matUniqueKey = Utils.getMatUniqueKey(orderDetl.getMat$().getMatnr(), orderDetl.getBatch(), orderDetl.getUniqueField());
+            double issued = Optional.of(orderDetl.getAnfme() - orderDetl.getQty() - orderDetl.getWorkQty()).orElse(0.0D);
+            if (locDetlStockMap.containsKey(matUniqueKey)) {
+                Double anfme = locDetlStockMap.get(matUniqueKey);
+                anfme += issued;
+                locDetlStockMap.put(matUniqueKey, anfme);
+            }else {
+                locDetlStockMap.put(matUniqueKey, issued);
+            }
+        }
+
+        List<MergePreviewDto> mergePreviewDtos = new ArrayList<>();
+        for (Map.Entry<String, Double> entry : locDetlStockMap.entrySet()) {
+            String matUniqueKey = entry.getKey();
+            Double anfme = entry.getValue();
+
+            MatUniqueObjDto matUniqueObj = Utils.getMatUniqueObj(matUniqueKey);
+            HashMap<String, Object> dynamicFields = new HashMap<>();
+            for (FieldParam fieldParam : matUniqueObj.getParams()) {
+                dynamicFields.put(fieldParam.getName(), fieldParam.getValue());
+            }
+
+            MergePreviewDto dto = new MergePreviewDto();
+            dto.setMatnr(matUniqueObj.getMatnr());
+            dto.setBatch(matUniqueObj.getBatch());
+            dto.setAnfme(anfme);
+            dto.setOrderIds(orderIds);
+            dto.setFieldParamsEncode(JSON.toJSONString(matUniqueObj.getParams()));
+            dto.setDynamicFields(dynamicFields);
+            mergePreviewDtos.add(dto);
+        }
+
+
+        return mergePreviewDtos;
+    }
+
+    @Transactional
+    public List<MergePreviewResultDto> orderOutMergeLocPreview(List<MergePreviewDto> param) {
+        if (param == null) {
+            throw new CoolException("鍙傛暟涓嶈兘涓虹┖");
+        }
+
+        if (param.isEmpty()) {
+            throw new CoolException("鍙傛暟涓嶈兘涓虹┖");
+        }
+
+        for (MergePreviewDto dto : param) {
+            List<FieldParam> fieldParams = JSON.parseArray(dto.getFieldParamsEncode(), FieldParam.class);
+            dto.setFieldParams(fieldParams);
+        }
+
+        FieldSortParam sortParam = new FieldSortParam("anfme","desc");
+        List<FieldSortParam> sortParams = new ArrayList<>();
+        sortParams.add(sortParam);
+
+        List<MergePreviewResultDto> resultDtos = new ArrayList<>();
+        for (MergePreviewDto dto : param) {
+            List<LocDetl> locDetls = locDetlService.queryStock(dto.getMatnr(), dto.getBatch(), dto.getFieldParams(), sortParams);
+            if(locDetls.isEmpty()){
+                continue;
+            }
+
+            List<MergePreviewResultLocDto> locDtos = new ArrayList<>();
+
+            MergePreviewResultDto resultDto = new MergePreviewResultDto();
+            resultDto.sync(dto);
+            resultDto.setLocs(locDtos);
+            resultDto.setOrderIds(dto.getOrderIds());
+
+            Double anfme = dto.getAnfme();
+            for (LocDetl locDetl : locDetls) {
+                MergePreviewResultLocDto locDto = new MergePreviewResultLocDto();
+                locDto.setLocId(locDetl.getLocId());
+                locDto.setLocNo(locDetl.getLocNo());
+                locDto.setLocDetlId(locDetl.getId());
+
+                locDtos.add(locDto);
+                if (anfme - locDetl.getAnfme() < 0) {
+                    locDto.setAnfme(anfme);
+                    break;
+                }
+                locDto.setAnfme(locDetl.getAnfme());
+                anfme -= locDetl.getAnfme();
+            }
+            resultDto.setAnfme(anfme < 0 ? 0 : anfme);
+
+            resultDtos.add(resultDto);
+        }
+
+        return resultDtos;
+    }
+
+    @Transactional
+    public void orderOutMerge(List<OrderOutMergeParam> params) {
+        if(params == null){
+            throw new CoolException("鍙傛暟涓嶈兘涓虹┖");
+        }
+
+        if (params.isEmpty()) {
+            throw new CoolException("鍙傛暟涓嶈兘涓虹┖");
+        }
+
+        List<Long> orderIds = null;
+
+        List<OrderOutMergeParam> filterParam = new ArrayList<>();
+        HashMap<String, OrderOutMergeParam> paramMap = new HashMap<>();
+        for (OrderOutMergeParam param : params) {
+            if (param.getLocId() == null) {
+                continue;
+            }
+
+            filterParam.add(param);
+
+            String matUniqueKey = Utils.getMatUniqueKey(param.getMatnr(), param.getBatch(), param.getFieldParams());
+            paramMap.put(matUniqueKey, param);
+
+            if (orderIds == null) {
+                orderIds = param.getOrderIds();
+            }
+        }
+
+        if (orderIds == null) {
+            throw new CoolException("璁㈠崟涓嶅瓨鍦�");
+        }
+
+        List<Order> orderList = orderService.listByIds(orderIds);
+        if (orderList.isEmpty()) {
+            throw new CoolException("璁㈠崟涓嶅瓨鍦�");
+        }
+
+        List<OrderDetl> orderDetls = orderDetlService.list(new LambdaQueryWrapper<OrderDetl>().in(OrderDetl::getOrderId, orderIds));
+        if (orderDetls.isEmpty()) {
+            throw new CoolException("璁㈠崟鏄庣粏涓嶅瓨鍦�");
+        }
+
+        HashMap<String, List<OrderDetl>> detlMap = new HashMap<>();
+        for (OrderDetl orderDetl : orderDetls) {
+            String matUniqueKey = Utils.getMatUniqueKey(orderDetl.getMat$().getMatnr(), orderDetl.getBatch(), orderDetl.getUniqueField());
+            if (detlMap.containsKey(matUniqueKey)) {
+                List<OrderDetl> detls = detlMap.get(matUniqueKey);
+                detls.add(orderDetl);
+                detlMap.put(matUniqueKey, detls);
+            }else {
+                List<OrderDetl> detls = new ArrayList<>();
+                detls.add(orderDetl);
+                detlMap.put(matUniqueKey, detls);
+            }
+        }
+
+        List<OrderOutMergeDto> orderOutMergeDtos = new ArrayList<>();
+        for (OrderOutMergeParam param : filterParam) {
+            String matUniqueKey = Utils.getMatUniqueKey(param.getMatnr(), param.getBatch(), param.getFieldParams());
+            if (!detlMap.containsKey(matUniqueKey)) {
+                continue;
+            }
+
+            Double requireAnfme = param.getAnfme();
+
+            List<OrderDetl> orderDetlList = detlMap.get(matUniqueKey);
+            for (OrderDetl orderDetl : orderDetlList) {
+                double issued = Optional.of(orderDetl.getAnfme() - orderDetl.getQty() - orderDetl.getWorkQty()).orElse(0.0D);
+                if (issued <= 0D) {
+                    continue;
+                }
+
+                OrderOutMergeDto orderOutMergeDto = new OrderOutMergeDto();
+                orderOutMergeDto.sync(param);
+                orderOutMergeDto.setOrderDetlId(orderDetl.getId());
+
+                Double anfme = orderDetl.getAnfme();
+                Double updateWorkQty = null;
+
+                double diffAnfme = requireAnfme - anfme;
+                if (diffAnfme >= 0) {
+                    orderOutMergeDto.setAnfme(anfme);
+                    updateWorkQty = anfme;
+                    requireAnfme -= anfme;
+                }else {
+                    orderOutMergeDto.setAnfme(requireAnfme);
+                    updateWorkQty = requireAnfme;
+                    requireAnfme -= requireAnfme;
+                }
+                orderOutMergeDtos.add(orderOutMergeDto);
+
+                orderUtils.updateWorkQty(orderDetl.getId(), updateWorkQty);
+                if (requireAnfme <= 0) {
+                    break;
+                }
+            }
+        }
+
+        HashMap<Long, List<OrderOutMergeDto>> map = new HashMap<>();
+        for (OrderOutMergeDto orderOutMergeDto : orderOutMergeDtos) {
+            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("鏄庣粏涓嶅瓨鍦�");
+                }
+
+                OrderDetl orderDetl = orderDetlService.getById(merge.getOrderDetlId());
+                if(orderDetl == null) {
+                    throw new CoolException("璁㈠崟鏄庣粏涓嶅瓨鍦�");
+                }
+
+                TaskDetl taskDetl = new TaskDetl();
+                taskDetl.sync(locDetl);
+                taskDetl.setTaskId(task.getId());
+                taskDetl.setAnfme(merge.getAnfme());
+                taskDetl.setStock(locDetl.getAnfme());
+                taskDetl.setOrderId(orderDetl.getOrderId());
+                taskDetl.setOrderNo(orderDetl.getOrderNo());
+                taskDetl.setDetlId(orderDetl.getId());
+                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.setDetlId(taskDetl.getId());
+                    boolean taskDetlFieldSave = taskDetlFieldService.save(taskDetlField);
+                    if(!taskDetlFieldSave){
+                        throw new CoolException("鏄庣粏鎵╁睍鐢熸垚澶辫触");
+                    }
+                }
+            }
+
+            //搴撲綅F => R
+            loc.setLocStsId(LocStsType.R.val());
+            loc.setUpdateTime(new Date());
+            boolean locUpdate = locService.updateById(loc);
+            if(!locUpdate){
+                throw new CoolException("搴撲綅鐘舵�佹洿鏂板け璐�");
+            }
+
+        }
+
+
+    }
+
 }
diff --git a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/mapper/ViewLocDetlMapper.java b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/mapper/ViewLocDetlMapper.java
index 503084d..e95b9bc 100644
--- a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/mapper/ViewLocDetlMapper.java
+++ b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/mapper/ViewLocDetlMapper.java
@@ -1,7 +1,6 @@
 package com.zy.asrs.wms.asrs.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.zy.asrs.wms.asrs.entity.LocDetl;
 import com.zy.asrs.wms.asrs.entity.ViewLocDetl;
 import com.zy.asrs.wms.asrs.entity.param.FieldParam;
 import com.zy.asrs.wms.asrs.entity.param.FieldSortParam;
@@ -16,7 +15,7 @@
 @Repository
 public interface ViewLocDetlMapper extends BaseMapper<ViewLocDetl> {
 
-    List<Map<String,Object>> getList(String matnr, String batch, List<FieldParam> param);
+    List<Map<String, Object>> getList(String matnr, String batch, List<FieldParam> param, @Param("sortParam") List<FieldSortParam> sortParam);
 
     List<Map<String,Object>> getListLike(String matnr, String batch, List<FieldParam> param);
 
diff --git a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/service/LocDetlService.java b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/service/LocDetlService.java
index cba2bb2..b7d6784 100644
--- a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/service/LocDetlService.java
+++ b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/service/LocDetlService.java
@@ -8,7 +8,6 @@
 import com.zy.asrs.wms.asrs.entity.param.FieldSortParam;
 import com.zy.asrs.wms.common.domain.BaseParam;
 import com.zy.asrs.wms.common.domain.PageParam;
-import org.apache.poi.ss.formula.functions.T;
 
 import java.util.List;
 import java.util.Map;
@@ -21,6 +20,8 @@
 
     List<LocDetl> parseLocDetl(List<LocDetl> list);
 
-    List<LocDetl> listSuitableMat( List<FieldParam> param, List<FieldSortParam> sortParam);
+    List<LocDetl> queryStock(String matnr, String batch, List<FieldParam> param);
+
+    List<LocDetl> queryStock(String matnr, String batch, List<FieldParam> param, List<FieldSortParam> sortParam);
 
 }
diff --git a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/service/OrderDetlService.java b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/service/OrderDetlService.java
index 086cd63..b8e6ac7 100644
--- a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/service/OrderDetlService.java
+++ b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/service/OrderDetlService.java
@@ -9,4 +9,6 @@
 
     List<OrderDetl> getOrderDetlByOrderId(Long orderId);
 
+    List<OrderDetl> parseDetl(List<OrderDetl> list);
+
 }
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 7a13a1a..d477f27 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
@@ -5,23 +5,23 @@
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.zy.asrs.wms.asrs.entity.LocDetl;
-import com.zy.asrs.wms.asrs.entity.LocDetlField;
-import com.zy.asrs.wms.asrs.entity.ViewLocDetl;
+import com.zy.asrs.framework.exception.CoolException;
+import com.zy.asrs.wms.asrs.entity.*;
+import com.zy.asrs.wms.asrs.entity.enums.LocStsType;
 import com.zy.asrs.wms.asrs.entity.param.FieldParam;
 import com.zy.asrs.wms.asrs.entity.param.FieldSortParam;
 import com.zy.asrs.wms.asrs.mapper.LocDetlMapper;
 import com.zy.asrs.wms.asrs.mapper.ViewLocDetlMapper;
+import com.zy.asrs.wms.asrs.service.LanewayRuleService;
 import com.zy.asrs.wms.asrs.service.LocDetlFieldService;
 import com.zy.asrs.wms.asrs.service.LocDetlService;
+import com.zy.asrs.wms.asrs.service.LocService;
 import com.zy.asrs.wms.common.domain.BaseParam;
 import com.zy.asrs.wms.common.domain.PageParam;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 
 @Service("locDetlService")
 public class LocDetlServiceImpl extends ServiceImpl<LocDetlMapper, LocDetl> implements LocDetlService {
@@ -30,6 +30,10 @@
     private ViewLocDetlMapper viewLocDetlMapper;
     @Autowired
     private LocDetlFieldService locDetlFieldService;
+    @Autowired
+    private LocService locService;
+    @Autowired
+    private LanewayRuleService lanewayRuleService;
 
     @Override
     public PageParam<ViewLocDetl, BaseParam> getPage(PageParam<ViewLocDetl, BaseParam> pageParam, QueryWrapper<ViewLocDetl> buildWrapper) {
@@ -88,22 +92,90 @@
         return list;
     }
 
-    /**
-     * 鏍规嵁鍑哄簱鏉′欢鏌ヨ绗﹀悎鐨勫簱瀛�
-     * @param param 鏌ヨ鏉′欢
-     * @param sortParam 鎺掑簭瀛楁
-     * @return
-     */
     @Override
-    public List<LocDetl> listSuitableMat( List<FieldParam> param, List<FieldSortParam> sortParam) {
-        List<Map<String, Object>> stock = viewLocDetlMapper.listSuitableMat(param, sortParam);
+    public List<LocDetl> queryStock(String matnr, String batch, List<FieldParam> param) {
+        return queryStock(matnr, batch, param, null);
+    }
+
+    @Override
+    public List<LocDetl> queryStock(String matnr, String batch, List<FieldParam> param, List<FieldSortParam> sortParam) {
+        List<Map<String, Object>> list = viewLocDetlMapper.getList(matnr, batch, param, sortParam);
+        List<LocDetl> locDetlsSort = resortDetls(list);
+        return locDetlsSort;
+    }
+
+    private List<LocDetl> resortDetls(List<Map<String, Object>> list) {
         List<LocDetl> locDetls = new ArrayList<>();
-        for (Map<String, Object> objectMap : stock) {
-            LocDetl detl = JSON.parseObject(JSON.toJSONString(objectMap), LocDetl.class);
-            detl.syncFieldMap(objectMap);
-            locDetls.add(detl);
+
+        for (Map<String, Object> map : list) {
+            LocDetl locDetl = JSON.parseObject(JSON.toJSONString(map), LocDetl.class);
+            locDetls.add(locDetl);
         }
-        return locDetls;
+
+        locDetls = parseLocDetl(locDetls);
+
+        List<Long> sortDirctLoc = new ArrayList<>();
+        HashMap<Long, List<LocDetl>> sortMap = new HashMap<>();
+        for (LocDetl locDetl : locDetls) {
+            List<LocDetl> detls = sortMap.get(locDetl.getLocId());
+            if (detls == null) {
+                detls = new ArrayList<>();
+                detls.add(locDetl);
+                sortMap.put(locDetl.getLocId(), detls);
+            }else {
+                detls.add(locDetl);
+                sortMap.put(locDetl.getLocId(), detls);
+            }
+
+            Loc loc = locService.getById(locDetl.getLocId());
+            if (loc == null) {
+                continue;
+            }
+
+            if(!loc.getLocStsId().equals(LocStsType.F.val())){
+                continue;
+            }
+
+            //鑾峰彇搴撲綅鎵�鍦ㄥ贩閬�
+            LanewayRule lanewayRule = lanewayRuleService.getLaneByLoc(loc);
+            if(lanewayRule == null) {
+                throw new CoolException("搴撲綅鏈厤缃贩閬�");
+            }
+
+            //鑾峰彇搴撲綅鏂瑰悜
+            List<Integer> direction = null;
+            if (lanewayRule.getLaneX$().contains(loc.getRow1())) {
+                direction = lanewayRule.getLaneX$();
+            }else {
+                direction = lanewayRule.getLaneY$();
+            }
+            Collections.reverse(direction);
+
+            for (Integer row : direction) {
+                Loc one = locService.getOne(new LambdaQueryWrapper<Loc>()
+                        .eq(Loc::getRow1, row)
+                        .eq(Loc::getBay1, loc.getBay1())
+                        .eq(Loc::getLev1, loc.getLev1()));
+                if (one == null) {
+                    continue;
+                }
+
+                sortDirctLoc.add(one.getId());
+            }
+        }
+
+        List<LocDetl> sortDirctDetls = new ArrayList<>();
+
+        for (Long locId : sortDirctLoc) {
+            List<LocDetl> detls = sortMap.get(locId);
+            if(detls == null) {
+                continue;
+            }
+
+            sortDirctDetls.addAll(detls);
+        }
+
+        return sortDirctDetls;
     }
 
 }
diff --git a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/service/impl/OrderDetlServiceImpl.java b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/service/impl/OrderDetlServiceImpl.java
index 42a0b9e..3e51f2a 100644
--- a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/service/impl/OrderDetlServiceImpl.java
+++ b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/service/impl/OrderDetlServiceImpl.java
@@ -10,6 +10,7 @@
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import java.util.Collections;
 import java.util.List;
 
 @Service("orderDetlService")
@@ -27,4 +28,13 @@
         }
         return orderDetls;
     }
+
+    @Override
+    public List<OrderDetl> parseDetl(List<OrderDetl> orderDetls) {
+        for (OrderDetl orderDetl : orderDetls) {
+            List<OrderDetlField> list = orderDetlFieldService.list(new LambdaQueryWrapper<OrderDetlField>().eq(OrderDetlField::getDetlId, orderDetl.getId()));
+            orderDetl.syncField(list);
+        }
+        return orderDetls;
+    }
 }
diff --git a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/utils/LocUtils.java b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/utils/LocUtils.java
index 210b416..02263e7 100644
--- a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/utils/LocUtils.java
+++ b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/utils/LocUtils.java
@@ -6,7 +6,6 @@
 import com.zy.asrs.wms.asrs.entity.*;
 import com.zy.asrs.wms.asrs.entity.enums.LocStsType;
 import com.zy.asrs.wms.asrs.entity.enums.LocTypeHeightType;
-import com.zy.asrs.wms.asrs.entity.enums.ShelvesRuleType;
 import com.zy.asrs.wms.asrs.entity.param.FieldParam;
 import com.zy.asrs.wms.asrs.mapper.ViewLocDetlMapper;
 import com.zy.asrs.wms.asrs.mapper.ViewTaskDetlMapper;
@@ -72,7 +71,7 @@
 
         //浠庡簱瀛樹腑杩涜鍖归厤
         List<Loc> locs2 = new ArrayList<>();
-        List<Map<String, Object>> list2 = viewLocDetlMapper.getList(mat.getMatnr(), batch, uniqueFields);
+        List<Map<String, Object>> list2 = viewLocDetlMapper.getList(mat.getMatnr(), batch, uniqueFields, null);
         for (Map<String, Object> map : list2) {
             Loc one = locService.getById(map.get("locId").toString());
             if (one == null) {
diff --git a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/utils/OrderUtils.java b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/utils/OrderUtils.java
new file mode 100644
index 0000000..98a6b46
--- /dev/null
+++ b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/utils/OrderUtils.java
@@ -0,0 +1,57 @@
+package com.zy.asrs.wms.utils;
+
+import com.zy.asrs.framework.exception.CoolException;
+import com.zy.asrs.wms.asrs.entity.Order;
+import com.zy.asrs.wms.asrs.entity.OrderDetl;
+import com.zy.asrs.wms.asrs.entity.enums.OrderSettleType;
+import com.zy.asrs.wms.asrs.service.OrderDetlService;
+import com.zy.asrs.wms.asrs.service.OrderService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.Date;
+
+@Component
+public class OrderUtils {
+
+    @Autowired
+    private OrderService orderService;
+    @Autowired
+    private OrderDetlService orderDetlService;
+
+    @Transactional
+    public void updateWorkQty(Long orderDetlId, Double qty) {
+        OrderDetl orderDetl = orderDetlService.getById(orderDetlId);
+        if(orderDetl == null) {
+            throw new CoolException("璁㈠崟鏄庣粏涓嶅瓨鍦�");
+        }
+
+        Order order = orderService.getById(orderDetl.getOrderId());
+        if(order == null) {
+            throw new CoolException("璁㈠崟涓嶅瓨鍦�");
+        }
+
+        if (order.getOrderSettle() == OrderSettleType.COMPLETE.val()
+                || order.getOrderSettle() == OrderSettleType.CANCEL.val()
+                || order.getOrderSettle() == OrderSettleType.WAIT_CANCEL.val()
+                || order.getOrderSettle() == OrderSettleType.REPORT_COMPLETE.val()) {
+            throw new CoolException("璁㈠崟褰撳墠鐘舵�佷笉鍙慨鏀�");
+        }
+
+        Double workQty = orderDetl.getWorkQty();
+        orderDetl.setWorkQty(workQty + qty);
+        orderDetl.setUpdateTime(new Date());
+        if (!orderDetlService.updateById(orderDetl)) {
+            throw new CoolException("璁㈠崟鏄庣粏鏇存柊澶辫触");
+        }
+
+
+        order.setOrderSettle(OrderSettleType.WORKING.val());
+        order.setUpdateTime(new Date());
+        if(!orderService.updateById(order)) {
+            throw new CoolException("璁㈠崟鏇存柊澶辫触");
+        }
+    }
+
+}
diff --git a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/utils/OutUtils.java b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/utils/OutUtils.java
index 5575378..ccc9f87 100644
--- a/zy-asrs-wms/src/main/java/com/zy/asrs/wms/utils/OutUtils.java
+++ b/zy-asrs-wms/src/main/java/com/zy/asrs/wms/utils/OutUtils.java
@@ -2,8 +2,11 @@
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.zy.asrs.wms.asrs.entity.LocDetl;
+import com.zy.asrs.wms.asrs.entity.dto.OrderOutBatchPreviewDto;
+import com.zy.asrs.wms.asrs.entity.dto.OrderOutMergeDto;
 import com.zy.asrs.wms.asrs.entity.dto.OutDetlDto;
 import com.zy.asrs.wms.asrs.entity.dto.OutLocDto;
+import com.zy.asrs.wms.asrs.entity.param.OrderOutMergeParam;
 import com.zy.asrs.wms.asrs.entity.param.OutParam;
 import com.zy.asrs.wms.asrs.service.LocDetlService;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -53,18 +56,8 @@
             OutLocDto locDto = entry.getValue();
             locDtos.add(locDto);
 
-            List<LocDetl> list = locDetlService.list(new LambdaQueryWrapper<LocDetl>().eq(LocDetl::getLocId, locDto.getLocId()));
-
-            Double sum = 0D;
-            for (LocDetl locDetl : list) {
-                sum += locDetl.getAnfme();
-            }
-
-            for (OutDetlDto detl : locDto.getDetls()) {
-                sum -= detl.getAnfme();
-            }
-
-            locDto.setAll(sum == 0);
+            Boolean all = this.isAllForOut(locDto.getLocId(), locDto.getDetls());
+            locDto.setAll(all);
             locDto.setOperationPort(outParam.getOperationPort());
         }
 
@@ -93,4 +86,46 @@
         return locDtos;
     }
 
+    public Boolean isAllForMerge(Long locId, List<OrderOutMergeDto> list) {
+        List<Double> anfmeList = new ArrayList<>();
+        for (OrderOutMergeDto dto : list) {
+            anfmeList.add(dto.getAnfme());
+        }
+        return isAll(locId, anfmeList);
+    }
+
+    public Boolean isAllForPreview(Long locId, List<OrderOutBatchPreviewDto> list) {
+        List<Double> anfmeList = new ArrayList<>();
+        for (OrderOutBatchPreviewDto outPreviewDto : list) {
+            anfmeList.add(outPreviewDto.getAnfme());
+        }
+        return isAll(locId, anfmeList);
+    }
+
+    public Boolean isAllForOut(Long locId, List<OutDetlDto> list) {
+        List<Double> anfmeList = new ArrayList<>();
+        for (OutDetlDto dto : list) {
+            anfmeList.add(dto.getAnfme());
+        }
+        return isAll(locId, anfmeList);
+    }
+
+    private Boolean isAll(Long locId, List<Double> anfmeList) {
+        if (anfmeList.isEmpty()) {
+            return false;
+        }
+
+        List<LocDetl> locDetls = locDetlService.list(new LambdaQueryWrapper<LocDetl>().eq(LocDetl::getLocId, locId));
+        Double sum = 0D;
+        for (LocDetl locDetl : locDetls) {
+            sum += locDetl.getAnfme();
+        }
+
+        for (Double anfme : anfmeList) {
+            sum -= anfme;
+        }
+
+        return sum <= 0;
+    }
+
 }
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 edeab46..998116d 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
@@ -1,14 +1,14 @@
 package com.zy.asrs.wms.utils;
 
 
+import com.alibaba.fastjson.JSON;
 import com.zy.asrs.framework.common.Cools;
+import com.zy.asrs.wms.asrs.entity.dto.MatUniqueObjDto;
+import com.zy.asrs.wms.asrs.entity.param.FieldParam;
 import com.zy.asrs.wms.common.constant.Constants;
 
 import javax.servlet.http.HttpServletResponse;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Optional;
+import java.util.*;
 import java.util.function.BiConsumer;
 import java.util.function.Function;
 
@@ -19,6 +19,66 @@
 
     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);
+
+        String encode = Base64.getEncoder().encodeToString(JSON.toJSONString(dto).getBytes());
+        return encode;
+    }
+
+    public static MatUniqueObjDto getMatUniqueObj(String matUniqueKey) {
+        byte[] decode = Base64.getDecoder().decode(matUniqueKey);
+        String decodeStr = new String(decode);
+        MatUniqueObjDto dto = JSON.parseObject(decodeStr, MatUniqueObjDto.class);
+        return dto;
+    }
+
+    public static boolean checkMatSame(String matnr1, String batch1, List<FieldParam> params1, String matnr2, String batch2, List<FieldParam> params2) {
+        if (!matnr1.equals(matnr2)) {
+            return false;
+        }
+
+        if (batch1 != null && batch2 != null) {
+            if(!batch1.equals(batch2)) {
+                return false;
+            }
+        }
+
+        boolean check = true;
+        if(params1 != null && params2 != null) {
+            if(params1.size() != params2.size()) {
+                return false;
+            }
+
+            for (int i = 0; i < params1.size(); i++) {
+                FieldParam param1 = params1.get(i);
+                FieldParam param2 = params2.get(i);
+
+                if (!param1.getName().equals(param2.getName())) {
+                    check = false;
+                    break;
+                }
+
+                if(Cools.isEmpty(param1.getValue()) && Cools.isEmpty(param2.getValue())) {
+                    continue;
+                }
+
+                if(!param1.getValue().equals(param2.getValue())) {
+                    check = false;
+                    break;
+                }
+            }
+
+        }
+
+        return check;
+    }
+
     /**
      * 閫氳繃搴撲綅鍙疯幏鍙� 鎺�
      */
diff --git a/zy-asrs-wms/src/main/resources/mapper/asrs/ViewLocDetlMapper.xml b/zy-asrs-wms/src/main/resources/mapper/asrs/ViewLocDetlMapper.xml
index a4f852b..23edb08 100644
--- a/zy-asrs-wms/src/main/resources/mapper/asrs/ViewLocDetlMapper.xml
+++ b/zy-asrs-wms/src/main/resources/mapper/asrs/ViewLocDetlMapper.xml
@@ -15,6 +15,11 @@
                 </if>
             </foreach>
         </if>
+        <if test="sortParam!=null and sortParam.size()>0">
+            <foreach collection="sortParam" item="item" open="order by " separator="," close="  ">
+                ${item.name} ${item.value}
+            </foreach>
+        </if>
     </select>
 
     <select id="getListLike" resultType="map">

--
Gitblit v1.9.1