From 13b690312e3397305fb20c2d3dc60be9e9452049 Mon Sep 17 00:00:00 2001
From: Junjie <xjj@123>
Date: 星期六, 18 五月 2024 10:43:44 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/Four-Way-Rack' into Four-Way-Rack

---
 zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/asrs/execute/LiftExecute.java             |  112 +++
 zy-asrs-flow/src/pages/core/taskLog/components/edit.jsx                             |  159 +++++
 zy-asrs-flow/src/pages/device/shuttle/index.jsx                                     |    2 
 zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/mapper/TaskMapper.java               |    2 
 zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/controller/BasShuttleController.java |    4 
 zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/asrs/execute/BaseExecute.java             |   52 +
 zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/asrs/execute/FlowExecute.java             |  202 ------
 zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/utils/CodeBuilder.java                    |    8 
 zy-asrs-wcs/src/main/java/taskLog.sql                                               |    9 
 zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/asrs/execute/DevpExecute.java             |   23 
 zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/controller/TaskLogController.java    |  101 +++
 zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/entity/Task.java                     |   10 
 zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/entity/TaskLog.java                  |  222 +++++++
 zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/service/TaskService.java             |    2 
 zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/service/impl/TaskServiceImpl.java    |    5 
 zy-asrs-flow/src/pages/map/drawer/shuttle/handle.jsx                                |    3 
 zy-asrs-wcs/src/main/resources/mapper/core/TaskMapper.xml                           |    7 
 zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/service/impl/TaskLogServiceImpl.java |   12 
 zy-asrs-flow/src/pages/core/taskLog/index.jsx                                       |  454 +++++++++++++++
 zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/asrs/execute/ShuttleExecute.java          |   80 ++
 zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/mapper/TaskLogMapper.java            |   12 
 zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/action/ShuttleAction.java            |   45 +
 zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/utils/ShuttleDispatcher.java         |   56 +
 zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/service/TaskLogService.java          |    8 
 zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/timer/TaskTimer.java                 |   98 +++
 zy-asrs-wcs/src/main/resources/mapper/core/TaskLogMapper.xml                        |    5 
 26 files changed, 1,492 insertions(+), 201 deletions(-)

