From b3cd0b749e427c5c8e4dba8e9f01c6cff51d07d7 Mon Sep 17 00:00:00 2001
From: vincentlu <t1341870251@gmail.com>
Date: 星期一, 19 一月 2026 12:47:44 +0800
Subject: [PATCH] #

---
 zy-acs-flow/src/page/code/CodeEdit.jsx |  196 +++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 191 insertions(+), 5 deletions(-)

diff --git a/zy-acs-flow/src/page/code/CodeEdit.jsx b/zy-acs-flow/src/page/code/CodeEdit.jsx
index 9741cd5..ec0ab8b 100644
--- a/zy-acs-flow/src/page/code/CodeEdit.jsx
+++ b/zy-acs-flow/src/page/code/CodeEdit.jsx
@@ -1,4 +1,4 @@
-import React, { useState, useRef, useEffect, useMemo } from "react";
+import React, { useEffect, useMemo } from "react";
 import {
     Edit,
     SimpleForm,
@@ -21,8 +21,8 @@
     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 { Stack, Grid, Box, Typography, ToggleButton, ToggleButtonGroup } from '@mui/material';
+import { alpha } from '@mui/material/styles';
 import { EDIT_MODE } from '@/config/setting';
 import EditBaseAside from "../components/EditBaseAside";
 import CustomerTopToolBar from "../components/EditTopToolBar";
@@ -39,6 +39,178 @@
         </Toolbar>
     )
 }
