Junjie
2024-05-18 13b690312e3397305fb20c2d3dc60be9e9452049
Merge remote-tracking branch 'origin/Four-Way-Rack' into Four-Way-Rack
12个文件已修改
14个文件已添加
1693 ■■■■ 已修改文件
zy-asrs-flow/src/pages/core/taskLog/components/edit.jsx 159 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-flow/src/pages/core/taskLog/index.jsx 454 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-flow/src/pages/device/shuttle/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-flow/src/pages/map/drawer/shuttle/handle.jsx 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/asrs/execute/BaseExecute.java 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/asrs/execute/DevpExecute.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/asrs/execute/FlowExecute.java 202 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/asrs/execute/LiftExecute.java 112 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/asrs/execute/ShuttleExecute.java 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/action/ShuttleAction.java 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/controller/BasShuttleController.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/controller/TaskLogController.java 101 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/entity/Task.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/entity/TaskLog.java 222 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/mapper/TaskLogMapper.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/mapper/TaskMapper.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/service/TaskLogService.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/service/TaskService.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/service/impl/TaskLogServiceImpl.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/service/impl/TaskServiceImpl.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/timer/TaskTimer.java 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/utils/ShuttleDispatcher.java 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/utils/CodeBuilder.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wcs/src/main/java/taskLog.sql 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wcs/src/main/resources/mapper/core/TaskLogMapper.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wcs/src/main/resources/mapper/core/TaskMapper.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-flow/src/pages/core/taskLog/components/edit.jsx
New file
@@ -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: '正常', 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;
zy-asrs-flow/src/pages/core/taskLog/index.jsx
New file
@@ -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: '正在添加' }));
    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: '正在更新' }));
    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: '正在删除' }));
    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: '正在导出' }));
    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: '正常', 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;
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>
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>
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/asrs/execute/BaseExecute.java
New file
@@ -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;
    }
}
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/asrs/execute/DevpExecute.java
New file
@@ -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;
    }
}
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) {
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/asrs/execute/LiftExecute.java
New file
@@ -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("类型异常");
    }
}
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/asrs/execute/ShuttleExecute.java
New file
@@ -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;
    }
}
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()) {//当X值大于X目标值
                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);
                }
            }
        }
    }
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();
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/controller/TaskLogController.java
New file
@@ -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);
    }
}
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(
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/entity/TaskLog.java
New file
@@ -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: 正常  0: 禁用
     */
    @ApiModelProperty(value= "状态 1: 正常  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 "正常";
            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;
    }
}
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/mapper/TaskLogMapper.java
New file
@@ -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> {
}
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);
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/service/TaskLogService.java
New file
@@ -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> {
}
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);
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/service/impl/TaskLogServiceImpl.java
New file
@@ -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 {
}
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);
    }
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/timer/TaskTimer.java
New file
@@ -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());
    }
}
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;
    }
    /**
     * 搜索避让库位,通过小车号和目标库位
     */
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();
zy-asrs-wcs/src/main/java/taskLog.sql
New file
@@ -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');
zy-asrs-wcs/src/main/resources/mapper/core/TaskLogMapper.xml
New file
@@ -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>
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)