14ddde5c41d8d98fc9b67ebae72b6cdbca73330b..da20b84fb1dbb266939deff9fd52f9a16f4e32fa
11 小时以前 zjj
#生成入库任务优化
da20b8 对比 | 目录
12 小时以前 zjj
#堆垛机生成入库任务ok
0a0f8d 对比 | 目录
15 小时以前 zjj
#找库位方法
d55404 对比 | 目录
18 小时以前 skyouc
动态字段拦截修改优化
d88eed 对比 | 目录
27个文件已添加
1 文件已重命名
6个文件已删除
6个文件已修改
2236 ■■■■ 已修改文件
rsf-admin/.env 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/basDevice/BasDeviceCreate.jsx 138 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/basDevice/BasDeviceEdit.jsx 110 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/basDevice/BasDeviceList.jsx 158 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/basDevice/BasDevicePanel.jsx 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/basDevice/index.jsx 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/basDevice.sql 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/api/controller/WcsController.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/api/controller/params/TaskInParam.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/api/controller/pda/MobileController.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/api/controller/pda/pdaOutStockController.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/api/entity/dto/InTaskMsgDto.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/api/entity/dto/LocTypeDto.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/api/service/PdaOutStockService.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/api/service/WcsService.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/PdaOutStockServiceImpl.java 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/WcsServiceImpl.java 561 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/api/utils/LocUtils.java 166 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/api/utils/SlaveProperties.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/common/config/WebMvcConfig.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/common/interceptor/DynamicFieldsInterceptor.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/common/interceptor/severlet/CustomParameterFilter.java 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/common/interceptor/severlet/DynamicFieldsInterceptor.java 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/common/interceptor/severlet/ParameterAddableRequest.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/common/interceptor/severlet/ParameterAddingFilter.java 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/common/security/SecurityConfig.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/BasDeviceController.java 110 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/BasDevice.java 154 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/DeviceBind.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/Loc.java 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/mapper/BasDeviceMapper.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/BasDeviceService.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/BasDeviceServiceImpl.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/order.sql 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/orderItem.sql 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/stockItem.sql 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/wave.sql 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/waveItem.sql 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/resources/application.yml 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/resources/mapper/manager/BasDeviceMapper.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/.env
@@ -1,3 +1,3 @@
VITE_BASE_IP=192.168.4.56
VITE_BASE_IP=127.0.0.1
# VITE_BASE_IP=47.76.147.249
VITE_BASE_PORT=8080
rsf-admin/src/page/basDevice/BasDeviceCreate.jsx
New file
@@ -0,0 +1,138 @@
import React, { useState, useRef, useEffect, useMemo } from "react";
import {
    CreateBase,
    useTranslate,
    TextInput,
    NumberInput,
    BooleanInput,
    DateInput,
    SaveButton,
    SelectInput,
    ReferenceInput,
    ReferenceArrayInput,
    AutocompleteInput,
    Toolbar,
    required,
    useDataProvider,
    useNotify,
    Form,
    useCreateController,
} from 'react-admin';
import {
    Dialog,
    DialogActions,
    DialogContent,
    DialogTitle,
    Stack,
    Grid,
    Box,
} from '@mui/material';
import DialogCloseButton from "../components/DialogCloseButton";
import StatusSelectInput from "../components/StatusSelectInput";
import MemoInput from "../components/MemoInput";
const BasDeviceCreate = (props) => {
    const { open, setOpen } = props;
    const translate = useTranslate();
    const notify = useNotify();
    const handleClose = (event, reason) => {
        if (reason !== "backdropClick") {
            setOpen(false);
        }
    };
    const handleSuccess = async (data) => {
        setOpen(false);
        notify('common.response.success');
    };
    const handleError = async (error) => {
        notify(error.message || 'common.response.fail', { type: 'error', messageArgs: { _: error.message } });
    };
    return (
        <>
            <CreateBase
                record={{}}
                transform={(data) => {
                    return data;
                }}
                mutationOptions={{ onSuccess: handleSuccess, onError: handleError }}
            >
                <Dialog
                    open={open}
                    onClose={handleClose}
                    aria-labelledby="form-dialog-title"
                    fullWidth
                    disableRestoreFocus
                    maxWidth="md"   // 'xs' | 'sm' | 'md' | 'lg' | 'xl'
                >
                    <Form>
                        <DialogTitle id="form-dialog-title" sx={{
                            position: 'sticky',
                            top: 0,
                            backgroundColor: 'background.paper',
                            zIndex: 1000
                        }}
                        >
                            {translate('create.title')}
                            <Box sx={{ position: 'absolute', top: 8, right: 8, zIndex: 1001 }}>
                                <DialogCloseButton onClose={handleClose} />
                            </Box>
                        </DialogTitle>
                        <DialogContent sx={{ mt: 2 }}>
                            <Grid container rowSpacing={2} columnSpacing={2}>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <NumberInput
                                        label="table.field.basDevice.deviceNo"
                                        source="deviceNo"
                                        autoFocus
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <TextInput
                                        label="table.field.basDevice.inEnable"
                                        source="inEnable"
                                        parse={v => v}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <TextInput
                                        label="table.field.basDevice.outEnable"
                                        source="outEnable"
                                        parse={v => v}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <TextInput
                                        label="table.field.basDevice.origin"
                                        source="origin"
                                        parse={v => v}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <StatusSelectInput />
                                </Grid>
                                <Grid item xs={12} display="flex" gap={1}>
                                    <Stack direction="column" spacing={1} width={'100%'}>
                                        <MemoInput />
                                    </Stack>
                                </Grid>
                            </Grid>
                        </DialogContent>
                        <DialogActions sx={{ position: 'sticky', bottom: 0, backgroundColor: 'background.paper', zIndex: 1000 }}>
                            <Toolbar sx={{ width: '100%', justifyContent: 'space-between' }}  >
                                <SaveButton />
                            </Toolbar>
                        </DialogActions>
                    </Form>
                </Dialog>
            </CreateBase>
        </>
    )
}
export default BasDeviceCreate;
rsf-admin/src/page/basDevice/BasDeviceEdit.jsx
New file
@@ -0,0 +1,110 @@
import React, { useState, useRef, useEffect, useMemo } from "react";
import {
    Edit,
    SimpleForm,
    FormDataConsumer,
    useTranslate,
    TextInput,
    NumberInput,
    BooleanInput,
    DateInput,
    SelectInput,
    ReferenceInput,
    ReferenceArrayInput,
    AutocompleteInput,
    SaveButton,
    Toolbar,
    Labeled,
    NumberField,
    required,
    useRecordContext,
    DeleteButton,
} from 'react-admin';
import { useWatch, useFormContext } from "react-hook-form";
import { Stack, Grid, Box, Typography } from '@mui/material';
import * as Common from '@/utils/common';
import { EDIT_MODE, REFERENCE_INPUT_PAGESIZE } from '@/config/setting';
import EditBaseAside from "../components/EditBaseAside";
import CustomerTopToolBar from "../components/EditTopToolBar";
import MemoInput from "../components/MemoInput";
import StatusSelectInput from "../components/StatusSelectInput";
const FormToolbar = () => {
    const { getValues } = useFormContext();
    return (
        <Toolbar sx={{ justifyContent: 'space-between' }}>
            <SaveButton />
            <DeleteButton mutationMode="optimistic" />
        </Toolbar>
    )
}
const BasDeviceEdit = () => {
    const translate = useTranslate();
    return (
        <Edit
            redirect="list"
            mutationMode={EDIT_MODE}
            actions={<CustomerTopToolBar />}
            aside={<EditBaseAside />}
        >
            <SimpleForm
                shouldUnregister
                warnWhenUnsavedChanges
                toolbar={<FormToolbar />}
                mode="onTouched"
                defaultValues={{}}
            // validate={(values) => { }}
            >
                <Grid container width={{ xs: '100%', xl: '80%' }} rowSpacing={3} columnSpacing={3}>
                    <Grid item xs={12} md={8}>
                        <Typography variant="h6" gutterBottom>
                            {translate('common.edit.title.main')}
                        </Typography>
                        <Stack direction='row' gap={2}>
                            <NumberInput
                                label="table.field.basDevice.deviceNo"
                                source="deviceNo"
                                autoFocus
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <TextInput
                                label="table.field.basDevice.inEnable"
                                source="inEnable"
                                parse={v => v}
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <TextInput
                                label="table.field.basDevice.outEnable"
                                source="outEnable"
                                parse={v => v}
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <TextInput
                                label="table.field.basDevice.origin"
                                source="origin"
                                parse={v => v}
                            />
                        </Stack>
                    </Grid>
                    <Grid item xs={12} md={4}>
                        <Typography variant="h6" gutterBottom>
                            {translate('common.edit.title.common')}
                        </Typography>
                        <StatusSelectInput />
                        <Box mt="2em" />
                        <MemoInput />
                    </Grid>
                </Grid>
            </SimpleForm>
        </Edit >
    )
}
export default BasDeviceEdit;
rsf-admin/src/page/basDevice/BasDeviceList.jsx
New file
@@ -0,0 +1,158 @@
import React, { useState, useRef, useEffect, useMemo, useCallback } from "react";
import { useNavigate } from 'react-router-dom';
import {
    List,
    DatagridConfigurable,
    SearchInput,
    TopToolbar,
    SelectColumnsButton,
    EditButton,
    FilterButton,
    CreateButton,
    ExportButton,
    BulkDeleteButton,
    WrapperField,
    useRecordContext,
    useTranslate,
    useNotify,
    useListContext,
    FunctionField,
    TextField,
    NumberField,
    DateField,
    BooleanField,
    ReferenceField,
    TextInput,
    DateTimeInput,
    DateInput,
    SelectInput,
    NumberInput,
    ReferenceInput,
    ReferenceArrayInput,
    AutocompleteInput,
    DeleteButton,
} from 'react-admin';
import { Box, Typography, Card, Stack } from '@mui/material';
import { styled } from '@mui/material/styles';
import BasDeviceCreate from "./BasDeviceCreate";
import BasDevicePanel from "./BasDevicePanel";
import EmptyData from "../components/EmptyData";
import MyCreateButton from "../components/MyCreateButton";
import MyExportButton from '../components/MyExportButton';
import PageDrawer from "../components/PageDrawer";
import MyField from "../components/MyField";
import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting';
import * as Common from '@/utils/common';
const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
    '& .css-1vooibu-MuiSvgIcon-root': {
        height: '.9em'
    },
    '& .RaDatagrid-row': {
        cursor: 'auto'
    },
    '& .column-name': {
    },
    '& .opt': {
        width: 200
    },
}));
const filters = [
    <SearchInput source="condition" alwaysOn />,
    <DateInput label='common.time.after' source="timeStart" alwaysOn />,
    <DateInput label='common.time.before' source="timeEnd" alwaysOn />,
    <NumberInput source="deviceNo" label="table.field.basDevice.deviceNo" />,
    <TextInput source="inEnable" label="table.field.basDevice.inEnable" />,
    <TextInput source="outEnable" label="table.field.basDevice.outEnable" />,
    <TextInput source="origin" label="table.field.basDevice.origin" />,
    <TextInput label="common.field.memo" source="memo" />,
    <SelectInput
        label="common.field.status"
        source="status"
        choices={[
            { id: '1', name: 'common.enums.statusTrue' },
            { id: '0', name: 'common.enums.statusFalse' },
        ]}
        resettable
    />,
]
const BasDeviceList = () => {
    const translate = useTranslate();
    const [createDialog, setCreateDialog] = useState(false);
    const [drawerVal, setDrawerVal] = useState(false);
    return (
        <Box display="flex">
            <List
                sx={{
                    flexGrow: 1,
                    transition: (theme) =>
                        theme.transitions.create(['all'], {
                            duration: theme.transitions.duration.enteringScreen,
                        }),
                    marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
                }}
                title={"menu.basDevice"}
                empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
                filters={filters}
                sort={{ field: "create_time", order: "desc" }}
                actions={(
                    <TopToolbar>
                        <FilterButton />
                        <MyCreateButton onClick={() => { setCreateDialog(true) }} />
                        <SelectColumnsButton preferenceKey='basDevice' />
                        <MyExportButton />
                    </TopToolbar>
                )}
                perPage={DEFAULT_PAGE_SIZE}
            >
                <StyledDatagrid
                    preferenceKey='basDevice'
                    bulkActionButtons={() => <BulkDeleteButton mutationMode={OPERATE_MODE} />}
                    rowClick={(id, resource, record) => false}
                    expand={() => <BasDevicePanel />}
                    expandSingle={true}
                    omit={['id', 'createTime', 'createBy', 'memo']}
                >
                    <NumberField source="id" />
                    <NumberField source="deviceNo" label="table.field.basDevice.deviceNo" />
                    <TextField source="inEnable" label="table.field.basDevice.inEnable" />
                    <TextField source="outEnable" label="table.field.basDevice.outEnable" />
                    <TextField source="origin" label="table.field.basDevice.origin" />
                    <ReferenceField source="updateBy" label="common.field.updateBy" reference="user" link={false} sortable={false}>
                        <TextField source="nickname" />
                    </ReferenceField>
                    <DateField source="updateTime" label="common.field.updateTime" showTime />
                    <ReferenceField source="createBy" label="common.field.createBy" reference="user" link={false} sortable={false}>
                        <TextField source="nickname" />
                    </ReferenceField>
                    <DateField source="createTime" label="common.field.createTime" showTime />
                    <BooleanField source="statusBool" label="common.field.status" sortable={false} />
                    <TextField source="memo" label="common.field.memo" sortable={false} />
                    <WrapperField cellClassName="opt" label="common.field.opt">
                        <EditButton sx={{ padding: '1px', fontSize: '.75rem' }} />
                        <DeleteButton sx={{ padding: '1px', fontSize: '.75rem' }} mutationMode={OPERATE_MODE} />
                    </WrapperField>
                </StyledDatagrid>
            </List>
            <BasDeviceCreate
                open={createDialog}
                setOpen={setCreateDialog}
            />
            <PageDrawer
                title='BasDevice Detail'
                drawerVal={drawerVal}
                setDrawerVal={setDrawerVal}
            >
            </PageDrawer>
        </Box>
    )
}
export default BasDeviceList;
rsf-admin/src/page/basDevice/BasDevicePanel.jsx
New file
@@ -0,0 +1,75 @@
import React, { useState, useRef, useEffect, useMemo } from "react";
import { Box, Card, CardContent, Grid, Typography, Tooltip } from '@mui/material';
import {
    useTranslate,
    useRecordContext,
} from 'react-admin';
import PanelTypography from "../components/PanelTypography";
import * as Common from '@/utils/common'
const BasDevicePanel = () => {
    const record = useRecordContext();
    if (!record) return null;
    const translate = useTranslate();
    return (
        <>
            <Card sx={{ width: { xs: 300, sm: 500, md: 600, lg: 800 }, margin: 'auto' }}>
                <CardContent>
                    <Grid container spacing={2}>
                        <Grid item xs={12} sx={{ display: 'flex', justifyContent: 'space-between' }}>
                            <Typography variant="h6" gutterBottom align="left" sx={{
                                maxWidth: { xs: '100px', sm: '180px', md: '260px', lg: '360px' },
                                whiteSpace: 'nowrap',
                                overflow: 'hidden',
                                textOverflow: 'ellipsis',
                            }}>
                                {Common.camelToPascalWithSpaces(translate('table.field.basDevice.id'))}: {record.id}
                            </Typography>
                            {/*  inherit, primary, secondary, textPrimary, textSecondary, error */}
                            <Typography variant="h6" gutterBottom align="right" >
                                ID: {record.id}
                            </Typography>
                        </Grid>
                    </Grid>
                    <Grid container spacing={2}>
                        <Grid item xs={12} container alignContent="flex-end">
                            <Typography variant="caption" color="textSecondary" sx={{ wordWrap: 'break-word', wordBreak: 'break-all' }}>
                                {Common.camelToPascalWithSpaces(translate('common.field.memo'))}:{record.memo}
                            </Typography>
                        </Grid>
                    </Grid>
                    <Box height={20}>&nbsp;</Box>
                    <Grid container spacing={2}>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.basDevice.deviceNo"
                                property={record.deviceNo}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.basDevice.inEnable"
                                property={record.inEnable}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.basDevice.outEnable"
                                property={record.outEnable}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.basDevice.origin"
                                property={record.origin}
                            />
                        </Grid>
                    </Grid>
                </CardContent>
            </Card >
        </>
    );
};
export default BasDevicePanel;
rsf-admin/src/page/basDevice/index.jsx
New file
@@ -0,0 +1,18 @@
import React, { useState, useRef, useEffect, useMemo } from "react";
import {
    ListGuesser,
    EditGuesser,
    ShowGuesser,
} from "react-admin";
import BasDeviceList from "./BasDeviceList";
import BasDeviceEdit from "./BasDeviceEdit";
export default {
    list: BasDeviceList,
    edit: BasDeviceEdit,
    show: ShowGuesser,
    recordRepresentation: (record) => {
        return `${record.id}`
    }
};
rsf-server/src/main/java/basDevice.sql
New file
@@ -0,0 +1,25 @@
-- save basDevice record
-- mysql
insert into `sys_menu` ( `name`, `parent_id`, `route`, `component`, `type`, `sort`, `tenant_id`, `status`) values ( 'menu.basDevice', '0', '/manager/basDevice', 'basDevice', '0' , '0', '1' , '1');
insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Query 基础设备表', '', '1', 'manager:basDevice:list', '0', '1', '1');
insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Create 基础设备表', '', '1', 'manager:basDevice:save', '1', '1', '1');
insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Update 基础设备表', '', '1', 'manager:basDevice:update', '2', '1', '1');
insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Delete 基础设备表', '', '1', 'manager:basDevice:remove', '3', '1', '1');
-- locale menu name
basDevice: 'BasDevice',
-- locale field
basDevice: {
    deviceNo: "deviceNo",
    inEnable: "inEnable",
    outEnable: "outEnable",
    origin: "origin",
},
-- ResourceContent
import basDevice from './basDevice';
case 'basDevice':
    return basDevice;