diff --git a/zy-asrs-flow/src/pages/core/taskLog/components/edit.jsx b/zy-asrs-flow/src/pages/core/taskLog/components/edit.jsx
new file mode 100644
index 0000000..c311488
--- /dev/null
+++ b/zy-asrs-flow/src/pages/core/taskLog/components/edit.jsx
@@ -0,0 +1,159 @@
+import React, { useState, useRef, useEffect } from 'react';
+import {
+    ProForm,
+    ProFormDigit,
+    ProFormText,
+    ProFormSelect,
+    ProFormDateTimePicker
+} from '@ant-design/pro-components';
+import { Form, Modal } from 'antd';
+import { FormattedMessage, useIntl } from '@umijs/max';
+import moment from 'moment';
+import Http from '@/utils/http';
+
+const Edit = (props) => {
+    const intl = useIntl();
+    const [form] = Form.useForm();
+    const { } = props;
+
+    useEffect(() => {
+        form.resetFields();
+        form.setFieldsValue({
+            ...props.values
+        })
+    }, [form, props])
+
+    const handleCancel = () => {
+        props.onCancel();
+    };
+
+    const handleOk = () => {
+        form.submit();
+    }
+
+    const handleFinish = async (values) => {
+        props.onSubmit({ ...values });
+    }
+
+    return (
+        <>
+            <Modal
+                title={
+                    Object.keys(props.values).length > 0
+                        ? intl.formatMessage({ id: 'page.edit', defaultMessage: '缂栬緫' })
+                        : intl.formatMessage({ id: 'page.add', defaultMessage: '娣诲姞' })
+                }
+                width={640}
+                forceRender
+                destroyOnClose
+                open={props.open}
+                onCancel={handleCancel}
+                onOk={handleOk}
+            >
+                <ProForm
+                    form={form}
+                    submitter={false}
+                    onFinish={handleFinish}
+                    layout="horizontal"
+                    grid={true}
+                >
+                    <ProFormDigit
+                        name="id"
+                        disabled
+                        hidden={true}
+                    />
+                    <ProForm.Group>
+                        <ProFormText
+                            name="uuid"
+                            label="缂栧彿"
+                            colProps={{ md: 12, xl: 12 }}
+                        />
+                        <ProFormText
+                            name="name"
+                            label="鍚嶇О"
+                            colProps={{ md: 12, xl: 12 }}
+                        />
+                    </ProForm.Group>
+                    <ProForm.Group>
+                        <ProFormText
+                            name="flag"
+                            label="鏍囪瘑"
+                            colProps={{ md: 12, xl: 12 }}
+                        />
+                        <ProFormText
+                            name="taskNo"
+                            label="浠诲姟鍙�"
+                            colProps={{ md: 12, xl: 12 }}
+                        />
+                    </ProForm.Group>
+                    <ProForm.Group>
+                        <ProFormText
+                            name="taskData"
+                            label="浠诲姟鏁版嵁"
+                            colProps={{ md: 12, xl: 12 }}
+                        />
+                        <ProFormSelect
+                            name="status"
+                            label="鐘舵��"
+                            colProps={{ md: 12, xl: 12 }}
+                            options={[
+                                { label: '姝e父', value: 1 },
+                                { label: '绂佺敤', value: 0 },
+                            ]}
+                        />
+                    </ProForm.Group>
+                    <ProForm.Group>
+                        <ProFormDateTimePicker
+                            name="createTime"
+                            label="娣诲姞鏃堕棿"
+                            colProps={{ md: 12, xl: 12 }}
+                            transform={(value) => moment(value).toISOString()}
+                        />
+                        <ProFormSelect
+                            name="createBy"
+                            label="娣诲姞浜哄憳"
+                            colProps={{ md: 12, xl: 12 }}
+                            fieldProps={{ precision: 0 }}
+                            showSearch
+                            debounceTime={300}
+                            request={async ({ keyWords }) => {
+                                const resp = await Http.doPostForm('api/user/query', { condition: keyWords });
+                                return resp.data;
+                            }}
+                        />
+                    </ProForm.Group>
+                    <ProForm.Group>
+                        <ProFormDateTimePicker
+                            name="updateTime"
+                            label="淇敼鏃堕棿"
+                            colProps={{ md: 12, xl: 12 }}
+                            transform={(value) => moment(value).toISOString()}
+                        />
+                        <ProFormSelect
+                            name="updateBy"
+                            label="淇敼浜哄憳"
+                            colProps={{ md: 12, xl: 12 }}
+                            fieldProps={{ precision: 0 }}
+                            showSearch
+                            debounceTime={300}
+                            request={async ({ keyWords }) => {
+                                const resp = await Http.doPostForm('api/user/query', { condition: keyWords });
+                                return resp.data;
+                            }}
+                        />
+                    </ProForm.Group>
+                    <ProForm.Group>
+                        <ProFormText
+                            name="memo"
+                            label="澶囨敞"
+                            colProps={{ md: 12, xl: 12 }}
+                        />
+                    </ProForm.Group>
+
+                </ProForm>
+            </Modal>
+        </>
+    )
+}
+
+export default Edit;
diff --git a/zy-asrs-flow/src/pages/core/taskLog/index.jsx b/zy-asrs-flow/src/pages/core/taskLog/index.jsx
new file mode 100644
index 0000000..17db031
--- /dev/null
+++ b/zy-asrs-flow/src/pages/core/taskLog/index.jsx
@@ -0,0 +1,454 @@
+
+import React, { useState, useRef, useEffect } from 'react';
+import { Button, message, Modal, Tag  } from 'antd';
+import {
+    FooterToolbar,
+    PageContainer,
+    ProTable,
+    LightFilter,
+} from '@ant-design/pro-components';
+import { FormattedMessage, useIntl } from '@umijs/max';
+import { PlusOutlined, ExportOutlined } from '@ant-design/icons';
+import Http from '@/utils/http';
+import Edit from './components/edit'
+import { TextFilter, SelectFilter, DatetimeRangeFilter, LinkFilter } from '@/components/TableSearch'
+import { statusMap } from '@/utils/enum-util'
+import { repairBug } from '@/utils/common-util';
+
+const TABLE_KEY = 'pro-table-taskLog';
+
+const handleSave = async (val, intl) => {
+    const hide = message.loading(intl.formatMessage({ id: 'page.adding', defaultMessage: '姝e湪娣诲姞' }));
+    try {
+        const resp = await Http.doPost('api/taskLog/save', val);
+        if (resp.code === 200) {
+            message.success(intl.formatMessage({ id: 'page.add.success', defaultMessage: '娣诲姞鎴愬姛' }));
+            return true;
+        } else {
+            message.error(resp.msg);
+            return false;
+        }
+    } catch (error) {
+        message.error(intl.formatMessage({ id: 'page.add.fail', defaultMessage: '娣诲姞澶辫触璇烽噸璇曪紒' }));
+        return false;
+    } finally {
+        hide();
+    }
+};
+
+const handleUpdate = async (val, intl) => {
+    const hide = message.loading(intl.formatMessage({ id: 'page.updating', defaultMessage: '姝e湪鏇存柊' }));
+    try {
+        const resp = await Http.doPost('api/taskLog/update', val);
+        if (resp.code === 200) {
+            message.success(intl.formatMessage({ id: 'page.update.success', defaultMessage: '鏇存柊鎴愬姛' }));
+            return true;
+        } else {
+            message.error(resp.msg);
+            return false;
+        }
+    } catch (error) {
+        message.error(intl.formatMessage({ id: 'page.update.fail', defaultMessage: '鏇存柊澶辫触璇烽噸璇曪紒' }));
+        return false;
+    } finally {
+        hide();
+    }
+};
+
+const handleRemove = async (rows, intl) => {
+    if (!rows) return true;
+    const hide = message.loading(intl.formatMessage({ id: 'page.deleting', defaultMessage: '姝e湪鍒犻櫎' }));
+    try {
+        const resp = await Http.doPost('api/taskLog/remove/' + rows.map((row) => row.id).join(','));
+        if (resp.code === 200) {
+            message.success(intl.formatMessage({ id: 'page.delete.success', defaultMessage: '鍒犻櫎鎴愬姛' }));
+            return true;
+        } else {
+            message.error(resp.msg);
+            return false;
+        }
+    } catch (error) {
+        message.error(intl.formatMessage({ id: 'page.delete.fail', defaultMessage: '鍒犻櫎澶辫触锛岃閲嶈瘯锛�' }));
+        return false;
+    } finally {
+        hide();
+    }
+};
+
+const handleExport = async (intl) => {
+    const hide = message.loading(intl.formatMessage({ id: 'page.exporting', defaultMessage: '姝e湪瀵煎嚭' }));
+    try {
+        const resp = await Http.doPostBlob('api/taskLog/export');
+        const blob = new Blob([resp], { type: 'application/vnd.ms-excel' });
+        window.location.href = window.URL.createObjectURL(blob);
+        message.success(intl.formatMessage({ id: 'page.export.success', defaultMessage: '瀵煎嚭鎴愬姛' }));
+        return true;
+    } catch (error) {
+        message.error(intl.formatMessage({ id: 'page.export.fail', defaultMessage: '瀵煎嚭澶辫触锛岃閲嶈瘯' }));
+        return false;
+    } finally {
+        hide();
+    }
+};
+
+
+const Main = () => {
+    const intl = useIntl();
+    const formTableRef = useRef();
+    const actionRef = useRef();
+    const [selectedRows, setSelectedRows] = useState([]);
+    const [modalVisible, setModalVisible] = useState(false);
+    const [currentRow, setCurrentRow] = useState();
+    const [searchParam, setSearchParam] = useState({});
+
+    useEffect(() => {
+
+    }, []);
+
+    const columns = [
+        {
+            title: intl.formatMessage({
+                id: 'page.table.no',
+                defaultMessage: 'No'
+            }),
+            dataIndex: 'index',
+            valueType: 'indexBorder',
+            width: 48,
+        },
+        {
+            title: '缂栧彿',
+            dataIndex: 'uuid',
+            valueType: 'text',
+            hidden: false,
+            width: 140,
+            filterDropdown: (props) => <TextFilter
+                name='uuid'
+                {...props}
+                actionRef={actionRef}
+                setSearchParam={setSearchParam}
+            />,
+        },
+        {
+            title: '鍚嶇О',
+            dataIndex: 'name',
+            valueType: 'text',
+            hidden: false,
+            width: 140,
+            copyable: true,
+            filterDropdown: (props) => <TextFilter
+                name='name'
+                {...props}
+                actionRef={actionRef}
+                setSearchParam={setSearchParam}
+            />,
+        },
+        {
+            title: '鏍囪瘑',
+            dataIndex: 'flag',
+            valueType: 'text',
+            hidden: false,
+            width: 140,
+            filterDropdown: (props) => <TextFilter
+                name='flag'
+                {...props}
+                actionRef={actionRef}
+                setSearchParam={setSearchParam}
+            />,
+        },
+        {
+            title: '浠诲姟鍙�',
+            dataIndex: 'taskNo',
+            valueType: 'text',
+            hidden: false,
+            width: 140,
+            filterDropdown: (props) => <TextFilter
+                name='taskNo'
+                {...props}
+                actionRef={actionRef}
+                setSearchParam={setSearchParam}
+            />,
+        },
+        {
+            title: '浠诲姟鏁版嵁',
+            dataIndex: 'taskData',
+            valueType: 'text',
+            hidden: false,
+            width: 140,
+            filterDropdown: (props) => <TextFilter
+                name='taskData'
+                {...props}
+                actionRef={actionRef}
+                setSearchParam={setSearchParam}
+            />,
+        },
+        {
+            title: '鐘舵��',
+            dataIndex: 'status$',
+            valueType: 'text',
+            hidden: false,
+            width: 140,
+            filterDropdown: (props) => <SelectFilter
+                name='status'
+                {...props}
+                actionRef={actionRef}
+                setSearchParam={setSearchParam}
+                data={[
+                    { label: '姝e父', value: 1 },
+                    { label: '绂佺敤', value: 0 },
+                ]}
+            />,
+        },
+        {
+            title: '娣诲姞鏃堕棿',
+            dataIndex: 'createTime$',
+            valueType: 'text',
+            hidden: false,
+            width: 140,
+            filterDropdown: (props) => <DatetimeRangeFilter
+                name='createTime'
+                {...props}
+                actionRef={actionRef}
+                setSearchParam={setSearchParam}
+            />,
+        },
+        {
+            title: '娣诲姞浜哄憳',
+            dataIndex: 'createBy$',
+            valueType: 'text',
+            hidden: false,
+            width: 140,
+            filterDropdown: (props) => <LinkFilter
+                name='createBy'
+                major='user'
+                {...props}
+                actionRef={actionRef}
+                setSearchParam={setSearchParam}
+            />,
+        },
+        {
+            title: '淇敼鏃堕棿',
+            dataIndex: 'updateTime$',
+            valueType: 'text',
+            hidden: false,
+            width: 140,
+            filterDropdown: (props) => <DatetimeRangeFilter
+                name='updateTime'
+                {...props}
+                actionRef={actionRef}
+                setSearchParam={setSearchParam}
+            />,
+        },
+        {
+            title: '淇敼浜哄憳',
+            dataIndex: 'updateBy$',
+            valueType: 'text',
+            hidden: false,
+            width: 140,
+            filterDropdown: (props) => <LinkFilter
+                name='updateBy'
+                major='user'
+                {...props}
+                actionRef={actionRef}
+                setSearchParam={setSearchParam}
+            />,
+        },
+        {
+            title: '澶囨敞',
+            dataIndex: 'memo',
+            valueType: 'text',
+            hidden: false,
+            width: 140,
+            filterDropdown: (props) => <TextFilter
+                name='memo'
+                {...props}
+                actionRef={actionRef}
+                setSearchParam={setSearchParam}
+            />,
+        },
+
+        {
+            title: '鎿嶄綔',
+            dataIndex: 'option',
+            width: 140,
+            valueType: 'option',
+            render: (_, record) => [
+                <Button
+                    type="link"
+                    key="edit"
+                    onClick={() => {
+                        setModalVisible(true);
+                        setCurrentRow(record);
+                    }}
+                >
+                    <FormattedMessage id='page.edit' defaultMessage='缂栬緫' />
+                </Button>,
+                <Button
+                    type="link"
+                    danger
+                    key="batchRemove"
+                    onClick={async () => {
+                        Modal.confirm({
+                            title: intl.formatMessage({ id: 'page.delete', defaultMessage: '鍒犻櫎' }),
+                            content: intl.formatMessage({ id: 'page.delete.confirm', defaultMessage: '纭畾鍒犻櫎璇ラ」鍚楋紵' }),
+                            onOk: async () => {
+                                const success = await handleRemove([record], intl);
+                                if (success) {
+                                    if (actionRef.current) {
+                                        actionRef.current.reload();
+                                    }
+                                }
+                            },
+                        });
+                    }}
+                >
+                    <FormattedMessage id='page.delete' defaultMessage='鍒犻櫎' />
+                </Button>,
+            ],
+        },
+    ];
+
+    return (
+        <PageContainer
+            header={{
+                breadcrumb: {},
+            }}
+        >
+            <div style={{ width: '100%', float: 'right' }}>
+                <ProTable
+                    key="taskLog"
+                    rowKey="id"
+                    actionRef={actionRef}
+                    formRef={formTableRef}
+                    columns={columns}
+                    cardBordered
+                    scroll={{ x: 1300 }}
+                    dateFormatter="string"
+                    pagination={{ pageSize: 16 }}
+                    search={false}
+                    toolbar={{
+                        search: {
+                            onSearch: (value) => {
+                                setSearchParam(prevState => ({
+                                    ...prevState,
+                                    condition: value
+                                }));
+                                actionRef.current?.reload();
+                            },
+                        },
+                        filter: (
+                            <LightFilter
+                                onValuesChange={(val) => {
+                                }}
+                            >
+                            </LightFilter>
+                        ),
+                        actions: [
+                            <Button
+                                type="primary"
+                                key="save"
+                                onClick={async () => {
+                                    setModalVisible(true)
+                                }}
+                            >
+                                <PlusOutlined />
+                                <FormattedMessage id='page.add' defaultMessage='娣诲姞' />
+                            </Button>,
+                            <Button
+                                key="export"
+                                onClick={async () => {
+                                    handleExport(intl);
+                                }}
+                            >
+                                <ExportOutlined />
+                                <FormattedMessage id='page.export' defaultMessage='瀵煎嚭' />
+                            </Button>,
+                        ],
+                    }}
+                    request={(params, sorter, filter) =>
+                        Http.doPostPromise('/api/taskLog/page', { ...params, ...searchParam }, (res) => {
+                            return {
+                                data: res.data.records,
+                                total: res.data.total,
+                                success: true,
+                            }
+                        })
+                    }
+                    rowSelection={{
+                        onChange: (ids, rows) => {
+                            setSelectedRows(rows);
+                        }
+                    }}
+                    columnsState={{
+                        persistenceKey: TABLE_KEY,
+                        persistenceType: 'localStorage',
+                        defaultValue: {
+                            // memo: { show: repairBug(TABLE_KEY, 'memo', false) },
+                            option: { fixed: 'right', disable: true },
+                        },
+                        onChange(value) {
+                        },
+                    }}
+                />
+            </div>
+
+            {selectedRows?.length > 0 && (
+                <FooterToolbar
+                    extra={
+                        <div>
+                            <a style={{ fontWeight: 600 }}>{selectedRows.length}</a>
+                            <FormattedMessage id='page.selected' defaultMessage=' 椤瑰凡閫夋嫨' />
+                        </div>
+                    }
+                >
+                    <Button
+                        key="remove"
+                        danger
+                        onClick={async () => {
+                            Modal.confirm({
+                                title: intl.formatMessage({ id: 'page.delete', defaultMessage: '鍒犻櫎' }),
+                                content: intl.formatMessage({ id: 'page.delete.confirm', defaultMessage: '纭畾鍒犻櫎璇ラ」鍚楋紵' }),
+                                onOk: async () => {
+                                    const success = await handleRemove(selectedRows, intl);
+                                    if (success) {
+                                        setSelectedRows([]);
+                                        actionRef.current?.reloadAndRest?.();
+                                    }
+                                },
+                            });
+                        }}
+                    >
+                        <FormattedMessage id='page.delete.batch' defaultMessage='鎵归噺鍒犻櫎' />
+                    </Button>
+                </FooterToolbar>
+            )}
+
+            <Edit
+                open={modalVisible}
+                values={currentRow || {}}
+                onCancel={
+                    () => {
+                        setModalVisible(false);
+                        setCurrentRow(undefined);
+                    }
+                }
+                onSubmit={async (values) => {
+                    let ok = false;
+                    if (values.id) {
+                        ok = await handleUpdate({ ...values }, intl)
+                    } else {
+                        ok = await handleSave({ ...values }, intl)
+                    }
+                    if (ok) {
+                        setModalVisible(false);
+                        setCurrentRow(undefined);
+                        if (actionRef.current) {
+                            actionRef.current.reload();
+                        }
+                    }
+                }}
+            />
+        </PageContainer>
+    );
+};
+
+export default Main;
diff --git a/zy-asrs-flow/src/pages/device/shuttle/index.jsx b/zy-asrs-flow/src/pages/device/shuttle/index.jsx
index 7b379a9..43eff9c 100644
--- a/zy-asrs-flow/src/pages/device/shuttle/index.jsx
+++ b/zy-asrs-flow/src/pages/device/shuttle/index.jsx
@@ -321,7 +321,7 @@
                                         defaultValue="0"
                                         onChange={moveLocTypeChange}
                                         style={{ width: 120 }}
