From c01d9b053852b12e7d3ced66367babb4d499b14b Mon Sep 17 00:00:00 2001
From: vincentlu <t1341870251@gmail.com>
Date: 星期四, 26 二月 2026 11:44:15 +0800
Subject: [PATCH] #
---
zy-acs-flow/src/page/guarantee/CronField.jsx | 150 ++++++++++
zy-acs-flow/src/page/userLogin/UserLoginList.jsx | 2
zy-acs-flow/src/page/action/ActionList.jsx | 2
zy-acs-flow/src/page/loc/LocList.jsx | 2
zy-acs-flow/src/page/guarantee/GuaranteeList.jsx | 59 +++-
zy-acs-flow/src/page/jam/JamList.jsx | 2
zy-acs-flow/src/page/vehFaultRec/VehFaultRecList.jsx | 2
zy-acs-flow/src/page/agvSts/AgvStsList.jsx | 2
zy-acs-flow/src/page/code/CodeList.jsx | 2
zy-acs-flow/src/page/config/ConfigList.jsx | 2
zy-acs-flow/src/page/actionSts/ActionStsList.jsx | 2
zy-acs-flow/src/page/role/RoleList.jsx | 4
zy-acs-flow/src/page/busSts/BusStsList.jsx | 2
zy-acs-flow/src/page/guarantee/ScopeField.jsx | 70 +++++
zy-acs-flow/src/page/user/UserList.jsx | 2
zy-acs-flow/src/page/locSts/LocStsList.jsx | 2
zy-acs-flow/src/page/operationRecord/OperationRecordList.jsx | 2
zy-acs-flow/src/page/travel/TravelList.jsx | 2
zy-acs-flow/src/page/bus/BusList.jsx | 2
zy-acs-flow/src/page/guarantee/cronUtils.js | 168 ++++++++++++
zy-acs-flow/src/page/guarantee/GuaranteeEdit.jsx | 70 ++--
zy-acs-flow/src/page/guarantee/GuaranteePanel.jsx | 18 +
zy-acs-flow/src/i18n/zh.js | 40 ++
zy-acs-flow/src/page/codeGap/CodeGapList.jsx | 2
zy-acs-flow/src/page/agvDetail/AgvDetailList.jsx | 2
zy-acs-flow/src/page/tenant/TenantList.jsx | 2
zy-acs-flow/src/i18n/en.js | 40 ++
zy-acs-flow/src/page/funcSta/FuncStaList.jsx | 2
zy-acs-flow/src/page/zone/ZoneList.jsx | 2
zy-acs-flow/src/page/lane/LaneList.jsx | 2
zy-acs-flow/src/page/task/TaskList.jsx | 2
zy-acs-flow/src/page/guarantee/guaranteeConstants.js | 63 ++++
zy-acs-flow/src/page/staType/StaTypeList.jsx | 2
zy-acs-flow/src/page/segment/SegmentList.jsx | 2
zy-acs-flow/src/page/staReserve/StaReserveList.jsx | 2
zy-acs-flow/src/page/actionType/ActionTypeList.jsx | 2
zy-acs-flow/src/page/integrationRecord/IntegrationRecordList.jsx | 2
zy-acs-flow/src/page/agv/AgvList.jsx | 2
zy-acs-flow/src/page/guarantee/GuaranteeCreate.jsx | 67 ++--
zy-acs-flow/src/page/sta/StaList.jsx | 2
zy-acs-flow/src/page/staSts/StaStsList.jsx | 2
zy-acs-flow/src/page/agvModel/AgvModelList.jsx | 2
zy-acs-flow/src/page/route/RouteList.jsx | 2
zy-acs-flow/src/page/host/HostList.jsx | 2
zy-acs-flow/src/page/locType/LocTypeList.jsx | 2
zy-acs-flow/src/page/mission/MissionResend.jsx | 4
zy-acs-flow/src/page/mission/MissionShow.jsx | 2
zy-acs-flow/src/page/area/AreaList.jsx | 2
zy-acs-flow/src/page/taskType/TaskTypeList.jsx | 2
zy-acs-flow/src/page/taskSts/TaskStsList.jsx | 2
50 files changed, 698 insertions(+), 131 deletions(-)
diff --git a/zy-acs-flow/src/i18n/en.js b/zy-acs-flow/src/i18n/en.js
index 2fd3b41..ed46a89 100644
--- a/zy-acs-flow/src/i18n/en.js
+++ b/zy-acs-flow/src/i18n/en.js
@@ -708,6 +708,46 @@
},
},
},
+ guarantee: {
+ scope: {
+ helper: 'Select the scope for this plan; defaults to global coverage',
+ global: 'Global',
+ model: 'By model',
+ area: 'By area',
+ biz: 'By business type',
+ agv: 'Specific vehicles',
+ globalHelper: 'Applies to all vehicles',
+ globalTip: 'Select a scope type to limit the plan',
+ },
+ schedule: {
+ label: 'Capacity window',
+ type: 'Frequency',
+ daily: 'Daily',
+ weekly: 'Weekly',
+ monthly: 'Monthly',
+ time: 'Execution time',
+ weeklyLabel: 'Weekdays',
+ monthlyLabel: 'Days of month',
+ monthHelper: 'Select at least one day',
+ monthDay: 'Day %{day}',
+ preview: 'Cron expression',
+ descriptionPrefix: 'Runs as %{desc}',
+ description: {
+ daily: 'every day at %{time}',
+ weekly: 'every week on %{days} at %{time}',
+ monthly: 'every month on %{days} at %{time}',
+ },
+ },
+ week: {
+ mon: 'Mon',
+ tue: 'Tue',
+ wed: 'Wed',
+ thu: 'Thu',
+ fri: 'Fri',
+ sat: 'Sat',
+ sun: 'Sun',
+ },
+ },
sta: {
depthHint: 'Set depth to 0 to keep the default value.',
enums: {
diff --git a/zy-acs-flow/src/i18n/zh.js b/zy-acs-flow/src/i18n/zh.js
index c0d2ad1..3f31d4a 100644
--- a/zy-acs-flow/src/i18n/zh.js
+++ b/zy-acs-flow/src/i18n/zh.js
@@ -708,6 +708,46 @@
},
},
},
+ guarantee: {
+ scope: {
+ helper: '閫夋嫨浣滅敤鑼冨洿锛岄粯璁や负鍏ㄥ眬鐢熸晥',
+ global: '鍏ㄥ眬',
+ model: '鎸夎溅鍨�',
+ area: '鎸夊尯鍩�',
+ biz: '鎸変笟鍔$被鍨�',
+ agv: '鎸囧畾杞﹁締',
+ globalHelper: '鍏ㄥ眬閫傜敤',
+ globalTip: '濡傞渶闄愬畾锛岃鍏堥�夋嫨浣滅敤鑼冨洿',
+ },
+ schedule: {
+ label: '淇濋殰鏃堕棿閰嶇疆',
+ type: '鎵ц棰戠巼',
+ daily: '姣忓ぉ',
+ weekly: '姣忓懆',
+ monthly: '姣忔湀',
+ time: '鎵ц鏃堕棿',
+ weeklyLabel: '鎵ц鏄熸湡',
+ monthlyLabel: '鎵ц鏃�',
+ monthHelper: '鑷冲皯閫夋嫨涓�涓棩鏈�',
+ monthDay: '%{day} 鏃�',
+ preview: 'Cron 琛ㄨ揪寮�',
+ descriptionPrefix: '绯荤粺灏嗗湪 %{desc} 瑙﹀彂',
+ description: {
+ daily: '姣忓ぉ %{time}',
+ weekly: '姣忓懆 %{days} %{time}',
+ monthly: '姣忔湀 %{days} %{time}',
+ },
+ },
+ week: {
+ mon: '鍛ㄤ竴',
+ tue: '鍛ㄤ簩',
+ wed: '鍛ㄤ笁',
+ thu: '鍛ㄥ洓',
+ fri: '鍛ㄤ簲',
+ sat: '鍛ㄥ叚',
+ sun: '鍛ㄦ棩',
+ },
+ },
sta: {
depthHint: '娣卞害璁剧疆涓� 0 琛ㄧず娌跨敤榛樿鍊笺��',
enums: {
diff --git a/zy-acs-flow/src/page/action/ActionList.jsx b/zy-acs-flow/src/page/action/ActionList.jsx
index aa0c286..8c77c3e 100644
--- a/zy-acs-flow/src/page/action/ActionList.jsx
+++ b/zy-acs-flow/src/page/action/ActionList.jsx
@@ -122,7 +122,7 @@
theme.transitions.create(['all'], {
duration: theme.transitions.duration.enteringScreen,
}),
- marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
+ marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
}}
title={"menu.action"}
empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
diff --git a/zy-acs-flow/src/page/actionSts/ActionStsList.jsx b/zy-acs-flow/src/page/actionSts/ActionStsList.jsx
index 7985600..c472f53 100644
--- a/zy-acs-flow/src/page/actionSts/ActionStsList.jsx
+++ b/zy-acs-flow/src/page/actionSts/ActionStsList.jsx
@@ -91,7 +91,7 @@
theme.transitions.create(['all'], {
duration: theme.transitions.duration.enteringScreen,
}),
- marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
+ marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
}}
title={"menu.actionSts"}
empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
diff --git a/zy-acs-flow/src/page/actionType/ActionTypeList.jsx b/zy-acs-flow/src/page/actionType/ActionTypeList.jsx
index 8e60509..0a3dd57 100644
--- a/zy-acs-flow/src/page/actionType/ActionTypeList.jsx
+++ b/zy-acs-flow/src/page/actionType/ActionTypeList.jsx
@@ -91,7 +91,7 @@
theme.transitions.create(['all'], {
duration: theme.transitions.duration.enteringScreen,
}),
- marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
+ marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
}}
title={"menu.actionType"}
empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
diff --git a/zy-acs-flow/src/page/agv/AgvList.jsx b/zy-acs-flow/src/page/agv/AgvList.jsx
index b0855da..56da0da 100644
--- a/zy-acs-flow/src/page/agv/AgvList.jsx
+++ b/zy-acs-flow/src/page/agv/AgvList.jsx
@@ -168,7 +168,7 @@
theme.transitions.create(['all'], {
duration: theme.transitions.duration.enteringScreen,
}),
- marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
+ marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
}}
title={"menu.agv"}
empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
diff --git a/zy-acs-flow/src/page/agvDetail/AgvDetailList.jsx b/zy-acs-flow/src/page/agvDetail/AgvDetailList.jsx
index b18562f..6889492 100644
--- a/zy-acs-flow/src/page/agvDetail/AgvDetailList.jsx
+++ b/zy-acs-flow/src/page/agvDetail/AgvDetailList.jsx
@@ -119,7 +119,7 @@
theme.transitions.create(['all'], {
duration: theme.transitions.duration.enteringScreen,
}),
- marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
+ marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
}}
title={"menu.agvDetail"}
empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
diff --git a/zy-acs-flow/src/page/agvModel/AgvModelList.jsx b/zy-acs-flow/src/page/agvModel/AgvModelList.jsx
index ab519aa..8297181 100644
--- a/zy-acs-flow/src/page/agvModel/AgvModelList.jsx
+++ b/zy-acs-flow/src/page/agvModel/AgvModelList.jsx
@@ -111,7 +111,7 @@
theme.transitions.create(['all'], {
duration: theme.transitions.duration.enteringScreen,
}),
- marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
+ marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
}}
title={"menu.agvModel"}
empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
diff --git a/zy-acs-flow/src/page/agvSts/AgvStsList.jsx b/zy-acs-flow/src/page/agvSts/AgvStsList.jsx
index aadf665..e58a09e 100644
--- a/zy-acs-flow/src/page/agvSts/AgvStsList.jsx
+++ b/zy-acs-flow/src/page/agvSts/AgvStsList.jsx
@@ -91,7 +91,7 @@
theme.transitions.create(['all'], {
duration: theme.transitions.duration.enteringScreen,
}),
- marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
+ marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
}}
title={"menu.agvSts"}
empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
diff --git a/zy-acs-flow/src/page/area/AreaList.jsx b/zy-acs-flow/src/page/area/AreaList.jsx
index 55ca554..02d5d4c 100644
--- a/zy-acs-flow/src/page/area/AreaList.jsx
+++ b/zy-acs-flow/src/page/area/AreaList.jsx
@@ -105,7 +105,7 @@
theme.transitions.create(['all'], {
duration: theme.transitions.duration.enteringScreen,
}),
- marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
+ marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
}}
title={"menu.area"}
empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
diff --git a/zy-acs-flow/src/page/bus/BusList.jsx b/zy-acs-flow/src/page/bus/BusList.jsx
index d411899..cf96b29 100644
--- a/zy-acs-flow/src/page/bus/BusList.jsx
+++ b/zy-acs-flow/src/page/bus/BusList.jsx
@@ -128,7 +128,7 @@
theme.transitions.create(['all'], {
duration: theme.transitions.duration.enteringScreen,
}),
- marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
+ marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
}}
title={"menu.bus"}
empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
diff --git a/zy-acs-flow/src/page/busSts/BusStsList.jsx b/zy-acs-flow/src/page/busSts/BusStsList.jsx
index 244f1bd..fbfa3a4 100644
--- a/zy-acs-flow/src/page/busSts/BusStsList.jsx
+++ b/zy-acs-flow/src/page/busSts/BusStsList.jsx
@@ -91,7 +91,7 @@
theme.transitions.create(['all'], {
duration: theme.transitions.duration.enteringScreen,
}),
- marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
+ marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
}}
title={"menu.busSts"}
empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
diff --git a/zy-acs-flow/src/page/code/CodeList.jsx b/zy-acs-flow/src/page/code/CodeList.jsx
index 797ea44..1f45bad 100644
--- a/zy-acs-flow/src/page/code/CodeList.jsx
+++ b/zy-acs-flow/src/page/code/CodeList.jsx
@@ -117,7 +117,7 @@
theme.transitions.create(['all'], {
duration: theme.transitions.duration.enteringScreen,
}),
- marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
+ marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
}}
title={"menu.code"}
empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
diff --git a/zy-acs-flow/src/page/codeGap/CodeGapList.jsx b/zy-acs-flow/src/page/codeGap/CodeGapList.jsx
index d665dfe..2ff4f3c 100644
--- a/zy-acs-flow/src/page/codeGap/CodeGapList.jsx
+++ b/zy-acs-flow/src/page/codeGap/CodeGapList.jsx
@@ -96,7 +96,7 @@
theme.transitions.create(['all'], {
duration: theme.transitions.duration.enteringScreen,
}),
- marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
+ marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
}}
title={"menu.codeGap"}
empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
diff --git a/zy-acs-flow/src/page/config/ConfigList.jsx b/zy-acs-flow/src/page/config/ConfigList.jsx
index 41850e9..c27a826 100644
--- a/zy-acs-flow/src/page/config/ConfigList.jsx
+++ b/zy-acs-flow/src/page/config/ConfigList.jsx
@@ -100,7 +100,7 @@
theme.transitions.create(['all'], {
duration: theme.transitions.duration.enteringScreen,
}),
- marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
+ marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
}}
title={"menu.config"}
empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
diff --git a/zy-acs-flow/src/page/funcSta/FuncStaList.jsx b/zy-acs-flow/src/page/funcSta/FuncStaList.jsx
index 8dff6cf..cfd649e 100644
--- a/zy-acs-flow/src/page/funcSta/FuncStaList.jsx
+++ b/zy-acs-flow/src/page/funcSta/FuncStaList.jsx
@@ -131,7 +131,7 @@
theme.transitions.create(['all'], {
duration: theme.transitions.duration.enteringScreen,
}),
- marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
+ marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
}}
title={"menu.funcSta"}
empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
diff --git a/zy-acs-flow/src/page/guarantee/CronField.jsx b/zy-acs-flow/src/page/guarantee/CronField.jsx
new file mode 100644
index 0000000..5517dc4
--- /dev/null
+++ b/zy-acs-flow/src/page/guarantee/CronField.jsx
@@ -0,0 +1,150 @@
+import React, { useEffect, useMemo, useState } from 'react';
+import { useInput, useTranslate } from 'react-admin';
+import {
+ Box,
+ FormControl,
+ InputLabel,
+ MenuItem,
+ Select,
+ Stack,
+ TextField,
+ ToggleButton,
+ ToggleButtonGroup,
+ Typography,
+ Chip,
+} from '@mui/material';
+import Autocomplete from '@mui/material/Autocomplete';
+import {
+ DEFAULT_CRON_EXPRESSION,
+ DEFAULT_SCHEDULE_STATE,
+ MONTH_DAY_OPTIONS,
+ SCHEDULE_MODES,
+ WEEK_DAYS,
+ buildCronExpression,
+ describeCronExpression,
+ getWeekdayLabel,
+ parseCronExpression,
+} from './cronUtils';
+
+const CronField = ({ source = 'cronExpr', ...rest }) => {
+ const translate = useTranslate();
+ const { field } = useInput({ source, defaultValue: DEFAULT_CRON_EXPRESSION, ...rest });
+ const [state, setState] = useState(() => parseCronExpression(field.value || DEFAULT_CRON_EXPRESSION));
+
+ useEffect(() => {
+ setState(parseCronExpression(field.value || DEFAULT_CRON_EXPRESSION));
+ }, [field.value]);
+
+ useEffect(() => {
+ const cron = buildCronExpression(state);
+ if (cron !== field.value) {
+ field.onChange(cron);
+ }
+ }, [state, field]);
+
+ const handleModeChange = (event) => {
+ const mode = event.target.value;
+ setState((prev) => ({
+ ...prev,
+ mode,
+ weekDays: mode === SCHEDULE_MODES.WEEKLY ? prev.weekDays || DEFAULT_SCHEDULE_STATE.weekDays : prev.weekDays,
+ monthDays: mode === SCHEDULE_MODES.MONTHLY ? prev.monthDays || DEFAULT_SCHEDULE_STATE.monthDays : prev.monthDays,
+ }));
+ };
+
+ const handleTimeChange = (event) => {
+ const newTime = event.target.value;
+ setState((prev) => ({ ...prev, time: newTime }));
+ };
+
+ const handleWeekDaysChange = (_, newDays) => {
+ if (!newDays.length) {
+ return;
+ }
+ setState((prev) => ({ ...prev, weekDays: newDays }));
+ };
+
+ const handleMonthDaysChange = (_, newDays) => {
+ if (!newDays.length) {
+ newDays = DEFAULT_SCHEDULE_STATE.monthDays;
+ }
+ setState((prev) => ({ ...prev, monthDays: newDays }));
+ };
+
+ const cronExpression = useMemo(() => buildCronExpression(state), [state]);
+ const description = useMemo(() => describeCronExpression(cronExpression, translate), [cronExpression, translate]);
+
+ return (
+ <Stack spacing={2} sx={{ width: '100%' }}>
+ <Typography variant="subtitle1">{translate('page.guarantee.schedule.label')}</Typography>
+ <FormControl fullWidth>
+ <InputLabel>{translate('page.guarantee.schedule.type')}</InputLabel>
+ <Select
+ label={translate('page.guarantee.schedule.type')}
+ value={state.mode || SCHEDULE_MODES.DAILY}
+ onChange={handleModeChange}
+ >
+ <MenuItem value={SCHEDULE_MODES.DAILY}>{translate('page.guarantee.schedule.daily')}</MenuItem>
+ <MenuItem value={SCHEDULE_MODES.WEEKLY}>{translate('page.guarantee.schedule.weekly')}</MenuItem>
+ <MenuItem value={SCHEDULE_MODES.MONTHLY}>{translate('page.guarantee.schedule.monthly')}</MenuItem>
+ </Select>
+ </FormControl>
+ <TextField
+ label={translate('page.guarantee.schedule.time')}
+ type="time"
+ value={state.time || DEFAULT_SCHEDULE_STATE.time}
+ onChange={handleTimeChange}
+ inputProps={{ step: 300 }}
+ />
+ {state.mode === SCHEDULE_MODES.WEEKLY && (
+ <Box>
+ <Typography variant="body2" gutterBottom>
+ {translate('page.guarantee.schedule.weeklyLabel')}
+ </Typography>
+ <ToggleButtonGroup value={state.weekDays || []} onChange={handleWeekDaysChange} size="small">
+ {WEEK_DAYS.map((day) => (
+ <ToggleButton key={day} value={day} aria-label={day} sx={{ textTransform: 'none' }}>
+ {getWeekdayLabel(day, translate)}
+ </ToggleButton>
+ ))}
+ </ToggleButtonGroup>
+ </Box>
+ )}
+ {state.mode === SCHEDULE_MODES.MONTHLY && (
+ <Autocomplete
+ multiple
+ options={MONTH_DAY_OPTIONS}
+ value={state.monthDays || []}
+ onChange={handleMonthDaysChange}
+ renderTags={(value, getTagProps) =>
+ value.map((option, index) => (
+ <Chip
+ variant="outlined"
+ label={translate('page.guarantee.schedule.monthDay', { day: option })}
+ {...getTagProps({ index })}
+ key={`month-day-${option}`}
+ />
+ ))
+ }
+ renderInput={(params) => (
+ <TextField
+ {...params}
+ label={translate('page.guarantee.schedule.monthlyLabel')}
+ helperText={translate('page.guarantee.schedule.monthHelper')}
+ />
+ )}
+ />
+ )}
+ <TextField
+ label={translate('page.guarantee.schedule.preview')}
+ value={cronExpression}
+ InputProps={{ readOnly: true }}
+ />
+ <Typography variant="caption" color="text.secondary">
+ {translate('page.guarantee.schedule.descriptionPrefix', { desc: description })}
+ </Typography>
+ </Stack>
+ );
+};
+
+export default CronField;
diff --git a/zy-acs-flow/src/page/guarantee/GuaranteeCreate.jsx b/zy-acs-flow/src/page/guarantee/GuaranteeCreate.jsx
index 7b28c4d..16239fa 100644
--- a/zy-acs-flow/src/page/guarantee/GuaranteeCreate.jsx
+++ b/zy-acs-flow/src/page/guarantee/GuaranteeCreate.jsx
@@ -4,19 +4,11 @@
useTranslate,
TextInput,
NumberInput,
- BooleanInput,
- DateInput,
SaveButton,
- SelectInput,
- ReferenceInput,
- ReferenceArrayInput,
- AutocompleteInput,
Toolbar,
required,
- useDataProvider,
useNotify,
Form,
- useCreateController,
} from 'react-admin';
import {
Dialog,
@@ -30,12 +22,25 @@
import DialogCloseButton from "../components/DialogCloseButton";
import StatusSelectInput from "../components/StatusSelectInput";
import MemoInput from "../components/MemoInput";
+import ScopeField from "./ScopeField";
+import CronField from "./CronField";
+import { DEFAULT_CRON_EXPRESSION } from "./cronUtils";
+import { DEFAULT_SCOPE_TYPE } from "./guaranteeConstants";
const GuaranteeCreate = (props) => {
const { open, setOpen } = props;
const translate = useTranslate();
const notify = useNotify();
+
+ const defaultRecord = {
+ scopeType: DEFAULT_SCOPE_TYPE,
+ cronExpr: DEFAULT_CRON_EXPRESSION,
+ requiredCount: 10,
+ minSoc: 50,
+ leadTime: 60,
+ status: 1,
+ };
const handleClose = (event, reason) => {
if (reason !== "backdropClick") {
@@ -55,9 +60,13 @@
return (
<>
<CreateBase
- record={{}}
+ record={defaultRecord}
transform={(data) => {
- return data;
+ return {
+ ...data,
+ cronExpr: (data.cronExpr || '').trim(),
+ scopeValue: data.scopeType === DEFAULT_SCOPE_TYPE ? null : data.scopeValue,
+ };
}}
mutationOptions={{ onSuccess: handleSuccess, onError: handleError }}
>
@@ -97,45 +106,39 @@
label="table.field.guarantee.name"
source="name"
parse={v => v}
+ validate={[required()]}
+ fullWidth
/>
</Grid>
- <Grid item xs={6} display="flex" gap={1}>
- <TextInput
- label="table.field.guarantee.scopeType"
- source="scopeType"
- parse={v => v}
- />
+ <Grid item xs={12}>
+ <ScopeField />
</Grid>
- <Grid item xs={6} display="flex" gap={1}>
- <TextInput
- label="table.field.guarantee.scopeValue"
- source="scopeValue"
- parse={v => v}
- />
+ <Grid item xs={12}>
+ <CronField />
</Grid>
- <Grid item xs={6} display="flex" gap={1}>
- <TextInput
- label="table.field.guarantee.cronExpr"
- source="cronExpr"
- parse={v => v}
- />
- </Grid>
- <Grid item xs={6} display="flex" gap={1}>
+ <Grid item xs={4} display="flex" gap={1}>
<NumberInput
label="table.field.guarantee.requiredCount"
source="requiredCount"
+ validate={[required()]}
+ min={1}
/>
</Grid>
- <Grid item xs={6} display="flex" gap={1}>
+ <Grid item xs={4} display="flex" gap={1}>
<NumberInput
label="table.field.guarantee.minSoc"
source="minSoc"
+ validate={[required()]}
+ min={1}
+ max={100}
/>
</Grid>
- <Grid item xs={6} display="flex" gap={1}>
+ <Grid item xs={4} display="flex" gap={1}>
<NumberInput
label="table.field.guarantee.leadTime"
source="leadTime"
+ validate={[required()]}
+ min={1}
/>
</Grid>
diff --git a/zy-acs-flow/src/page/guarantee/GuaranteeEdit.jsx b/zy-acs-flow/src/page/guarantee/GuaranteeEdit.jsx
index 4580c59..aae03b9 100644
--- a/zy-acs-flow/src/page/guarantee/GuaranteeEdit.jsx
+++ b/zy-acs-flow/src/page/guarantee/GuaranteeEdit.jsx
@@ -2,36 +2,25 @@
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 { EDIT_MODE } from '@/config/setting';
import EditBaseAside from "../components/EditBaseAside";
import CustomerTopToolBar from "../components/EditTopToolBar";
import MemoInput from "../components/MemoInput";
import StatusSelectInput from "../components/StatusSelectInput";
+import ScopeField from "./ScopeField";
+import CronField from "./CronField";
+import { DEFAULT_SCOPE_TYPE } from "./guaranteeConstants";
const FormToolbar = () => {
- const { getValues } = useFormContext();
-
return (
<Toolbar sx={{ justifyContent: 'space-between' }}>
<SaveButton />
@@ -76,45 +65,36 @@
label="table.field.guarantee.name"
source="name"
parse={v => v}
+ validate={[required()]}
/>
</Stack>
- <Stack direction='row' gap={2}>
- <TextInput
- label="table.field.guarantee.scopeType"
- source="scopeType"
- parse={v => v}
- />
- </Stack>
- <Stack direction='row' gap={2}>
- <TextInput
- label="table.field.guarantee.scopeValue"
- source="scopeValue"
- parse={v => v}
- />
- </Stack>
- <Stack direction='row' gap={2}>
- <TextInput
- label="table.field.guarantee.cronExpr"
- source="cronExpr"
- parse={v => v}
- />
- </Stack>
+ <ScopeField />
+ <Box mt={2}>
+ <CronField />
+ </Box>
<Stack direction='row' gap={2}>
<NumberInput
label="table.field.guarantee.requiredCount"
source="requiredCount"
+ validate={[required()]}
+ min={1}
/>
</Stack>
<Stack direction='row' gap={2}>
<NumberInput
label="table.field.guarantee.minSoc"
source="minSoc"
+ validate={[required()]}
+ min={1}
+ max={100}
/>
</Stack>
<Stack direction='row' gap={2}>
<NumberInput
label="table.field.guarantee.leadTime"
source="leadTime"
+ validate={[required()]}
+ min={1}
/>
</Stack>
@@ -133,4 +113,20 @@
)
}
-export default GuaranteeEdit;
+const GuaranteeEditWrapper = () => (
+ <Edit
+ redirect="list"
+ mutationMode={EDIT_MODE}
+ actions={<CustomerTopToolBar />}
+ aside={<EditBaseAside />}
+ transform={(data) => ({
+ ...data,
+ cronExpr: (data.cronExpr || '').trim(),
+ scopeValue: data.scopeType === DEFAULT_SCOPE_TYPE ? null : data.scopeValue,
+ })}
+ >
+ <GuaranteeEdit />
+ </Edit>
+);
+
+export default GuaranteeEditWrapper;
diff --git a/zy-acs-flow/src/page/guarantee/GuaranteeList.jsx b/zy-acs-flow/src/page/guarantee/GuaranteeList.jsx
index 576e125..cd953e2 100644
--- a/zy-acs-flow/src/page/guarantee/GuaranteeList.jsx
+++ b/zy-acs-flow/src/page/guarantee/GuaranteeList.jsx
@@ -1,21 +1,14 @@
-import React, { useState, useRef, useEffect, useMemo, useCallback } from "react";
-import { useNavigate } from 'react-router-dom';
+import React, { useState, useCallback } from "react";
import {
List,
DatagridConfigurable,
SearchInput,
TopToolbar,
SelectColumnsButton,
- EditButton,
FilterButton,
- CreateButton,
- ExportButton,
BulkDeleteButton,
WrapperField,
- useRecordContext,
useTranslate,
- useNotify,
- useListContext,
FunctionField,
TextField,
NumberField,
@@ -27,10 +20,8 @@
DateInput,
SelectInput,
NumberInput,
- ReferenceInput,
- ReferenceArrayInput,
- AutocompleteInput,
DeleteButton,
+ EditButton,
} from 'react-admin';
import { Box, Typography, Card, Stack } from '@mui/material';
import { styled } from '@mui/material/styles';
@@ -40,9 +31,10 @@
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';
+import { describeCronExpression } from "./cronUtils";
+import { DEFAULT_SCOPE_TYPE, SCOPE_FILTER_CHOICES, getScopeLabel } from "./guaranteeConstants";
const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
'& .css-1vooibu-MuiSvgIcon-root': {
@@ -65,7 +57,14 @@
<TextInput source="uuid" label="table.field.guarantee.uuid" />,
<TextInput source="name" label="table.field.guarantee.name" />,
- <TextInput source="scopeType" label="table.field.guarantee.scopeType" />,
+ <SelectInput
+ source="scopeType"
+ label="table.field.guarantee.scopeType"
+ choices={SCOPE_FILTER_CHOICES}
+ translateChoice
+ allowEmpty
+ resettable
+ />,
<TextInput source="scopeValue" label="table.field.guarantee.scopeValue" />,
<TextInput source="cronExpr" label="table.field.guarantee.cronExpr" />,
<NumberInput source="requiredCount" label="table.field.guarantee.requiredCount" />,
@@ -90,6 +89,32 @@
const [createDialog, setCreateDialog] = useState(false);
const [drawerVal, setDrawerVal] = useState(false);
+ const renderScopeType = useCallback((record) => {
+ if (!record) {
+ return '';
+ }
+ return getScopeLabel(record.scopeType, translate);
+ }, [translate]);
+
+ const renderScopeValue = useCallback((record) => {
+ if (!record) {
+ return '';
+ }
+ if (!record.scopeValue) {
+ return record.scopeType === DEFAULT_SCOPE_TYPE
+ ? translate('page.guarantee.scope.globalHelper')
+ : translate('common.enums.na');
+ }
+ return record.scopeValue;
+ }, [translate]);
+
+ const renderCron = useCallback((record) => {
+ if (!record || !record.cronExpr) {
+ return translate('common.enums.na');
+ }
+ return describeCronExpression(record.cronExpr, translate);
+ }, [translate]);
+
return (
<Box display="flex">
<List
@@ -99,7 +124,7 @@
theme.transitions.create(['all'], {
duration: theme.transitions.duration.enteringScreen,
}),
- marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
+ marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
}}
title={"menu.guarantee"}
empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
@@ -126,9 +151,9 @@
<NumberField source="id" />
<TextField source="uuid" label="table.field.guarantee.uuid" />
<TextField source="name" label="table.field.guarantee.name" />
- <TextField source="scopeType" label="table.field.guarantee.scopeType" />
- <TextField source="scopeValue" label="table.field.guarantee.scopeValue" />
- <TextField source="cronExpr" label="table.field.guarantee.cronExpr" />
+ <FunctionField label="table.field.guarantee.scopeType" render={renderScopeType} />
+ <FunctionField label="table.field.guarantee.scopeValue" render={renderScopeValue} />
+ <FunctionField label="table.field.guarantee.cronExpr" render={renderCron} />
<NumberField source="requiredCount" label="table.field.guarantee.requiredCount" />
<NumberField source="minSoc" label="table.field.guarantee.minSoc" />
<NumberField source="leadTime" label="table.field.guarantee.leadTime" />
diff --git a/zy-acs-flow/src/page/guarantee/GuaranteePanel.jsx b/zy-acs-flow/src/page/guarantee/GuaranteePanel.jsx
index 300213c..8c95403 100644
--- a/zy-acs-flow/src/page/guarantee/GuaranteePanel.jsx
+++ b/zy-acs-flow/src/page/guarantee/GuaranteePanel.jsx
@@ -6,11 +6,23 @@
} from 'react-admin';
import PanelTypography from "../components/PanelTypography";
import * as Common from '@/utils/common'
+import { describeCronExpression } from "./cronUtils";
+import { DEFAULT_SCOPE_TYPE, getScopeLabel } from "./guaranteeConstants";
const GuaranteePanel = () => {
const record = useRecordContext();
if (!record) return null;
const translate = useTranslate();
+ const scopeTypeLabel = getScopeLabel(record.scopeType, translate);
+ const scopeValueLabel = record.scopeValue
+ ? record.scopeValue
+ : record.scopeType === DEFAULT_SCOPE_TYPE
+ ? translate('page.guarantee.scope.globalHelper')
+ : translate('common.enums.na');
+ const cronDesc = record.cronExpr
+ ? `${describeCronExpression(record.cronExpr, translate)} (${record.cronExpr})`
+ : translate('common.enums.na');
+
return (
<>
<Card sx={{ width: { xs: 300, sm: 500, md: 600, lg: 800 }, margin: 'auto' }}>
@@ -55,19 +67,19 @@
<Grid item xs={6}>
<PanelTypography
title="table.field.guarantee.scopeType"
- property={record.scopeType}
+ property={scopeTypeLabel}
/>
</Grid>
<Grid item xs={6}>
<PanelTypography
title="table.field.guarantee.scopeValue"
- property={record.scopeValue}
+ property={scopeValueLabel}
/>
</Grid>
<Grid item xs={6}>
<PanelTypography
title="table.field.guarantee.cronExpr"
- property={record.cronExpr}
+ property={cronDesc}
/>
</Grid>
<Grid item xs={6}>
diff --git a/zy-acs-flow/src/page/guarantee/ScopeField.jsx b/zy-acs-flow/src/page/guarantee/ScopeField.jsx
new file mode 100644
index 0000000..0b89c90
--- /dev/null
+++ b/zy-acs-flow/src/page/guarantee/ScopeField.jsx
@@ -0,0 +1,70 @@
+import React from 'react';
+import { Stack, TextField } from '@mui/material';
+import {
+ AutocompleteInput,
+ FormDataConsumer,
+ ReferenceInput,
+ SelectInput,
+ required,
+ useTranslate,
+} from 'react-admin';
+import { REFERENCE_INPUT_PAGESIZE } from '@/config/setting';
+import { DEFAULT_SCOPE_TYPE, SCOPE_OPTIONS, getScopeConfig } from './guaranteeConstants';
+
+const ScopeField = () => {
+ const translate = useTranslate();
+
+ return (
+ <Stack spacing={2} sx={{ width: '100%' }}>
+ <SelectInput
+ label="table.field.guarantee.scopeType"
+ source="scopeType"
+ choices={SCOPE_OPTIONS}
+ optionText={(choice) => translate(choice.labelKey)}
+ optionValue="id"
+ translateChoice={false}
+ defaultValue={DEFAULT_SCOPE_TYPE}
+ helperText={translate('page.guarantee.scope.helper')}
+ />
+ <FormDataConsumer>
+ {({ formData, ...rest }) => {
+ const currentType = formData.scopeType || DEFAULT_SCOPE_TYPE;
+ const config = getScopeConfig(currentType);
+
+ if (config.valueType === 'reference') {
+ return (
+ <ReferenceInput
+ key={currentType}
+ source="scopeValue"
+ reference={config.reference}
+ perPage={REFERENCE_INPUT_PAGESIZE}
+ {...rest}
+ >
+ <AutocompleteInput
+ label="table.field.guarantee.scopeValue"
+ optionText={config.optionText}
+ optionValue={config.optionValue || 'id'}
+ filterToQuery={config.filterToQuery}
+ validate={[required()]}
+ fullWidth
+ />
+ </ReferenceInput>
+ );
+ }
+
+ return (
+ <TextField
+ label={translate('table.field.guarantee.scopeValue')}
+ value={translate('page.guarantee.scope.globalHelper')}
+ helperText={translate('page.guarantee.scope.globalTip')}
+ disabled
+ fullWidth
+ />
+ );
+ }}
+ </FormDataConsumer>
+ </Stack>
+ );
+};
+
+export default ScopeField;
diff --git a/zy-acs-flow/src/page/guarantee/cronUtils.js b/zy-acs-flow/src/page/guarantee/cronUtils.js
new file mode 100644
index 0000000..29b8120
--- /dev/null
+++ b/zy-acs-flow/src/page/guarantee/cronUtils.js
@@ -0,0 +1,168 @@
+export const SCHEDULE_MODES = {
+ DAILY: 'DAILY',
+ WEEKLY: 'WEEKLY',
+ MONTHLY: 'MONTHLY',
+};
+
+export const WEEK_DAYS = ['MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT', 'SUN'];
+export const MONTH_DAY_OPTIONS = Array.from({ length: 31 }, (_, idx) => idx + 1);
+
+const DEFAULT_TIME = '10:00';
+const pad = (value) => value.toString().padStart(2, '0');
+
+const sanitizeWeekDays = (days) => {
+ if (!Array.isArray(days) || days.length === 0) {
+ return ['MON'];
+ }
+ const unique = [...new Set(days.filter((day) => WEEK_DAYS.includes(day)))];
+ return unique.length ? unique : ['MON'];
+};
+
+const sanitizeMonthDays = (days) => {
+ if (!Array.isArray(days) || days.length === 0) {
+ return [1];
+ }
+ const unique = [...new Set(days.map((day) => Number(day)).filter((day) => day >= 1 && day <= 31))];
+ return unique.length ? unique : [1];
+};
+
+const sanitizeTime = (time = DEFAULT_TIME) => {
+ if (typeof time !== 'string') {
+ return DEFAULT_TIME;
+ }
+ const [hour = '10', minute = '00'] = time.split(':');
+ const parsedHour = Math.min(23, Math.max(0, parseInt(hour, 10) || 0));
+ const parsedMinute = Math.min(59, Math.max(0, parseInt(minute, 10) || 0));
+ return `${pad(parsedHour)}:${pad(parsedMinute)}`;
+};
+
+export const DEFAULT_SCHEDULE_STATE = {
+ mode: SCHEDULE_MODES.DAILY,
+ time: DEFAULT_TIME,
+ weekDays: ['MON'],
+ monthDays: [1],
+};
+
+export const buildCronExpression = (state = DEFAULT_SCHEDULE_STATE) => {
+ const mode = state?.mode || SCHEDULE_MODES.DAILY;
+ const time = sanitizeTime(state?.time);
+ const [hour, minute] = time.split(':');
+
+ if (mode === SCHEDULE_MODES.WEEKLY) {
+ const days = sanitizeWeekDays(state?.weekDays).join(',');
+ return `0 ${minute} ${hour} ? * ${days}`;
+ }
+
+ if (mode === SCHEDULE_MODES.MONTHLY) {
+ const days = sanitizeMonthDays(state?.monthDays).sort((a, b) => a - b).join(',');
+ return `0 ${minute} ${hour} ${days} * ?`;
+ }
+
+ return `0 ${minute} ${hour} * * ?`;
+};
+
+export const DEFAULT_CRON_EXPRESSION = buildCronExpression(DEFAULT_SCHEDULE_STATE);
+
+const createParsedState = () => ({
+ ...DEFAULT_SCHEDULE_STATE,
+ valid: false,
+});
+
+export const parseCronExpression = (expr) => {
+ const state = createParsedState();
+ if (!expr || typeof expr !== 'string') {
+ return state;
+ }
+ const tokens = expr.trim().split(/\s+/);
+ if (tokens.length < 6) {
+ return state;
+ }
+ const [, minute, hour, dayOfMonth, , dayOfWeek] = tokens;
+ const time = sanitizeTime(`${hour}:${minute}`);
+
+ if (dayOfMonth === '*' && dayOfWeek === '?') {
+ return {
+ ...state,
+ valid: true,
+ mode: SCHEDULE_MODES.DAILY,
+ time,
+ };
+ }
+
+ if (dayOfMonth === '?' && dayOfWeek && dayOfWeek !== '?') {
+ const weekDays = dayOfWeek.split(',').filter((day) => WEEK_DAYS.includes(day));
+ return {
+ ...state,
+ valid: true,
+ mode: SCHEDULE_MODES.WEEKLY,
+ time,
+ weekDays: sanitizeWeekDays(weekDays),
+ };
+ }
+
+ if (dayOfMonth && dayOfMonth !== '*' && dayOfWeek === '?') {
+ const monthDays = dayOfMonth
+ .split(',')
+ .map((day) => parseInt(day, 10))
+ .filter((day) => !Number.isNaN(day));
+ return {
+ ...state,
+ valid: true,
+ mode: SCHEDULE_MODES.MONTHLY,
+ time,
+ monthDays: sanitizeMonthDays(monthDays),
+ };
+ }
+
+ return state;
+};
+
+export const getWeekdayLabel = (day, translate) => {
+ const key = `page.guarantee.week.${day?.toLowerCase?.()}`;
+ return translate ? translate(key) : day;
+};
+
+const formatWeekdays = (days, translate) => {
+ const normalized = sanitizeWeekDays(days);
+ return normalized.map((day) => getWeekdayLabel(day, translate)).join(' / ');
+};
+
+const formatMonthDays = (days, translate) => {
+ const normalized = sanitizeMonthDays(days).sort((a, b) => a - b);
+ return normalized
+ .map((day) => (translate ? translate('page.guarantee.schedule.monthDay', { day }) : `${day}`))
+ .join(' / ');
+};
+
+export const describeCronExpression = (expr, translate) => {
+ if (!expr) {
+ return '';
+ }
+ const parsed = parseCronExpression(expr);
+ const time = parsed.time || DEFAULT_TIME;
+
+ if (!parsed.valid) {
+ return expr;
+ }
+
+ switch (parsed.mode) {
+ case SCHEDULE_MODES.WEEKLY:
+ return translate
+ ? translate('page.guarantee.schedule.description.weekly', {
+ days: formatWeekdays(parsed.weekDays, translate),
+ time,
+ })
+ : `Weekly ${formatWeekdays(parsed.weekDays)} ${time}`;
+ case SCHEDULE_MODES.MONTHLY:
+ return translate
+ ? translate('page.guarantee.schedule.description.monthly', {
+ days: formatMonthDays(parsed.monthDays, translate),
+ time,
+ })
+ : `Monthly ${formatMonthDays(parsed.monthDays)} ${time}`;
+ default:
+ return translate
+ ? translate('page.guarantee.schedule.description.daily', { time })
+ : `Daily ${time}`;
+ }
+};
diff --git a/zy-acs-flow/src/page/guarantee/guaranteeConstants.js b/zy-acs-flow/src/page/guarantee/guaranteeConstants.js
new file mode 100644
index 0000000..fbc0aba
--- /dev/null
+++ b/zy-acs-flow/src/page/guarantee/guaranteeConstants.js
@@ -0,0 +1,63 @@
+const buildFilter = (field) => (value) => ({ [field]: value });
+
+export const SCOPE_CONFIGS = {
+ GLOBAL: {
+ id: 'GLOBAL',
+ labelKey: 'page.guarantee.scope.global',
+ valueType: 'none',
+ },
+ MODEL: {
+ id: 'MODEL',
+ labelKey: 'page.guarantee.scope.model',
+ valueType: 'reference',
+ reference: 'agvModel',
+ optionText: 'name',
+ optionValue: 'id',
+ filterToQuery: buildFilter('name'),
+ },
+ AREA: {
+ id: 'AREA',
+ labelKey: 'page.guarantee.scope.area',
+ valueType: 'reference',
+ reference: 'area',
+ optionText: 'name',
+ optionValue: 'id',
+ filterToQuery: buildFilter('name'),
+ },
+ BIZ: {
+ id: 'BIZ',
+ labelKey: 'page.guarantee.scope.biz',
+ valueType: 'reference',
+ reference: 'taskType',
+ optionText: 'name',
+ optionValue: 'id',
+ filterToQuery: buildFilter('name'),
+ },
+ AGV: {
+ id: 'AGV',
+ labelKey: 'page.guarantee.scope.agv',
+ valueType: 'reference',
+ reference: 'agv',
+ optionText: 'uuid',
+ optionValue: 'id',
+ filterToQuery: buildFilter('uuid'),
+ },
+};
+
+export const DEFAULT_SCOPE_TYPE = SCOPE_CONFIGS.GLOBAL.id;
+
+export const SCOPE_OPTIONS = Object.values(SCOPE_CONFIGS);
+
+export const SCOPE_FILTER_CHOICES = SCOPE_OPTIONS.map(({ id, labelKey }) => ({
+ id,
+ name: labelKey,
+}));
+
+export const getScopeConfig = (scopeType) => SCOPE_CONFIGS[scopeType] || SCOPE_CONFIGS.GLOBAL;
+
+export const getScopeLabelKey = (scopeType) => getScopeConfig(scopeType).labelKey;
+
+export const getScopeLabel = (scopeType, translate) => {
+ const key = getScopeLabelKey(scopeType);
+ return translate ? translate(key) : key;
+};
diff --git a/zy-acs-flow/src/page/host/HostList.jsx b/zy-acs-flow/src/page/host/HostList.jsx
index ac9be3d..6bad995 100644
--- a/zy-acs-flow/src/page/host/HostList.jsx
+++ b/zy-acs-flow/src/page/host/HostList.jsx
@@ -82,7 +82,7 @@
theme.transitions.create(['all'], {
duration: theme.transitions.duration.enteringScreen,
}),
- marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
+ marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
}}
title={"menu.host"}
empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
diff --git a/zy-acs-flow/src/page/integrationRecord/IntegrationRecordList.jsx b/zy-acs-flow/src/page/integrationRecord/IntegrationRecordList.jsx
index 8d6e450..016e5cf 100644
--- a/zy-acs-flow/src/page/integrationRecord/IntegrationRecordList.jsx
+++ b/zy-acs-flow/src/page/integrationRecord/IntegrationRecordList.jsx
@@ -106,7 +106,7 @@
theme.transitions.create(['all'], {
duration: theme.transitions.duration.enteringScreen,
}),
- marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
+ marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
}}
title={"menu.integrationRecord"}
empty={<EmptyDataLoader />}
diff --git a/zy-acs-flow/src/page/jam/JamList.jsx b/zy-acs-flow/src/page/jam/JamList.jsx
index 212cfb0..c2a12ab 100644
--- a/zy-acs-flow/src/page/jam/JamList.jsx
+++ b/zy-acs-flow/src/page/jam/JamList.jsx
@@ -147,7 +147,7 @@
theme.transitions.create(['all'], {
duration: theme.transitions.duration.enteringScreen,
}),
- marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
+ marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
}}
title={"menu.jam"}
empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
diff --git a/zy-acs-flow/src/page/lane/LaneList.jsx b/zy-acs-flow/src/page/lane/LaneList.jsx
index 8fc152c..0b47a33 100644
--- a/zy-acs-flow/src/page/lane/LaneList.jsx
+++ b/zy-acs-flow/src/page/lane/LaneList.jsx
@@ -112,7 +112,7 @@
theme.transitions.create(['all'], {
duration: theme.transitions.duration.enteringScreen,
}),
- marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
+ marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
}}
title={"menu.lane"}
empty={<EmptyDataLoader />}
diff --git a/zy-acs-flow/src/page/loc/LocList.jsx b/zy-acs-flow/src/page/loc/LocList.jsx
index 657c561..ecff579 100644
--- a/zy-acs-flow/src/page/loc/LocList.jsx
+++ b/zy-acs-flow/src/page/loc/LocList.jsx
@@ -132,7 +132,7 @@
theme.transitions.create(['all'], {
duration: theme.transitions.duration.enteringScreen,
}),
- marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
+ marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
}}
title={"menu.loc"}
empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
diff --git a/zy-acs-flow/src/page/locSts/LocStsList.jsx b/zy-acs-flow/src/page/locSts/LocStsList.jsx
index e72434b..0bf9f4b 100644
--- a/zy-acs-flow/src/page/locSts/LocStsList.jsx
+++ b/zy-acs-flow/src/page/locSts/LocStsList.jsx
@@ -91,7 +91,7 @@
theme.transitions.create(['all'], {
duration: theme.transitions.duration.enteringScreen,
}),
- marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
+ marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
}}
title={"menu.locSts"}
empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
diff --git a/zy-acs-flow/src/page/locType/LocTypeList.jsx b/zy-acs-flow/src/page/locType/LocTypeList.jsx
index 34b50b7..eeea2f3 100644
--- a/zy-acs-flow/src/page/locType/LocTypeList.jsx
+++ b/zy-acs-flow/src/page/locType/LocTypeList.jsx
@@ -91,7 +91,7 @@
theme.transitions.create(['all'], {
duration: theme.transitions.duration.enteringScreen,
}),
- marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
+ marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
}}
title={"menu.locType"}
empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
diff --git a/zy-acs-flow/src/page/mission/MissionResend.jsx b/zy-acs-flow/src/page/mission/MissionResend.jsx
index 85823b3..a8ad383 100644
--- a/zy-acs-flow/src/page/mission/MissionResend.jsx
+++ b/zy-acs-flow/src/page/mission/MissionResend.jsx
@@ -57,7 +57,7 @@
}}
>
<DialogContent sx={{ padding: 0 }}>
- {!!id ? (
+ {id ? (
<ShowBase id={id}>
<MissionResendContent handleClose={handleClose} />
</ShowBase>
@@ -231,7 +231,7 @@
};
const resendSubmit = () => {
- if (!!selected?.length) {
+ if (selected?.length) {
request.post("/mission/resend", selected.map(id => ({ id }))).then(res => {
const { code, msg, data } = res.data;
if (code === 200) {
diff --git a/zy-acs-flow/src/page/mission/MissionShow.jsx b/zy-acs-flow/src/page/mission/MissionShow.jsx
index 4ccffc4..c78511e 100644
--- a/zy-acs-flow/src/page/mission/MissionShow.jsx
+++ b/zy-acs-flow/src/page/mission/MissionShow.jsx
@@ -53,7 +53,7 @@
}}
>
<DialogContent sx={{ padding: 0 }}>
- {!!id ? (
+ {id ? (
<ShowBase id={id}>
<MissionShowContent handleClose={handleClose} />
</ShowBase>
diff --git a/zy-acs-flow/src/page/operationRecord/OperationRecordList.jsx b/zy-acs-flow/src/page/operationRecord/OperationRecordList.jsx
index 940424a..8c2d42a 100644
--- a/zy-acs-flow/src/page/operationRecord/OperationRecordList.jsx
+++ b/zy-acs-flow/src/page/operationRecord/OperationRecordList.jsx
@@ -122,7 +122,7 @@
theme.transitions.create(['all'], {
duration: theme.transitions.duration.enteringScreen,
}),
- marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
+ marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
}}
title={"menu.operation"}
empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
diff --git a/zy-acs-flow/src/page/role/RoleList.jsx b/zy-acs-flow/src/page/role/RoleList.jsx
index d03ab60..6c43310 100644
--- a/zy-acs-flow/src/page/role/RoleList.jsx
+++ b/zy-acs-flow/src/page/role/RoleList.jsx
@@ -112,7 +112,7 @@
theme.transitions.create(['all'], {
duration: theme.transitions.duration.enteringScreen,
}),
- marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
+ marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
}}
title={"menu.role"}
empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
@@ -163,7 +163,7 @@
<PageDrawer
drawerVal={drawerVal}
setDrawerVal={setDrawerVal}
- title={!!drawerVal ? `Scope by ${drawerVal.code || drawerVal.name}` : 'Role Detail'}
+ title={drawerVal ? `Scope by ${drawerVal.code || drawerVal.name}` : 'Role Detail'}
closeCallback={() => {
setMenuIds([]);
}}
diff --git a/zy-acs-flow/src/page/route/RouteList.jsx b/zy-acs-flow/src/page/route/RouteList.jsx
index 6175fa1..e8e7b6d 100644
--- a/zy-acs-flow/src/page/route/RouteList.jsx
+++ b/zy-acs-flow/src/page/route/RouteList.jsx
@@ -113,7 +113,7 @@
theme.transitions.create(['all'], {
duration: theme.transitions.duration.enteringScreen,
}),
- marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
+ marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
}}
title={"menu.route"}
empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
diff --git a/zy-acs-flow/src/page/segment/SegmentList.jsx b/zy-acs-flow/src/page/segment/SegmentList.jsx
index 43b51fd..0537618 100644
--- a/zy-acs-flow/src/page/segment/SegmentList.jsx
+++ b/zy-acs-flow/src/page/segment/SegmentList.jsx
@@ -108,7 +108,7 @@
theme.transitions.create(['all'], {
duration: theme.transitions.duration.enteringScreen,
}),
- marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
+ marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
}}
title={"menu.segment"}
empty={<EmptyData />}
diff --git a/zy-acs-flow/src/page/sta/StaList.jsx b/zy-acs-flow/src/page/sta/StaList.jsx
index 6d91a9a..3991595 100644
--- a/zy-acs-flow/src/page/sta/StaList.jsx
+++ b/zy-acs-flow/src/page/sta/StaList.jsx
@@ -111,7 +111,7 @@
theme.transitions.create(['all'], {
duration: theme.transitions.duration.enteringScreen,
}),
- marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
+ marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
}}
title={"menu.sta"}
empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
diff --git a/zy-acs-flow/src/page/staReserve/StaReserveList.jsx b/zy-acs-flow/src/page/staReserve/StaReserveList.jsx
index a4948d6..102d53e 100644
--- a/zy-acs-flow/src/page/staReserve/StaReserveList.jsx
+++ b/zy-acs-flow/src/page/staReserve/StaReserveList.jsx
@@ -128,7 +128,7 @@
theme.transitions.create(['all'], {
duration: theme.transitions.duration.enteringScreen,
}),
- marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
+ marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
}}
title={"menu.staReserve"}
empty={<EmptyDataLoader />}
diff --git a/zy-acs-flow/src/page/staSts/StaStsList.jsx b/zy-acs-flow/src/page/staSts/StaStsList.jsx
index 80d676b..e61db0b 100644
--- a/zy-acs-flow/src/page/staSts/StaStsList.jsx
+++ b/zy-acs-flow/src/page/staSts/StaStsList.jsx
@@ -91,7 +91,7 @@
theme.transitions.create(['all'], {
duration: theme.transitions.duration.enteringScreen,
}),
- marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
+ marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
}}
title={"menu.staSts"}
empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
diff --git a/zy-acs-flow/src/page/staType/StaTypeList.jsx b/zy-acs-flow/src/page/staType/StaTypeList.jsx
index 3a2f665..d459e0e 100644
--- a/zy-acs-flow/src/page/staType/StaTypeList.jsx
+++ b/zy-acs-flow/src/page/staType/StaTypeList.jsx
@@ -91,7 +91,7 @@
theme.transitions.create(['all'], {
duration: theme.transitions.duration.enteringScreen,
}),
- marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
+ marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
}}
title={"menu.staType"}
empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
diff --git a/zy-acs-flow/src/page/task/TaskList.jsx b/zy-acs-flow/src/page/task/TaskList.jsx
index 09e7397..bf8aa94 100644
--- a/zy-acs-flow/src/page/task/TaskList.jsx
+++ b/zy-acs-flow/src/page/task/TaskList.jsx
@@ -371,7 +371,7 @@
theme.transitions.create(['all'], {
duration: theme.transitions.duration.enteringScreen,
}),
- marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
+ marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
}}
title={"menu.task"}
empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
diff --git a/zy-acs-flow/src/page/taskSts/TaskStsList.jsx b/zy-acs-flow/src/page/taskSts/TaskStsList.jsx
index ccda9d0..61ea519 100644
--- a/zy-acs-flow/src/page/taskSts/TaskStsList.jsx
+++ b/zy-acs-flow/src/page/taskSts/TaskStsList.jsx
@@ -91,7 +91,7 @@
theme.transitions.create(['all'], {
duration: theme.transitions.duration.enteringScreen,
}),
- marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
+ marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
}}
title={"menu.taskSts"}
empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
diff --git a/zy-acs-flow/src/page/taskType/TaskTypeList.jsx b/zy-acs-flow/src/page/taskType/TaskTypeList.jsx
index 0aa9053..9bbcfad 100644
--- a/zy-acs-flow/src/page/taskType/TaskTypeList.jsx
+++ b/zy-acs-flow/src/page/taskType/TaskTypeList.jsx
@@ -91,7 +91,7 @@
theme.transitions.create(['all'], {
duration: theme.transitions.duration.enteringScreen,
}),
- marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
+ marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
}}
title={"menu.taskType"}
empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
diff --git a/zy-acs-flow/src/page/tenant/TenantList.jsx b/zy-acs-flow/src/page/tenant/TenantList.jsx
index 3470c93..ed914b3 100644
--- a/zy-acs-flow/src/page/tenant/TenantList.jsx
+++ b/zy-acs-flow/src/page/tenant/TenantList.jsx
@@ -86,7 +86,7 @@
theme.transitions.create(['all'], {
duration: theme.transitions.duration.enteringScreen,
}),
- marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
+ marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
}}
title={"menu.tenant"}
empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
diff --git a/zy-acs-flow/src/page/travel/TravelList.jsx b/zy-acs-flow/src/page/travel/TravelList.jsx
index 04b27f2..f97986a 100644
--- a/zy-acs-flow/src/page/travel/TravelList.jsx
+++ b/zy-acs-flow/src/page/travel/TravelList.jsx
@@ -120,7 +120,7 @@
theme.transitions.create(['all'], {
duration: theme.transitions.duration.enteringScreen,
}),
- marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
+ marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
}}
title={"menu.travel"}
empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
diff --git a/zy-acs-flow/src/page/user/UserList.jsx b/zy-acs-flow/src/page/user/UserList.jsx
index 63f81bd..fab2f71 100644
--- a/zy-acs-flow/src/page/user/UserList.jsx
+++ b/zy-acs-flow/src/page/user/UserList.jsx
@@ -127,7 +127,7 @@
theme.transitions.create(['all'], {
duration: theme.transitions.duration.enteringScreen,
}),
- marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
+ marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
}}
title={"menu.user"}
empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
diff --git a/zy-acs-flow/src/page/userLogin/UserLoginList.jsx b/zy-acs-flow/src/page/userLogin/UserLoginList.jsx
index bfa653c..f0621ab 100644
--- a/zy-acs-flow/src/page/userLogin/UserLoginList.jsx
+++ b/zy-acs-flow/src/page/userLogin/UserLoginList.jsx
@@ -100,7 +100,7 @@
theme.transitions.create(['all'], {
duration: theme.transitions.duration.enteringScreen,
}),
- marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
+ marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
}}
title={"menu.userLogin"}
empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
diff --git a/zy-acs-flow/src/page/vehFaultRec/VehFaultRecList.jsx b/zy-acs-flow/src/page/vehFaultRec/VehFaultRecList.jsx
index b40f636..99fde60 100644
--- a/zy-acs-flow/src/page/vehFaultRec/VehFaultRecList.jsx
+++ b/zy-acs-flow/src/page/vehFaultRec/VehFaultRecList.jsx
@@ -104,7 +104,7 @@
theme.transitions.create(['all'], {
duration: theme.transitions.duration.enteringScreen,
}),
- marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
+ marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
}}
title={"menu.vehFaultRec"}
empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
diff --git a/zy-acs-flow/src/page/zone/ZoneList.jsx b/zy-acs-flow/src/page/zone/ZoneList.jsx
index 904ff2f..b5ba9f8 100644
--- a/zy-acs-flow/src/page/zone/ZoneList.jsx
+++ b/zy-acs-flow/src/page/zone/ZoneList.jsx
@@ -93,7 +93,7 @@
theme.transitions.create(['all'], {
duration: theme.transitions.duration.enteringScreen,
}),
- marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
+ marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
}}
title={"menu.zone"}
empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
--
Gitblit v1.9.1