1
昨天 5e53e4f9156c5712de7cdb7f72e7cd1605c279be
lsh#
7个文件已修改
12个文件已添加
1563 ■■■■■ 已修改文件
rsf-admin/src/page/taskPathTemplateMerge/TaskPathTemplateMergeCreate.jsx 219 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/taskPathTemplateMerge/TaskPathTemplateMergeEdit.jsx 191 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/taskPathTemplateMerge/TaskPathTemplateMergeList.jsx 182 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/taskPathTemplateMerge/TaskPathTemplateMergePanel.jsx 147 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/taskPathTemplateMerge/index.jsx 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/BasStation.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/TaskMissionSchedules.java 119 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/TaskSchedules.java 229 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/system/controller/TaskPathTemplateMergeController.java 110 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/system/entity/FlowInstance.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/system/entity/FlowStepInstance.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/system/entity/TaskInstance.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/system/entity/TaskInstanceNode.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/system/entity/TaskPathTemplateMerge.java 234 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/system/mapper/TaskPathTemplateMergeMapper.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/system/service/TaskPathTemplateMergeService.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/system/service/impl/TaskPathTemplateMergeServiceImpl.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/taskPathTemplateMerge.sql 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/resources/mapper/system/TaskPathTemplateMergeMapper.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/taskPathTemplateMerge/TaskPathTemplateMergeCreate.jsx
New file
@@ -0,0 +1,219 @@
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 TaskPathTemplateMergeCreate = (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}>
                                    <TextInput
                                        label="table.field.taskPathTemplateMerge.templateCode"
                                        source="templateCode"
                                        parse={v => v}
                                        autoFocus
                                        validate={required()}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <TextInput
                                        label="table.field.taskPathTemplateMerge.templateName"
                                        source="templateName"
                                        parse={v => v}
                                        validate={required()}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <TextInput
                                        label="table.field.taskPathTemplateMerge.sourceType"
                                        source="sourceType"
                                        parse={v => v}
                                        validate={required()}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <TextInput
                                        label="table.field.taskPathTemplateMerge.targetType"
                                        source="targetType"
                                        parse={v => v}
                                        validate={required()}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <TextInput
                                        label="table.field.taskPathTemplateMerge.conditionExpression"
                                        source="conditionExpression"
                                        parse={v => v}
                                        validate={required()}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <TextInput
                                        label="table.field.taskPathTemplateMerge.conditionDesc"
                                        source="conditionDesc"
                                        parse={v => v}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <NumberInput
                                        label="table.field.taskPathTemplateMerge.version"
                                        source="version"
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <NumberInput
                                        label="table.field.taskPathTemplateMerge.isCurrent"
                                        source="isCurrent"
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <DateInput
                                        label="table.field.taskPathTemplateMerge.effectiveTime"
                                        source="effectiveTime"
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <DateInput
                                        label="table.field.taskPathTemplateMerge.expireTime"
                                        source="expireTime"
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <NumberInput
                                        label="table.field.taskPathTemplateMerge.priority"
                                        source="priority"
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <NumberInput
                                        label="table.field.taskPathTemplateMerge.timeoutMinutes"
                                        source="timeoutMinutes"
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <NumberInput
                                        label="table.field.taskPathTemplateMerge.maxRetryTimes"
                                        source="maxRetryTimes"
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <NumberInput
                                        label="table.field.taskPathTemplateMerge.retryIntervalSeconds"
                                        source="retryIntervalSeconds"
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <TextInput
                                        label="table.field.taskPathTemplateMerge.remark"
                                        source="remark"
                                        parse={v => v}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <NumberInput
                                        label="table.field.taskPathTemplateMerge.stepSize"
                                        source="stepSize"
                                    />
                                </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 TaskPathTemplateMergeCreate;
rsf-admin/src/page/taskPathTemplateMerge/TaskPathTemplateMergeEdit.jsx
New file
@@ -0,0 +1,191 @@
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 TaskPathTemplateMergeEdit = () => {
    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}>
                            <TextInput
                                label="table.field.taskPathTemplateMerge.templateCode"
                                source="templateCode"
                                parse={v => v}
                                autoFocus
                                validate={required()}
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <TextInput
                                label="table.field.taskPathTemplateMerge.templateName"
                                source="templateName"
                                parse={v => v}
                                validate={required()}
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <TextInput
                                label="table.field.taskPathTemplateMerge.sourceType"
                                source="sourceType"
                                parse={v => v}
                                validate={required()}
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <TextInput
                                label="table.field.taskPathTemplateMerge.targetType"
                                source="targetType"
                                parse={v => v}
                                validate={required()}
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <TextInput
                                label="table.field.taskPathTemplateMerge.conditionExpression"
                                source="conditionExpression"
                                parse={v => v}
                                validate={required()}
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <TextInput
                                label="table.field.taskPathTemplateMerge.conditionDesc"
                                source="conditionDesc"
                                parse={v => v}
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <NumberInput
                                label="table.field.taskPathTemplateMerge.version"
                                source="version"
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <NumberInput
                                label="table.field.taskPathTemplateMerge.isCurrent"
                                source="isCurrent"
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <DateInput
                                label="table.field.taskPathTemplateMerge.effectiveTime"
                                source="effectiveTime"
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <DateInput
                                label="table.field.taskPathTemplateMerge.expireTime"
                                source="expireTime"
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <NumberInput
                                label="table.field.taskPathTemplateMerge.priority"
                                source="priority"
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <NumberInput
                                label="table.field.taskPathTemplateMerge.timeoutMinutes"
                                source="timeoutMinutes"
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <NumberInput
                                label="table.field.taskPathTemplateMerge.maxRetryTimes"
                                source="maxRetryTimes"
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <NumberInput
                                label="table.field.taskPathTemplateMerge.retryIntervalSeconds"
                                source="retryIntervalSeconds"
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <TextInput
                                label="table.field.taskPathTemplateMerge.remark"
                                source="remark"
                                parse={v => v}
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <NumberInput
                                label="table.field.taskPathTemplateMerge.stepSize"
                                source="stepSize"
                            />
                        </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 TaskPathTemplateMergeEdit;