-                                        options={[{ value: '0', label: '璺戣建閬�' }, { value: '1', label: '璺戝簱浣�' }, { value: '2', label: '姣嶈建閬撳惊鐜窇' }, { value: '3', label: '瀛愯建閬撳惊鐜窇' }]}
+                                        options={[{ value: '0', label: '璺戣建閬�' }, { value: '1', label: '璺戝簱浣�' }, { value: '2', label: '姣嶈建閬撳惊鐜窇' }, { value: '3', label: '瀛愯建閬撳惊鐜窇' }, { value: '4', label: '鍙栨斁璐�' }]}
                                     />
                                 </div>
                                 <Button onClick={() => shuttleMoveLoc()}>璺戝簱</Button>
diff --git a/zy-asrs-flow/src/pages/map/drawer/shuttle/handle.jsx b/zy-asrs-flow/src/pages/map/drawer/shuttle/handle.jsx
index d485bfd..8ec4f2c 100644
--- a/zy-asrs-flow/src/pages/map/drawer/shuttle/handle.jsx
+++ b/zy-asrs-flow/src/pages/map/drawer/shuttle/handle.jsx
@@ -160,7 +160,8 @@
                                         { value: '0', label: '璺戣建閬�' },
                                         { value: '1', label: '璺戝簱浣�' },
                                         { value: '2', label: '姣嶈建閬撳惊鐜窇' },
-                                        { value: '3', label: '瀛愯建閬撳惊鐜窇' }
+                                        { value: '3', label: '瀛愯建閬撳惊鐜窇' },
+                                        { value: '4', label: '鍙栨斁璐�' }
                                     ]}
                                 />
                             </div>
diff --git a/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/asrs/execute/BaseExecute.java b/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/asrs/execute/BaseExecute.java
new file mode 100644
index 0000000..60e20da
--- /dev/null
+++ b/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/asrs/execute/BaseExecute.java
@@ -0,0 +1,52 @@
+package com.zy.asrs.wcs.asrs.execute;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.zy.asrs.wcs.core.utils.RedisUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+@Component
+public class BaseExecute {
+
+    @Autowired
+    private RedisUtil redisUtil;
+
+    public boolean redisSet(String redisKey, String key, Object data) {
+        if (redisUtil.hasKey(redisKey)) {
+            Object obj = redisUtil.get(redisKey);
+            JSONObject object = JSON.parseObject(String.valueOf(obj));
+            object.put(key, data);
+            redisUtil.set(redisKey, JSON.toJSONString(object));
+        } else {
+            JSONObject object = new JSONObject();
+            object.put(key, data);
+            redisUtil.set(redisKey, JSON.toJSONString(object));
+        }
+        return true;
+    }
+
+    public Object redisGet(String redisKey, String key) {
+        if (redisUtil.hasKey(redisKey)) {
+            Object obj = redisUtil.get(redisKey);
+            JSONObject object = JSON.parseObject(String.valueOf(obj));
+            if (!object.containsKey(key)) {
+                return null;
+            }
+            return object.get(key);
+        }
+        return null;
+    }
+
+    public JSONObject findFLow(List<JSONObject> list, String id) {
+        for (JSONObject flow : list) {
+            if (flow.getString("id").equals(id)) {
+                return flow;
+            }
+        }
+        return null;
+    }
+
+}
diff --git a/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/asrs/execute/DevpExecute.java b/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/asrs/execute/DevpExecute.java
new file mode 100644
index 0000000..b556e83
--- /dev/null
+++ b/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/asrs/execute/DevpExecute.java
@@ -0,0 +1,23 @@
+package com.zy.asrs.wcs.asrs.execute;
+
+import com.alibaba.fastjson.JSONObject;
+import com.zy.asrs.wcs.core.entity.Task;
+import com.zy.asrs.wcs.core.utils.RedisUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component
+public class DevpExecute extends BaseExecute {
+
+    @Autowired
+    private RedisUtil redisUtil;
+
+    public boolean execute(Task task, JSONObject data, String redisKey) {
+        JSONObject devpType = data.getJSONObject("devpType");
+        String staNo = devpType.getString("staNo");
+        //鎼滅储宸ヤ綔
+
+        return true;
+    }
+
+}
diff --git a/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/asrs/execute/FlowExecute.java b/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/asrs/execute/FlowExecute.java
index 07dca21..a666188 100644
--- a/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/asrs/execute/FlowExecute.java
+++ b/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/asrs/execute/FlowExecute.java
@@ -4,22 +4,10 @@
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.zy.asrs.framework.common.Cools;
-import com.zy.asrs.framework.exception.CoolException;
-import com.zy.asrs.wcs.core.domain.dto.MotionDto;
 import com.zy.asrs.wcs.core.entity.Motion;
 import com.zy.asrs.wcs.core.entity.Task;
-import com.zy.asrs.wcs.core.kernel.KernelService;
 import com.zy.asrs.wcs.core.service.TaskService;
 import com.zy.asrs.wcs.core.utils.RedisUtil;
-import com.zy.asrs.wcs.core.utils.ShuttleDispatcher;
-import com.zy.asrs.wcs.core.utils.Utils;
-import com.zy.asrs.wcs.rcs.cache.SlaveConnection;
-import com.zy.asrs.wcs.rcs.entity.Device;
-import com.zy.asrs.wcs.rcs.model.enums.SlaveType;
-import com.zy.asrs.wcs.rcs.model.protocol.LiftProtocol;
-import com.zy.asrs.wcs.rcs.model.protocol.ShuttleProtocol;
-import com.zy.asrs.wcs.rcs.thread.LiftThread;
-import com.zy.asrs.wcs.rcs.thread.ShuttleThread;
 import org.apache.commons.codec.digest.DigestUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
@@ -28,16 +16,18 @@
 import java.util.List;
 
 @Component
