Browse Source

设备信息store

master
zhangjiming 4 months ago
parent
commit
578c8e2ff4
  1. 12
      src/App.tsx
  2. 49
      src/components/CustomNavBar.tsx
  3. 44
      src/pages/Measure.tsx
  4. 35
      src/store/features/contextSlice.ts
  5. 2
      src/store/features/measureSlice.ts
  6. 4
      src/store/index.ts

12
src/App.tsx

@ -12,8 +12,9 @@ import icon_4_s from './assets/tabIcon/icon_tab4_s.svg';
import icon_4_u from './assets/tabIcon/icon_tab4_u.svg'; import icon_4_u from './assets/tabIcon/icon_tab4_u.svg';
import { bridgeOb } from './utils/bridge'; import { bridgeOb } from './utils/bridge';
import { useAppDispatch } from './utils/hooks'; import { useAppDispatch } from './utils/hooks';
import { addNewPoint, updateTaskState } from './store/measureSlice';
import { TrackRecordSig } from './services/wsTypes';
import { addNewPoint, updateTaskState } from './store/features/measureSlice';
import { DeviceStatus, TrackRecordSig } from './services/wsTypes';
import { updateDevice } from './store/features/contextSlice';
const BottomBar = () => { const BottomBar = () => {
const navigate = useNavigate(); const navigate = useNavigate();
@ -73,13 +74,12 @@ function App() {
if (func === '/measurement-task/event') { if (func === '/measurement-task/event') {
if (Array.isArray(data)) return; if (Array.isArray(data)) return;
dispatch(updateTaskState(data.data)); dispatch(updateTaskState(data.data));
// switch (data.data) {
// case "START_RECORD_LEFT":
// break;
// }
} else if (func === '/measurement-task/point-report') { } else if (func === '/measurement-task/point-report') {
if (Array.isArray(data)) return; if (Array.isArray(data)) return;
dispatch(addNewPoint(data as TrackRecordSig['data'])); dispatch(addNewPoint(data as TrackRecordSig['data']));
} else if (func === '/profiler-state/get-state') {
if (Array.isArray(data)) return;
dispatch(updateDevice(data as DeviceStatus['data']));
} }
}); });
return () => subscription.unsubscribe(); return () => subscription.unsubscribe();

49
src/components/CustomNavBar.tsx