+
+const DIR_RULE_ANGLES = [0, 90, 180, 270];
+const DEFAULT_DIR_RULES = DIR_RULE_ANGLES.map(angle => ({ angle, enabled: true }));
+
+const normalizeDirRuleValue = (value) => {
+    let parsed = [];
+
+    if (Array.isArray(value)) {
+        parsed = value;
+    } else if (typeof value === 'string' && value.trim()) {
+        try {
+            parsed = JSON.parse(value);
+        } catch (error) {
+            parsed = [];
+        }
+    } else if (value && typeof value === 'object') {
+        parsed = [value];
+    }
+
+    const angleMap = new Map();
+
+    parsed.forEach(item => {
+        const angle = typeof item?.angle === 'number' ? item.angle : Number(item?.angle);
+        if (!Number.isFinite(angle)) {
+            return;
+        }
+        const enabled = !(
+            item?.enabled === false ||
+            item?.enabled === 'false' ||
+            item?.enabled === 0 ||
+            item?.enabled === '0'
+        );
+        angleMap.set(angle, { angle, enabled });
+    });
+
+    let disabledCaptured = false;
+
+    return DIR_RULE_ANGLES.map(angle => {
+        const matched = angleMap.get(angle);
+        if (matched && matched.enabled === false) {
+            if (disabledCaptured) {
+                return { angle, enabled: true };
+            }
+            disabledCaptured = true;
+            return { angle, enabled: false };
+        }
+
+        return { angle, enabled: true };
+    });
+};
+
+const DirectionRuleInput = () => {
+    const translate = useTranslate();
+    const record = useRecordContext();
+    const { register, setValue } = useFormContext();
+    const dirRuleValue = useWatch({ name: 'dirRule' });
+
+    useEffect(() => {
+        register('dirRule');
+    }, [register]);
+
+    const initialDirRuleString = useMemo(() => {
+        const source = record?.dirRule ?? DEFAULT_DIR_RULES;
+        return JSON.stringify(normalizeDirRuleValue(source));
+    }, [record]);
+
+    useEffect(() => {
+        if (dirRuleValue === undefined || dirRuleValue === null || dirRuleValue === '') {
+            setValue('dirRule', initialDirRuleString, { shouldDirty: false, shouldTouch: false });
+            return;
+        }
+
+        const normalizedString = JSON.stringify(normalizeDirRuleValue(dirRuleValue));
+        if (dirRuleValue !== normalizedString) {
+            setValue('dirRule', normalizedString, { shouldDirty: false, shouldTouch: false });
+        }
+    }, [dirRuleValue, initialDirRuleString, setValue]);
+
+    const rules = useMemo(
+        () => normalizeDirRuleValue(dirRuleValue ?? initialDirRuleString),
+        [dirRuleValue, initialDirRuleString]
+    );
+
+    const disabledAngle = useMemo(() => {
+        const disabled = rules.find(rule => !rule.enabled);
+        return typeof disabled?.angle === 'number' ? disabled.angle : null;
+    }, [rules]);
+
+    const handleToggle = (_, newDisabledAngle) => {
+        if (newDisabledAngle === null) {
+            const resetRules = rules.map(rule => ({ ...rule, enabled: true }));
+            setValue('dirRule', JSON.stringify(resetRules), { shouldDirty: true, shouldTouch: true });
+            return;
+        }
+
+        const parsedAngle = typeof newDisabledAngle === 'number' ? newDisabledAngle : Number(newDisabledAngle);
+        if (Number.isNaN(parsedAngle)) {
+            return;
+        }
+
+        const nextRules = rules.map(rule =>
+            rule.angle === parsedAngle ? { ...rule, enabled: false } : { ...rule, enabled: true }
+        );
+
+        setValue('dirRule', JSON.stringify(nextRules), { shouldDirty: true, shouldTouch: true });
+    };
+
+    return (
+        <Box>
+            <Typography variant="subtitle2" sx={{ fontWeight: 500, mb: 1 }}>
+                {translate('table.field.code.dirRule')}
+            </Typography>
+            <Typography variant="caption" color="text.secondary" sx={{ display: 'block', mb: 1 }}>
+                {translate('page.code.dirRule.helper')}
+            </Typography>
+            <ToggleButtonGroup
+                fullWidth
+                exclusive
+                value={disabledAngle}
+                onChange={handleToggle}
+                color="primary"
+            >
+                {rules.map(rule => {
+                    const isDisabled = !rule.enabled;
+                    const disabledStyles = {
+                        color: (theme) => theme.palette.error.main,
+                        borderColor: (theme) => theme.palette.error.main,
+                        bgcolor: (theme) => alpha(theme.palette.error.main, 0.08),
+                        '&:hover': {
+                            bgcolor: (theme) => alpha(theme.palette.error.main, 0.16),
+                        },
+                    };
+                    return (
+                        <ToggleButton
+                            key={rule.angle}
+                            value={rule.angle}
+                            sx={{
+                                textTransform: 'none',
+                                flex: 1,
+                                flexDirection: 'column',
+                                gap: 0.5,
+                                py: 1.5,
+                                ...(isDisabled ? disabledStyles : {}),
+                                '&.Mui-selected': disabledStyles,
+                                '& .dirRuleStatus': {
+                                    color: isDisabled ? 'error.main' : 'text.secondary',
+                                },
+                                '& .dirRuleAngle': {
+                                    fontWeight: 600,
+                                },
+                                '&.Mui-selected .dirRuleStatus': {
+                                    color: (theme) => theme.palette.error.main,
+                                },
+                            }}
+                        >
+                            <Typography className="dirRuleAngle" variant="body2">
+                                {rule.angle}掳
+                            </Typography>
+                            <Typography
+                                variant="caption"
+                                className="dirRuleStatus"
+                                sx={{ fontWeight: 600, letterSpacing: 0.2, textTransform: 'uppercase' }}
+                            >
+                                {translate(isDisabled ? 'page.code.dirRule.status.disabled' : 'page.code.dirRule.status.enabled')}
+                            </Typography>
+                        </ToggleButton>
+                    );
+                })}
+            </ToggleButtonGroup>
+        </Box>
+    );
+};
 
 const CodeEdit = () => {
     const translate = useTranslate();
@@ -98,13 +270,27 @@
                                 source="y"
                             />
                         </Stack>
-                        <Stack direction='row' gap={2}>
+                        {/* <Stack direction='row' gap={2}>
+                            <SelectInput
+                                label="table.field.code.spin"
+                                source="spin"
+                                choices={[
+                                    { id: 0, name: 'page.code.enums.spin.na' },
+                                    { id: 1, name: 'page.code.enums.spin.cw' },
+                                    { id: 2, name: 'page.code.enums.spin.ccw' },
+                                ]}
+                                validate={required()}
+                            />
                             <TextInput
                                 label="table.field.code.scale"
                                 source="scale"
                                 parse={v => v}
                             />
-                        </Stack>
+                        </Stack> */}
+
+                        <Box mt={2}>
+                            <DirectionRuleInput />
+                        </Box>
 
                     </Grid>
                     <Grid item xs={12} md={4}>

--
Gitblit v1.9.1