-public class FlowExecute {
+public class FlowExecute extends BaseExecute {
 
     @Autowired
     private RedisUtil redisUtil;
     @Autowired
     private TaskService taskService;
     @Autowired
-    private ShuttleDispatcher shuttleDispatcher;
+    private ShuttleExecute shuttleExecute;
     @Autowired
-    private KernelService kernelService;
+    private LiftExecute liftExecute;
+    @Autowired
+    private DevpExecute devpExecute;
 
     //鎵ц娴佺▼鍥�
     public boolean execute(List<JSONObject> list) {
@@ -85,191 +75,15 @@
         String type = data.getString("type");
         boolean result = false;
         if (type.equals("devp")) {
-            result = executeDevpFlow(task, data, redisKey);
+            result = devpExecute.execute(task, data, redisKey);
         } else if (type.equals("shuttle")) {
-            result = executeShuttleFlow(task, data, redisKey);
+            result = shuttleExecute.execute(task, data, redisKey);
         } else if (type.equals("lift")) {
-            result = executeLiftFlow(task, data, redisKey);
+            result = liftExecute.execute(task, data, redisKey);
         }
         return result;
     }
 
-    private JSONObject findFLow(List<JSONObject> list, String id) {
-        for (JSONObject flow : list) {
-            if (flow.getString("id").equals(id)) {
-                return flow;
-            }
-        }
-        return null;
-    }
-
-    private boolean executeDevpFlow(Task task, JSONObject data, String redisKey) {
-        JSONObject devpType = data.getJSONObject("devpType");
-        String staNo = devpType.getString("staNo");
-        //鎼滅储宸ヤ綔
-
-        return true;
-    }
-
-    private boolean executeShuttleFlow(Task task, JSONObject data, String redisKey) {
-        JSONObject shuttleType = data.getJSONObject("shuttleType");
-        String oper = shuttleType.getString("shuttleOper");
-        if (oper.equals("searchIdleShuttle")) {
-            //鎼滅储绌洪棽杞�
-            ShuttleThread shuttleThread = shuttleDispatcher.searchIdleShuttle(task);
-            if (shuttleThread == null) {
-                throw new CoolException("绌挎杞︿笉瀛樺湪");
-            }
-            //瀛樺叆缂撳瓨
-            redisSet(redisKey, "shuttleDevice", shuttleThread.getDevice());
-            return true;
-        } else if (oper.equals("judgeShuttleCurrentTaskLev")) {
-            //鍒ゆ柇灏忚溅鏄惁鍦ㄤ换鍔℃ゼ灞�
-            //鍙栧嚭缂撳瓨灏忚溅
-            Object shuttleDeviceObj = redisGet(redisKey, "shuttleDevice");
-            if (shuttleDeviceObj == null) {
-                throw new CoolException("绌挎杞︾紦瀛樹负绌�");
-            }
-            Device device = JSON.parseObject(String.valueOf(shuttleDeviceObj), Device.class);
-            if (device == null) {
-                throw new CoolException("绌挎杞﹁澶囦笉瀛樺湪");
-            }
-
-            ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, device.getId().intValue());
-            if (shuttleThread == null) {
-                throw new CoolException("绌挎杞︿笉瀛樺湪");
-            }
-
-            ShuttleProtocol shuttleProtocol = shuttleThread.getStatus();
-            if (shuttleProtocol == null) {
-                throw new CoolException("绌挎杞︿笉瀛樺湪");
-            }
-
-            //灏忚溅鍧愭爣
-            String shuttleLocNo = shuttleProtocol.getCurrentLocNo();
-            String taskLocNo = null;
-            if (task.getTaskSts() < 100) {
-                taskLocNo = task.getDestLoc();
-            } else if (task.getTaskSts() > 100 && task.getTaskSts() < 200) {
-                taskLocNo = task.getOriginLoc();
-            }
-
-            // 灏忚溅鍜屼换鍔℃ゼ灞備竴鑷�
-            if (Utils.getLev(shuttleLocNo) == Utils.getLev(taskLocNo)) {
-                return true;
-            }else {
-                return false;
-            }
-        }
-
-        return true;
-    }
-
-    private boolean executeLiftFlow(Task task, JSONObject data, String redisKey) {
-        Object object = redisGet(redisKey, "motionList");
-        List<Motion> motionList = JSON.parseArray(JSON.toJSONString(object), Motion.class);
-
-        Object liftDeviceObj = redisGet(redisKey, "liftDevice");
-        if (liftDeviceObj == null) {
-            throw new CoolException("鎻愬崌鏈虹紦瀛樹负绌�");
-        }
-
-        Device device = JSON.parseObject(String.valueOf(liftDeviceObj), Device.class);
-        if (device == null) {
-            throw new CoolException("鎻愬崌鏈鸿澶囦笉瀛樺湪");
-        }
-
-        LiftThread liftThread = (LiftThread) SlaveConnection.get(SlaveType.Lift, device.getId().intValue());
-        if (liftThread == null) {
-            throw new CoolException("鎻愬崌鏈轰笉瀛樺湪");
-        }
-
-        LiftProtocol liftProtocol = liftThread.getStatus();
-        if (liftProtocol == null) {
-            throw new CoolException("鎻愬崌鏈轰笉瀛樺湪");
-        }
-
-        JSONObject liftType = data.getJSONObject("liftType");
-        String opera = liftType.getString("liftOper");
-        if (opera.equals("move")) {
-            //鎻愬崌鏈哄崌闄�
-            String sourceLevStr = liftType.getString("sourceLev");
-            String targetLevStr = liftType.getString("targetLev");
-            Integer sourceLev = getLiftOperaLev(sourceLevStr, task, redisKey);
-            Integer targetLev = getLiftOperaLev(targetLevStr, task, redisKey);
-
-            motionList.addAll(kernelService.liftMove(
-                    MotionDto.build((dto -> {
-                        dto.setLiftNo(device.getId().intValue());
-                        dto.setLev(sourceLev);
-                    }))
-                    , MotionDto.build((dto -> {
-                        dto.setLiftNo(device.getId().intValue());
-                        dto.setLev(targetLev);
-                    }))
-            ));
-        }
-
-        return true;
-    }
-
-    private Integer getLiftOperaLev(String opera, Task task, String redisKey) {
-        if (opera.equals("sourceLev")) {
-            return Utils.getLev(task.getOriginLoc());
-        } else if (opera.equals("targetLev")) {
-            return Utils.getLev(task.getDestLoc());
-        } else if (opera.equals("shuttleLev")) {
-            //鍙栧嚭缂撳瓨灏忚溅
-            Object shuttleDeviceObj = redisGet(redisKey, "shuttleDevice");
-            if (shuttleDeviceObj == null) {
-                throw new CoolException("绌挎杞︾紦瀛樹负绌�");
-            }
-            Device device = JSON.parseObject(String.valueOf(shuttleDeviceObj), Device.class);
-            if (device == null) {
-                throw new CoolException("绌挎杞﹁澶囦笉瀛樺湪");
-            }
-
-            ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, device.getId().intValue());
-            if (shuttleThread == null) {
-                throw new CoolException("绌挎杞︿笉瀛樺湪");
-            }
-
-            ShuttleProtocol shuttleProtocol = shuttleThread.getStatus();
-            if (shuttleProtocol == null) {
-                throw new CoolException("绌挎杞︿笉瀛樺湪");
-            }
-
-            return Utils.getLev(shuttleProtocol.getCurrentLocNo());
-        }
-
-        throw new CoolException("绫诲瀷寮傚父");
-    }
-
-    private boolean redisSet(String redisKey, String key, Object data) {
-        if (redisUtil.hasKey(redisKey)) {
-            Object obj = redisUtil.get(redisKey);
-            JSONObject object = JSON.parseObject(String.valueOf(obj));
-            object.put(key, data);
-            redisUtil.set(redisKey, JSON.toJSONString(object));
-        } else {
-            JSONObject object = new JSONObject();
-            object.put(key, data);
-            redisUtil.set(redisKey, JSON.toJSONString(object));
-        }
-        return true;
-    }
-
-    private Object redisGet(String redisKey, String key) {
-        if (redisUtil.hasKey(redisKey)) {
-            Object obj = redisUtil.get(redisKey);
-            JSONObject object = JSON.parseObject(String.valueOf(obj));
-            if (!object.containsKey(key)) {
-                return null;
-            }
-            return object.get(key);
-        }
-        return null;
-    }
 
 //    private boolean executeFlow(List<Map<String, Object>> list) {
 //        for (Map<String, Object> map : list) {