rsf-server/src/main/java/com/vincent/rsf/server/api/controller/WcsController.java
New file
@@ -0,0 +1,47 @@
package com.vincent.rsf.server.api.controller;
import com.vincent.rsf.framework.common.Cools;
import com.vincent.rsf.framework.common.R;
import com.vincent.rsf.server.api.entity.dto.InTaskMsgDto;
import com.vincent.rsf.server.api.controller.params.TaskInParam;
import com.vincent.rsf.server.api.entity.enums.TaskType;
import com.vincent.rsf.server.api.service.WcsService;
import com.vincent.rsf.server.system.controller.BaseController;
import io.swagger.annotations.Api;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/wcs")
@Api(tags = "wcs接口对接")
public class WcsController extends BaseController {
    @Autowired
    private WcsService wcsService;
//    @ApiOperation(value = "wcs生成入库任务接口")
    @PostMapping("/create/in/task")
    public R createInTask(@RequestBody TaskInParam param) {
        if (Cools.isEmpty(param.getIoType())) {
            return R.error("入出库类型不能为空");
        }
        if (Cools.isEmpty(param.getSourceStaNo())) {
            return R.error("源站编号不能为空");
        }
        if (Cools.isEmpty(param.getBarcode()) && param.getIoType().equals(TaskType.TASK_TYPE_IN.type)) {
            return R.error("条码不能为空");
        }
        if (Cools.isEmpty(param.getLocType1())){
            return R.error("高低检测信号不能为空");
        }
        InTaskMsgDto msgDto = wcsService.createInTask(param,getLoginUserId());
        return R.ok(msgDto);
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/api/controller/params/TaskInParam.java
New file
@@ -0,0 +1,15 @@
package com.vincent.rsf.server.api.controller.params;
import lombok.Data;
@Data
public class TaskInParam {
    private Integer ioType;  //作业类型
    private Integer sourceStaNo; //作业站点 or 来源站点
    private String barcode; //容器条码
    private Integer locType1; //库位类型
    private Integer area;
//    private Integer locType2; //库位类型
//    private Integer locType3; //库位类型
}
rsf-server/src/main/java/com/vincent/rsf/server/api/controller/pda/MobileController.java
File was renamed from rsf-server/src/main/java/com/vincent/rsf/server/api/controller/MobileController.java
@@ -1,4 +1,4 @@
package com.vincent.rsf.server.api.controller;
package com.vincent.rsf.server.api.controller.pda;
import com.vincent.rsf.framework.common.R;
import com.vincent.rsf.framework.exception.CoolException;
rsf-server/src/main/java/com/vincent/rsf/server/api/controller/pda/pdaOutStockController.java
New file
@@ -0,0 +1,28 @@
package com.vincent.rsf.server.api.controller.pda;
import com.vincent.rsf.framework.common.R;
import com.vincent.rsf.server.api.service.PdaOutStockService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
@Api(tags = "PDA出库操作接口")
@RequestMapping("/pda")
@RestController
public class pdaOutStockController {
    @Autowired
    private PdaOutStockService pdaOutStockService;
    @PreAuthorize("hasAuthority('manager:task:list')")
    @GetMapping("/outStockTaskItem/{barcode}")
    @ApiOperation("快速拣货查询")
    public R getOutStockTaskItem(@PathVariable String barcode) {
        return pdaOutStockService.getOutStockTaskItem(barcode);
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/api/entity/dto/InTaskMsgDto.java
New file
@@ -0,0 +1,16 @@
package com.vincent.rsf.server.api.entity.dto;
import lombok.Data;
@Data
public class InTaskMsgDto {
    private Integer sourceStaNo;
    private Integer staNo;
    private Integer deviceNo;
    private String locNo;
    private String workNo;
}
rsf-server/src/main/java/com/vincent/rsf/server/api/entity/dto/LocTypeDto.java
New file
@@ -0,0 +1,21 @@
package com.vincent.rsf.server.api.entity.dto;
import com.vincent.rsf.server.api.controller.params.TaskInParam;
import lombok.Data;
@Data
public class LocTypeDto {
    // 高低类型{0:未知,1:低库位,2:高库位}
    private Integer locType1;
    // 宽窄类型{0:未知,1:窄库位,2:宽库位}
    private Integer locType2;
    // 轻重类型{0:未知,1:轻库位,2:重库位}
    private Integer locType3;
    public LocTypeDto(TaskInParam param) {
         this.locType1 = param.getLocType1(); // 高库位
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/api/service/PdaOutStockService.java
New file
@@ -0,0 +1,9 @@
package com.vincent.rsf.server.api.service;
import com.vincent.rsf.framework.common.R;
import java.util.Map;
public interface PdaOutStockService {
    R getOutStockTaskItem(String barcode);
}
rsf-server/src/main/java/com/vincent/rsf/server/api/service/WcsService.java
New file
@@ -0,0 +1,8 @@
package com.vincent.rsf.server.api.service;
import com.vincent.rsf.server.api.entity.dto.InTaskMsgDto;
import com.vincent.rsf.server.api.controller.params.TaskInParam;
public interface WcsService {
    InTaskMsgDto createInTask(TaskInParam param, Long loginUserId);
}
rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/PdaOutStockServiceImpl.java
New file
@@ -0,0 +1,45 @@
package com.vincent.rsf.server.api.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.vincent.rsf.framework.common.R;
import com.vincent.rsf.server.api.service.PdaOutStockService;
import com.vincent.rsf.server.manager.entity.AsnOrder;
import com.vincent.rsf.server.manager.entity.Task;
import com.vincent.rsf.server.manager.entity.TaskItem;
import com.vincent.rsf.server.manager.service.AsnOrderService;
import com.vincent.rsf.server.manager.service.OutStockService;
import com.vincent.rsf.server.manager.service.TaskItemService;
import com.vincent.rsf.server.manager.service.TaskService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@Service
public class PdaOutStockServiceImpl implements PdaOutStockService {
    @Resource
    private TaskService taskService;
    @Resource
    private TaskItemService taskItemService;
    @Override
    public R getOutStockTaskItem(String barcode) {
        LambdaQueryWrapper<Task> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Task::getBarcode, barcode);
        Task task = taskService.getOne(lambdaQueryWrapper);
        if (null == task){
            return R.error("未查询到相关任务");
        }
        List<TaskItem> taskItems = taskItemService.list(new LambdaQueryWrapper<TaskItem>().eq(TaskItem::getTaskId, task.getId()));
        if (null == taskItems || taskItems.size() <= 0){
            return R.error("任务出错,未查询到相关任务明细");
        }
        return R.ok(taskItems);
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/WcsServiceImpl.java
New file
@@ -0,0 +1,561 @@
package com.vincent.rsf.server.api.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.vincent.rsf.framework.common.Cools;
import com.vincent.rsf.framework.exception.CoolException;
import com.vincent.rsf.server.api.entity.dto.InTaskMsgDto;
import com.vincent.rsf.server.api.entity.dto.LocTypeDto;
import com.vincent.rsf.server.api.controller.params.TaskInParam;
import com.vincent.rsf.server.api.entity.enums.OrderType;
import com.vincent.rsf.server.api.entity.enums.TaskStsType;
import com.vincent.rsf.server.api.entity.enums.TaskType;
import com.vincent.rsf.server.api.service.WcsService;
import com.vincent.rsf.server.api.utils.LocUtils;
import com.vincent.rsf.server.api.utils.SlaveProperties;
import com.vincent.rsf.server.manager.entity.*;
import com.vincent.rsf.server.manager.enums.PakinIOStatus;
import com.vincent.rsf.server.manager.service.*;
import com.vincent.rsf.server.manager.service.impl.LocServiceImpl;
import com.vincent.rsf.server.manager.utils.LocManageUtil;
import com.vincent.rsf.server.system.constant.SerialRuleCode;
import com.vincent.rsf.server.system.enums.LocStsType;
import com.vincent.rsf.server.system.utils.SerialRuleUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
@Service
public class WcsServiceImpl implements WcsService {
    @Autowired
    private DeviceSiteService deviceSiteService;
    @Autowired
    private WaitPakinService waitPakinService;
    @Autowired
    private DeviceBindService deviceBindService;
    @Autowired
    private LocServiceImpl locService;
    @Autowired
    private LocItemService locItemService;
    @Autowired
    private SlaveProperties slaveProperties;
    @Autowired
    private WarehouseAreasService warehouseAreasService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private TaskItemService taskItemService;
    @Autowired
    private WaitPakinItemService waitPakinItemService;
    @Override
    @Transactional(rollbackFor = Exception.class)
    public InTaskMsgDto createInTask(TaskInParam param, Long loginUserId) {
        // 获取库位号
        InTaskMsgDto locNo = getLocNo(param);
        // 验证设备站点
        DeviceSite deviceSite = validateDeviceSite(param);
        // 验证组拖状态
        WaitPakin waitPakin = validateWaitPakin(param.getBarcode());
        // 生成任务编码
        String ruleCode = generateTaskCode();
        // 创建并保存任务
        Task task = createTask(ruleCode, locNo.getLocNo(), waitPakin.getBarcode(),
                deviceSite.getDeviceSite(), param.getSourceStaNo().toString(), loginUserId);
        // 更新库位状态
        updateLocStatus(task.getTargLoc(), waitPakin.getBarcode());
        // 获取并验证组拖明细
        List<WaitPakinItem> waitPakinItems = getWaitPakinItems(waitPakin.getId());
        // 创建并保存任务明细
        saveTaskItems(task.getId(), waitPakinItems, loginUserId);
        // 更新组托状态
        updateWaitPakinStatus(param.getBarcode(), loginUserId);
        // 设置工作单号并返回
        locNo.setWorkNo(ruleCode);
        return locNo;
    }
    /**
     * 验证设备站点
     */
    private DeviceSite validateDeviceSite(TaskInParam param) {
        DeviceSite deviceSite = deviceSiteService.getOne(new LambdaQueryWrapper<DeviceSite>()
                .eq(DeviceSite::getSite, param.getSourceStaNo())
                .eq(DeviceSite::getType, param.getIoType()));
        if (Objects.isNull(deviceSite)) {
            throw new CoolException("站点不存在!!");
        }
        return deviceSite;
    }
    /**
     * 验证组拖状态
     */
    private WaitPakin validateWaitPakin(String barcode) {
        WaitPakin waitPakin = waitPakinService.getOne(new LambdaQueryWrapper<WaitPakin>()
                .eq(WaitPakin::getBarcode, barcode)
                .eq(WaitPakin::getIoStatus, Short.parseShort(PakinIOStatus.PAKIN_IO_STATUS_DONE.val)));
        if (Cools.isEmpty(waitPakin)) {
            throw new CoolException("请检查组拖状态是否完成!!");
        }
        return waitPakin;
    }
    /**
     * 生成任务编码
     */
    private String generateTaskCode() {
        String ruleCode = SerialRuleUtils.generateRuleCode(SerialRuleCode.SYS_TASK_CODE, null);
        if (StringUtils.isBlank(ruleCode)) {
            throw new CoolException("编码错误:请确认编码「SYS_TASK_CODE」是否已生成!!");
        }
        return ruleCode;
    }
    /**
     * 创建并保存任务
     */
    private Task createTask(String ruleCode, String targetLoc, String barcode,
                            String targetSite, String sourceSiteNo, Long loginUserId) {
        Task task = new Task();
        task.setTaskCode(ruleCode)
                .setTaskStatus(TaskStsType.GENERATE_IN.id.shortValue())
                .setTaskType(TaskType.TASK_TYPE_IN.type.shortValue())
                .setTargLoc(targetLoc)
                .setBarcode(barcode)
                .setTargSite(targetSite)
                .setCreateBy(loginUserId)
                .setUpdateBy(loginUserId)
                .setOrgSite(sourceSiteNo);
        if (!taskService.save(task)) {
            throw new CoolException("任务保存失败!!");
        }
        return task;
    }
    /**
     * 更新库位状态
     */
    private void updateLocStatus(String locCode, String barcode) {
        boolean updated = locService.update(new LambdaUpdateWrapper<Loc>()
                .eq(Loc::getCode, locCode)
                .set(Loc::getUseStatus, LocStsType.LOC_STS_TYPE_S.type)
                .set(Loc::getBarcode, barcode));
        if (!updated) {
            throw new CoolException("库位预约失败!!");
        }
    }
    /**
     * 获取并验证组拖明细
     */
    private List<WaitPakinItem> getWaitPakinItems(Long pakinId) {
        List<WaitPakinItem> waitPakinItems = waitPakinItemService.list(
                new LambdaQueryWrapper<WaitPakinItem>().eq(WaitPakinItem::getPakinId, pakinId));
        if (waitPakinItems.isEmpty()) {
            throw new CoolException("数据错误:组拖明细不存在");
        }
        return waitPakinItems;
    }
    /**
     * 创建并保存任务明细
     */
    private void saveTaskItems(Long taskId, List<WaitPakinItem> waitPakinItems, Long loginUserId) {
        List<TaskItem> taskItems = waitPakinItems.stream().map(item -> {
            TaskItem taskItem = new TaskItem();
            BeanUtils.copyProperties(item, taskItem);
            return taskItem.setTaskId(taskId)
                    .setOrderType(OrderType.ORDER_RECEIPT.type)
                    .setSource(item.getId())
                    .setTrackCode(item.getTrackCode())
                    .setCreateBy(loginUserId)
                    .setUpdateBy(loginUserId)
                    .setOrderId(item.getAsnId())
                    .setOrderItemId(item.getAsnItemId());
        }).collect(Collectors.toList());
        if (!taskItemService.saveBatch(taskItems)) {
            throw new CoolException("任务明细保存失败!!");
        }
    }
    /**
     * 更新组托状态
     */
    private void updateWaitPakinStatus(String barcode, Long loginUserId) {
        boolean updated = waitPakinService.update(new LambdaUpdateWrapper<WaitPakin>()
                .eq(WaitPakin::getBarcode, barcode)
                .set(WaitPakin::getUpdateBy, loginUserId)
                .set(WaitPakin::getCreateBy, loginUserId)
                .set(WaitPakin::getIoStatus, PakinIOStatus.PAKIN_IO_STATUS_TASK_EXCE.val));
        if (!updated) {
            throw new CoolException("组托状态修改失败!!");
        }
    }
//    @Override
//    public InTaskMsgDto createInTask(TaskInParam param, Long loginUserId) {
//        InTaskMsgDto locNo = getLocNo(param);
//        DeviceSite deviceSite = deviceSiteService.getOne(new LambdaQueryWrapper<DeviceSite>()
//                .eq(DeviceSite::getSite, param.getSourceStaNo())
//                .eq(DeviceSite::getType,param.getIoType())
//        );
//        if (Objects.isNull(deviceSite)) {
//            throw new CoolException("站点不存在!!");
//        }
//
//        WaitPakin waitPakin = waitPakinService.getOne(new LambdaQueryWrapper<WaitPakin>()
//                .eq(WaitPakin::getBarcode, param.getBarcode())
//                .eq(WaitPakin::getIoStatus, Short.parseShort(PakinIOStatus.PAKIN_IO_STATUS_DONE.val)));
//        if (Cools.isEmpty(waitPakin)) {
//            throw new CoolException("请检查组拖状态是否完成!!");
//        }
//
//            List<TaskItem> taskItems = new ArrayList<>();
//            String ruleCode = SerialRuleUtils.generateRuleCode(SerialRuleCode.SYS_TASK_CODE, null);
//            if (StringUtils.isBlank(ruleCode)) {
//                throw new CoolException("编码错误:请确认编码「SYS_TASK_CODE」是否已生成!!");
//            }
//            Task task = new Task();
//            task.setTaskCode(ruleCode)
//                    .setTaskStatus(TaskStsType.GENERATE_IN.id.shortValue())
//                    .setTaskType(TaskType.TASK_TYPE_IN.type.shortValue())
//                    .setTargLoc(locNo.getLocNo())
//                    .setBarcode(waitPakin.getBarcode())
//                    .setTargSite(deviceSite.getDeviceSite())
//                    .setCreateBy(loginUserId)
//                    .setUpdateBy(loginUserId)
//                    .setOrgSite(param.getSourceStaNo().toString());
//
//
//
//
//            if (!taskService.save(task)) {
//                throw new CoolException("任务保存失败!!");
//            }
//            if (!locService.update(new LambdaUpdateWrapper<Loc>().eq(Loc::getCode, task.getTargLoc())
//                    .set(Loc::getUseStatus, LocStsType.LOC_STS_TYPE_S.type).set(Loc::getBarcode, waitPakin.getBarcode()))) {
//                throw new CoolException("库位预约失败!!");
//            }
//            /**获取组拖明细**/
//            List<WaitPakinItem> waitPakinItems = waitPakinItemService.list(new LambdaQueryWrapper<WaitPakinItem>().eq(WaitPakinItem::getPakinId, waitPakin.getId()));
//            if (waitPakinItems.isEmpty()) {
//                throw new CoolException("数据错误:组拖明细不存在");
//            }
//            waitPakinItems.forEach(item -> {
//                TaskItem taskItem = new TaskItem();
//                BeanUtils.copyProperties(item, taskItem);
////                AsnOrder order = asnOrderService.getOne(new LambdaQueryWrapper<AsnOrder>().eq(AsnOrder::getId, item.getAsnId()));
////                if (Objects.isNull(order)) {
////                    throw new CoolException("数据错误: 单据不存在!!");
////                }
//                taskItem.setTaskId(task.getId())
//                        .setOrderType(OrderType.ORDER_RECEIPT.type)
//                        .setSource(item.getId())
//                        .setTrackCode(item.getTrackCode())
//                        .setCreateBy(loginUserId)
//                        .setUpdateBy(loginUserId)
//                        .setOrderId(item.getAsnId())
//                        .setOrderItemId(item.getAsnItemId());
//                taskItems.add(taskItem);
//            });
//            if (!taskItemService.saveBatch(taskItems)) {
//                throw new CoolException("任务明细保存失败!!");
//            }
//
//
//        if (!waitPakinService.update(new LambdaUpdateWrapper<WaitPakin>()
//                .eq(WaitPakin::getBarcode, param.getBarcode())
//                .set(WaitPakin::getUpdateBy, loginUserId)
//                .set(WaitPakin::getCreateBy, loginUserId)
//                .set(WaitPakin::getIoStatus, PakinIOStatus.PAKIN_IO_STATUS_TASK_EXCE.val))) {
//            throw new CoolException("组托状态修改失败!!");
//        }
//        locNo.setWorkNo(ruleCode);
//        return locNo;
//    }
    public InTaskMsgDto getLocNo(TaskInParam param) {
        String matnr = null; String batch = null;
        List<WaitPakin> waitPakins = waitPakinService.list(new LambdaQueryWrapper<WaitPakin>().eq(WaitPakin::getBarcode, param.getBarcode()));
        if (Cools.isEmpty(waitPakins) && param.getIoType().equals(TaskType.TASK_TYPE_IN.type)) {
            throw new CoolException("未找到组托信息,请组托");
        }else if (!Cools.isEmpty(waitPakins)) {
            matnr = waitPakins.get(0).getCode();
            batch = waitPakins.get(0).getCode();
        }
        List<DeviceSite> deviceSites = deviceSiteService.list(new LambdaQueryWrapper<DeviceSite>()
                .eq(DeviceSite::getSite, param.getSourceStaNo())
                .eq(DeviceSite::getType,param.getIoType())
        );
        if (Cools.isEmpty(deviceSites)) {
            throw new CoolException("未找到站点路径信息");
        }
        WarehouseAreas warehouseArea = warehouseAreasService.getById(param.getArea());
        if (Cools.isEmpty(warehouseArea)) {
            throw new CoolException("未找到所属库区信息");
        }
        LocTypeDto locTypeDto = new LocTypeDto(param);
        InTaskMsgDto dto = null;
        switch (warehouseArea.getType()) {
            case "CRN": //堆垛机
                dto = getLocNoCrn(param.getArea(), param.getSourceStaNo(), matnr,batch, locTypeDto, 0, param.getIoType());
                break;
            case "SXC": //四向库
                break;
            case "CTU": //四向库
                break;
        }
        return dto;
    }
    private InTaskMsgDto getLocNoCrn(Integer area,Integer sourceStaNo, String matnr, String batch,LocTypeDto locTypeDto, int times,Integer ioType){
        if (Cools.isEmpty(matnr)) {  //物料号
            matnr = "";
        }
        if (Cools.isEmpty(batch)) {  //批次
            batch = "";
        }
        // 初始化参数
        int deviceNo = 0;      //堆垛机号
        int nearRow = 0;    //最浅库位排
        int curRow = 0;     //最深库位排
        int rowCount = 0;   //轮询轮次
        Loc loc = null;     // 目标库位
        InTaskMsgDto inTaskMsgDto = new InTaskMsgDto();
        DeviceBind deviceBind = deviceBindService.getById(LocUtils.getAreaType(sourceStaNo));
        if (Cools.isEmpty(deviceBind)) {
            throw new CoolException("数据异常,请联系管理员===>库位规则未知");
        }
        int sRow = deviceBind.getStartRow();
        int eRow = deviceBind.getEndRow();
        int deviceQty = deviceBind.getDeviceQty();
        // ===============>>>> 开始执行
        curRow = deviceBind.getCurrentRow();
        //此程序用于优化堆垛机异常时的运行时间
        for (int i = times; i <= deviceQty * 2; i++) {
            int[] locNecessaryParameters = LocUtils.LocNecessaryParameters(deviceBind, curRow, deviceQty);
            curRow = locNecessaryParameters[1];
            deviceNo = locNecessaryParameters[2];
            rowCount = locNecessaryParameters[0];
            nearRow = locNecessaryParameters[3];
            break;
        }
        if (nearRow == 0) {
            throw new CoolException("无可用堆垛机");
        }
        //入库靠近摆放
        if (ioType== 1 && deviceBind.getBeSimilar().equals("1") && !Cools.isEmpty(matnr)) {
            if (nearRow != curRow) {
                List<LocItem> locItems = locItemService.list(new LambdaQueryWrapper<LocItem>().eq(LocItem::getMatnrCode, matnr));
                for (LocItem locItem : locItems) {
                    Loc loc1 = locService.getById(locItem.getLocId());
                    if (LocUtils.isShallowLoc(slaveProperties, loc1.getCode())) {
                        continue;
                    }
                    String shallowLocNo = LocUtils.getShallowLoc(slaveProperties, loc1.getCode());
                    // 检测目标库位是否为空库位
                    Loc shallowLoc = locService.getOne(new LambdaQueryWrapper<Loc>().eq(Loc::getCode,shallowLocNo));
                    if (shallowLoc != null && shallowLoc.getUseStatus().equals("O")) {
                        if (LocUtils.locMoveCheckLocTypeComplete(shallowLoc, locTypeDto)) {
                                loc = shallowLoc;
                                deviceNo = shallowLoc.getDeviceNo();
                                break;
                        }
                    }
                }
            }
        }
//        // 靠近摆放规则 --- 空托 //互通版
//        if (ioType == 10 && deviceBind.getEmptySimilar().equals("1")) {
//            List<LocMast> locMasts = locMastService.selectList(new EntityWrapper<LocMast>()
//                    .eq("loc_sts", "D").ge("row1", sRow).le("row1", eRow).eq("whs_type", rowLastnoType.getType().longValue()));
//            if (!locMasts.isEmpty()) {
//                for (LocMast loc : locMasts) {
//                    if (Utils.isShallowLoc(slaveProperties, loc.getLocNo())) {
//                        continue;
//                    }
//                    String shallowLocNo = Utils.getShallowLoc(slaveProperties, loc.getLocNo());
//                    // 检测目标库位是否为空库位
//                    LocMast shallowLoc = locMastService.selectById(shallowLocNo);
//                    if (shallowLoc != null && shallowLoc.getLocSts().equals("O")) {
//                        if (VersionUtils.locMoveCheckLocTypeComplete(shallowLoc, locTypeDto)) {
//                            if (basCrnpService.checkSiteError(shallowLoc.getCrnNo(), true)) {
//                                locMast = shallowLoc;
//                                crnNo = locMast.getCrnNo();
//                                break;
//                            }
//                        }
//                    }
//                }
//            }
//        }
        //查找路径
        DeviceSite deviceSite = deviceSiteService.getOne(new LambdaQueryWrapper<DeviceSite>()
                .eq(DeviceSite::getType, ioType)
                .eq(DeviceSite::getSite, sourceStaNo)
                .eq(DeviceSite::getDeviceCode, deviceNo)
        );
        if (Cools.isEmpty(deviceSite)){
            deviceNo = 0;
        }else {
            inTaskMsgDto.setStaNo(Integer.parseInt(deviceSite.getDeviceSite()));
        }
        //更新当前排
        deviceBind.setCurrentRow(curRow);
        deviceBindService.updateById(deviceBind);
        // 开始查找库位 ==============================>>
        // 1.按规则查找库位
        if (Cools.isEmpty(loc) && deviceNo != 0) {
            List<Loc> locMasts = null;
            locMasts = locService.list(new LambdaQueryWrapper<Loc>()
                    .eq(Loc::getRow, nearRow)
                    .eq(Loc::getUseStatus, "O")
                    .eq(Loc::getType, locTypeDto.getLocType1())
                    .eq(Loc::getAreaId,area)
                    .orderByAsc(Loc::getLev)
                    .orderByAsc(Loc::getCol)
            );
            for (Loc locMast1 : locMasts) {
                if (!LocUtils.locMoveCheckLocTypeComplete(locMast1, locTypeDto)) {
                    continue;
                }
                String shallowLoc = LocUtils.getDeepLoc(slaveProperties, locMast1.getCode());
                if ((ioType== 1 && deviceBind.getBeSimilar().equals("1"))) {
                    //相似物料打开,判断深库位有没有货,没货就放深库位,有货就不操作
                    Loc locMast2 = locService.getOne(new LambdaQueryWrapper<Loc>()
                            .eq(Loc::getRow, shallowLoc)
                            .eq(Loc::getUseStatus, "O")
                            .eq(Loc::getAreaId,area)
                    );
                    if (!Cools.isEmpty(locMast2)) {
                        loc = locMast2;
                        break;
                    }
                } else {
                    //相似物料关闭,判断深库位有没有货,有货就放浅库位,无货就不操作
                    Loc locMast2 = locService.getOne(new LambdaQueryWrapper<Loc>()
                            .eq(Loc::getCode, shallowLoc)
                            .in(Loc::getUseStatus, "D","F")
                            .eq(Loc::getAreaId,area)
                    );
                    if (!Cools.isEmpty(locMast2)) {
                        loc = locMast1;
                        break;
                    }else{
                        locMast2 = locService.getOne(new LambdaQueryWrapper<Loc>()
                                .eq(Loc::getCode, shallowLoc)
                                .eq(Loc::getUseStatus, "O")
                                .eq(Loc::getAreaId,area)
                        );
                        if (!Cools.isEmpty(locMast2)) {
                            loc = locMast2;
                            break;
                        }
                    }
                }
            }
            if (Cools.isEmpty(loc) && deviceBind.getBeSimilar().equals("1")) {
                for (Loc locMast1 : locMasts) {
                    if (!LocUtils.locMoveCheckLocTypeComplete(locMast1, locTypeDto)) {
                        continue;
                    }
                    if (deviceBind.getBeSimilar().equals("1")) {
                        String shallowLoc = LocUtils.getDeepLoc(slaveProperties, locMast1.getCode());
                        Loc locMast2 = locService.getOne(new LambdaQueryWrapper<Loc>()
                                .eq(Loc::getCode, shallowLoc)
                                .eq(Loc::getUseStatus, "O")
                                .eq(Loc::getAreaId,area)
                        );
                        if (!Cools.isEmpty(locMast2)) {
                            loc = locMast2;
                            break;
                        } else {
                            locMast2 = locService.getOne(new LambdaQueryWrapper<Loc>()
                                    .eq(Loc::getCode, shallowLoc)
                                    .in(Loc::getUseStatus, "D","F")
                                    .eq(Loc::getAreaId,area)
                            );
                            if (!Cools.isEmpty(locMast2)) {
                                loc = locMast1;
                                break;
                            }
                        }
                    } else {
                        if (!Cools.isEmpty(locMast1)) {
                            loc = locMast1;
                            break;
                        }
                    }
                }
            }
        }
        //查询当前库位类型空库位 小于5个则locmast = null
        List<Loc> locTypeLocMasts = locService.list(new LambdaQueryWrapper<Loc>()
                .eq(Loc::getUseStatus, "O")
                .eq(Loc::getDeviceNo, deviceNo)
                .eq(Loc::getType, locTypeDto.getLocType1())
                .eq(Loc::getAreaId,area)
        );
        if (null !=locTypeLocMasts && locTypeLocMasts.size()<=5){
            loc = null;
        }
        // 递归查询
        if (Cools.isEmpty(loc) || !loc.getUseStatus().equals("O")) {
            // 当前巷道无空库位时,递归调整至下一巷道,检索全部巷道无果后,跳出递归
            if (times < rowCount * 2) {
                times = times + 1;
                return getLocNoCrn(area,sourceStaNo,matnr,batch,locTypeDto,times, ioType);
            }
            // 2.库位当前所属尺寸无空库位时,调整尺寸参数,向上兼容检索库位
            if (locTypeDto.getLocType1() < 3) {
                int i = locTypeDto.getLocType1() + 1;
                locTypeDto.setLocType1(i);
                return getLocNoCrn(area,sourceStaNo,matnr,batch,locTypeDto,0, ioType);
            }
            throw new CoolException("没有空库位");
        }
        String locNo = loc.getCode();
        // 返回dto
        inTaskMsgDto.setDeviceNo(deviceNo);
        inTaskMsgDto.setSourceStaNo(sourceStaNo);
//        inTaskMsgDto.setStaNo();
        inTaskMsgDto.setLocNo(locNo);
        return inTaskMsgDto;
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/api/utils/LocUtils.java
New file
@@ -0,0 +1,166 @@
package com.vincent.rsf.server.api.utils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.vincent.rsf.framework.common.Arith;
import com.vincent.rsf.framework.common.Cools;
import com.vincent.rsf.framework.common.SpringUtils;
import com.vincent.rsf.framework.exception.CoolException;
import com.vincent.rsf.server.api.entity.dto.LocTypeDto;
import com.vincent.rsf.server.manager.entity.DeviceBind;
import com.vincent.rsf.server.manager.entity.Loc;
import com.vincent.rsf.server.manager.service.DeviceBindService;
import java.util.List;
public class LocUtils {
    /**
     * 获取 浅库位对应的深库位号
     */
    public static String getDeepLoc(SlaveProperties slaveProperties, String shallowLoc) {
        int row = getRow(shallowLoc);
        int remainder = (int) Arith.remainder(row, slaveProperties.getGroupCount());
        int targetRow;
        if (remainder == 2) {
            targetRow = row - 1;
        } else if (remainder == 3) {
            targetRow = row + 1;
        } else {
            throw new CoolException(shallowLoc + "不是浅库位,系统繁忙");
        }
        return zerofill(String.valueOf(targetRow), 2) + shallowLoc.substring(2);
    }
    /**
     * 获取 深库位对应的浅库位号
     */
    public static String getShallowLoc(SlaveProperties slaveProperties, String deepLoc) {
        int row = getRow(deepLoc);
        int remainder = (int) Arith.remainder(row, slaveProperties.getGroupCount());
        int shallowRow = remainder == 1 ? (row + 1) : (row - 1);
        return zerofill(String.valueOf(shallowRow), 2) + deepLoc.substring(2);
    }
    /**
     * 判断是否为浅库位
     */
    public static boolean isShallowLoc(SlaveProperties slaveProperties, String locNo) {
        if (slaveProperties.isDoubleDeep()) {
            int row = getRow(locNo);
            return !slaveProperties.getDoubleLocs().contains(row);
        } else {
            return false;
        }
    }
    //获取站点对应的库类型
    public static Long getAreaType(Integer sourceStaNo) {
        DeviceBindService rowLastnoService = SpringUtils.getBean(DeviceBindService.class);
        List<DeviceBind> deviceBinds = rowLastnoService.list(new LambdaQueryWrapper<DeviceBind>());
        for (DeviceBind deviceBind : deviceBinds) {
            String[] staNoList = deviceBind.getStaList().split(";");
            for (String staNo : staNoList) {
                if (staNo.equals(sourceStaNo.toString())) {
                    return deviceBind.getId();
                }
            }
        }
        return 0L;
    }
    //库位排号分配
    public static int[] LocNecessaryParameters(DeviceBind deviceBind, Integer curRow, Integer crnNumber) {
      return LocNecessaryParametersDoubleExtension(curRow, crnNumber); //已完善
    }
    //经典双伸库位
    public static int[] LocNecessaryParametersDoubleExtension( Integer curRow, Integer crnNumber) {
        int[] necessaryParameters = new int[]{0, 0, 0, 0};
        necessaryParameters[0] = crnNumber; // 轮询次数
        //满板正常入库
        if (curRow.equals(crnNumber * 4)) {
            necessaryParameters[1] = 1;    //curRow   最深库位排
            necessaryParameters[2] = 1;     //crnNo     堆垛机号
            necessaryParameters[3] = 2;    //nearRow  最浅库位排
        } else if (curRow.equals(crnNumber * 4 - 3)) {
            necessaryParameters[1] = 4;    //curRow   最深库位排
            necessaryParameters[2] = 1;     //crnNo     堆垛机号
            necessaryParameters[3] = 3;    //nearRow  最浅库位排
        } else {
            curRow = curRow + 4;
            if (curRow < 1 || curRow > (crnNumber * 4)) {
                throw new CoolException("库位排号异常:排号:" + curRow);
            }
            if ((curRow - 1) % 4 == 0) {
                necessaryParameters[1] = curRow;    //curRow   最深库位排
                necessaryParameters[2] = (curRow + 3) / 4;     //crnNo     堆垛机号
                necessaryParameters[3] = curRow + 1;    //nearRow  最浅库位排
            } else if (curRow % 4 == 0) {
                necessaryParameters[1] = curRow;    //curRow   最深库位排
                necessaryParameters[2] = curRow / 4;     //crnNo     堆垛机号
                necessaryParameters[3] = curRow - 1;    //nearRow  最浅库位排
            } else {
                throw new CoolException("库位排号异常:排号:" + curRow);
            }
        }
        return necessaryParameters;
    }
    /**
     * 通过库位号获取 排
     */
    public static int getRow(String locNo) {
        if (!Cools.isEmpty(locNo)) {
            return Integer.parseInt(locNo.substring(0, 2));
        }
        throw new RuntimeException("库位解析异常");
    }
    /**
     * 通过库位号获取 列
     */
    public static int getBay(String locNo) {
        if (!Cools.isEmpty(locNo)) {
            return Integer.parseInt(locNo.substring(2, 5));
        }
        throw new RuntimeException("库位解析异常");
    }
    /**
     * 通过库位号获取 层
     */
    public static int getLev(String locNo) {
        if (!Cools.isEmpty(locNo)) {
            return Integer.parseInt(locNo.substring(5, 7));
        }
        throw new RuntimeException("库位解析异常");
    }
    /**
     * 类型检测
     * 完全检测
     **/
    public static boolean locMoveCheckLocTypeComplete(Loc loc, LocTypeDto dto) {
        // 如果源库位是高库位,目标库位是低库位
        return dto.getLocType1().equals(Integer.parseInt(loc.getType()));
    }
    public static String zerofill(String msg, Integer count) {
        if (msg.length() == count) {
            return msg;
        } else if (msg.length() > count) {
            return msg.substring(0, 16);
        } else {
            StringBuilder msgBuilder = new StringBuilder(msg);
            for (int i = 0; i < count - msg.length(); i++) {
                msgBuilder.insert(0, "0");
            }
            return msgBuilder.toString();
        }
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/api/utils/SlaveProperties.java
New file
@@ -0,0 +1,28 @@
package com.vincent.rsf.server.api.utils;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import java.util.ArrayList;
import java.util.List;
/**
 * Created by vincent on 2020/8/4
 */
@Data
@Configuration
@ConfigurationProperties(prefix = "wcs-slave")
public class SlaveProperties {
    private boolean doubleDeep;
    // 双深库位排号
    private List<Integer> doubleLocs = new ArrayList<>();
    // 左深库位排号
    private List<Integer> doubleLocsLeft = new ArrayList<>();
    // 右深库位排号
    private List<Integer> doubleLocsRight = new ArrayList<>();
    private int groupCount;
}
rsf-server/src/main/java/com/vincent/rsf/server/common/config/WebMvcConfig.java
@@ -1,7 +1,7 @@
package com.vincent.rsf.server.common.config;
import com.vincent.rsf.server.common.constant.Constants;
import com.vincent.rsf.server.common.interceptor.DynamicFieldsInterceptor;
import com.vincent.rsf.server.common.interceptor.severlet.DynamicFieldsInterceptor;
import com.vincent.rsf.server.common.utils.Http;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
rsf-server/src/main/java/com/vincent/rsf/server/common/interceptor/DynamicFieldsInterceptor.java
File was deleted
rsf-server/src/main/java/com/vincent/rsf/server/common/interceptor/severlet/CustomParameterFilter.java
New file
@@ -0,0 +1,37 @@
package com.vincent.rsf.server.common.interceptor.severlet;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component
public class CustomParameterFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain filterChain)
            throws ServletException, IOException {
        ParameterAddableRequest wrappedRequest = new ParameterAddableRequest(request);
        // 添加系统级参数
        wrappedRequest.addParameter("systemVersion", "1.0.0");
        wrappedRequest.addParameter("environment", System.getProperty("spring.profiles.active", "default"));
        // 添加请求追踪信息
        addTraceInfo(wrappedRequest);
        filterChain.doFilter(wrappedRequest, response);
    }
    private void addTraceInfo(ParameterAddableRequest request) {
        String traceId = request.getHeader("X-Trace-Id");
//        if (traceId == null || traceId.isEmpty()) {
//            traceId = UUID.randomUUID().toString();
//        }
        request.addParameter("traceId", "traceId");
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/common/interceptor/severlet/DynamicFieldsInterceptor.java
New file
@@ -0,0 +1,66 @@
package com.vincent.rsf.server.common.interceptor.severlet;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
 * @author Ryan
 * @version 1.0
 * @title DynamicFieldsInterceptor
 * @description
 * @create 2025/4/16 16:10
 */
@Slf4j
public class DynamicFieldsInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//        if (request instanceof ParameterAddableRequest) {
//            ParameterAddableRequest wrappedRequest = (ParameterAddableRequest) request;
//
//            // 添加业务参数
//            wrappedRequest.addParameter("processedBy", "CustomParameterInterceptor");
//
//            // 可以从Session或其他地方获取数据
//            Object userId = request.getSession().getAttribute("userId");
//            if (userId != null) {
//                wrappedRequest.addParameter("currentUserId", userId.toString());
//            }
//        }
//
//        return true;
//        List<Fields> fields = FieldsUtils.getFieldsSta();
//        List<String> fieldsKey = fields.stream().filter(item -> item.getFlagEnable() == 1).map(Fields::getFields).collect(Collectors.toList());
//        fieldsKey.forEach(key -> {
//            if (request.getParameterMap().keySet().contains(key)) {
//                request.setAttribute(key, request.getParameterMap().get(key));
//            }
//        })
//        if (request instanceof ParameterAddableRequest) {
//            ParameterAddableRequest wrappedRequest = (ParameterAddableRequest) request;
//            wrappedRequest.addParameter("DynamicFields", "springValue");
//        }
//        return true;
        return HandlerInterceptor.super.preHandle(request, response, handler);
    }
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println(response.getOutputStream().toString());
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/common/interceptor/severlet/ParameterAddableRequest.java
New file
@@ -0,0 +1,61 @@
package com.vincent.rsf.server.common.interceptor.severlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.util.*;
public class ParameterAddableRequest extends HttpServletRequestWrapper {
    private final Map<String, String[]> additionalParams = new HashMap<>();
    public ParameterAddableRequest(HttpServletRequest request) {
        super(request);
    }
    /**
     * 添加新参数
     * @param name 参数名
     * @param value 参数值
     */
    public void addParameter(String name, String value) {
        additionalParams.put(name, new String[]{value});
    }
    /**
     * 添加新参数(多值)
     * @param name 参数名
     * @param values 参数值数组
     */
    public void addParameter(String name, String[] values) {
        additionalParams.put(name, values);
    }
    @Override
    public String getParameter(String name) {
        if (additionalParams.containsKey(name)) {
            return additionalParams.get(name)[0];
        }
        return super.getParameter(name);
    }
    @Override
    public Map<String, String[]> getParameterMap() {
        Map<String, String[]> combinedMap = new HashMap<>(super.getParameterMap());
        combinedMap.putAll(additionalParams);
        return Collections.unmodifiableMap(combinedMap);
    }
    @Override
    public Enumeration<String> getParameterNames() {
        Set<String> names = new HashSet<>(Collections.list(super.getParameterNames()));
        names.addAll(additionalParams.keySet());
        return Collections.enumeration(names);
    }
    @Override
    public String[] getParameterValues(String name) {
        if (additionalParams.containsKey(name)) {
            return additionalParams.get(name);
        }
        return super.getParameterValues(name);
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/common/interceptor/severlet/ParameterAddingFilter.java
New file
@@ -0,0 +1,52 @@
package com.vincent.rsf.server.common.interceptor.severlet;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
@WebFilter("/*") // 拦截所有请求
public class ParameterAddingFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 初始化逻辑
    }
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        if (request instanceof HttpServletRequest) {
            // 创建可修改参数的请求包装器
            ParameterAddableRequest wrappedRequest =
                    new ParameterAddableRequest((HttpServletRequest) request);
            // 添加自定义参数
            addCustomParameters(wrappedRequest);
            // 继续过滤器链
            chain.doFilter(wrappedRequest, response);
        } else {
            chain.doFilter(request, response);
        }
    }
    private void addCustomParameters(ParameterAddableRequest request) {
        // 添加请求ID和时间戳
//        request.addParameter("requestId", UUID.randomUUID().toString());
        request.addParameter("timestamp", String.valueOf(System.currentTimeMillis()));
        // 根据业务需求添加其他参数
        String userAgent = request.getHeader("User-Agent");
        if (userAgent != null && userAgent.contains("Mobile")) {
            request.addParameter("deviceType", "mobile");
        } else {
            request.addParameter("deviceType", "desktop");
        }
    }
    @Override
    public void destroy() {
        // 清理逻辑
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/common/security/SecurityConfig.java
@@ -51,7 +51,8 @@
            "/v2/api-docs/**",
            "/v3/api-docs/**",
            "/swagger-ui/**",
            "/ws/**"
            "/ws/**",
            "/wcs/**"
    };
    @Resource
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/BasDeviceController.java
New file
@@ -0,0 +1,110 @@
package com.vincent.rsf.server.manager.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.vincent.rsf.framework.common.Cools;
import com.vincent.rsf.framework.common.R;
import com.vincent.rsf.server.common.utils.ExcelUtil;
import com.vincent.rsf.server.common.annotation.OperationLog;
import com.vincent.rsf.server.common.domain.BaseParam;
import com.vincent.rsf.server.common.domain.KeyValVo;
import com.vincent.rsf.server.common.domain.PageParam;
import com.vincent.rsf.server.manager.entity.BasDevice;
import com.vincent.rsf.server.manager.service.BasDeviceService;
import com.vincent.rsf.server.system.controller.BaseController;
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.*;
@RestController
public class BasDeviceController extends BaseController {
    @Autowired
    private BasDeviceService basDeviceService;
    @PreAuthorize("hasAuthority('manager:basDevice:list')")
    @PostMapping("/basDevice/page")
    public R page(@RequestBody Map<String, Object> map) {
        BaseParam baseParam = buildParam(map, BaseParam.class);
        PageParam<BasDevice, BaseParam> pageParam = new PageParam<>(baseParam, BasDevice.class);
        return R.ok().add(basDeviceService.page(pageParam, pageParam.buildWrapper(true)));
    }
    @PreAuthorize("hasAuthority('manager:basDevice:list')")
    @PostMapping("/basDevice/list")
    public R list(@RequestBody Map<String, Object> map) {
        return R.ok().add(basDeviceService.list());
    }
    @PreAuthorize("hasAuthority('manager:basDevice:list')")
    @PostMapping({"/basDevice/many/{ids}", "/basDevices/many/{ids}"})
    public R many(@PathVariable Long[] ids) {
        return R.ok().add(basDeviceService.listByIds(Arrays.asList(ids)));
    }
    @PreAuthorize("hasAuthority('manager:basDevice:list')")
    @GetMapping("/basDevice/{id}")
    public R get(@PathVariable("id") Long id) {
        return R.ok().add(basDeviceService.getById(id));
    }
    @PreAuthorize("hasAuthority('manager:basDevice:save')")
    @OperationLog("Create 基础设备表")
    @PostMapping("/basDevice/save")
    public R save(@RequestBody BasDevice basDevice) {
        basDevice.setCreateBy(getLoginUserId());
        basDevice.setCreateTime(new Date());
        basDevice.setUpdateBy(getLoginUserId());
        basDevice.setUpdateTime(new Date());
        if (!basDeviceService.save(basDevice)) {
            return R.error("Save Fail");
        }
        return R.ok("Save Success").add(basDevice);
    }
    @PreAuthorize("hasAuthority('manager:basDevice:update')")
    @OperationLog("Update 基础设备表")
    @PostMapping("/basDevice/update")
    public R update(@RequestBody BasDevice basDevice) {
        basDevice.setUpdateBy(getLoginUserId());
        basDevice.setUpdateTime(new Date());
        if (!basDeviceService.updateById(basDevice)) {
            return R.error("Update Fail");
        }
        return R.ok("Update Success").add(basDevice);
    }
    @PreAuthorize("hasAuthority('manager:basDevice:remove')")
    @OperationLog("Delete 基础设备表")
    @PostMapping("/basDevice/remove/{ids}")
    public R remove(@PathVariable Long[] ids) {
        if (!basDeviceService.removeByIds(Arrays.asList(ids))) {
            return R.error("Delete Fail");
        }
        return R.ok("Delete Success").add(ids);
    }
    @PreAuthorize("hasAuthority('manager:basDevice:list')")
    @PostMapping("/basDevice/query")
    public R query(@RequestParam(required = false) String condition) {
        List<KeyValVo> vos = new ArrayList<>();
        LambdaQueryWrapper<BasDevice> wrapper = new LambdaQueryWrapper<>();
        if (!Cools.isEmpty(condition)) {
            wrapper.like(BasDevice::getId, condition);
        }
        basDeviceService.page(new Page<>(1, 30), wrapper).getRecords().forEach(
                item -> vos.add(new KeyValVo(item.getId(), item.getId()))
        );
        return R.ok().add(vos);
    }
    @PreAuthorize("hasAuthority('manager:basDevice:list')")
    @PostMapping("/basDevice/export")
    public void export(@RequestBody Map<String, Object> map, HttpServletResponse response) throws Exception {
        ExcelUtil.build(ExcelUtil.create(basDeviceService.list(), BasDevice.class), response);
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/BasDevice.java
New file
@@ -0,0 +1,154 @@
package com.vincent.rsf.server.manager.entity;
import java.text.SimpleDateFormat;
import java.util.Date;
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.vincent.rsf.framework.common.Cools;
import com.vincent.rsf.framework.common.SpringUtils;
import com.vincent.rsf.server.system.service.UserService;
import com.vincent.rsf.server.system.entity.User;
import java.io.Serializable;
import java.util.Date;
@Data
@TableName("man_bas_device")
public class BasDevice implements Serializable {
    private static final long serialVersionUID = 1L;
    /**
     * id
     */
    @ApiModelProperty(value= "id")
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;
    /**
     * 设备号
     */
    @ApiModelProperty(value= "设备号")
    private Long deviceNo;
    /**
     * 可入
     */
    @ApiModelProperty(value= "可入")
    private String inEnable;
    /**
     * 可出
     */
    @ApiModelProperty(value= "可出")
    private String outEnable;
    /**
     * 状态
     */
    @ApiModelProperty(value= "状态")
    private String status;
    /**
     * 源数据
     */
    @ApiModelProperty(value= "源数据")
    private String origin;
    /**
     * 创建人
     */
    @ApiModelProperty(value= "创建人")
    private Long createBy;
    /**
     * 创建时间
     */
    @ApiModelProperty(value= "创建时间")
    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
    private Date createTime;
    /**
     * 更新人
     */
    @ApiModelProperty(value= "更新人")
    private Long updateBy;
    /**
     * 更新时间
     */
    @ApiModelProperty(value= "更新时间")
    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
    private Date updateTime;
    /**
     * 备注
     */
    @ApiModelProperty(value= "备注")
    private String memo;
    public BasDevice() {}
    public BasDevice(Long deviceNo,String inEnable,String outEnable,String status,String origin,Long createBy,Date createTime,Long updateBy,Date updateTime,String memo) {
        this.deviceNo = deviceNo;
        this.inEnable = inEnable;
        this.outEnable = outEnable;
        this.status = status;
        this.origin = origin;
        this.createBy = createBy;
        this.createTime = createTime;
        this.updateBy = updateBy;
        this.updateTime = updateTime;
        this.memo = memo;
    }
//    BasDevice basDevice = new BasDevice(
//            null,    // 设备号
//            null,    // 可入
//            null,    // 可出
//            null,    // 状态
//            null,    // 源数据
//            null,    // 创建人
//            null,    // 创建时间
//            null,    // 更新人
//            null,    // 更新时间
//            null    // 备注
//    );
    public String getCreateTime$(){
        if (Cools.isEmpty(this.createTime)){
            return "";
        }
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.createTime);
    }
    public String getUpdateTime$(){
        if (Cools.isEmpty(this.updateTime)){
            return "";
        }
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.updateTime);
    }
//    public Boolean getStatusBool(){
//        if (null == this.status){ return null; }
//        switch (this.status){
//            case "1":
//                return true;
//            case "0":
//                return false;
//            default:
//                return null;
//        }
//    }
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/DeviceBind.java
@@ -130,4 +130,5 @@
//        }
//    }
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/Loc.java
@@ -107,7 +107,6 @@
     */
    @ApiModelProperty(value= "宽")
    private Double width;
    /**
     * 排
     */
@@ -116,6 +115,12 @@
    private Integer row;
    /**
     * 设备号
     */
    @ApiModelProperty(value= "设备号")
    private Integer deviceNo;
    /**
     * 列
     */
    @ApiModelProperty(value= "列")
rsf-server/src/main/java/com/vincent/rsf/server/manager/mapper/BasDeviceMapper.java
New file
@@ -0,0 +1,12 @@
package com.vincent.rsf.server.manager.mapper;
import com.vincent.rsf.server.manager.entity.BasDevice;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
@Mapper
@Repository
public interface BasDeviceMapper extends BaseMapper<BasDevice> {
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/BasDeviceService.java
New file
@@ -0,0 +1,8 @@
package com.vincent.rsf.server.manager.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.vincent.rsf.server.manager.entity.BasDevice;
public interface BasDeviceService extends IService<BasDevice> {
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/BasDeviceServiceImpl.java
New file
@@ -0,0 +1,12 @@
package com.vincent.rsf.server.manager.service.impl;
import com.vincent.rsf.server.manager.mapper.BasDeviceMapper;
import com.vincent.rsf.server.manager.entity.BasDevice;
import com.vincent.rsf.server.manager.service.BasDeviceService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
@Service("basDeviceService")
public class BasDeviceServiceImpl extends ServiceImpl<BasDeviceMapper, BasDevice> implements BasDeviceService {
}
rsf-server/src/main/java/order.sql
File was deleted
rsf-server/src/main/java/orderItem.sql
File was deleted
rsf-server/src/main/java/stockItem.sql
File was deleted
rsf-server/src/main/java/wave.sql
File was deleted
rsf-server/src/main/java/waveItem.sql
File was deleted
rsf-server/src/main/resources/application.yml
@@ -40,3 +40,16 @@
logging:
  file:
    path: logs/@pom.artifactId@
# 下位机配置
wcs-slave:
  # 双深
  doubleDeep: true
  # 双深库位排号
  doubleLocs: 1,4,5,8
  # 一个堆垛机负责的货架排数
  groupCount: 4
  # 左深库位排号
  doubleLocsLeft: 1,5,9,13
  # 右深库位排号
  doubleLocsRight: 4,8,12,16
rsf-server/src/main/resources/mapper/manager/BasDeviceMapper.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.vincent.rsf.server.manager.mapper.BasDeviceMapper">
</mapper>