| | |
| | | -- auto-generated definition |
| | | create table man_lane |
| | | ( |
| | | id bigint unsigned auto_increment comment 'ID' |
| | | primary key, |
| | | uuid varchar(255) null comment '编号(*)', |
| | | zone_id bigint null comment '库区[man_zone]', |
| | | name varchar(255) null comment '名称', |
| | | hash_code varchar(255) not null comment '哈希值', |
| | | codes text not null comment '条码集', |
| | | entry_angle int default -1 null comment '入口角度', |
| | | maximum int default -1 null comment '承载量', |
| | | status int(1) default 1 not null comment '状态{1:正常,0:冻结}', |
| | | deleted int(1) default 0 not null comment '是否删除{1:是,0:否}', |
| | | tenant_id int null comment '租户[sys_tenant]', |
| | | create_by bigint null comment '添加人员[sys_user]', |
| | | create_time timestamp default CURRENT_TIMESTAMP not null comment '添加时间', |
| | | update_by bigint null comment '修改人员[sys_user]', |
| | | update_time timestamp default CURRENT_TIMESTAMP null comment '修改时间', |
| | | memo varchar(255) null comment '备注' |
| | | ) |
| | | charset = utf8; |
| | | |
| | | alter table man_code |
| | | add dir_rule varchar(255) null comment '方向规则' after corner; |
| | |
| | | x: "x", |
| | | y: "y", |
| | | corner: "corner", |
| | | dirRule: "direction rule", |
| | | scale: "scale", |
| | | spin: "spin", |
| | | }, |
| | |
| | | }, |
| | | page: { |
| | | code: { |
| | | dirRule: { |
| | | helper: 'Select one direction to disable; other directions remain available.', |
| | | status: { |
| | | enabled: 'Enabled', |
| | | disabled: 'Disabled', |
| | | }, |
| | | }, |
| | | enums: { |
| | | spin: { |
| | | na: 'N/A', |
| | |
| | | x: "x", |
| | | y: "y", |
| | | corner: "拐角", |
| | | dirRule: "方向规则", |
| | | scale: "比例", |
| | | spin: "旋转", |
| | | }, |
| | |
| | | }, |
| | | page: { |
| | | code: { |
| | | dirRule: { |
| | | helper: '选择一个方向禁用,其余方向保持可用', |
| | | status: { |
| | | enabled: '可用', |
| | | disabled: '禁用', |
| | | }, |
| | | }, |
| | | enums: { |
| | | spin: { |
| | | na: '全向', |
| | |
| | | import React, { useState, useRef, useEffect, useMemo } from "react"; |
| | | import React, { useEffect, useMemo } from "react"; |
| | | import { |
| | | Edit, |
| | | SimpleForm, |
| | |
| | | DeleteButton, |
| | | } from 'react-admin'; |
| | | import { useWatch, useFormContext } from "react-hook-form"; |
| | | import { Stack, Grid, Box, Typography } from '@mui/material'; |
| | | import { Stack, Grid, Box, Typography, ToggleButton, ToggleButtonGroup } from '@mui/material'; |
| | | import { alpha } from '@mui/material/styles'; |
| | | import * as Common from '@/utils/common'; |
| | | import { EDIT_MODE } from '@/config/setting'; |
| | | import EditBaseAside from "../components/EditBaseAside"; |
| | |
| | | </Toolbar> |
| | | ) |
| | | } |
| | | |
| | | const DIR_RULE_ANGLES = [0, 90, 180, 270]; |
| | | |
| | | 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 { register, setValue } = useFormContext(); |
| | | const dirRuleValue = useWatch({ name: 'dirRule' }); |
| | | |
| | | useEffect(() => { |
| | | register('dirRule'); |
| | | }, [register]); |
| | | |
| | | const rules = useMemo(() => normalizeDirRuleValue(dirRuleValue), [dirRuleValue]); |
| | | const normalizedRulesString = useMemo(() => JSON.stringify(rules), [rules]); |
| | | |
| | | useEffect(() => { |
| | | if (dirRuleValue !== normalizedRulesString) { |
| | | setValue('dirRule', normalizedRulesString, { shouldDirty: false, shouldTouch: false }); |
| | | } |
| | | }, [dirRuleValue, normalizedRulesString, setValue]); |
| | | |
| | | 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; |
| | | return ( |
| | | <ToggleButton |
| | | key={rule.angle} |
| | | value={rule.angle} |
| | | sx={{ |
| | | textTransform: 'none', |
| | | flex: 1, |
| | | flexDirection: 'column', |
| | | gap: 0.5, |
| | | py: 1.5, |
| | | '&.Mui-selected': { |
| | | 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), |
| | | }, |
| | | }, |
| | | '& .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(); |
| | |
| | | /> |
| | | </Stack> */} |
| | | |
| | | <Box mt={2}> |
| | | <DirectionRuleInput /> |
| | | </Box> |
| | | |
| | | </Grid> |
| | | <Grid item xs={12} md={4}> |
| | | <Typography variant="h6" gutterBottom> |
| | |
| | | return list; |
| | | } |
| | | |
| | | public static List<DirectionDto> initCodeDirections0() { |
| | | List<DirectionDto> list = new ArrayList<>(); |
| | | DirectionDto northDto = new DirectionDto(); |
| | | northDto.setAngle(CodeDirectionType.NORTH.angle); |
| | | northDto.setEnabled(true); |
| | | list.add(northDto); |
| | | |
| | | DirectionDto eastDto = new DirectionDto(); |
| | | eastDto.setAngle(CodeDirectionType.EAST.angle); |
| | | eastDto.setEnabled(false); |
| | | list.add(eastDto); |
| | | |
| | | DirectionDto southDto = new DirectionDto(); |
| | | southDto.setAngle(CodeDirectionType.SOUTH.angle); |
| | | southDto.setEnabled(true); |
| | | list.add(southDto); |
| | | |
| | | DirectionDto westDto = new DirectionDto(); |
| | | westDto.setAngle(CodeDirectionType.WEST.angle); |
| | | westDto.setEnabled(true); |
| | | list.add(westDto); |
| | | |
| | | return list; |
| | | } |
| | | |
| | | } |
| | |
| | | import com.zy.acs.manager.core.domain.DirectionDto; |
| | | import com.zy.acs.manager.core.domain.SortCodeDto; |
| | | import com.zy.acs.manager.core.domain.UnlockPathTask; |
| | | import com.zy.acs.manager.core.domain.type.CodeDirectionType; |
| | | import com.zy.acs.manager.core.service.astart.*; |
| | | import com.zy.acs.manager.core.service.astart.domain.AStarNavigateNode; |
| | | import com.zy.acs.manager.core.service.astart.domain.DynamicNode; |
| | |
| | | public static void main(String[] args) { |
| | | CodeSpinType codeSpinType = calcSpinDirection(null, 260.0, 10.0); |
| | | List<DirectionDto> directionDtoList = DirectionDto.initCodeDirections(); |
| | | System.out.println(JSON.toJSONString(directionDtoList)); |
| | | System.out.println(codeSpinType.toString()); |
| | | } |
| | | |
| | |
| | | return CodeSpinType.NA; |
| | | } |
| | | List<Double> disableAngleList = new ArrayList<>(); |
| | | List<DirectionDto> directionDtoList = DirectionDto.initCodeDirections(); |
| | | if (code.getData().contains("57")) { |
| | | directionDtoList = DirectionDto.initCodeDirections0(); |
| | | List<DirectionDto> directionDtoList; |
| | | if (!Cools.isEmpty(code.getDirRule())) { |
| | | directionDtoList = JSON.parseArray(code.getDirRule(), DirectionDto.class); |
| | | } else { |
| | | directionDtoList = DirectionDto.initCodeDirections(); |
| | | } |
| | | for (DirectionDto dto : directionDtoList) { |
| | | if (null != dto.getEnabled() && !dto.getEnabled()) { |
| | |
| | | private String scale; |
| | | |
| | | /** |
| | | * 方向规则 |
| | | */ |
| | | @ApiModelProperty(value= "方向规则") |
| | | private String dirRule; |
| | | |
| | | /** |
| | | * 旋转方向 0: N/A 1: 顺时针 2: 逆时针 |
| | | */ |
| | | @ApiModelProperty(value= "旋转方向 0: N/A 1: 顺时针 2: 逆时针 ") |