diff --git a/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/asrs/execute/LiftExecute.java b/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/asrs/execute/LiftExecute.java
new file mode 100644
index 0000000..156151e
--- /dev/null
+++ b/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/asrs/execute/LiftExecute.java
@@ -0,0 +1,112 @@
+package com.zy.asrs.wcs.asrs.execute;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.zy.asrs.framework.exception.CoolException;
+import com.zy.asrs.wcs.core.domain.dto.MotionDto;
+import com.zy.asrs.wcs.core.entity.Motion;
+import com.zy.asrs.wcs.core.entity.Task;
+import com.zy.asrs.wcs.core.kernel.KernelService;
+import com.zy.asrs.wcs.core.utils.RedisUtil;
+import com.zy.asrs.wcs.core.utils.Utils;
+import com.zy.asrs.wcs.rcs.cache.SlaveConnection;
+import com.zy.asrs.wcs.rcs.entity.Device;
+import com.zy.asrs.wcs.rcs.model.enums.SlaveType;
+import com.zy.asrs.wcs.rcs.model.protocol.LiftProtocol;
+import com.zy.asrs.wcs.rcs.model.protocol.ShuttleProtocol;
+import com.zy.asrs.wcs.rcs.thread.LiftThread;
+import com.zy.asrs.wcs.rcs.thread.ShuttleThread;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+@Component
+public class LiftExecute extends BaseExecute{
+
+    @Autowired
+    private RedisUtil redisUtil;
+    @Autowired
+    private KernelService kernelService;
+
+    public boolean execute(Task task, JSONObject data, String redisKey) {
+        Object object = redisGet(redisKey, "motionList");
+        List<Motion> motionList = JSON.parseArray(JSON.toJSONString(object), Motion.class);
+
+        Object liftDeviceObj = redisGet(redisKey, "liftDevice");
+        if (liftDeviceObj == null) {
+            throw new CoolException("鎻愬崌鏈虹紦瀛樹负绌�");
+        }
+
+        Device device = JSON.parseObject(String.valueOf(liftDeviceObj), Device.class);
+        if (device == null) {
+            throw new CoolException("鎻愬崌鏈鸿澶囦笉瀛樺湪");
+        }
+
+        LiftThread liftThread = (LiftThread) SlaveConnection.get(SlaveType.Lift, device.getId().intValue());
+        if (liftThread == null) {
+            throw new CoolException("鎻愬崌鏈轰笉瀛樺湪");
+        }
+
+        LiftProtocol liftProtocol = liftThread.getStatus();
+        if (liftProtocol == null) {
+            throw new CoolException("鎻愬崌鏈轰笉瀛樺湪");
+        }
+
+        JSONObject liftType = data.getJSONObject("liftType");
+        String opera = liftType.getString("liftOper");
+        if (opera.equals("move")) {
+            //鎻愬崌鏈哄崌闄�
+            String sourceLevStr = liftType.getString("sourceLev");
+            String targetLevStr = liftType.getString("targetLev");
+            Integer sourceLev = getLiftOperaLev(sourceLevStr, task, redisKey);
+            Integer targetLev = getLiftOperaLev(targetLevStr, task, redisKey);
+
+            motionList.addAll(kernelService.liftMove(
+                    MotionDto.build((dto -> {
+                        dto.setLiftNo(device.getId().intValue());
+                        dto.setLev(sourceLev);
+                    }))
+                    , MotionDto.build((dto -> {
+                        dto.setLiftNo(device.getId().intValue());
+                        dto.setLev(targetLev);
+                    }))
+            ));
+        }
+
+        return true;
+    }
+
+    private Integer getLiftOperaLev(String opera, Task task, String redisKey) {
+        if (opera.equals("sourceLev")) {
+            return Utils.getLev(task.getOriginLoc());
+        } else if (opera.equals("targetLev")) {
+            return Utils.getLev(task.getDestLoc());
+        } else if (opera.equals("shuttleLev")) {
+            //鍙栧嚭缂撳瓨灏忚溅
+            Object shuttleDeviceObj = redisGet(redisKey, "shuttleDevice");
+            if (shuttleDeviceObj == null) {
+                throw new CoolException("绌挎杞︾紦瀛樹负绌�");
+            }
+            Device device = JSON.parseObject(String.valueOf(shuttleDeviceObj), Device.class);
+            if (device == null) {
+                throw new CoolException("绌挎杞﹁澶囦笉瀛樺湪");
+            }
+
+            ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, device.getId().intValue());
+            if (shuttleThread == null) {
+                throw new CoolException("绌挎杞︿笉瀛樺湪");
+            }
+
+            ShuttleProtocol shuttleProtocol = shuttleThread.getStatus();
+            if (shuttleProtocol == null) {
+                throw new CoolException("绌挎杞︿笉瀛樺湪");
+            }
+
+            return Utils.getLev(shuttleProtocol.getCurrentLocNo());
+        }
+
+        throw new CoolException("绫诲瀷寮傚父");
+    }
+
+}
diff --git a/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/asrs/execute/ShuttleExecute.java b/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/asrs/execute/ShuttleExecute.java
new file mode 100644
index 0000000..62cb72f
--- /dev/null
+++ b/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/asrs/execute/ShuttleExecute.java
@@ -0,0 +1,80 @@
+package com.zy.asrs.wcs.asrs.execute;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.zy.asrs.framework.exception.CoolException;
+import com.zy.asrs.wcs.core.entity.Task;
+import com.zy.asrs.wcs.core.utils.RedisUtil;
+import com.zy.asrs.wcs.core.utils.ShuttleDispatcher;
+import com.zy.asrs.wcs.core.utils.Utils;
+import com.zy.asrs.wcs.rcs.cache.SlaveConnection;
+import com.zy.asrs.wcs.rcs.entity.Device;
+import com.zy.asrs.wcs.rcs.model.enums.SlaveType;
+import com.zy.asrs.wcs.rcs.model.protocol.ShuttleProtocol;
+import com.zy.asrs.wcs.rcs.thread.ShuttleThread;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component
+public class ShuttleExecute extends BaseExecute {
+
+    @Autowired
+    private RedisUtil redisUtil;
+    @Autowired
+    private ShuttleDispatcher shuttleDispatcher;
+
+    public boolean execute(Task task, JSONObject data, String redisKey) {
+        JSONObject shuttleType = data.getJSONObject("shuttleType");
+        String oper = shuttleType.getString("shuttleOper");
+        if (oper.equals("searchIdleShuttle")) {
+            //鎼滅储绌洪棽杞�
+            ShuttleThread shuttleThread = shuttleDispatcher.searchIdleShuttle(task);
+            if (shuttleThread == null) {
+                throw new CoolException("绌挎杞︿笉瀛樺湪");
+            }
+            //瀛樺叆缂撳瓨
+            redisSet(redisKey, "shuttleDevice", shuttleThread.getDevice());
+            return true;
+        } else if (oper.equals("judgeShuttleCurrentTaskLev")) {
+            //鍒ゆ柇灏忚溅鏄惁鍦ㄤ换鍔℃ゼ灞�
+            //鍙栧嚭缂撳瓨灏忚溅
+            Object shuttleDeviceObj = redisGet(redisKey, "shuttleDevice");
+            if (shuttleDeviceObj == null) {
+                throw new CoolException("绌挎杞︾紦瀛樹负绌�");
+            }
+            Device device = JSON.parseObject(String.valueOf(shuttleDeviceObj), Device.class);
+            if (device == null) {
+                throw new CoolException("绌挎杞﹁澶囦笉瀛樺湪");
+            }
+
+            ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, device.getId().intValue());
+            if (shuttleThread == null) {
+                throw new CoolException("绌挎杞︿笉瀛樺湪");
+            }
+
+            ShuttleProtocol shuttleProtocol = shuttleThread.getStatus();
+            if (shuttleProtocol == null) {
+                throw new CoolException("绌挎杞︿笉瀛樺湪");
+            }
+
+            //灏忚溅鍧愭爣
+            String shuttleLocNo = shuttleProtocol.getCurrentLocNo();
+            String taskLocNo = null;
+            if (task.getTaskSts() < 100) {
+                taskLocNo = task.getDestLoc();
+            } else if (task.getTaskSts() > 100 && task.getTaskSts() < 200) {
+                taskLocNo = task.getOriginLoc();
+            }
+
+            // 灏忚溅鍜屼换鍔℃ゼ灞備竴鑷�
+            if (Utils.getLev(shuttleLocNo) == Utils.getLev(taskLocNo)) {
+                return true;
+            } else {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+}
diff --git a/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/action/ShuttleAction.java b/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/action/ShuttleAction.java
index 9ca36f9..fc14bc2 100644
--- a/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/action/ShuttleAction.java
+++ b/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/action/ShuttleAction.java
@@ -11,6 +11,7 @@
 import com.zy.asrs.wcs.core.model.command.ShuttleAssignCommand;
 import com.zy.asrs.wcs.core.model.command.ShuttleCommand;
 import com.zy.asrs.wcs.core.model.command.ShuttleRedisCommand;
+import com.zy.asrs.wcs.core.model.enums.LocStsType;
 import com.zy.asrs.wcs.core.model.enums.MotionCtgType;
 import com.zy.asrs.wcs.core.model.enums.ShuttleCommandModeType;
 import com.zy.asrs.wcs.core.model.enums.ShuttleTaskModeType;
@@ -382,6 +383,50 @@
                     }
                 }
             }
+        } else if (shuttleProtocol.getMoveType() == 4) {//鍙栨斁璐�
+            Integer xCurrent = shuttleProtocol.getXCurrent();
+            if (xCurrent > shuttleProtocol.getXTarget()) {//褰揦鍊煎ぇ浜嶺鐩爣鍊�
+                shuttleProtocol.setXCurrent(shuttleProtocol.getXStart());
+                shuttleProtocol.setYCurrent(shuttleProtocol.getYStart());
+                return;
+            }
+
+            //鎼滅储鏈夎揣搴撲綅
+            List<Loc> list = locService.list(new LambdaQueryWrapper<Loc>()
+                    .eq(Loc::getLocSts, LocStsType.F.val())
+                    .eq(Loc::getHostId, device.getHostId())
+                    .eq(Loc::getStatus, 1));
+            if (list.isEmpty()) {
+                return;
+            }
+
+            Loc start = list.get(0);
+
+            Integer yCurrent = shuttleProtocol.getYCurrent();
+            String locNo = Utils.getLocNo(xCurrent, yCurrent, lev);
+            Loc target = locService.getOne(new LambdaQueryWrapper<Loc>()
+                    .eq(Loc::getLocNo, locNo)
+                    .eq(Loc::getHostId, device.getHostId())
+                    .eq(Loc::getStatus, 1));
+            if (target == null) {
+                shuttleProtocol.setXCurrent(shuttleProtocol.getXCurrent() + 1);
+                return;
+            }
+
+            if (target.getLocSts() != LocStsType.O.val()) {
+                shuttleProtocol.setXCurrent(shuttleProtocol.getXCurrent() + 1);
+                return;
+            }
+
+            //璋冨害鍘荤洰鏍囦綅缃�
+            if (shuttleProtocol.getCurrentLocNo().equals(target.getLocNo())) {
+                shuttleProtocol.setXCurrent(shuttleProtocol.getXCurrent() + 1);//灏忚溅鍜岀洰鏍囦綅缃竴鑷达紝璺宠繃
+            } else {
+                Task task = shuttleDispatcher.generateManuaTakeMoveTask(device, start.getLocNo(), target.getLocNo());
+                if(task != null) {//璋冨害鎴愬姛
+                    shuttleProtocol.setXCurrent(shuttleProtocol.getXCurrent() + 1);
+                }
+            }
         }
     }
 
