();
const items: MenuProps["items"] = [
@@ -133,24 +83,6 @@ export default function Header() {
},
];
- const getBtList = () => {
- let Dom = null;
- if (!isConnect) {
- Dom = (
-
- {bluetoothList.map(item => {
- return (
-
-
-
- );
- })}
-
- );
- }
- return Dom;
- };
-
//设备已连接
const getBtContent = () => {
return (
@@ -169,16 +101,6 @@ export default function Header() {
);
};
- //断开蓝牙连接
- const onDisconnectBt = () => {
- setIsConnect(false);
- };
-
- const connectBt = () => {
- setIsConnect(true);
- setTimeout(() => {}, 1000);
- };
-
return (
<>
{contextHolder}
@@ -200,9 +122,6 @@ export default function Header() {
>
)}
- {/*
-
- */}
{showBlueImg()}
@@ -213,7 +132,6 @@ export default function Header() {
- {isShowModal && }
>
);
}
diff --git a/src/components/syncData.tsx b/src/components/syncData.tsx
index d7c97b1..7f5e435 100644
--- a/src/components/syncData.tsx
+++ b/src/components/syncData.tsx
@@ -1,60 +1,31 @@
import { useState, useEffect } from "react";
-import { Progress } from "antd";
+import { message, Progress } from "antd";
+import { useAppDispatch, useAppSelector } from "../utils/hooks";
import "./sync.scss";
-import { update } from "../services/ktj/org";
-export default function SyncData(props:{isShowModal:boolean, closeModal:Function}) {
- //同步科天健基础数据
- const onSyncKTJData = () => {
- update().then(res => {
- setPercent(100)
- props.closeModal()
- setTimeout(() => {
- setPercent(0)
- }, 2000);
- })
- }
-
- useEffect(()=>{
- onSyncKTJData()
- }, [props.isShowModal])
-
+export default function SyncData(props:{isShowModal:boolean, closeModal:Function, setIsSync:Function}) {
const [percent, setPercent] = useState(0)
- useEffect(() => {
- const intervalId = setInterval(() => {
- if (percent < 100) {
- const randomIncrement = Math.floor(Math.random() * 3) + 1;
- const newProgress = Math.min(percent + randomIncrement, 100);
- setPercent(newProgress);
- } else {
- clearInterval(intervalId);
- }
- }, 1000);
- if(percent >= 90){
- clearInterval(intervalId);
+ const syncDataProcess = useAppSelector(store => store.orgState.syncDataProcess);
+ useEffect(()=>{
+ setPercent(syncDataProcess)
+ if(syncDataProcess === 100){
+ props.closeModal();
+ props.setIsSync(false)
}
- return () => {
- clearInterval(intervalId);
- };
-}, [props.isShowModal,percent]);
+ },[syncDataProcess])
const styleObj:any = {
position: "absolute",
marginTop: "-200px",
- color: "#0051b9",
+ color: "#1677ff",
fontSize: "20px"
}
return (
- <>
-
-
-
正在进行数据同步
-
-
+
+
正在进行数据同步
+
+
- >
+
);
}
diff --git a/src/pages/measure/components/Detail.tsx b/src/pages/measure/components/Detail.tsx
index 5188f28..04c1b3f 100644
--- a/src/pages/measure/components/Detail.tsx
+++ b/src/pages/measure/components/Detail.tsx
@@ -6,22 +6,26 @@ import { useNavigate, useParams } from 'react-router-dom';
import type { AnalysisReport } from "../../../services/measure/type";
import { AnalysisData, BenchmarkShape, MeasurementCanvasRef } from './konva/MeasurementCanvas';
import MeasurementCanvas from "./konva/MeasurementCanvas";
-import {
- getReport
-} from "../../../services/measure/analysis";
+import { getReport } from "../../../services/measure/analysis";
import { getBaseRecordPointSetByCode } from "../../../services/track/trackShape"
-import { GX_CODE } from '../../../constant';
+import { useAppSelector } from "../../../utils/hooks";
export default function MeasureDetail() {
const {id} = useParams()
-
+ const measureState = useAppSelector((store) => store.measureState);
const [measureId, setMeasureId] = useState
(Number(id))
+
useEffect(()=>{
onShowDetail(measureId)
}, [])
+ const [gxCode, setGxCode] = useState('')
+ useEffect(()=>{
+ setGxCode(measureState.gxCode)
+ }, [measureState])
+
const onShowDetail = (measureId:number)=> {
//获取基线
- getBaseRecordPointSetByCode(GX_CODE).then(res => {
+ getBaseRecordPointSetByCode(gxCode).then(res => {
if (res.success && res.data && res.data.points) {
const benchmarkShapes = JSON.parse(res.data.points) as BenchmarkShape[];
if (canvasRef.current) {
@@ -42,7 +46,7 @@ export default function MeasureDetail() {
//法线
const onDetaiResult = (uuid:string) => {
- getReport(uuid,GX_CODE).then(res=> {
+ getReport(uuid,gxCode).then(res=> {
if (res.success) {
const report: AnalysisReport = res.data;
console.log(report);
diff --git a/src/pages/measure/components/MeasureAction.tsx b/src/pages/measure/components/MeasureAction.tsx
index c69dd0c..94c6f50 100644
--- a/src/pages/measure/components/MeasureAction.tsx
+++ b/src/pages/measure/components/MeasureAction.tsx
@@ -1,13 +1,15 @@
import React, { useState, useEffect, useRef, useCallback, useMemo } from "react";
-import { Button, Checkbox, CheckboxProps, Drawer, message, Select, Switch } from "antd";
+import { Button, Checkbox, CheckboxProps, Drawer, message, Select, Spin, Switch } from "antd";
import { useNavigate } from "react-router";
import {
fetchAnalysisReport,
+ getAlignPointsByRailSize,
startMeasurement,
} from "../../../services/measure/analysis";
import { getBaseRecordPointSetByCode, gx_list } from "../../../services/track/trackShape"
import { createWebSocket, sharedWsUrl } from "../../../services/socket";
import { switchMeasureAfterSave } from "../../../store/features/contextSlice";
+import measureState, { updateGxState } from "../../../store/measure/measureState";
import { AnalysisReport, trackItem } from "../../../services/measure/type";
import { MeasureState, TaskState, TrackRecordSig } from "../../../services/wsTypes";
import { useAppDispatch, useAppSelector } from "../../../utils/hooks";
@@ -23,6 +25,9 @@ const wsClient = createWebSocket(sharedWsUrl);
export default function MeasureAction() {
const dispatch = useAppDispatch();
const navigate = useNavigate();
+ const measureState = useAppSelector((store) => store.measureState);
+ const [gxCode, setGxCode] = useState(GX_CODE)
+
const STEP_COLOR_GREEN = "green";
const STEP_COLOR_BLUE = "blue";
const STEP_COLOR_GREY = "grey";
@@ -67,13 +72,18 @@ export default function MeasureAction() {
dispatch(switchMeasureAfterSave(e.target.checked));
};
+ useEffect(()=>{
+ setGxCode(measureState.gxCode)
+ }, [measureState])
+
+
// 分析按钮点击事件
const onAnalysisBtnClick = () => {
if (analysisReport) {
setOpenDrawer(true);
return;
}
- fetchAnalysisReport(GX_CODE).then(res => {
+ fetchAnalysisReport(gxCode).then(res => {
if (res.success) {
const report: AnalysisReport = res.data;
console.log(report);
@@ -104,7 +114,7 @@ export default function MeasureAction() {
// 重置测量相关状态
setMeasurementFinished(false);
setAnalysisReport(null);
-
+ setshowCalibration(false)//校准线
isLeftFinished.current = false;
leftPoints.current = [];
rightPoints.current = [];
@@ -162,6 +172,25 @@ export default function MeasureAction() {
// });
};
+ //校准
+ const [showCalibration, setshowCalibration] = useState(false)
+ const [caloading, setCaLoading] = useState(false)
+ const onCalibrationBtnClick = () => {
+ setCaLoading(true)
+ //获取校准数据
+ getAlignPointsByRailSize({railSize:railSize}).then(res => {
+ if(res.success){
+ setshowCalibration(true)
+ canvasRef.current?.setMeasurementCalibrationData(res.data)
+ }else{
+ message.error('校准失败!')
+ }
+ setCaLoading(false)
+ }).catch(e=>{
+ message.error('校准失败!')
+ })
+ }
+
// 辅助函数:渲染状态项的图标
const renderStatusIcon = (item: (typeof initialStatusList)[0]) => {
if (item.color === STEP_COLOR_GREEN) {
@@ -299,13 +328,14 @@ export default function MeasureAction() {
return () => subscription.unsubscribe();
}, [onStart]);
- /** ----------------------- 页面加载获取基础图形数据 ----------------------- **/
+ /** ----------------------- 页面加载获取基础图形数据 -------基线---------------- **/
useEffect(() => {
- queryBasePoints(GX_CODE)
+ queryBasePoints(gxCode)
//获取轨型
getTrackDataList()
}, []);
+ //获取测量基线
const queryBasePoints = (gxCode:string) => {
getBaseRecordPointSetByCode(gxCode).then(res => {
if (res.success) {
@@ -343,11 +373,18 @@ export default function MeasureAction() {
},[trackList])
+ //当前选择的轨型 默认"GX-60"
+ const [railSize, setRailSize] = useState(GX_CODE)
const onTrackChange = (value: string) => {
+ setRailSize(value)
queryBasePoints(value)
+ //缓存至STORE
+ dispatch(updateGxState(value))
}
- const onExport = () => {};
+ const onExport = () => {
+
+ };
/** ----------------------- 渲染 ----------------------- **/
return (
<>
@@ -410,26 +447,27 @@ export default function MeasureAction() {
)}
-
-
-
-
-
+
+
+
+
+
{/* 右侧区域:根据 showAnalysisTable 状态显示测量步骤或分析表格 */}
@@ -469,6 +507,15 @@ export default function MeasureAction() {
>
保存
+ {/* */}
保存后自动开始新测量
@@ -508,11 +555,11 @@ export default function MeasureAction() {
- */}
>
)}
diff --git a/src/pages/measure/components/MeasureDetail.tsx b/src/pages/measure/components/MeasureDetail.tsx
index a033e7f..b362548 100644
--- a/src/pages/measure/components/MeasureDetail.tsx
+++ b/src/pages/measure/components/MeasureDetail.tsx
@@ -1,6 +1,6 @@
-import {getDetailList, delDetail, getDetail, getPointByUuid, getPointsById} from '../../../services/measure/analysis'
+import {getDetailList, delDetail, getDetail, getPointByUuid, getPointsById, getAlignPointById} from '../../../services/measure/analysis'
import { useState, useEffect, useRef } from 'react'
-import {message, Button, type TableColumnsType, type TableProps, Modal, Table, Pagination, Input, Select, Switch, Progress } from 'antd';
+import {message, Button, type TableColumnsType, type TableProps, Modal, Table, Pagination, Input, Select, Switch, Progress, Flex, Spin } from 'antd';
import type { AnalysisReport, DetailTable, SearchParams } from "../../../services/measure/type";
import { ExclamationCircleFilled, CheckCircleOutlined, WarningOutlined } from '@ant-design/icons';
import { AnalysisData, BenchmarkShape, MeasurementCanvasRef } from './konva/MeasurementCanvas';
@@ -176,27 +176,14 @@ export default function MeasureDetail() {
const handleCloseUpload = () => {
}
-
- const onDel = (item:DetailTable) => {
- confirm({
- title: '提示',
- icon: ,
- content: '请确认是否删除选中的数据',
- okText:'确认',
- cancelText:'取消',
- onOk() {
- doDel({ids:item.id})
- },
- onCancel() {
- console.log('Cancel');
- },
- });
- }
+ const [currentRecord, setCurrentRecord] = useState>({})
const onShowDetail = async (item:DetailTable)=> {
//获取基线
setIsModalOpen(true)
- let res = await getBaseRecordPointSetByCode(GX_CODE)
+ setCurrentRecord(item)
+ setshowCalibration(false)
+ let res = await getBaseRecordPointSetByCode(item.railSize)
if (res.success && res.data && res.data.points) {
const benchmarkShapes = JSON.parse(res.data.points) as BenchmarkShape[];
if(!benchmarkShapes || !benchmarkShapes.length){
@@ -215,11 +202,10 @@ export default function MeasureDetail() {
if(resData){
// navigate(`/measure/detail/${item.id}`)
//@ts-ignore
- getRecordByUuid(resData.data.uuid)
+ // getRecordByUuid(resData.data.uuid)
//@ts-ignore
onDetaiResult(resData.data.uuid)
}
-
//获取测量的坐标点
getMeasurePoints(item)
}
@@ -267,7 +253,8 @@ export default function MeasureDetail() {
//法线
const [analysisReport, setAnalysisReport] = useState();
const onDetaiResult = (uuid:string) => {
- getReport(uuid,GX_CODE).then(res=> {
+ const gxValue= currentRecord.railSize || GX_CODE
+ getReport(uuid, gxValue).then(res=> {
if (res.success) {
const report: AnalysisReport = res.data;
console.log(report);
@@ -381,6 +368,26 @@ export default function MeasureDetail() {
setIsModalOpen(false)
}
+ //校准
+ const [showCalibration, setshowCalibration] = useState(false)
+ const [caloading, setCaLoading] = useState(false)
+ const handleCalibration = () => {
+ setCaLoading(true)
+ if(currentRecord && currentRecord.id){
+ getAlignPointById({id:currentRecord.id}).then(res=>{
+ if(res.success){
+ setshowCalibration(true)
+ canvasRef.current?.setMeasurementCalibrationData(res.data)
+ }else{
+ message.error('校准失败!')
+ }
+ setCaLoading(false)
+ }).catch(e=>{
+ message.error('校准失败!')
+ })
+ }
+ }
+
useEffect(() => {
const intervalId = setInterval(() => {
@@ -406,7 +413,7 @@ export default function MeasureDetail() {
{isModalOpen ?
-
+
setShowGrid(checked)} />
参考线
@@ -438,11 +445,10 @@ export default function MeasureDetail() {
角度线
-
-
+
@@ -494,15 +501,20 @@ export default function MeasureDetail() {
+ {/*
+
+
*/}
-
}
+
-
:
<>
@@ -537,6 +549,7 @@ export default function MeasureDetail() {
+ style={{height:"70vh"}}
locale={{
emptyText: '无数据',
}}
diff --git a/src/pages/measure/components/konva/MeasurementCanvas.tsx b/src/pages/measure/components/konva/MeasurementCanvas.tsx
index 9ac930c..5d7dd56 100644
--- a/src/pages/measure/components/konva/MeasurementCanvas.tsx
+++ b/src/pages/measure/components/konva/MeasurementCanvas.tsx
@@ -62,11 +62,13 @@ export interface MeasurementCanvasProps {
initialBenchmarkData?: BenchmarkShape[];
initialMeasurementDataLeft?: Point[];
initialMeasurementDataRight?: Point[];
+ initMeasurementCalibrationData?: Point[];
initialAnalysisData?: AnalysisData[];
// 控制是否显示标准线(benchmark shapes)
showBenchmark?: boolean;
// 控制是否显示分析线
showAnalysis?: boolean;
+ showCalibration?: boolean;
}
export interface MeasurementCanvasRef {
@@ -75,6 +77,7 @@ export interface MeasurementCanvasRef {
setBenchmarkData: (data: BenchmarkShape[]) => void;
setMeasurementDataLeft: (data: Point[]) => void;
setMeasurementDataRight: (data: Point[]) => void;
+ setMeasurementCalibrationData: (data: Point[]) => void;
setMeasurementData: (data: Point[]) => void;
setAnalysisData: (data: AnalysisData[]) => void;
redraw: () => void;
@@ -106,9 +109,11 @@ const MeasurementCanvas = forwardRef([...initialMeasurementDataRight]);
const [measurementDataLeft, setMeasurementDataLeftState] = useState(initialMeasurementDataLeft);
const [measurementDataRight, setMeasurementDataRightState] = useState(initialMeasurementDataRight);
+ const [measurementCalibrationData, setMeasurementCalibrationDataState] = useState(initMeasurementCalibrationData);
const [measurementData, setMeasurementDataState] = useState([]);
const refreshInterval = 50;
const refreshTimer = useRef(null);
@@ -190,6 +196,10 @@ const MeasurementCanvas = forwardRef {
setScale((prev) => prev);
},
+
+ setMeasurementCalibrationData: (data: Point[])=>{
+ setMeasurementCalibrationDataState(data)
+ }
}));
const stageRef = useRef(null);
@@ -482,9 +492,11 @@ const MeasurementCanvas = forwardRef {
- if (measurementDataRight.length === 0) return null;
- const pts = measurementDataRight
+ //校准线
+ const [points, setPoints] = useState<{x:number;y:number}[]>([])
+ const renderMeasurementCalibration = () => {
+ if (!measurementCalibrationData || measurementCalibrationData.length === 0) return null;
+ const pts = measurementCalibrationData
.map((pt) => {
const p = transform(pt);
return [p.x, p.y];
@@ -498,6 +510,79 @@ const MeasurementCanvas = forwardRef
+ );
+ }
+ // 拖动开始时的 X 坐标
+ const [dragStartX, setDragStartX] = useState(0);
+ // 拖动开始时的 Y 坐标
+ const [dragStartY, setDragStartY] = useState(0);
+ // 拖动偏移量 X
+ const [dragOffsetX, setDragOffsetX] = useState(0);
+ // 拖动偏移量 Y
+ const [dragOffsetY, setDragOffsetY] = useState(0);
+ // 是否正在拖动
+ const [isDragging, setIsDragging] = useState(false);
+ // 折线的引用
+ const lineRef = useRef(null);
+
+ // 拖动开始的处理函数
+ const onHandDragStrat = (e:any) => {
+ setIsDragging(true);
+ if (lineRef.current) {
+ const pos = lineRef.current.position();
+ setDragStartX(pos.x);
+ setDragStartY(pos.y);
+ const offset = stageRef.current.getPointerPosition();
+ if (offset) {
+ setDragOffsetX(offset.x);
+ setDragOffsetY(offset.y);
+ }
+ console.log('start========', pos.x, pos.y, offset.x, offset.y)
+ }
+ };
+
+ // 拖动过程中的处理函数
+ const onHandleDragMove = (e:any) => {
+ if (isDragging && lineRef.current && e.nativeEvent) {
+ const pos = lineRef.current.position();
+ const newX = pos.x + (e.nativeEvent.offsetX - dragOffsetX);
+ const newY = pos.y + (e.nativeEvent.offsetY - dragOffsetY);
+ lineRef.current.position({ x: newX, y: newY });
+ console.log('Move========', pos.x, pos.y, newX, newY)
+ }
+ };
+
+ // 拖动结束的处理函数
+ const onHandleDragEnd = (e:any) => {
+ const newPoints = lineRef.current.points();
+ const newCoords = [];
+ for (let i = 0; i < newPoints.length; i += 2) {
+ newCoords.push({ x: newPoints[i], y: newPoints[i + 1] });
+ }
+ console.log('原坐标点:', measurementCalibrationData);
+ console.log('移动后的新坐标点:', newCoords);
+ };
+
+ const renderMeasurementCurveRight = () => {
+ if (measurementDataRight.length === 0) return null;
+ const pts = measurementDataRight.map((pt) => {
+ const p = transform(pt);
+ return [p.x, p.y];
+ }).flat();
+ return (
+
);
};
@@ -534,7 +619,6 @@ const MeasurementCanvas = forwardRef
+
{showGrid && renderGridAndAxes()}
+ {/**基线层 */}
{showBenchmark && renderBenchmarkShapes()}
- {renderMeasurementCurveLeft()}
- {renderMeasurementCurveRight()}
+ {/**左线层 校准时不显示*/}
+ {!showCalibration && renderMeasurementCurveLeft()}
+ {/**右线层 */}
+ {!showCalibration && renderMeasurementCurveRight()}
+ {/**校准层 */}
+ {showCalibration && renderMeasurementCalibration()}
{renderMeasurementCurve()}
{showAnalysis && renderAnalysis()}
diff --git a/src/services/measure/analysis.ts b/src/services/measure/analysis.ts
index d37e857..8cd664d 100644
--- a/src/services/measure/analysis.ts
+++ b/src/services/measure/analysis.ts
@@ -124,3 +124,18 @@ export function getPointsById(params:{id:number}){
});
}
+//测量记录校正测量
+export function getAlignPointById(params:{id:number}){
+ return httpRequest({
+ url: `/api/measurement-data/getAlignPointById/${params.id}`,
+ method: "POST",
+ });
+}
+
+//开始测量校正测量
+export function getAlignPointsByRailSize(params:{railSize:string}){
+ return httpRequest({
+ url: `/api/align/catch/points/${params.railSize}`,
+ method: "GET",
+ });
+}
\ No newline at end of file
diff --git a/src/services/measure/type.ts b/src/services/measure/type.ts
index c905e33..5a0e857 100644
--- a/src/services/measure/type.ts
+++ b/src/services/measure/type.ts
@@ -16,6 +16,7 @@ export type DetailTable = {
direction:string;
dataSource:string;
extraDesc:string;
+ railSize:string;
}
export type MeasureRecord = {
diff --git a/src/services/wsTypes.ts b/src/services/wsTypes.ts
index 699f8a4..d4875e2 100644
--- a/src/services/wsTypes.ts
+++ b/src/services/wsTypes.ts
@@ -137,4 +137,15 @@ export type DeviceStatus = {
path: "/api/profiler-state/get-state";
};
-export type Datagram = TrackRecordSig | TaskState | ContextMessage | MeasureState | ChannelMessage | DeviceStatus;
+
+export type ProgressStatus = {
+ messageType: "SYNC";
+ data: {
+ progress: number; //同步进度
+ message: string; //消息
+ success: boolean;//同步状态
+ };
+ path: "/get-task-progress";
+};
+
+export type Datagram = TrackRecordSig | TaskState | ContextMessage | MeasureState | ChannelMessage | DeviceStatus | ProgressStatus;
diff --git a/src/store/index.ts b/src/store/index.ts
index 175eee5..5ae86cd 100644
--- a/src/store/index.ts
+++ b/src/store/index.ts
@@ -5,6 +5,7 @@ import counterSlice from "./features/counterSlice";
import contextSlice from "./features/contextSlice";
import deviceStateSlice from "./device/deviceState";
import orgStateSlice from "./ktj/orgState";
+import measureStateSlice from "./measure/measureState";
// configureStore创建一个redux数据
const store = configureStore({
// 合并多个Slice
@@ -12,7 +13,8 @@ const store = configureStore({
counter: counterSlice,
context: contextSlice,
deviceState: deviceStateSlice,
- orgState: orgStateSlice
+ orgState: orgStateSlice,
+ measureState:measureStateSlice
},
});
diff --git a/src/store/ktj/orgState.ts b/src/store/ktj/orgState.ts
index 6795853..d21371e 100644
--- a/src/store/ktj/orgState.ts
+++ b/src/store/ktj/orgState.ts
@@ -3,14 +3,18 @@ import { createSlice } from '@reduxjs/toolkit';
const orgSlice = createSlice({
name: 'orgData',
initialState: {
- value: null
+ value: null,
+ syncDataProcess:0
},
reducers: {
setOrgData: (state, action) => {
state.value = action.payload;
+ },
+ setSyncData: (state, action) => {
+ state.syncDataProcess = action.payload
}
}
});
-export const { setOrgData } = orgSlice.actions;
+export const { setOrgData, setSyncData } = orgSlice.actions;
export default orgSlice.reducer;
\ No newline at end of file
diff --git a/src/store/measure/measureState.ts b/src/store/measure/measureState.ts
new file mode 100644
index 0000000..e11eeed
--- /dev/null
+++ b/src/store/measure/measureState.ts
@@ -0,0 +1,22 @@
+import { createSlice } from "@reduxjs/toolkit";
+
+const initialState = {
+ gxCode:''
+}
+
+// 创建一个 Slice
+export const measureStateSlice = createSlice({
+ name: "measureState",
+ initialState,
+ // 定义 reducers 并生成关联的操作
+ reducers: {
+ // 更新轨型
+ updateGxState: (state, { payload }) => {
+ state.gxCode = payload.gxCode || "GX-60";
+ },
+ },
+});
+export const { updateGxState } = measureStateSlice.actions;
+
+// 默认导出
+export default measureStateSlice.reducer;
\ No newline at end of file