From 3af7a0f80502c71a76151be3db2b870b81d96677 Mon Sep 17 00:00:00 2001 From: 16337 <1633794139@qq.com> Date: Thu, 22 Jan 2026 17:26:28 +0800 Subject: [PATCH] =?UTF-8?q?fix(roi-editor):=E4=BF=AE=E5=A4=8D=20ROI=20?= =?UTF-8?q?=E7=BC=96=E8=BE=91=E5=99=A8=E4=B8=AD=E6=97=B6=E9=97=B4=E6=AE=B5?= =?UTF-8?q?=E9=80=89=E6=8B=A9=E5=99=A8=EF=BC=88TimePicker.RangePicker?= =?UTF-8?q?=EF=BC=89=E5=9B=A0=E8=BF=9E=E7=BB=AD=E8=B0=83=E7=94=A8=E4=B8=A4?= =?UTF-8?q?=E6=AC=A1=E7=8A=B6=E6=80=81=E6=9B=B4=E6=96=B0=E5=AF=BC=E8=87=B4?= =?UTF-8?q?=E7=9A=84=E6=B8=85=E7=A9=BA=E9=97=AE=E9=A2=98=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 `updateWorkingHoursRange` 批量更新函数,将 start/end 作为原子操作同步更新 - 在 onChange 回调中添加 `Array.isArray(dates) && dates.length >= 2` 类型校验 - 避免 React 异步 setState 冲突导致 workingHoursList 意外重置 --- frontend/src/pages/ROIEditor.tsx | 109 ++++++++++++++++++++----------- 1 file changed, 71 insertions(+), 38 deletions(-) diff --git a/frontend/src/pages/ROIEditor.tsx b/frontend/src/pages/ROIEditor.tsx index 5213d45..0f9c089 100644 --- a/frontend/src/pages/ROIEditor.tsx +++ b/frontend/src/pages/ROIEditor.tsx @@ -37,12 +37,38 @@ const ROIEditor: React.FC = () => { const [selectedROI, setSelectedROI] = useState(null); const [drawerVisible, setDrawerVisible] = useState(false); const [form] = Form.useForm(); + const [workingHoursList, setWorkingHoursList] = useState<{start: dayjs.Dayjs | null, end: dayjs.Dayjs | null}[]>([]); const [isDrawing, setIsDrawing] = useState(false); const [tempPoints, setTempPoints] = useState([]); const [backgroundImage, setBackgroundImage] = useState(null); const stageRef = useRef(null); + const addWorkingHours = () => { + setWorkingHoursList([...workingHoursList, { start: null, end: null }]); + }; + + const removeWorkingHours = (index: number) => { + const newList = workingHoursList.filter((_, i) => i !== index); + setWorkingHoursList(newList); + }; + + const updateWorkingHours = (index: number, field: 'start' | 'end', value: dayjs.Dayjs | null) => { + const newList = [...workingHoursList]; + newList[index] = { ...newList[index], [field]: value }; + setWorkingHoursList(newList); + }; + + const updateWorkingHoursRange = (index: number, start: dayjs.Dayjs | null, end: dayjs.Dayjs | null) => { + setWorkingHoursList(prev => { + const newList = [...prev]; + if (newList[index]) { + newList[index] = { start, end }; + } + return newList; + }); + }; + const fetchCameras = async () => { try { const res = await axios.get('/api/cameras?enabled_only=true'); @@ -103,10 +129,12 @@ const ROIEditor: React.FC = () => { const handleSaveROI = async (values: any) => { if (!selectedCamera || !selectedROI) return; try { - const workingHours = values.working_hours?.map((item: any) => ({ - start: [item.start.hour(), item.start.minute()], - end: [item.end.hour(), item.end.minute()], - })); + const workingHours = workingHoursList + .filter(item => item.start && item.end) + .map(item => ({ + start: [item.start!.hour(), item.start!.minute()], + end: [item.end!.hour(), item.end!.minute()], + })); await axios.put(`/api/camera/${selectedCamera}/roi/${selectedROI.id}`, { name: values.name, @@ -119,6 +147,7 @@ const ROIEditor: React.FC = () => { }); message.success('保存成功'); setDrawerVisible(false); + setWorkingHoursList([]); fetchROIs(); } catch (err: any) { message.error(`保存失败: ${err.response?.data?.detail || '未知错误'}`); @@ -226,11 +255,11 @@ const ROIEditor: React.FC = () => { threshold_sec: roi.threshold_sec, confirm_sec: roi.confirm_sec, enabled: roi.enabled, - working_hours: roi.working_hours?.map((wh: WorkingHours) => ({ - start: dayjs().hour(wh.start[0]).minute(wh.start[1]), - end: dayjs().hour(wh.end[0]).minute(wh.end[1]), - })), }); + setWorkingHoursList(roi.working_hours?.map((wh: WorkingHours) => ({ + start: wh.start ? dayjs().hour(wh.start[0]).minute(wh.start[1]) : null, + end: wh.end ? dayjs().hour(wh.end[0]).minute(wh.end[1]) : null, + })) || []); setDrawerVisible(true); }} onMouseEnter={(e) => { @@ -387,11 +416,11 @@ const ROIEditor: React.FC = () => { threshold_sec: roi.threshold_sec, confirm_sec: roi.confirm_sec, enabled: roi.enabled, - working_hours: roi.working_hours?.map((wh: WorkingHours) => ({ - start: dayjs().hour(wh.start[0]).minute(wh.start[1]), - end: dayjs().hour(wh.end[0]).minute(wh.end[1]), - })), }); + setWorkingHoursList(roi.working_hours?.map((wh: WorkingHours) => ({ + start: wh.start ? dayjs().hour(wh.start[0]).minute(wh.start[1]) : null, + end: wh.end ? dayjs().hour(wh.end[0]).minute(wh.end[1]) : null, + })) || []); setDrawerVisible(true); }} > @@ -426,6 +455,7 @@ const ROIEditor: React.FC = () => { onClose={() => { setDrawerVisible(false); setSelectedROI(null); + setWorkingHoursList([]); }} width={400} > @@ -458,33 +488,35 @@ const ROIEditor: React.FC = () => { 工作时间配置(可选) - - {(fields, { add, remove }) => ( -
- {fields.map((field, index) => ( - - - - - - - ))} - -
- )} -
+ + ))} + + 不配置工作时间则使用系统全局设置 @@ -501,6 +533,7 @@ const ROIEditor: React.FC = () => {