@ -2,8 +2,12 @@ import icon_bluetooth from '../assets/icon_bluetooth.svg';
import icon_arr_d from '../assets/icon_arr_down.svg'; import icon_arr_d from '../assets/icon_arr_down.svg';
import './CustomNavBar.scss'; import './CustomNavBar.scss';
import { useState } from 'react'; import { useState } from 'react';
import { useAppSelector } from '../utils/hooks';
import { useNavigate } from 'react-router-dom';
export default function CustomNavBar({ title }: { title: string }) { export default function CustomNavBar({ title }: { title: string }) {
const navigate = useNavigate();
const device = useAppSelector((state) => state.context.device);
const [showDetail, setShowDetail] = useState(false); const [showDetail, setShowDetail] = useState(false);
return ( return (
@ -11,23 +15,42 @@ export default function CustomNavBar({ title }: { title: string }) {
{/** 温度,水平仪 */} {/** 温度,水平仪 */}
<div <div
className="absolute h-[30px] w-full bg-white border border-[#D8D8D8] flex items-center gap-2 px-4" className="absolute h-[30px] w-full bg-white border border-[#D8D8D8] flex items-center gap-2 px-4"
style={{ top: showDetail ? '100%' : 0, transition: 'top 300ms' }}>
<span className="flex-1">温度: 31.2°C</span>
<span className="flex-1">X轴倾斜: -0.496</span>
<span className="flex-1">Y轴倾斜: 3.005</span>
style={{ top: device.isConnected && showDetail ? '100%' : 0, transition: 'top 300ms' }}
>
<span className="flex-1">: {device.temperature}°C</span>
<span className="flex-1">X轴倾斜: {device.inclinatorX}</span>
<span className="flex-1">Y轴倾斜: {device.inclinatorY}</span>
</div> </div>
{/** 导航栏 */} {/** 导航栏 */}
<div className="absolute left-0 top-0 w-full h-full flex items-center px-3 bg-white"> <div className="absolute left-0 top-0 w-full h-full flex items-center px-3 bg-white">
<h1 className="text-lg text-text ml-3">{title}</h1> <h1 className="text-lg text-text ml-3">{title}</h1>
<div className="ml-auto flex items-center cursor-pointer" onClick={() => setShowDetail(!showDetail)}>
<div className="bluetooth-battery flex justify-center items-center">78%</div>
<img src={icon_bluetooth} alt="icon" className="mx-2" />
<span></span>
<img src={icon_arr_d} alt="arr" style={{
transform: showDetail ? 'rotate(180deg)' : 'rotate(0deg)',
transition: 'transform 300ms'
}} />
</div>
{/** 蓝牙连接状态 */}
{device.isConnected ? (
<div
className="ml-auto flex items-center cursor-pointer"
onClick={() => setShowDetail(!showDetail)}
>
<div className="bluetooth-battery flex justify-center items-center">{device.power}%</div>
<img src={icon_bluetooth} alt="icon" className="mx-2" />
<span></span>
<img
src={icon_arr_d}
alt="arr"
style={{
transform: device.isConnected && showDetail ? 'rotate(180deg)' : 'rotate(0deg)',
transition: 'transform 300ms',
}}
/>
</div>
) : (
<div
className="ml-auto flex items-center cursor-pointer"
onClick={() => navigate('/home/bluetooth')}
>
<img src={icon_bluetooth} alt="icon" className="mx-2" />
<span></span>
</div>
)}
</div> </div>
</div> </div>
); );

44
src/pages/Measure.tsx

@ -10,9 +10,8 @@ import { rail6001, railTypes } from '../utils/constant';
import RailTypeBtn from '../components/RailTypeBtn'; import RailTypeBtn from '../components/RailTypeBtn';
import { Picker } from 'antd-mobile'; import { Picker } from 'antd-mobile';
import { bridgeOb } from '../utils/bridge';
import { useAppDispatch, useAppSelector } from '../utils/hooks'; import { useAppDispatch, useAppSelector } from '../utils/hooks';
import { updateTaskState } from '../store/measureSlice';
import { updateTaskState } from '../store/features/measureSlice';
declare global { declare global {
interface Window { interface Window {
@ -42,18 +41,7 @@ export default function Measure() {
const [railPickerVisible, setRailPickerVisible] = useState(false); const [railPickerVisible, setRailPickerVisible] = useState(false);
const [railId, setRailId] = useState<(number | string | null)[]>([1]); const [railId, setRailId] = useState<(number | string | null)[]>([1]);
const onStartClick = () => {
// if (typeof window.ReactNativeWebView !== "undefined") {
// window.ReactNativeWebView.postMessage(JSON.stringify(["add", 2, 3]));
// } else {
// console.log("当前环境不支持 React Native WebView");
// }
dispatch(updateTaskState('START_RECORD_SIG'));
};
const onSaveClick = () => {
navigate('/measure/save');
};
// 绘制轨型基准线
useEffect(() => { useEffect(() => {
const benchmarkShapes = JSON.parse(rail6001.points) as BenchmarkShape[]; const benchmarkShapes = JSON.parse(rail6001.points) as BenchmarkShape[];
if (canvasRef.current) { if (canvasRef.current) {
@ -61,6 +49,19 @@ export default function Measure() {
} }
}, []); }, []);
// 绘制测量坐标线
useEffect(() => {
if (canvasRef.current) {
canvasRef.current.setMeasurementDataLeft(measureState.leftPoints);
}
}, [measureState.leftPoints]);
useEffect(() => {
if (canvasRef.current) {
canvasRef.current.setMeasurementDataLeft(measureState.rightPoints);
}
}, [measureState.rightPoints]);
// 播放音频 步骤 // 播放音频 步骤
useEffect(() => { useEffect(() => {
if (measureState.taskState === 'START_RECORD_LEFT') { if (measureState.taskState === 'START_RECORD_LEFT') {
@ -81,6 +82,19 @@ export default function Measure() {
} }
}, [measureState.taskState]); }, [measureState.taskState]);
const onSaveClick = () => {
navigate('/measure/save');
};
const onStartClick = () => {
// if (typeof window.ReactNativeWebView !== "undefined") {
// window.ReactNativeWebView.postMessage(JSON.stringify(["add", 2, 3]));
// } else {
// console.log("当前环境不支持 React Native WebView");
// }
dispatch(updateTaskState('START_RECORD_SIG'));
};
function stepState(step: StepName): StepState { function stepState(step: StepName): StepState {
if (!measureState.taskState) { if (!measureState.taskState) {
return 'none'; return 'none';
@ -170,7 +184,7 @@ export default function Measure() {
<section className="flex items-center gap-4 px-4 my-4"> <section className="flex items-center gap-4 px-4 my-4">
<div className="btn-contained rounded-md text-sm h-10 flex-1" onClick={onStartClick}> <div className="btn-contained rounded-md text-sm h-10 flex-1" onClick={onStartClick}>
{measureState.leftPoints.length > 0 ? '重新测量' : '开始测量'}
</div> </div>
<div className="btn-contained rounded-md text-sm h-10 flex-1" onClick={onSaveClick}> <div className="btn-contained rounded-md text-sm h-10 flex-1" onClick={onSaveClick}>

35
src/store/features/contextSlice.ts

@ -0,0 +1,35 @@
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
import { DeviceStatus } from '../../services/wsTypes';
interface ContextState {
device: DeviceStatus['data'];
currRailTypeId: number;
}
const initialState: ContextState = {
device: {
isConnected: true, //是否链接
power: 60, //电量
inclinatorX: 0.276, //x轴倾斜
inclinatorY: 3.019, //y轴倾斜
temperature: 32.026, //温度
},
// 当前选择的轨型
currRailTypeId: 1,
};
export const contextSlice = createSlice({
name: 'context',
initialState,
reducers: {
updateDevice: (state, action: PayloadAction<DeviceStatus['data']>) => {
state.device = action.payload;
},
updateRailTypeId: (state, action: PayloadAction<number>) => {
state.currRailTypeId = action.payload;
},
},
});
export const { updateDevice, updateRailTypeId } = contextSlice.actions;
export default contextSlice.reducer;

2
src/store/measureSlice.ts → src/store/features/measureSlice.ts

@ -1,5 +1,5 @@
import { createSlice, PayloadAction } from '@reduxjs/toolkit'; import { createSlice, PayloadAction } from '@reduxjs/toolkit';
import { TaskState, TrackRecordSig } from '../services/wsTypes';
import { TaskState, TrackRecordSig } from '../../services/wsTypes';
export interface MeasureState { export interface MeasureState {
taskState?: TaskState['data']; taskState?: TaskState['data'];

4
src/store/index.ts

@ -1,10 +1,12 @@
import { configureStore } from '@reduxjs/toolkit'; import { configureStore } from '@reduxjs/toolkit';
import measureSlice from './measureSlice';
import measureSlice from './features/measureSlice';
import contextSlice from './features/contextSlice';
// configureStore创建一个redux数据 // configureStore创建一个redux数据
const store = configureStore({ const store = configureStore({
// 合并多个Slice // 合并多个Slice
reducer: { reducer: {
measure: measureSlice, measure: measureSlice,
context: contextSlice,
}, },
}); });

Loading…
Cancel
Save