diff --git a/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/controller/BasShuttleController.java b/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/controller/BasShuttleController.java
index fe88604..7b00292 100644
--- a/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/controller/BasShuttleController.java
+++ b/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/controller/BasShuttleController.java
@@ -192,6 +192,10 @@
         task.setStatus(1);
         task.setMemo("manual");
         task.setShuttleNo(param.getShuttleNo());
+
+        if (param.getShuttleTaskMode().equals("taskMove")) {
+            task.setRecordLoc("Y");//璁板綍搴撳瓨淇℃伅
+        }
         boolean result = taskService.save(task);
         if (!result) {
             return R.error();
diff --git a/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/controller/TaskLogController.java b/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/controller/TaskLogController.java
new file mode 100644
index 0000000..fd1731c
--- /dev/null
+++ b/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/controller/TaskLogController.java
@@ -0,0 +1,101 @@
+package com.zy.asrs.wcs.system.controller;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+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.wcs.common.annotation.OperationLog;
+import com.zy.asrs.wcs.common.domain.BaseParam;
+import com.zy.asrs.wcs.common.domain.KeyValVo;
+import com.zy.asrs.wcs.common.domain.PageParam;
+import com.zy.asrs.wcs.core.entity.TaskLog;
+import com.zy.asrs.wcs.core.service.TaskLogService;
+import com.zy.asrs.wcs.utils.ExcelUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+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;
+
+@RestController
+@RequestMapping("/api")
+public class TaskLogController extends BaseController {
+
+    @Autowired
+    private TaskLogService taskLogService;
+
+    @PreAuthorize("hasAuthority('core:taskLog:list')")
+    @PostMapping("/taskLog/page")
+    public R page(@RequestBody Map<String, Object> map) {
+        BaseParam baseParam = buildParam(map, BaseParam.class);
+        PageParam<TaskLog, BaseParam> pageParam = new PageParam<>(baseParam, TaskLog.class);
+        return R.ok().add(taskLogService.page(pageParam, pageParam.buildWrapper(true)));
+    }
+
+    @PreAuthorize("hasAuthority('core:taskLog:list')")
+    @PostMapping("/taskLog/list")
+    public R list(@RequestBody Map<String, Object> map) {
+        return R.ok().add(taskLogService.list());
+    }
+
+    @PreAuthorize("hasAuthority('core:taskLog:list')")
+    @GetMapping("/taskLog/{id}")
+    public R get(@PathVariable("id") Long id) {
+        return R.ok().add(taskLogService.getById(id));
+    }
+
+    @PreAuthorize("hasAuthority('core:taskLog:save')")
+    @OperationLog("娣诲姞浠诲姟鍘嗗彶璁板綍")
+    @PostMapping("/taskLog/save")
+    public R save(@RequestBody TaskLog taskLog) {
+        if (!taskLogService.save(taskLog)) {
+            return R.error("娣诲姞澶辫触");
+        }
+        return R.ok("娣诲姞鎴愬姛");
+    }
+
+    @PreAuthorize("hasAuthority('core:taskLog:update')")
+    @OperationLog("淇敼浠诲姟鍘嗗彶璁板綍")
+    @PostMapping("/taskLog/update")
+    public R update(@RequestBody TaskLog taskLog) {
+        if (!taskLogService.updateById(taskLog)) {
+            return R.error("淇敼澶辫触");
+        }
+        return R.ok("淇敼鎴愬姛");
+    }
+
+    @PreAuthorize("hasAuthority('core:taskLog:remove')")
+    @OperationLog("鍒犻櫎浠诲姟鍘嗗彶璁板綍")
+    @PostMapping("/taskLog/remove/{ids}")
+    public R remove(@PathVariable Long[] ids) {
+        if (!taskLogService.removeByIds(Arrays.asList(ids))) {
+            return R.error("鍒犻櫎澶辫触");
+        }
+        return R.ok("鍒犻櫎鎴愬姛");
+    }
+
+    @PreAuthorize("hasAuthority('core:taskLog:list')")
+    @PostMapping("/taskLog/query")
+    public R query(@RequestParam(required = false) String condition) {
+        List<KeyValVo> vos = new ArrayList<>();
+        LambdaQueryWrapper<TaskLog> wrapper = new LambdaQueryWrapper<>();
+        if (!Cools.isEmpty(condition)) {
+            wrapper.like(TaskLog::getName, condition);
+        }
+        taskLogService.page(new Page<>(1, 30), wrapper).getRecords().forEach(
+                item -> vos.add(new KeyValVo(item.getId(), item.getName()))
+        );
+        return R.ok().add(vos);
+    }
+
+    @PreAuthorize("hasAuthority('core:taskLog:list')")
+    @PostMapping("/taskLog/export")
+    public void export(@RequestBody Map<String, Object> map, HttpServletResponse response) throws Exception {
+        ExcelUtil.build(ExcelUtil.create(taskLogService.list(), TaskLog.class), response);
+    }
+
+}
diff --git a/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/entity/Task.java b/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/entity/Task.java
index 4ec07d8..f7591fb 100644
--- a/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/entity/Task.java
+++ b/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/entity/Task.java
@@ -255,9 +255,16 @@
     @ApiModelProperty(value= "AGV鍙�")
     private Integer agvNo;
 
+    /**
+     * 鏄惁璁板綍搴撲綅淇℃伅
+     */
+    @ApiModelProperty(value= "鏄惁璁板綍搴撲綅淇℃伅")
+    private String recordLoc;
+
+
     public Task() {}
 
-    public Task(String uuid, Long busId, String taskNo, String serialNum, String title, Long taskSts, Long taskCtg, Integer priority, String originSite, String originLoc, String destSite, String destLoc, Integer emptyMk, String zpallet, String phase, Date ioTime, Date startTime, Date endTime, Date exceptionTime, String exceptionDesc, Long hostId, Integer status, Integer deleted, Date createTime, Long createBy, Date updateTime, Long updateBy, String memo, Integer shuttleNo, Integer liftNo, Integer crnNo, Integer rgvNo, Integer agvNo) {
+    public Task(String uuid, Long busId, String taskNo, String serialNum, String title, Long taskSts, Long taskCtg, Integer priority, String originSite, String originLoc, String destSite, String destLoc, Integer emptyMk, String zpallet, String phase, Date ioTime, Date startTime, Date endTime, Date exceptionTime, String exceptionDesc, Long hostId, Integer status, Integer deleted, Date createTime, Long createBy, Date updateTime, Long updateBy, String memo, Integer shuttleNo, Integer liftNo, Integer crnNo, Integer rgvNo, Integer agvNo, String recordLoc) {
         this.uuid = uuid;
         this.busId = busId;
         this.taskNo = taskNo;
@@ -291,6 +298,7 @@
         this.crnNo = crnNo;
         this.rgvNo = rgvNo;
         this.agvNo = agvNo;
+        this.recordLoc = recordLoc;
     }
 
     //    Task task = new Task(
diff --git a/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/entity/TaskLog.java b/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/entity/TaskLog.java
new file mode 100644
index 0000000..c62a259
--- /dev/null
+++ b/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/entity/TaskLog.java
@@ -0,0 +1,222 @@
+package com.zy.asrs.wcs.core.entity;
+
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import com.zy.asrs.wcs.system.entity.Host;
+import com.zy.asrs.wcs.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;
+import com.zy.asrs.framework.common.SpringUtils;
+import com.zy.asrs.wcs.system.service.UserService;
+import com.zy.asrs.wcs.system.service.HostService;
+
+import java.io.Serializable;
+import java.util.Date;
+
+@Data
+@TableName("wcs_task_log")
+public class TaskLog implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * ID
+     */
+    @ApiModelProperty(value= "ID")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 缂栧彿
+     */
+    @ApiModelProperty(value= "缂栧彿")
+    private String uuid;
+
+    /**
+     * 鍚嶇О
+     */
+    @ApiModelProperty(value= "鍚嶇О")
+    private String name;
+
+    /**
+     * 鏍囪瘑
+     */
+    @ApiModelProperty(value= "鏍囪瘑")
+    private String flag;
+
+    /**
+     * 浠诲姟鍙�
+     */
+    @ApiModelProperty(value= "浠诲姟鍙�")
+    private String taskNo;
+
+    /**
+     * 浠诲姟鏁版嵁
+     */
+    @ApiModelProperty(value= "浠诲姟鏁版嵁")
+    private String taskData;
+
+    /**
+     * 鎵�灞炴満鏋�
+     */
+    @ApiModelProperty(value= "鎵�灞炴満鏋�")
+    private Long hostId;
+
+    /**
+     * 鐘舵�� 1: 姝e父  0: 绂佺敤  
+     */
+    @ApiModelProperty(value= "鐘舵�� 1: 姝e父  0: 绂佺敤  ")
+    private Integer status;
+
+    /**
+     * 鏄惁鍒犻櫎 1: 鏄�  0: 鍚�  
+     */
+    @ApiModelProperty(value= "鏄惁鍒犻櫎 1: 鏄�  0: 鍚�  ")
+    @TableLogic
+    private Integer deleted;
+
+    /**
+     * 娣诲姞鏃堕棿
+     */
+    @ApiModelProperty(value= "娣诲姞鏃堕棿")
+    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
+    private Date createTime;
+
+    /**
+     * 娣诲姞浜哄憳
+     */
+    @ApiModelProperty(value= "娣诲姞浜哄憳")
+    private Long createBy;
+
+    /**
+     * 淇敼鏃堕棿
+     */
+    @ApiModelProperty(value= "淇敼鏃堕棿")
+    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
+    private Date updateTime;
+
+    /**
+     * 淇敼浜哄憳
+     */
+    @ApiModelProperty(value= "淇敼浜哄憳")
+    private Long updateBy;
+
+    /**
+     * 澶囨敞
+     */
+    @ApiModelProperty(value= "澶囨敞")
+    private String memo;
+
+    public TaskLog() {}
+
+    public TaskLog(String uuid,String name,String flag,String taskNo,String taskData,Long hostId,Integer status,Integer deleted,Date createTime,Long createBy,Date updateTime,Long updateBy,String memo) {
+        this.uuid = uuid;
+        this.name = name;
+        this.flag = flag;
+        this.taskNo = taskNo;
+        this.taskData = taskData;
+        this.hostId = hostId;
+        this.status = status;
+        this.deleted = deleted;
+        this.createTime = createTime;
+        this.createBy = createBy;
+        this.updateTime = updateTime;
+        this.updateBy = updateBy;
+        this.memo = memo;
+    }
+
+//    TaskLog taskLog = new TaskLog(
+//            null,    // 缂栧彿
+//            null,    // 鍚嶇О
+//            null,    // 鏍囪瘑
+//            null,    // 浠诲姟鍙�
+//            null,    // 浠诲姟鏁版嵁
+//            null,    // 鎵�灞炴満鏋�
+//            null,    // 鐘舵��
+//            null,    // 鏄惁鍒犻櫎
+//            null,    // 娣诲姞鏃堕棿
+//            null,    // 娣诲姞浜哄憳
+//            null,    // 淇敼鏃堕棿
+//            null,    // 淇敼浜哄憳
+//            null    // 澶囨敞
+//    );
+
+    public String getHostId$(){
+        HostService service = SpringUtils.getBean(HostService.class);
+        Host host = service.getById(this.hostId);
+        if (!Cools.isEmpty(host)){
+            return String.valueOf(host.getName());
+        }
+        return null;
+    }
+
+    public String getStatus$(){
+        if (null == this.status){ return null; }
+        switch (this.status){
+            case 1:
+                return "姝e父";
+            case 0:
+                return "绂佺敤";
+            default:
+                return String.valueOf(this.status);
+        }
+    }
+
+    public String getDeleted$(){
+        if (null == this.deleted){ return null; }
+        switch (this.deleted){
+            case 1:
+                return "鏄�";
+            case 0:
+                return "鍚�";
+            default:
+                return String.valueOf(this.deleted);
+        }
+    }
+
+    public String getCreateTime$(){
+        if (Cools.isEmpty(this.createTime)){
+            return "";
+        }
+        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.createTime);
+    }
+
+    public String getCreateBy$(){
+        UserService service = SpringUtils.getBean(UserService.class);
+        User user = service.getById(this.createBy);
+        if (!Cools.isEmpty(user)){
+            return String.valueOf(user.getNickname());
+        }
+        return null;
+    }
+
+    public String getUpdateTime$(){
+        if (Cools.isEmpty(this.updateTime)){
+            return "";
+        }
+        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.updateTime);
+    }
+
+    public String getUpdateBy$(){
+        UserService service = SpringUtils.getBean(UserService.class);
+        User user = service.getById(this.updateBy);
+        if (!Cools.isEmpty(user)){
+            return String.valueOf(user.getNickname());
+        }
+        return null;
+    }
+
+
+}
diff --git a/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/mapper/TaskLogMapper.java b/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/mapper/TaskLogMapper.java
new file mode 100644
index 0000000..b266853
--- /dev/null
+++ b/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/mapper/TaskLogMapper.java
@@ -0,0 +1,12 @@
+package com.zy.asrs.wcs.core.mapper;
+
+import com.zy.asrs.wcs.core.entity.TaskLog;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+import org.springframework.stereotype.Repository;
+
+@Mapper
+@Repository
+public interface TaskLogMapper extends BaseMapper<TaskLog> {
+
+}
diff --git a/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/mapper/TaskMapper.java b/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/mapper/TaskMapper.java
index e560ada..46318d6 100644
--- a/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/mapper/TaskMapper.java
+++ b/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/mapper/TaskMapper.java
@@ -38,6 +38,8 @@
 
     Task selectMoveWorking(Integer shuttleNo);
 
