import StepItem from '../components/StepItem'; import { useNavigate } from 'react-router-dom'; import CustomNavBar from '../components/CustomNavBar'; import MeasurementCanvas, { BenchmarkShape, MeasurementCanvasRef, Point, } from '../components/konva/MeasurementCanvas'; import { useEffect, useRef, useState } from 'react'; import RailTypeBtn from '../components/RailTypeBtn'; import { Cascader, Dialog, Mask, Picker, SpinLoading, Toast } from 'antd-mobile'; import { useAppDispatch, useAppSelector } from '../utils/hooks'; import { updateMeasureData, updateTaskState, updateMeasureStatus, updateMeasureFinish, updateShowCalibration } from '../store/features/measureSlice'; import Bridge from '../utils/bridge'; import { selectLabeledKtjOrgs, updateRailPoints } from '../store/features/baseData'; import { updateOrg } from '../store/features/contextSlice'; import { selectOrgTextArr } from '../store'; import icon_left from '../assets/icon_left.svg'; import icon_right from '../assets/icon_right.svg'; import icon_up from '../assets/icon_up.svg'; import icon_down from '../assets/icon_down.svg'; import icon_leftR from '../assets/icon_leftR.svg'; import icon_rightR from '../assets/icon_rightR.svg'; export default function Measure() { const navigate = useNavigate(); const dispatch = useAppDispatch(); const labeledKtjOrgs = useAppSelector(selectLabeledKtjOrgs); const orgTextArr = useAppSelector(selectOrgTextArr); const measureState = useAppSelector((state) => state.measure); const contextState = useAppSelector((state) => state.context); const baseState = useAppSelector((state) => state.baseData); const [railPickerVisible, setRailPickerVisible] = useState(false); const [railId, setRailId] = useState<(number | string | null)[]>([]); const canvasRef = useRef(null); const [railSize, setRailSize] = useState(); const iconWidth = 40; const [showStandard, setShowStandard] = useState(false); // 默认选中第一个轨型 useEffect(() => { if (baseState.railTypes.length > 0) { let railData = baseState.railTypes[0]; setRailId([railData.id]); setRailSize(railData.code); } }, [baseState.railTypes]); function drawRailBaseLine(points: string) { const benchmarkShapes = JSON.parse(points) as BenchmarkShape[]; if (canvasRef.current) { canvasRef.current.setBenchmarkData(benchmarkShapes); } } // useEffect(() => { // // setTimeout(() => { // // setShowStandard(false) // // setMeasurementCanvasKey(measurementCanvasKey + 1) // // }, 1000) // // return () =>{ // console.log(111) // setMeasurementCanvasKey(measurementCanvasKey + 1) // } // }, []); // 检查轨型有没有坐标,如果有,绘制轨型基准线,如果没,拉取再绘制其线 useEffect(() => { if (railId.length > 0) { const r = baseState.railTypes.find((rail) => rail.id === railId[0]); if (!r) return; if (!!r.points) { drawRailBaseLine(r.points); return; } Bridge.getTrackPoint({ code: r.code }).then((res) => { if (res.success) { dispatch(updateRailPoints(res.data)); drawRailBaseLine(res.data.points!); console.log(r.points) } else { Toast.show(res.message); } }); } }, [baseState.railTypes, dispatch, railId, measureState.measureFinishData]); useEffect(() => { if (canvasRef.current && measureState.measureFinishData.length) { setTimeout(() => { setShowStandard(true) }, 100); canvasRef.current?.setMeasurementCalibrationData(measureState.measureFinishData); setShowMeasureFinish(true) } }, [baseState.railTypes, measureState.measureFinishData, railId]); // 绘制测量坐标线 useEffect(() => { if (canvasRef.current) { canvasRef.current.setMeasurementDataLeft(measureState.leftPoints); } }, [measureState.leftPoints]); useEffect(() => { if (canvasRef.current) { canvasRef.current.setMeasurementDataRight(measureState.rightPoints); } }, [measureState.rightPoints]); // 左右两测量完成,转换后的测量线(两线合一线) // useEffect(() => { // const points = baseState.railTypes.find((r) => r.id === railId[0]) // console.log(1111, points) // // if (canvasRef.current && measureState.measureFinishData.length) { // setTimeout(() => { // const points = baseState.railTypes.find((r) => r.code === railId[0])?.points // drawRailBaseLine(points || '[]') // setShowStandard(true) // }, 100); // canvasRef.current?.setMeasurementCalibrationData(measureState.measureFinishData); // // setShowCalibration(true); // setShowMeasureFinish(true) // setLoading(false) // // // } // }, [measureState.measureFinishData]) useEffect(() => { if(measureState.measureStatus === 'FINISH_RECORD'){ setLoading(true) Bridge.record().then((res) => { if (res.success) { dispatch(updateMeasureFinish(res.data)); } else { dispatch(updateMeasureFinish([])); setState({ left_ready: 'none', right_ready: 'none', left_begin: 'none', right_begin: 'none', left_end: 'none', right_end: 'none', }); Toast.show(res.message); } }).finally(() => { setLoading(false) }) } }, [dispatch, measureState.measureStatus]) useEffect(() => { return () => { dispatch(updateMeasureStatus('')) } }, [dispatch]) const onSaveClick = () => { if (!contextState.currOrgCode || !orgTextArr) { Dialog.alert({ content: '请选择铁路局/工务段/线路', onConfirm: () => { onOrgBarClick(); }, }); return; } dispatch(updateMeasureData(newMeasureData)); navigate('/measure/save'); }; const [loading, setLoading] = useState(false); const [showMeasureFinish, setShowMeasureFinish] = useState(false); const onCalibrationBtnClick = () => { setLoading(true); Bridge.alignPoints({ railSize: railSize || 'GX-60' }) .then((res) => { if (res.success) { // setShowCalibration(true); dispatch(updateShowCalibration(true)) canvasRef.current?.setMeasurementCalibrationData(res.data); dispatch(updateMeasureFinish(res.data)) } else { } setLoading(false); }) .catch((e) => { setLoading(false); Toast.show({ content: 服务器异常, position: 'top', }); }); }; const [initStart, setInitStart] = useState(false); const [measurementCanvasKey, setMeasurementCanvasKey] = useState(0); const [state, setState] = useState({ left_ready: 'none', right_ready: 'none', left_begin: 'none', right_begin: 'none', left_end: 'none', right_end: 'none', }); const onStartClick = () => { setMeasurementCanvasKey(measurementCanvasKey+1) // setShowCalibration(false); dispatch(updateShowCalibration(false)) setShowMeasureFinish(false) dispatch(updateMeasureData([])); if (!contextState.device.connected) { Dialog.alert({ content: '蓝牙未连接,请先连接蓝牙', onConfirm: () => { navigate('/home/bluetooth'); }, }); return; } if (baseState.ktjOrgs.length === 0) { Dialog.alert({ content: '请在基础数据同步完成后重试', onConfirm: () => { navigate('/home/mine'); }, }); return; } if (!contextState.currOrgCode || !orgTextArr) { Dialog.alert({ content: '请选择铁路局/工务段/线路', onConfirm: () => { onOrgBarClick(); }, }); return; } // if (contextState.device.power < 20) { // Toast.show("电量低于20%,请充电后测量"); // return; // } Bridge.startMeasure().then((res) => { if (res.success) { dispatch(updateTaskState('START_RECORD_SIG')); } else { Toast.show(res.message); } setInitStart(true); setShowStandard(false) }); }; const onOrgBarClick = async () => { if (baseState.ktjOrgs.length === 0) { Dialog.alert({ content: '请在基础数据同步完成后重试', onConfirm: () => { navigate('/home/mine'); }, }); return; } const value = await Cascader.prompt({ options: labeledKtjOrgs, placeholder: '请选择', }); console.log(value) // Toast.show(value ? `你选择了 ${value.join(' - ')}` : '你没有进行选择'); if (value?.length) { dispatch(updateOrg(value as string[])); }else { Toast.show('请选择组织机构'); } }; const [status, setStatus] = useState(0) useEffect(() => { console.log(measureState.taskState) switch (measureState.taskState) { case 'WAITING_FOR_RECORD_THE_1ST_SIDE': setStatus(1); setState({ left_ready: 'ongoing', right_ready: 'none', left_begin: 'none', right_begin: 'none', left_end: 'none', right_end: 'none', }); break; case 'WAITING_FOR_RECORD_THE_2ND_SIDE': setStatus(2) break; case 'START_RECORD_SIG': setState({ left_ready: 'ongoing', right_ready: 'none', left_begin: 'none', right_begin: 'none', left_end: 'none', right_end: 'none', }); break; case 'START_RECORD_LEFT': case 'START_RECORD_RIGHT': if (status === 1) { setState({ left_ready: 'done', right_ready: 'none', left_begin: 'ongoing', right_begin: 'none', left_end: 'none', right_end: 'none', }); } else if (status === 2) { setState({ left_ready: 'done', right_ready: 'done', left_begin: 'done', right_begin: 'ongoing', left_end: 'done', right_end: 'none', }); } break; case 'FINISH_RECORD_LEFT': case 'FINISH_RECORD_RIGHT': if (status === 1) { setState({ left_ready: 'done', right_ready: 'none', left_begin: 'done', right_begin: 'none', left_end: 'done', right_end: 'none', }); } else if (status === 2) { setState({ left_ready: 'done', right_ready: 'done', left_begin: 'done', right_begin: 'done', left_end: 'done', right_end: 'done', }); } break; case 'FINISH_RECORD': setState({ left_ready: 'done', right_ready: 'done', left_begin: 'done', right_begin: 'done', left_end: 'done', right_end: 'done', }); // 测量完成,显示基线 break; default: setState({ left_ready: 'none', right_ready: 'none', left_begin: 'none', right_begin: 'none', left_end: 'none', right_end: 'none', }); } }, [measureState.taskState, status]); function railName() { return baseState.railTypes.find((r) => r.id === railId[0])?.name || ''; } function onRailSizeChange(ids: (number | string | null)[]) { if (ids && ids.length) { setRailId(ids); let id = ids[0]; const codes = baseState.railTypes.map((item) => { if (item.id === id) { return item.code; } return item.code; }); if (codes && codes.length) { setRailSize(codes[0]); } } } const [style, setStyle] = useState({ left: 'none', right: 'none', up: 'none', down: 'none', left_rotation:'none', right_rotation:'none', }); //上下移动 let timerRef = useRef(null); const handlePressStart = (type: string) => { setStyle({...style, [type]: 'active'}) console.log('你进行了长按操作!'); if (timerRef.current) { return } timerRef.current = setInterval(() => { console.log('111!'); onHandleMove(type); }, 100); console.log(timerRef.current) }; const handlePressEnd = () => { setStyle({ left: 'none', right: 'none', up: 'none', down: 'none', left_rotation:'none', right_rotation:'none', }) clearInterval(timerRef.current); timerRef.current = null; }; const onMoveLine = (type: string) => { console.log('这是点击'); onHandleMove(type); }; const onHandleMove = (type: string) => { let list = canvasRef.current?.getMeasurementCalibrationData(); console.log(list) if (list && list.length) { const updatedList = list.map((item) => { const mutableItem = { ...item }; // 创建副本 if (type === 'up') { mutableItem.y -= distance / 1000; } else if (type === 'down') { mutableItem.y += distance / 1000; } else if (type === 'left') { mutableItem.x -= distance / 1000; } else if (type === 'right') { mutableItem.x += distance / 1000; } return mutableItem; }); canvasRef.current?.setMeasurementCalibrationData(updatedList); dispatch(updateMeasureFinish(list)); setNewMeasureData(updatedList); } }; const handleRotationPressStart = (type: string) => { setStyle({...style, [type === 'left' ? 'left_rotation' : 'right_rotation']: 'active'}) timerRef.current = setInterval(() => { onRotationLine(type); }, 500); }; //旋转 let [measurementRotation] = useState(0); let [newMeasureData, setNewMeasureData] = useState(); let [angle] = useState(5); //角度单位 分 let [distance] = useState(100); const onRotationLine = (type: string) => { let mrValue = 0; if (type === 'left') { //逆时针 mrValue = measurementRotation - ((angle / 60) * Math.PI) / 180; } if (type === 'right') { //顺时针 mrValue = measurementRotation + ((angle / 60) * Math.PI) / 180; } let list = canvasRef.current?.getMeasurementCalibrationData(); if (list && list.length) { const updatedList = list.map((item) => { const mutableItem = { ...item }; // 创建副本 let cloneItem = rotatePoint(mutableItem, mrValue); mutableItem.x = cloneItem.x; mutableItem.y = cloneItem.y; return mutableItem; }); canvasRef.current?.setMeasurementCalibrationData(updatedList); dispatch(updateMeasureFinish(list)); setNewMeasureData(updatedList); } }; const rotatePoint = (pt: { x: number; y: number }, angle: number) => { const item = { x: pt.x * Math.cos(angle) - pt.y * Math.sin(angle), y: pt.x * Math.sin(angle) + pt.y * Math.cos(angle), }; return item; }; const handleContextMenu = (e: any) => { e.preventDefault(); }; return ( <>
{/**正在校准时的loading */} {/*loading*/} {loading && (
请稍候...
)} {/**测量区 */}
{/**选择轨型区 */} {railId.length > 0 && (
setRailPickerVisible(true)} />
)}
{/**局段线区 */}