rsf-admin/src/page/taskPathTemplateMerge/TaskPathTemplateMergeList.jsx
New file
@@ -0,0 +1,182 @@
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 TaskPathTemplateMergeCreate from "./TaskPathTemplateMergeCreate";
import TaskPathTemplateMergePanel from "./TaskPathTemplateMergePanel";
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 />,
    <TextInput source="templateCode" label="table.field.taskPathTemplateMerge.templateCode" />,
    <TextInput source="templateName" label="table.field.taskPathTemplateMerge.templateName" />,
    <TextInput source="sourceType" label="table.field.taskPathTemplateMerge.sourceType" />,
    <TextInput source="targetType" label="table.field.taskPathTemplateMerge.targetType" />,
    <TextInput source="conditionExpression" label="table.field.taskPathTemplateMerge.conditionExpression" />,
    <TextInput source="conditionDesc" label="table.field.taskPathTemplateMerge.conditionDesc" />,
    <NumberInput source="version" label="table.field.taskPathTemplateMerge.version" />,
    <NumberInput source="isCurrent" label="table.field.taskPathTemplateMerge.isCurrent" />,
    <DateInput source="effectiveTime" label="table.field.taskPathTemplateMerge.effectiveTime" />,
    <DateInput source="expireTime" label="table.field.taskPathTemplateMerge.expireTime" />,
    <NumberInput source="priority" label="table.field.taskPathTemplateMerge.priority" />,
    <NumberInput source="timeoutMinutes" label="table.field.taskPathTemplateMerge.timeoutMinutes" />,
    <NumberInput source="maxRetryTimes" label="table.field.taskPathTemplateMerge.maxRetryTimes" />,
    <NumberInput source="retryIntervalSeconds" label="table.field.taskPathTemplateMerge.retryIntervalSeconds" />,
    <TextInput source="remark" label="table.field.taskPathTemplateMerge.remark" />,
    <NumberInput source="stepSize" label="table.field.taskPathTemplateMerge.stepSize" />,
    <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 TaskPathTemplateMergeList = () => {
    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.taskPathTemplateMerge"}
                empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
                filters={filters}
                sort={{ field: "create_time", order: "desc" }}
                actions={(
                    <TopToolbar>
                        <FilterButton />
                        <MyCreateButton onClick={() => { setCreateDialog(true) }} />
                        <SelectColumnsButton preferenceKey='taskPathTemplateMerge' />
                        <MyExportButton />
                    </TopToolbar>
                )}
                perPage={DEFAULT_PAGE_SIZE}
            >
                <StyledDatagrid
                    preferenceKey='taskPathTemplateMerge'
                    bulkActionButtons={() => <BulkDeleteButton mutationMode={OPERATE_MODE} />}
                    rowClick={(id, resource, record) => false}
                    expand={() => <TaskPathTemplateMergePanel />}
                    expandSingle={true}
                    omit={['id', 'createTime', 'createBy', 'memo']}
                >
                    <NumberField source="id" />
                    <TextField source="templateCode" label="table.field.taskPathTemplateMerge.templateCode" />
                    <TextField source="templateName" label="table.field.taskPathTemplateMerge.templateName" />
                    <TextField source="sourceType" label="table.field.taskPathTemplateMerge.sourceType" />
                    <TextField source="targetType" label="table.field.taskPathTemplateMerge.targetType" />
                    <TextField source="conditionExpression" label="table.field.taskPathTemplateMerge.conditionExpression" />
                    <TextField source="conditionDesc" label="table.field.taskPathTemplateMerge.conditionDesc" />
                    <NumberField source="version" label="table.field.taskPathTemplateMerge.version" />
                    <NumberField source="isCurrent" label="table.field.taskPathTemplateMerge.isCurrent" />
                    <DateField source="effectiveTime" label="table.field.taskPathTemplateMerge.effectiveTime" showTime />
                    <DateField source="expireTime" label="table.field.taskPathTemplateMerge.expireTime" showTime />
                    <NumberField source="priority" label="table.field.taskPathTemplateMerge.priority" />
                    <NumberField source="timeoutMinutes" label="table.field.taskPathTemplateMerge.timeoutMinutes" />
                    <NumberField source="maxRetryTimes" label="table.field.taskPathTemplateMerge.maxRetryTimes" />
                    <NumberField source="retryIntervalSeconds" label="table.field.taskPathTemplateMerge.retryIntervalSeconds" />
                    <TextField source="remark" label="table.field.taskPathTemplateMerge.remark" />
                    <NumberField source="stepSize" label="table.field.taskPathTemplateMerge.stepSize" />
                    <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>
            <TaskPathTemplateMergeCreate
                open={createDialog}
                setOpen={setCreateDialog}
            />
            <PageDrawer
                title='TaskPathTemplateMerge Detail'
                drawerVal={drawerVal}
                setDrawerVal={setDrawerVal}
            >
            </PageDrawer>
        </Box>
    )
}
export default TaskPathTemplateMergeList;
rsf-admin/src/page/taskPathTemplateMerge/TaskPathTemplateMergePanel.jsx
New file
@@ -0,0 +1,147 @@
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 TaskPathTemplateMergePanel = () => {
    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.taskPathTemplateMerge.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.taskPathTemplateMerge.templateCode"
                                property={record.templateCode}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.taskPathTemplateMerge.templateName"
                                property={record.templateName}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.taskPathTemplateMerge.sourceType"
                                property={record.sourceType}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.taskPathTemplateMerge.targetType"
                                property={record.targetType}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.taskPathTemplateMerge.conditionExpression"
                                property={record.conditionExpression}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.taskPathTemplateMerge.conditionDesc"
                                property={record.conditionDesc}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.taskPathTemplateMerge.version"
                                property={record.version}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.taskPathTemplateMerge.isCurrent"
                                property={record.isCurrent}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.taskPathTemplateMerge.effectiveTime"
                                property={record.effectiveTime$}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.taskPathTemplateMerge.expireTime"
                                property={record.expireTime$}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.taskPathTemplateMerge.priority"
                                property={record.priority}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.taskPathTemplateMerge.timeoutMinutes"
                                property={record.timeoutMinutes}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.taskPathTemplateMerge.maxRetryTimes"
                                property={record.maxRetryTimes}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.taskPathTemplateMerge.retryIntervalSeconds"
                                property={record.retryIntervalSeconds}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.taskPathTemplateMerge.remark"
                                property={record.remark}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.taskPathTemplateMerge.stepSize"
                                property={record.stepSize}
                            />
                        </Grid>
                    </Grid>
                </CardContent>
            </Card >
        </>
    );
};
export default TaskPathTemplateMergePanel;
rsf-admin/src/page/taskPathTemplateMerge/index.jsx
New file
@@ -0,0 +1,18 @@
import React, { useState, useRef, useEffect, useMemo } from "react";
import {
    ListGuesser,
    EditGuesser,
    ShowGuesser,
} from "react-admin";
import TaskPathTemplateMergeList from "./TaskPathTemplateMergeList";
import TaskPathTemplateMergeEdit from "./TaskPathTemplateMergeEdit";
export default {
    list: TaskPathTemplateMergeList,
    edit: TaskPathTemplateMergeEdit,
    show: ShowGuesser,
    recordRepresentation: (record) => {
        return `${record.id}`
    }
};
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/BasStation.java
@@ -7,6 +7,7 @@
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import com.vincent.rsf.server.manager.enums.StationTypeEnum;
import com.vincent.rsf.server.manager.service.WarehouseAreasService;
import com.vincent.rsf.server.system.entity.DictData;
@@ -26,7 +27,7 @@
import java.util.stream.Collectors;
@Data
@TableName("man_bas_station")
@TableName(value = "man_bas_station", autoResultMap = true)
public class BasStation implements Serializable {
    private static final long serialVersionUID = 1L;
@@ -171,6 +172,13 @@
    @TableField(exist = false)
    private List<Long> containerTypes;
    /**
     * 别名
     */
    @ApiModelProperty(value = "别名")
    @TableField(typeHandler = JacksonTypeHandler.class)
    private List<String> stationAlias;
    public BasStation() {
    }
rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/TaskMissionSchedules.java
@@ -2,18 +2,13 @@
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.vincent.rsf.framework.common.Cools;
import com.vincent.rsf.framework.exception.CoolException;
import com.vincent.rsf.server.manager.controller.params.LocToTaskParams;
import com.vincent.rsf.server.manager.entity.*;
import com.vincent.rsf.server.manager.enums.LocStsType;
import com.vincent.rsf.server.manager.enums.StationTypeEnum;
import com.vincent.rsf.framework.common.SnowflakeIdWorker;
import com.vincent.rsf.server.manager.entity.Loc;
import com.vincent.rsf.server.manager.entity.Task;
import com.vincent.rsf.server.manager.enums.TaskStsType;
import com.vincent.rsf.server.manager.enums.TaskType;
import com.vincent.rsf.server.manager.service.LocItemService;
import com.vincent.rsf.server.manager.service.LocService;
import com.vincent.rsf.server.manager.service.TaskService;
import com.vincent.rsf.server.manager.service.impl.BasContainerServiceImpl;
import com.vincent.rsf.server.manager.service.impl.WarehouseAreasServiceImpl;
import com.vincent.rsf.server.system.constant.GlobalConfigCode;
import com.vincent.rsf.server.system.entity.*;
import com.vincent.rsf.server.system.service.ConfigService;
@@ -47,31 +42,27 @@
    @Autowired
    private ConfigService configService;
    @Autowired
    private WarehouseAreasServiceImpl warehouseAreasService;
    @Autowired
    private LocService locService;
    @Autowired
    private LocItemService locItemService;
    private TaskPathTemplateMergeServiceImpl taskPathTemplateMergeService;
    @Autowired
    private BasContainerServiceImpl basContainerService;
    private TaskInstanceServiceImpl taskInstanceService;
    @Autowired
    private TaskPathTemplateServiceImpl taskPathTemplateService;
    @Autowired
    private TaskPathTemplateNodeServiceImpl taskPathTemplateNodeService;
    @Autowired
    private TaskInstanceServiceImpl taskInstanceService;
    @Autowired
    private TaskInstanceNodeServiceImpl taskInstanceNodeService;
    @Autowired
    private SubsystemFlowTemplateServiceImpl subsystemFlowTemplateService;
    @Autowired
    private FlowStepLogServiceImpl flowStepLogService;
    @Autowired
    private FlowStepTemplateServiceImpl flowStepTemplateService;
    @Autowired
    private FlowStepInstanceServiceImpl flowStepInstanceService;
    private TaskInstanceNodeServiceImpl taskInstanceNodeService;
    @Autowired
    private SnowflakeIdWorker snowflakeIdWorker;
    @Autowired
    private FlowInstanceServiceImpl flowInstanceService;
    @Autowired
    private FlowStepInstanceServiceImpl flowStepInstanceService;
    /**
     * @author Munch D. Luffy
@@ -86,7 +77,6 @@
        if (!Boolean.parseBoolean(config.getVal())) {
            return;
        }
        List<Task> taskList = taskService.list(new LambdaQueryWrapper<Task>().eq(Task::getTaskStatus, TaskStsType.MISSION_INITIAL.id));
        if (Objects.isNull(taskList)) {
            return;
@@ -103,6 +93,7 @@
                sou = task.getOrgSite();
                Loc loc = locService.getOne(new LambdaQueryWrapper<Loc>().eq(Loc::getCode, task.getTargLoc()));
                end = loc.getAreaId().toString();
                task.setTaskStatus(TaskStsType.GENERATE_IN.id);
            } else if (task.getTaskType().equals(TaskType.TASK_TYPE_OUT.type)
                    || task.getTaskType().equals(TaskType.TASK_TYPE_PICK_AGAIN_OUT.type)
                    || task.getTaskType().equals(TaskType.TASK_TYPE_MERGE_OUT.type)
@@ -111,10 +102,11 @@
                Loc loc = locService.getOne(new LambdaQueryWrapper<Loc>().eq(Loc::getCode, task.getOrgLoc()));
                sou = loc.getAreaId().toString();
                end = task.getTargSite();
                task.setTaskStatus(TaskStsType.GENERATE_OUT.id);
            }
            List<TaskPathTemplate> taskPathTemplates = taskPathTemplateService.list(new LambdaQueryWrapper<TaskPathTemplate>().eq(TaskPathTemplate::getSourceType, sou).eq(TaskPathTemplate::getTargetType, end));
            if (Objects.isNull(taskPathTemplates) || taskPathTemplates.isEmpty()) {
                List<TaskPathTemplate> list = taskPathTemplateService.list(new LambdaQueryWrapper<>());
            List<TaskPathTemplateMerge> taskPathTemplateMergeList = taskPathTemplateMergeService.list(new LambdaQueryWrapper<TaskPathTemplateMerge>().eq(TaskPathTemplateMerge::getSourceType, sou).eq(TaskPathTemplateMerge::getTargetType, end));
            if (Objects.isNull(taskPathTemplateMergeList) || taskPathTemplateMergeList.isEmpty()) {
                List<TaskPathTemplateMerge> list = taskPathTemplateMergeService.list(new LambdaQueryWrapper<TaskPathTemplateMerge>().eq(TaskPathTemplateMerge::getStepSize,1));
                if (!Cools.isEmpty(list)) {
                    List<String[]> stationList = new ArrayList<>();
                    list.forEach(taskPathTemplate -> {
@@ -122,16 +114,85 @@
                    });
                    List<Long> longs = RouteWmsStepFlow.routeGet(stationList, sou, end);
                    if (longs != null && !longs.isEmpty()) {
                        TaskPathTemplate taskPathTemplate = new TaskPathTemplate();
                        taskPathTemplate.setTemplateCode(sou+"===>"+end);
                        taskPathTemplate.setTemplateName(sou+"===>"+end);
                        taskPathTemplate.setSourceType(sou);
                        taskPathTemplate.setTargetType(end);
                        taskPathTemplateService.save(taskPathTemplate);
                        TaskPathTemplateMerge taskPathTemplateMerge = new TaskPathTemplateMerge();
                        taskPathTemplateMerge.setTemplateCode(sou+"===>"+end);
                        taskPathTemplateMerge.setTemplateName(sou+"===>"+end);
                        taskPathTemplateMerge.setSourceType(sou);
                        taskPathTemplateMerge.setTargetType(end);
                        List<Integer> longList = new ArrayList<>();
                        for (Long id : longs) {
                            TaskPathTemplateMerge one = taskPathTemplateMergeService.getOne(new LambdaQueryWrapper<TaskPathTemplateMerge>().eq(TaskPathTemplateMerge::getId, id));
                            longList.addAll(one.getConditionExpression());
                        }
                        taskPathTemplateMerge.setConditionExpression(longList);
                        taskPathTemplateMerge.setStepSize(longList.size());
                        taskPathTemplateMergeService.save(taskPathTemplateMerge);
                    }
                    System.out.println("任务:"+task.getTaskCode()+"查询步序为:"+longs);
                }
            } else {
                //生成实际路径
                boolean actualPath = generateActualPath(task, taskPathTemplateMergeList.get(0));
                if (!actualPath) {
                    log.error("生成实际路径失败");
                }
            }
        });
    }
    public boolean generateActualPath(Task task,TaskPathTemplateMerge taskPathTemplateMerge) {
        boolean actualPath = false;
        List<Integer> conditionExpression = taskPathTemplateMerge.getConditionExpression();
        Integer i = 0;//it顺序
        Integer j = 0;//suT顺序
        TaskInstance taskInstance = new TaskInstance(taskPathTemplateMerge,task);
        boolean save = taskInstanceService.save(taskInstance);
        if (!save) {
            return false;
        }
        for (Integer id : conditionExpression) {
            TaskPathTemplate taskPathTemplate = taskPathTemplateService.getById(id);
            if (taskPathTemplate == null) {
                return false;
            }
            List<TaskPathTemplateNode> taskPathTemplateNodeList = taskPathTemplateNodeService.list(new LambdaQueryWrapper<TaskPathTemplateNode>().eq(TaskPathTemplateNode::getTemplateId, taskPathTemplate.getId()));
            for (TaskPathTemplateNode taskPathTemplateNode : taskPathTemplateNodeList) {
                TaskInstanceNode taskInstanceNode = new TaskInstanceNode(taskPathTemplateNode);
                taskInstanceNode.setTaskId(taskInstance.getId());
                taskInstanceNode.setTaskNo(taskInstance.getTaskNo());
                i++;
                taskInstanceNode.setNodeOrder(i);
                taskInstanceNode.setNodeCode(String.valueOf(snowflakeIdWorker.nextId()));
                taskInstanceNodeService.save(taskInstanceNode);
                List<SubsystemFlowTemplate> subsystemFlowTemplateList = subsystemFlowTemplateService.list(new LambdaQueryWrapper<SubsystemFlowTemplate>().eq(SubsystemFlowTemplate::getFlowCode, taskPathTemplateNode.getNodeCode())
                        .eq(SubsystemFlowTemplate::getSystemCode, taskPathTemplateNode.getSystemCode()));
                for (SubsystemFlowTemplate subsystemFlowTemplate : subsystemFlowTemplateList) {
                    FlowInstance flowInstance = new FlowInstance(subsystemFlowTemplate);
                    flowInstance.setFlowInstanceNo(String.valueOf(snowflakeIdWorker.nextId()));
                    flowInstance.setTaskId(taskInstance.getId());
                    flowInstance.setTaskNo(taskInstance.getTaskNo());
                    flowInstance.setNodeInstanceId(taskInstanceNode.getId());
                    flowInstance.setNodeCode(String.valueOf(snowflakeIdWorker.nextId()));
                    flowInstanceService.save(flowInstance);
                    List<FlowStepTemplate> flowStepTemplateList = flowStepTemplateService.list(new LambdaQueryWrapper<FlowStepTemplate>().eq(FlowStepTemplate::getFlowId, subsystemFlowTemplate.getId()));
                    for (FlowStepTemplate flowStepTemplate : flowStepTemplateList) {
                        j++;
                        FlowStepInstance flowStepInstance = new FlowStepInstance(flowStepTemplate);
                        flowStepInstance.setFlowInstanceId(flowInstance.getId());
                        flowStepInstance.setFlowInstanceNo(flowInstance.getFlowInstanceNo());
                        flowStepInstance.setStepOrder(j);
                        flowStepInstance.setStepCode(String.valueOf(snowflakeIdWorker.nextId()));
                        flowStepInstanceService.save(flowStepInstance);
                    }
                }
            }
        }
        task.setDeviceSiteId(taskInstance.getId());
        taskService.updateById(task);
        return actualPath;
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/TaskSchedules.java
@@ -94,6 +94,43 @@
    @Autowired
    private BasStationService basStationService;
//    /**
//     * 任务下发
//     */
//    @Scheduled(cron = "0/5 * * * * ?  ")
//    @Transactional(rollbackFor = Exception.class)
//    public void pubTaskToWcs() {
//        Long loginUserId = SystemAuthUtils.getLoginUserId();
//        List<Integer> list = Arrays.asList(TaskType.TASK_TYPE_IN.type, TaskType.TASK_TYPE_OUT.type, TaskType.TASK_TYPE_LOC_MOVE.type, TaskType.TASK_TYPE_EMPTY_IN.type
//                , TaskType.TASK_TYPE_CHECK_IN.type, TaskType.TASK_TYPE_MERGE_IN.type, TaskType.TASK_TYPE_EMPTY_OUT.type, TaskType.TASK_TYPE_PICK_IN.type,
//                TaskType.TASK_TYPE_PICK_AGAIN_OUT.type, TaskType.TASK_TYPE_CHECK_OUT.type, TaskType.TASK_TYPE_MERGE_OUT.type);
//        List<Integer> integers = Arrays.asList(TaskStsType.GENERATE_IN.id, TaskStsType.GENERATE_OUT.id);
//        List<Task> tasks = taskService.list(new LambdaQueryWrapper<Task>()
//                .in(Task::getTaskType, list)
//                .in(Task::getTaskStatus, integers).last("limit 1")
//                .orderByDesc(Task::getSort));
//        for (Task task : tasks) {
//            /**移库不做站点操作*/
//            if (!task.getTaskType().equals(TaskType.TASK_TYPE_LOC_MOVE.type)) {
//                BasStation station = basStationService.getOne(new LambdaQueryWrapper<BasStation>()
//                        .eq(BasStation::getStationName,
//                                task.getTaskStatus().equals(TaskStsType.GENERATE_IN.id) ? task.getOrgSite() : task.getTargSite()));
//                if (Cools.isEmpty(station)){
//                    log.info("非光电站点任务下发:站点信息异常,任务信息:"+ JSON.toJSONString(task));
//                    continue;
//                }
//                if (station.getType().equals(StationTypeEnum.STATION_TYPE_MUTI.type)) {
//                    continue;
//                }
//            }
//            /**下发普通站点任务,报错回滚,不再往下执行*/
//            pubTaskToWcs(task);
//        }
//    }
    /**
     * @param
     * @return
@@ -235,102 +272,102 @@
//            });
//        }
    }
    /**
     * 非光电站点任务下发
     */
    @Scheduled(cron = "0/5 * * * * ?  ")
    @Transactional(rollbackFor = Exception.class)
    public void pubTaskToWcs() {
        Long loginUserId = SystemAuthUtils.getLoginUserId();
        List<Integer> list = Arrays.asList(TaskType.TASK_TYPE_IN.type, TaskType.TASK_TYPE_OUT.type, TaskType.TASK_TYPE_LOC_MOVE.type, TaskType.TASK_TYPE_EMPTY_IN.type
                , TaskType.TASK_TYPE_CHECK_IN.type, TaskType.TASK_TYPE_MERGE_IN.type, TaskType.TASK_TYPE_EMPTY_OUT.type, TaskType.TASK_TYPE_PICK_IN.type,
                TaskType.TASK_TYPE_PICK_AGAIN_OUT.type, TaskType.TASK_TYPE_CHECK_OUT.type, TaskType.TASK_TYPE_MERGE_OUT.type);
        List<Integer> integers = Arrays.asList(TaskStsType.GENERATE_IN.id, TaskStsType.GENERATE_OUT.id);
        List<Task> tasks = taskService.list(new LambdaQueryWrapper<Task>()
                .in(Task::getTaskType, list)
                .in(Task::getTaskStatus, integers).last("limit 1")
                .orderByDesc(Task::getSort));
        for (Task task : tasks) {
            /**移库不做站点操作*/
            if (!task.getTaskType().equals(TaskType.TASK_TYPE_LOC_MOVE.type)) {
                BasStation station = basStationService.getOne(new LambdaQueryWrapper<BasStation>()
                        .eq(BasStation::getStationName,
                        task.getTaskStatus().equals(TaskStsType.GENERATE_IN.id) ? task.getOrgSite() : task.getTargSite()));
                if (Cools.isEmpty(station)){
                    log.info("非光电站点任务下发:站点信息异常,任务信息:"+ JSON.toJSONString(task));
                    continue;
                }
                if (station.getType().equals(StationTypeEnum.STATION_TYPE_MUTI.type)) {
                    continue;
                }
            }
            /**下发普通站点任务,报错回滚,不再往下执行*/
            pubTaskToWcs(task);
        }
    }
    /**
     * @author Ryan
     * @date 2025/9/4
     * @description: 光电站点任务下发
     * @version 1.0
     */
    @Scheduled(cron = "0/5 * * * * ?  ")
    @Transactional(rollbackFor = Exception.class)
    public void taskToWCS() throws Exception {
        Long loginUserId = SystemAuthUtils.getLoginUserId();
        List<Integer> list = Arrays.asList(TaskType.TASK_TYPE_IN.type, TaskType.TASK_TYPE_OUT.type, TaskType.TASK_TYPE_LOC_MOVE.type, TaskType.TASK_TYPE_EMPTY_IN.type
                , TaskType.TASK_TYPE_CHECK_IN.type, TaskType.TASK_TYPE_MERGE_IN.type, TaskType.TASK_TYPE_EMPTY_OUT.type,
                TaskType.TASK_TYPE_PICK_AGAIN_OUT.type, TaskType.TASK_TYPE_CHECK_OUT.type, TaskType.TASK_TYPE_MERGE_OUT.type);
        List<Integer> integers = Arrays.asList(TaskStsType.GENERATE_IN.id, TaskStsType.GENERATE_OUT.id);
        List<Task> tasks = taskService.list(new LambdaQueryWrapper<Task>()
                .in(Task::getTaskType, list)
                .in(Task::getTaskStatus, integers)
                .orderByDesc(Task::getSort));
        for (Task task : tasks) {
            /**移库不做站点操作*/
            if (!task.getTaskType().equals(TaskType.TASK_TYPE_LOC_MOVE.type)) {
                BasStation station = basStationService.getOne(new LambdaQueryWrapper<BasStation>().eq(BasStation::getStationName,
                        task.getTaskStatus().equals(TaskStsType.GENERATE_IN.id) ? task.getOrgSite() : task.getTargSite()));
                /**过滤掉普通站点任务*/
                if (station.getType().equals(StationTypeEnum.STATION_TYPE_NORMAL.type)) {
                    continue;
                }
                Loc loc = locService.getOne(new LambdaQueryWrapper<Loc>().eq(Loc::getBarcode, task.getBarcode()));
                if (Objects.isNull(loc)) {
                    continue;
                }
                //判断是否深库位
                if (!LocUtils.isShallowLoc(loc.getCode())) {
                    //获取深库位对应的浅库位
                    String shallowLoc = LocUtils.getShallowLoc(loc.getCode());
                    if (StringUtils.isBlank(shallowLoc)) {
                        continue;
                    }
                    Loc shalloc = locService.getOne(new LambdaQueryWrapper<Loc>().eq(Loc::getCode, shallowLoc));
                    if (Objects.isNull(shalloc) || !shalloc.getUseStatus().equals(LocStsType.LOC_STS_TYPE_F.type)) {
                        //如果浅库位不在库跳出循环
                        continue;
                    }
                    LocToTaskParams params = new LocToTaskParams();
                    params.setOrgLoc(shallowLoc).setType(TaskType.TASK_TYPE_LOC_MOVE.type + "");
                    //生成移库任务
                    Task moveTask = locItemService.genMoveTask(params, loginUserId);
                    moveTask.setSort(!Objects.isNull(task.getSort()) ? task.getSort() + 1 : Constants.TASK_SORT_DEFAULT_VALUE + 1);
                    if (!taskService.updateById(moveTask)) {
                        throw new Exception("任务优先级更新失败!!");
                    }
                }
            }
            /**下发任务*/
            try {
                pubTaskToWcs(task);
            } catch (Exception e) {
                log.error("任务下发失败!!", e);
            }
        }
    }
//
//    /**
//     * 非光电站点任务下发
//     */
//    @Scheduled(cron = "0/5 * * * * ?  ")
//    @Transactional(rollbackFor = Exception.class)
//    public void pubTaskToWcs() {
//        Long loginUserId = SystemAuthUtils.getLoginUserId();
//        List<Integer> list = Arrays.asList(TaskType.TASK_TYPE_IN.type, TaskType.TASK_TYPE_OUT.type, TaskType.TASK_TYPE_LOC_MOVE.type, TaskType.TASK_TYPE_EMPTY_IN.type
//                , TaskType.TASK_TYPE_CHECK_IN.type, TaskType.TASK_TYPE_MERGE_IN.type, TaskType.TASK_TYPE_EMPTY_OUT.type, TaskType.TASK_TYPE_PICK_IN.type,
//                TaskType.TASK_TYPE_PICK_AGAIN_OUT.type, TaskType.TASK_TYPE_CHECK_OUT.type, TaskType.TASK_TYPE_MERGE_OUT.type);
//        List<Integer> integers = Arrays.asList(TaskStsType.GENERATE_IN.id, TaskStsType.GENERATE_OUT.id);
//        List<Task> tasks = taskService.list(new LambdaQueryWrapper<Task>()
//                .in(Task::getTaskType, list)
//                .in(Task::getTaskStatus, integers).last("limit 1")
//                .orderByDesc(Task::getSort));
//        for (Task task : tasks) {
//            /**移库不做站点操作*/
//            if (!task.getTaskType().equals(TaskType.TASK_TYPE_LOC_MOVE.type)) {
//                BasStation station = basStationService.getOne(new LambdaQueryWrapper<BasStation>()
//                        .eq(BasStation::getStationName,
//                        task.getTaskStatus().equals(TaskStsType.GENERATE_IN.id) ? task.getOrgSite() : task.getTargSite()));
//                if (Cools.isEmpty(station)){
//                    log.info("非光电站点任务下发:站点信息异常,任务信息:"+ JSON.toJSONString(task));
//                    continue;
//                }
//                if (station.getType().equals(StationTypeEnum.STATION_TYPE_MUTI.type)) {
//                    continue;
//                }
//            }
//            /**下发普通站点任务,报错回滚,不再往下执行*/
//            pubTaskToWcs(task);
//        }
//    }
//
//    /**
//     * @author Ryan
//     * @date 2025/9/4
//     * @description: 光电站点任务下发
//     * @version 1.0
//     */
//    @Scheduled(cron = "0/5 * * * * ?  ")
//    @Transactional(rollbackFor = Exception.class)
//    public void taskToWCS() throws Exception {
//        Long loginUserId = SystemAuthUtils.getLoginUserId();
//        List<Integer> list = Arrays.asList(TaskType.TASK_TYPE_IN.type, TaskType.TASK_TYPE_OUT.type, TaskType.TASK_TYPE_LOC_MOVE.type, TaskType.TASK_TYPE_EMPTY_IN.type
//                , TaskType.TASK_TYPE_CHECK_IN.type, TaskType.TASK_TYPE_MERGE_IN.type, TaskType.TASK_TYPE_EMPTY_OUT.type,
//                TaskType.TASK_TYPE_PICK_AGAIN_OUT.type, TaskType.TASK_TYPE_CHECK_OUT.type, TaskType.TASK_TYPE_MERGE_OUT.type);
//        List<Integer> integers = Arrays.asList(TaskStsType.GENERATE_IN.id, TaskStsType.GENERATE_OUT.id);
//        List<Task> tasks = taskService.list(new LambdaQueryWrapper<Task>()
//                .in(Task::getTaskType, list)
//                .in(Task::getTaskStatus, integers)
//                .orderByDesc(Task::getSort));
//        for (Task task : tasks) {
//            /**移库不做站点操作*/
//            if (!task.getTaskType().equals(TaskType.TASK_TYPE_LOC_MOVE.type)) {
//                BasStation station = basStationService.getOne(new LambdaQueryWrapper<BasStation>().eq(BasStation::getStationName,
//                        task.getTaskStatus().equals(TaskStsType.GENERATE_IN.id) ? task.getOrgSite() : task.getTargSite()));
//                /**过滤掉普通站点任务*/
//                if (station.getType().equals(StationTypeEnum.STATION_TYPE_NORMAL.type)) {
//                    continue;
//                }
//                Loc loc = locService.getOne(new LambdaQueryWrapper<Loc>().eq(Loc::getBarcode, task.getBarcode()));
//                if (Objects.isNull(loc)) {
//                    continue;
//                }
//                //判断是否深库位
//                if (!LocUtils.isShallowLoc(loc.getCode())) {
//                    //获取深库位对应的浅库位
//                    String shallowLoc = LocUtils.getShallowLoc(loc.getCode());
//                    if (StringUtils.isBlank(shallowLoc)) {
//                        continue;
//                    }
//                    Loc shalloc = locService.getOne(new LambdaQueryWrapper<Loc>().eq(Loc::getCode, shallowLoc));
//                    if (Objects.isNull(shalloc) || !shalloc.getUseStatus().equals(LocStsType.LOC_STS_TYPE_F.type)) {
//                        //如果浅库位不在库跳出循环
//                        continue;
//                    }
//                    LocToTaskParams params = new LocToTaskParams();
//                    params.setOrgLoc(shallowLoc).setType(TaskType.TASK_TYPE_LOC_MOVE.type + "");
//                    //生成移库任务
//                    Task moveTask = locItemService.genMoveTask(params, loginUserId);
//                    moveTask.setSort(!Objects.isNull(task.getSort()) ? task.getSort() + 1 : Constants.TASK_SORT_DEFAULT_VALUE + 1);
//                    if (!taskService.updateById(moveTask)) {
//                        throw new Exception("任务优先级更新失败!!");
//                    }
//                }
//            }
//            /**下发任务*/
//            try {
//                pubTaskToWcs(task);
//            } catch (Exception e) {
//                log.error("任务下发失败!!", e);
//            }
//        }
//    }
    /**
     * 每五秒校验深库位是否为空,如果浅库位有货,将浅库位移至深库位
rsf-server/src/main/java/com/vincent/rsf/server/system/controller/TaskPathTemplateMergeController.java
New file
@@ -0,0 +1,110 @@
package com.vincent.rsf.server.system.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.system.entity.TaskPathTemplateMerge;
import com.vincent.rsf.server.system.service.TaskPathTemplateMergeService;
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 TaskPathTemplateMergeController extends BaseController {
    @Autowired
    private TaskPathTemplateMergeService taskPathTemplateMergeService;
    @PreAuthorize("hasAuthority('system:taskPathTemplateMerge:list')")
    @PostMapping("/taskPathTemplateMerge/page")
    public R page(@RequestBody Map<String, Object> map) {
        BaseParam baseParam = buildParam(map, BaseParam.class);
        PageParam<TaskPathTemplateMerge, BaseParam> pageParam = new PageParam<>(baseParam, TaskPathTemplateMerge.class);
        return R.ok().add(taskPathTemplateMergeService.page(pageParam, pageParam.buildWrapper(true)));
    }
    @PreAuthorize("hasAuthority('system:taskPathTemplateMerge:list')")
    @PostMapping("/taskPathTemplateMerge/list")
    public R list(@RequestBody Map<String, Object> map) {
        return R.ok().add(taskPathTemplateMergeService.list());
    }
    @PreAuthorize("hasAuthority('system:taskPathTemplateMerge:list')")
    @PostMapping({"/taskPathTemplateMerge/many/{ids}", "/taskPathTemplateMerges/many/{ids}"})
    public R many(@PathVariable Long[] ids) {
        return R.ok().add(taskPathTemplateMergeService.listByIds(Arrays.asList(ids)));
    }
    @PreAuthorize("hasAuthority('system:taskPathTemplateMerge:list')")
    @GetMapping("/taskPathTemplateMerge/{id}")
    public R get(@PathVariable("id") Long id) {
        return R.ok().add(taskPathTemplateMergeService.getById(id));
    }
    @PreAuthorize("hasAuthority('system:taskPathTemplateMerge:save')")
    @OperationLog("Create 物料权限")
    @PostMapping("/taskPathTemplateMerge/save")
    public R save(@RequestBody TaskPathTemplateMerge taskPathTemplateMerge) {
        taskPathTemplateMerge.setCreateBy(getLoginUserId());
        taskPathTemplateMerge.setCreateTime(new Date());
        taskPathTemplateMerge.setUpdateBy(getLoginUserId());
        taskPathTemplateMerge.setUpdateTime(new Date());
        if (!taskPathTemplateMergeService.save(taskPathTemplateMerge)) {
            return R.error("Save Fail");
        }
        return R.ok("Save Success").add(taskPathTemplateMerge);
    }
    @PreAuthorize("hasAuthority('system:taskPathTemplateMerge:update')")
    @OperationLog("Update 物料权限")
    @PostMapping("/taskPathTemplateMerge/update")
    public R update(@RequestBody TaskPathTemplateMerge taskPathTemplateMerge) {
        taskPathTemplateMerge.setUpdateBy(getLoginUserId());
        taskPathTemplateMerge.setUpdateTime(new Date());
        if (!taskPathTemplateMergeService.updateById(taskPathTemplateMerge)) {
            return R.error("Update Fail");
        }
        return R.ok("Update Success").add(taskPathTemplateMerge);
    }
    @PreAuthorize("hasAuthority('system:taskPathTemplateMerge:remove')")
    @OperationLog("Delete 物料权限")
    @PostMapping("/taskPathTemplateMerge/remove/{ids}")
    public R remove(@PathVariable Long[] ids) {
        if (!taskPathTemplateMergeService.removeByIds(Arrays.asList(ids))) {
            return R.error("Delete Fail");
        }
        return R.ok("Delete Success").add(ids);
    }
    @PreAuthorize("hasAuthority('system:taskPathTemplateMerge:list')")
    @PostMapping("/taskPathTemplateMerge/query")
    public R query(@RequestParam(required = false) String condition) {
        List<KeyValVo> vos = new ArrayList<>();
        LambdaQueryWrapper<TaskPathTemplateMerge> wrapper = new LambdaQueryWrapper<>();
        if (!Cools.isEmpty(condition)) {
            wrapper.like(TaskPathTemplateMerge::getId, condition);
        }
        taskPathTemplateMergeService.page(new Page<>(1, 30), wrapper).getRecords().forEach(
                item -> vos.add(new KeyValVo(item.getId(), item.getId()))
        );
        return R.ok().add(vos);
    }
    @PreAuthorize("hasAuthority('system:taskPathTemplateMerge:list')")
    @PostMapping("/taskPathTemplateMerge/export")
    public void export(@RequestBody Map<String, Object> map, HttpServletResponse response) throws Exception {
        ExcelUtil.build(ExcelUtil.create(taskPathTemplateMergeService.list(), TaskPathTemplateMerge.class), response);
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/system/entity/FlowInstance.java
@@ -183,6 +183,12 @@
    private Date updateTime;
    public FlowInstance() {}
    public FlowInstance(SubsystemFlowTemplate subsystemFlowTemplate) {
        this.flowTemplateId = subsystemFlowTemplate.getId();
        this.flowTemplateCode = subsystemFlowTemplate.getFlowCode();
        this.templateVersion = subsystemFlowTemplate.getVersion();
    }
    public FlowInstance(String flowInstanceNo,Long taskId,String taskNo,Long nodeInstanceId,String nodeCode,Long flowTemplateId,String flowTemplateCode,Integer templateVersion,Short status,String currentStepCode,Integer currentStepOrder,String executeParams,String executeResult,String errorCode,String errorMessage,Date startTime,Date endTime,Date timeoutAt,Integer durationSeconds,Integer retryTimes,Date lastRetryTime,String contextData,Date createTime,Date updateTime) {
        this.flowInstanceNo = flowInstanceNo;
rsf-server/src/main/java/com/vincent/rsf/server/system/entity/FlowStepInstance.java
@@ -147,6 +147,11 @@
    private Date updateTime;
    public FlowStepInstance() {}
    public FlowStepInstance(FlowStepTemplate  flowStepTemplate) {
        this.stepTemplateId = flowStepTemplate.getId();
        this.stepName = flowStepTemplate.getStepName();
        this.stepType = flowStepTemplate.getStepType();
    }
    public FlowStepInstance(Long flowInstanceId,String flowInstanceNo,Integer stepOrder,String stepCode,String stepName,String stepType,Long stepTemplateId,Short status,String executeResult,String errorCode,String errorMessage,Date startTime,Date endTime,Integer durationSeconds,String inputData,String outputData,Integer retryTimes,Date createTime,Date updateTime) {
        this.flowInstanceId = flowInstanceId;
rsf-server/src/main/java/com/vincent/rsf/server/system/entity/TaskInstance.java
@@ -2,6 +2,8 @@
import java.text.SimpleDateFormat;
import java.util.Date;
import com.vincent.rsf.server.manager.entity.Task;
import org.springframework.format.annotation.DateTimeFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
@@ -243,6 +245,17 @@
    private Date updateTime;
    public TaskInstance() {}
    public TaskInstance(TaskPathTemplateMerge taskPathTemplateMerge, Task task) {
        this.templateId = taskPathTemplateMerge.getId();
        this.templateCode = taskPathTemplateMerge.getTemplateCode();
        this.templateVersion = taskPathTemplateMerge.getVersion();
        this.sourceCode = taskPathTemplateMerge.getSourceType();
        this.targetCode = taskPathTemplateMerge.getTargetType();
//        this.sourceInfo = taskPathTemplateMerge.getSourceType();
//        this.targetInfo = taskPathTemplateMerge.getTargetType();
        this.taskNo = task.getTaskCode();
        this.bizType = task.getTaskType$();
    }
    public TaskInstance(String taskNo,String bizNo,String bizType,Long templateId,String templateCode,Integer templateVersion,String sourceInfo,String targetInfo,String sourceCode,String targetCode,String plannedPath,String actualPath,Short priority,Date timeoutAt,Short status,String currentNodeCode,String currentNodeName,Integer totalNodes,Integer completedNodes,Double progressRate,Integer estimatedDurationMinutes,Integer actualDurationMinutes,Date startTime,Date endTime,String resultCode,String resultMessage,String resultData,Integer retryTimes,Date lastRetryTime,String extParams,String remark,Long createBy,Long updateBy,Date createTime,Date updateTime) {
        this.taskNo = taskNo;
rsf-server/src/main/java/com/vincent/rsf/server/system/entity/TaskInstanceNode.java
@@ -177,6 +177,12 @@
    private Date updateTime;
    public TaskInstanceNode() {}
    public TaskInstanceNode(TaskPathTemplateNode taskPathTemplateNode) {
        this.nodeName = taskPathTemplateNode.getNodeName();
        this.nodeType = taskPathTemplateNode.getNodeType();
        this.systemCode = taskPathTemplateNode.getSystemCode();
        this.systemName = taskPathTemplateNode.getSystemName();
    }
    public TaskInstanceNode(Long taskId,String taskNo,Integer nodeOrder,String nodeCode,String nodeName,String nodeType,String systemCode,String systemName,String executeParams,Short status,String executeResult,String errorCode,String errorMessage,Date estimatedStartTime,Date actualStartTime,Date actualEndTime,Date timeoutAt,Integer durationSeconds,Integer retryTimes,Integer maxRetryTimes,String dependsOnNodes,Date createTime,Date updateTime) {
        this.taskId = taskId;
rsf-server/src/main/java/com/vincent/rsf/server/system/entity/TaskPathTemplateMerge.java
New file
@@ -0,0 +1,234 @@
package com.vincent.rsf.server.system.entity;
import java.text.SimpleDateFormat;
import java.util.*;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import lombok.experimental.Accessors;
import org.springframework.format.annotation.DateTimeFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.text.SimpleDateFormat;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.TableLogic;
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
@Accessors(chain = true)
@TableName(value = "mission_task_path_template_merge", autoResultMap = true)
public class TaskPathTemplateMerge 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 templateCode;
    /**
     * 模板名称
     */
    @ApiModelProperty(value= "模板名称")
    private String templateName;
    /**
     * 起点类型/起点系统标识
     */
    @ApiModelProperty(value= "起点类型/起点系统标识")
    private String sourceType;
    /**
     * 终点类型/终点系统标识
     */
    @ApiModelProperty(value= "终点类型/终点系统标识")
    private String targetType;
    /**
     * 条件表达式(JSON),用于更复杂的匹配
     */
    @ApiModelProperty(value = "条件表达式(JSON),用于更复杂的匹配")
    @TableField(typeHandler = JacksonTypeHandler.class)
    private List<Integer> conditionExpression;
    /**
     * 条件描述,人工可读
     */
    @ApiModelProperty(value= "条件描述,人工可读")
    private String conditionDesc;
    /**
     * 版本号
     */
    @ApiModelProperty(value= "版本号")
    private Integer version;
    /**
     * 是否为当前生效版本 0-否 1-是
     */
    @ApiModelProperty(value= "是否为当前生效版本 0-否 1-是")
    private Short isCurrent;
    /**
     * 生效时间
     */
    @ApiModelProperty(value= "生效时间")
    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
    private Date effectiveTime;
    /**
     * 失效时间
     */
    @ApiModelProperty(value= "失效时间")
    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
    private Date expireTime;
    /**
     * 优先级 1-10,数字越小优先级越高
     */
    @ApiModelProperty(value= "优先级 1-10,数字越小优先级越高")
    private Short priority;
    /**
     * 整体超时时间(分钟)
     */
    @ApiModelProperty(value= "整体超时时间(分钟)")
    private Integer timeoutMinutes;
    /**
     * 最大重试次数
     */
    @ApiModelProperty(value= "最大重试次数")
    private Integer maxRetryTimes;
    /**
     * 重试间隔(秒)
     */
    @ApiModelProperty(value= "重试间隔(秒)")
    private Integer retryIntervalSeconds;
    /**
     * 状态 0-禁用 1-启用
     */
    @ApiModelProperty(value= "状态 0-禁用 1-启用")
    private Short status;
    /**
     * 备注
     */
    @ApiModelProperty(value= "备注")
    private String remark;
    /**
     * 创建人
     */
    @ApiModelProperty(value= "创建人")
    private Long createBy;
    /**
     * 更新人
     */
    @ApiModelProperty(value= "更新人")
    private Long updateBy;
    /**
     * 创建时间
     */
    @ApiModelProperty(value= "创建时间")
    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
    private Date createTime;
    /**
     * 更新时间
     */
    @ApiModelProperty(value= "更新时间")
    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
    private Date updateTime;
    /**
     * 步序长度
     */
    @ApiModelProperty(value= "步序长度")
    private Integer stepSize;
    /**
     * 租户
     */
    @ApiModelProperty(value= "租户")
    private Long tenantId;
    /**
     * 是否删除 1: 是  0: 否
     */
    @ApiModelProperty(value= "是否删除 1: 是  0: 否  ")
    @TableLogic
    private Long deleted;
    public TaskPathTemplateMerge() {}
    public String getEffectiveTime$(){
        if (Cools.isEmpty(this.effectiveTime)){
            return "";
        }
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.effectiveTime);
    }
    public String getExpireTime$(){
        if (Cools.isEmpty(this.expireTime)){
            return "";
        }
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.expireTime);
    }
    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;
        }
    }
    public String[] route(){
        return new String[]{this.sourceType, this.targetType, this.stepSize.toString(), this.id.toString()};
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/system/mapper/TaskPathTemplateMergeMapper.java
New file
@@ -0,0 +1,12 @@
package com.vincent.rsf.server.system.mapper;
import com.vincent.rsf.server.system.entity.TaskPathTemplateMerge;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
@Mapper
@Repository
public interface TaskPathTemplateMergeMapper extends BaseMapper<TaskPathTemplateMerge> {
}
rsf-server/src/main/java/com/vincent/rsf/server/system/service/TaskPathTemplateMergeService.java
New file
@@ -0,0 +1,8 @@
package com.vincent.rsf.server.system.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.vincent.rsf.server.system.entity.TaskPathTemplateMerge;
public interface TaskPathTemplateMergeService extends IService<TaskPathTemplateMerge> {
}
rsf-server/src/main/java/com/vincent/rsf/server/system/service/impl/TaskPathTemplateMergeServiceImpl.java
New file
@@ -0,0 +1,12 @@
package com.vincent.rsf.server.system.service.impl;
import com.vincent.rsf.server.system.mapper.TaskPathTemplateMergeMapper;
import com.vincent.rsf.server.system.entity.TaskPathTemplateMerge;
import com.vincent.rsf.server.system.service.TaskPathTemplateMergeService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
@Service("taskPathTemplateMergeService")
public class TaskPathTemplateMergeServiceImpl extends ServiceImpl<TaskPathTemplateMergeMapper, TaskPathTemplateMerge> implements TaskPathTemplateMergeService {
}
rsf-server/src/main/java/taskPathTemplateMerge.sql
New file
@@ -0,0 +1,37 @@
-- save taskPathTemplateMerge record
-- mysql
insert into `sys_menu` ( `name`, `parent_id`, `route`, `component`, `type`, `sort`, `tenant_id`, `status`) values ( 'menu.taskPathTemplateMerge', '0', '/system/taskPathTemplateMerge', 'taskPathTemplateMerge', '0' , '0', '1' , '1');
insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Query 项目实际路径', '', '1', 'system:taskPathTemplateMerge:list', '0', '1', '1');
insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Create 项目实际路径', '', '1', 'system:taskPathTemplateMerge:save', '1', '1', '1');
insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Update 项目实际路径', '', '1', 'system:taskPathTemplateMerge:update', '2', '1', '1');
insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Delete 项目实际路径', '', '1', 'system:taskPathTemplateMerge:remove', '3', '1', '1');
-- locale menu name
taskPathTemplateMerge: 'TaskPathTemplateMerge',
-- locale field
taskPathTemplateMerge: {
    templateCode: "templateCode",
    templateName: "templateName",
    sourceType: "sourceType",
    targetType: "targetType",
    conditionExpression: "conditionExpression",
    conditionDesc: "conditionDesc",
    version: "version",
    isCurrent: "isCurrent",
    effectiveTime: "effectiveTime",
    expireTime: "expireTime",
    priority: "priority",
    timeoutMinutes: "timeoutMinutes",
    maxRetryTimes: "maxRetryTimes",
    retryIntervalSeconds: "retryIntervalSeconds",
    remark: "remark",
    stepSize: "stepSize",
},
-- ResourceContent
import taskPathTemplateMerge from './taskPathTemplateMerge';
case 'taskPathTemplateMerge':
    return taskPathTemplateMerge;
rsf-server/src/main/resources/mapper/system/TaskPathTemplateMergeMapper.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.system.mapper.TaskPathTemplateMergeMapper">
</mapper>