+    Task selectManualWorking(Integer shuttleNo);
+
     List<Task> selectWorkingByShuttle(Integer shuttleNo);
 
     List<Task> selectWorkingByLift(Integer liftNo);
diff --git a/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/service/TaskLogService.java b/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/service/TaskLogService.java
new file mode 100644
index 0000000..03c1946
--- /dev/null
+++ b/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/service/TaskLogService.java
@@ -0,0 +1,8 @@
+package com.zy.asrs.wcs.core.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.zy.asrs.wcs.core.entity.TaskLog;
+
+public interface TaskLogService extends IService<TaskLog> {
+
+}
diff --git a/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/service/TaskService.java b/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/service/TaskService.java
index 47ecd7a..38ba46e 100644
--- a/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/service/TaskService.java
+++ b/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/service/TaskService.java
@@ -36,6 +36,8 @@
 
     Task selectMoveWorking(Integer shuttleNo);
 
+    Task selectManualWorking(Integer shuttleNo);
+
     List<Task> selectWorkingByShuttle(Integer shuttleNo);
 
     List<Task> selectWorkingByLift(Integer liftNo);
diff --git a/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/service/impl/TaskLogServiceImpl.java b/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/service/impl/TaskLogServiceImpl.java
new file mode 100644
index 0000000..c0d770c
--- /dev/null
+++ b/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/service/impl/TaskLogServiceImpl.java
@@ -0,0 +1,12 @@
+package com.zy.asrs.wcs.core.service.impl;
+
+import com.zy.asrs.wcs.core.mapper.TaskLogMapper;
+import com.zy.asrs.wcs.core.entity.TaskLog;
+import com.zy.asrs.wcs.core.service.TaskLogService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+@Service("taskLogService")
+public class TaskLogServiceImpl extends ServiceImpl<TaskLogMapper, TaskLog> implements TaskLogService {
+
+}
diff --git a/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/service/impl/TaskServiceImpl.java b/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/service/impl/TaskServiceImpl.java
index 8004414..cb3a328 100644
--- a/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/service/impl/TaskServiceImpl.java
+++ b/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/service/impl/TaskServiceImpl.java
@@ -117,6 +117,11 @@
     }
 
     @Override
+    public Task selectManualWorking(Integer shuttleNo) {
+        return this.baseMapper.selectManualWorking(shuttleNo);
+    }
+
+    @Override
     public List<Task> selectWorkingByShuttle(Integer shuttleNo) {
         return this.baseMapper.selectWorkingByShuttle(shuttleNo);
     }