{contextState.currOrgCode && orgTextArr ? orgTextArr.join('/') : '点击此处选择铁路局和工务段'}

修改
{/**手动校准区 */} {(measureState.showCalibration && measureState.measureFinishData.length>0) && (
onMoveLine('left')} onTouchStart={() => handlePressStart('left')} onTouchEnd={handlePressEnd} onTouchCancel={handlePressEnd} onContextMenu={handleContextMenu} className={ style.left === 'active' ? 'text-[20px] ml-[5px] icon-button active-icon-button' : 'text-[20px] ml-[5px] icon-button' } alt="左移" /> onMoveLine('right')} onTouchStart={() => handlePressStart('right')} onTouchEnd={handlePressEnd} onTouchCancel={handlePressEnd} onContextMenu={handleContextMenu} className={ style.right === 'active' ? 'text-[20px] ml-[5px] icon-button active-icon-button' : 'text-[20px] ml-[5px] icon-button' } alt="右移" /> onMoveLine('up')} onTouchStart={() => handlePressStart('up')} onTouchEnd={handlePressEnd} onTouchCancel={handlePressEnd} onContextMenu={handleContextMenu} className={ style.up === 'active' ? 'text-[20px] ml-[5px] icon-button active-icon-button' : 'text-[20px] ml-[5px] icon-button' } alt="上移" /> onMoveLine('down')} onTouchStart={() => handlePressStart('down')} onTouchEnd={handlePressEnd} onTouchCancel={handlePressEnd} onContextMenu={handleContextMenu} className={ style.down === 'active' ? 'text-[20px] ml-[5px] icon-button active-icon-button' : 'text-[20px] ml-[5px] icon-button' } alt="下移" /> onRotationLine('left')} onTouchStart={() => handleRotationPressStart('left')} onTouchEnd={handlePressEnd} onTouchCancel={handlePressEnd} onContextMenu={handleContextMenu} className={ style.left_rotation === 'active' ? 'text-[20px] ml-[5px] icon-button active-icon-button' : 'text-[20px] ml-[5px] icon-button' } alt="逆时针旋转" /> onRotationLine('right')} onTouchStart={() => handleRotationPressStart('right')} onTouchEnd={handlePressEnd} onTouchCancel={handlePressEnd} onContextMenu={handleContextMenu} className={ style.right_rotation === 'active' ? 'text-[20px] ml-[5px] icon-button active-icon-button' : 'text-[20px] ml-[5px] icon-button' } alt="顺时针旋转" />
)} {/**按钮操作区 */}
{/**测量状态区 */}
({ label: t.name, value: t.id }))]} visible={railPickerVisible} onClose={() => { setRailPickerVisible(false); }} value={railId} onConfirm={(v) => { onRailSizeChange(v); }} /> ); }