diff --git a/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/timer/TaskTimer.java b/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/timer/TaskTimer.java
new file mode 100644
index 0000000..cf5f724
--- /dev/null
+++ b/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/timer/TaskTimer.java
@@ -0,0 +1,98 @@
+package com.zy.asrs.wcs.core.timer;
+
+import com.alibaba.fastjson.JSON;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.zy.asrs.wcs.core.entity.Loc;
+import com.zy.asrs.wcs.core.entity.Task;
+import com.zy.asrs.wcs.core.entity.TaskLog;
+import com.zy.asrs.wcs.core.model.enums.LocStsType;
+import com.zy.asrs.wcs.core.model.enums.TaskStsType;
+import com.zy.asrs.wcs.core.service.LocService;
+import com.zy.asrs.wcs.core.service.TaskLogService;
+import com.zy.asrs.wcs.core.service.TaskService;
+import lombok.extern.slf4j.Slf4j;
+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 java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+@Slf4j
+@Component
+public class TaskTimer {
+
+    @Autowired
+    private TaskService taskService;
+    @Autowired
+    private TaskLogService taskLogService;
+    @Autowired
+    private LocService locService;
+
+    @Scheduled(cron = "0/1 * * * * ? ")
+    @Transactional
+    public synchronized void clearCompletedTask() {
+        ArrayList<Long> taskSts = new ArrayList<>();
+        taskSts.add(TaskStsType.COMPLETE_INBOUND.sts);
+        taskSts.add(TaskStsType.COMPLETE_OUTBOUND.sts);
+        taskSts.add(TaskStsType.COMPLETE_CHARGE.sts);
+        taskSts.add(TaskStsType.COMPLETE_MOVE.sts);
+        taskSts.add(TaskStsType.COMPLETE_MANUAL.sts);
+
+        List<Task> tasks = taskService.list(new LambdaQueryWrapper<Task>()
+                .eq(Task::getStatus, 1)
+                .in(Task::getTaskSts, taskSts));
+        for (Task task : tasks) {
+            //璁板綍搴撳瓨淇℃伅
+            updateRecordLoc(task);
+            //浠诲姟杞巻鍙叉。
+            saveTaskLog(task);
+        }
+    }
+
+    //鏇存柊搴撳瓨淇℃伅
+    @Transactional
+    public void updateRecordLoc(Task task) {
+        if (task.getRecordLoc().equals("Y")) {//璁板綍搴撳瓨淇℃伅
+            //婧愬簱浣� => 绌哄簱
+            //鐩爣搴撲綅 => 鍦ㄥ簱
+            Loc originLoc = locService.selectByLocNo(task.getOriginLoc());
+            if (originLoc != null) {
+                originLoc.setLocSts(LocStsType.O.val());
+                locService.updateById(originLoc);
+            }
+
+            Loc destLoc = locService.selectByLocNo(task.getDestLoc());
+            if (destLoc != null) {
+                destLoc.setLocSts(LocStsType.F.val());
+                locService.updateById(destLoc);
+            }
+        } else if (task.getRecordLoc().equals("record-dest")) {//鍙褰曠洰鏍囧簱浣嶄俊鎭�
+            //鐩爣搴撲綅 => 鍦ㄥ簱
+            Loc destLoc = locService.selectByLocNo(task.getDestLoc());
+            if (destLoc != null) {
+                destLoc.setLocSts(LocStsType.F.val());
+                locService.updateById(destLoc);
+            }
+        }
+    }
+
+    //鏇存柊鍘嗗彶妗�
+    @Transactional
+    public void saveTaskLog(Task task) {
+        //鍒涘缓鍘嗗彶妗�
+        Date date = new Date();
+        TaskLog taskLog = new TaskLog();
+        taskLog.setTaskNo(task.getTaskNo());
+        taskLog.setTaskData(JSON.toJSONString(task));
+        taskLog.setCreateTime(date);
+        taskLog.setUpdateTime(date);
+        taskLogService.save(taskLog);
+
+        //鍒犻櫎婧愪换鍔�
+        taskService.removeById(task.getId());
+    }
+
+}
diff --git a/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/utils/ShuttleDispatcher.java b/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/utils/ShuttleDispatcher.java
index 19b2732..93b8596 100644
--- a/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/utils/ShuttleDispatcher.java
+++ b/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/utils/ShuttleDispatcher.java
@@ -4,6 +4,7 @@
 import com.alibaba.fastjson.JSONArray;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.zy.asrs.framework.common.Cools;
+import com.zy.asrs.framework.common.R;
 import com.zy.asrs.framework.common.SnowflakeIdWorker;
 import com.zy.asrs.framework.exception.CoolException;
 import com.zy.asrs.wcs.core.entity.*;
@@ -198,6 +199,61 @@
         return task;
     }
 
+    //鐢熸垚鎵嬪姩鍙栨斁璐т换鍔�
+    public synchronized Task generateManuaTakeMoveTask(Device device, String sourceLocNo, String locNo) {
+        // 宸叉湁鎵嬪姩浠诲姟
+        if (taskService.selectManualWorking(Integer.valueOf(device.getDeviceNo())) != null) {
+            return null;
+        }
+
+        //鑾峰彇鎵嬪姩浠诲姟绫诲瀷
+        TaskCtg taskCtg = taskCtgService.getOne(new LambdaQueryWrapper<TaskCtg>()
+                .eq(TaskCtg::getFlag, "MANUAL")
+                .eq(TaskCtg::getStatus, 1));
+        if (taskCtg == null) {
+            return null;
+        }
+
+        ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, device.getId().intValue());
+        if (shuttleThread == null) {
+            return null;
+        }
+
+        Task task = new Task();
+        task.setUuid(String.valueOf(snowflakeIdWorker.nextId()));
+        task.setTaskNo(String.valueOf(Utils.getTaskNo("MANUAL")));
+        task.setTaskSts(TaskStsType.NEW_MANUAL.sts);
+        task.setTaskCtg(taskCtg.getId());
+        task.setPriority(10);
+        task.setOriginSite(null);
+        task.setOriginLoc(sourceLocNo);
+        task.setDestSite("takeMove");
+        task.setDestLoc(locNo);
+        task.setIoTime(new Date());
+        task.setStartTime(new Date());
+        task.setStatus(1);
+        task.setMemo("manual");
+        task.setShuttleNo(Integer.valueOf(device.getDeviceNo()));
+        task.setRecordLoc("Y");//璁板綍搴撳瓨淇℃伅
+
+        // generate motion list
+        List<Motion> motionList = analyzeService.generateShuttleManualMotion(task);
+        if (Cools.isEmpty(motionList)) {
+            News.error("淇濆瓨{}鍙峰洓鍚戠┛姊溅鎵嬪姩浠诲姟澶辫触!!!", device.getDeviceNo());
+            return null;
+        }
+        motionService.batchInsert(motionList, task.getUuid(), Integer.valueOf(task.getTaskNo()), device.getHostId());
+
+        task.setTaskSts(TaskStsType.ANALYZE_MANUAL.sts);
+
+        if (!taskService.save(task)) {
+            News.error("淇濆瓨{}鍙峰洓鍚戠┛姊溅鎵嬪姩浠诲姟澶辫触!!!", device.getDeviceNo());
+            return null;
+        }
+
+        return task;
+    }
+
     /**
      * 鎼滅储閬胯搴撲綅锛岄�氳繃灏忚溅鍙峰拰鐩爣搴撲綅
      */
diff --git a/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/utils/CodeBuilder.java b/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/utils/CodeBuilder.java
index 4d191e9..73b2398 100644
--- a/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/utils/CodeBuilder.java
+++ b/zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/utils/CodeBuilder.java
@@ -15,15 +15,15 @@
         generator.frontendPrefixPath = "zy-asrs-flow/";
 
         generator.sqlOsType = SqlOsType.MYSQL;
-        generator.url="127.0.0.1:3306/asrs";
+        generator.url="192.168.4.15:3306/asrs";
         generator.username="root";
-        generator.password="root";
+        generator.password="xltys1995";
 //        generator.url="47.97.1.152:51433;databasename=jkasrs";
 //        generator.username="sa";
 //        generator.password="Zoneyung@zy56$";
 
-        generator.table="wcs_device_barcode";
-        generator.tableName="鏉$爜璁惧";
+        generator.table="wcs_task_log";
+        generator.tableName="浠诲姟鍘嗗彶璁板綍";
         generator.packagePath="com.zy.asrs.wcs.core";
 
         generator.build();
diff --git a/zy-asrs-wcs/src/main/java/taskLog.sql b/zy-asrs-wcs/src/main/java/taskLog.sql
new file mode 100644
index 0000000..6cd1aff
--- /dev/null
+++ b/zy-asrs-wcs/src/main/java/taskLog.sql
@@ -0,0 +1,9 @@
+-- save taskLog record
+-- mysql
+insert into `sys_menu` ( `name`, `parent_id`, `route`, `component`, `type`, `sort`, `host_id`, `status`) values ( '浠诲姟鍘嗗彶璁板綍绠$悊', '0', '/core/taskLog', '/core/taskLog', '0' , '0', '1' , '1');
+
+insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `host_id`, `status`) values ( '鏌ヨ浠诲姟鍘嗗彶璁板綍', '', '1', 'core:taskLog:list', '0', '1', '1');
+insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `host_id`, `status`) values ( '娣诲姞浠诲姟鍘嗗彶璁板綍', '', '1', 'core:taskLog:save', '1', '1', '1');
+insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `host_id`, `status`) values ( '淇敼浠诲姟鍘嗗彶璁板綍', '', '1', 'core:taskLog:update', '2', '1', '1');
+insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `host_id`, `status`) values ( '鍒犻櫎浠诲姟鍘嗗彶璁板綍', '', '1', 'core:taskLog:remove', '3', '1', '1');
+
diff --git a/zy-asrs-wcs/src/main/resources/mapper/core/TaskLogMapper.xml b/zy-asrs-wcs/src/main/resources/mapper/core/TaskLogMapper.xml
new file mode 100644
index 0000000..a4e1b86
--- /dev/null
+++ b/zy-asrs-wcs/src/main/resources/mapper/core/TaskLogMapper.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.zy.asrs.wcs.core.mapper.TaskLogMapper">
+
+</mapper>
diff --git a/zy-asrs-wcs/src/main/resources/mapper/core/TaskMapper.xml b/zy-asrs-wcs/src/main/resources/mapper/core/TaskMapper.xml
index 4558156..a4df9e5 100644
--- a/zy-asrs-wcs/src/main/resources/mapper/core/TaskMapper.xml
+++ b/zy-asrs-wcs/src/main/resources/mapper/core/TaskMapper.xml
@@ -91,6 +91,13 @@
         order by priority desc,start_time,task_no asc
     </select>
 
+    <select id="selectManualWorking" resultType="com.zy.asrs.wcs.core.entity.Task">
+        select * from wcs_task
+        where task_sts in (401,402,403)
+        and shuttle_no = #{shuttleNo}
+        order by priority desc,start_time,task_no asc
+    </select>
+
     <select id="selectWorkingByShuttle" resultType="com.zy.asrs.wcs.core.entity.Task">
         select * from wcs_task
         where task_sts in (1,2,3,101,102,103,301,302,303,401,402,403)

--
Gitblit v1.9.1