Commit af2e92c033abafef873cbe779ab743548b4a2fd1

Authored by 谢忠泽
1 parent 39e29489

add:车辆管理系统:完成整个运维管理模块

src/pages/vms/OperationAdministration/api.ts 0 → 100644
  1 +import { http } from '@/typing/http';
  2 +import request from '@/utils/request';
  3 +import { HOST_VMS } from '@/utils/host';
  4 +
  5 +type PromiseResp<T> = Promise<http.Response<T>>;
  6 +type PromiseRespArr<T> = Promise<http.Response<T[]>>;
  7 +
  8 +export function getPointsDataMock(params:any):PromiseResp<string> {
  9 + return request.get(`https://tsapi.amap.com/v1/track/terminal/trsearch`, {params});
  10 +}
  11 +// 查询GPS设备信息分页列表
  12 +export function getGpsTableData(params?:any):PromiseResp<any> {
  13 + return request.get(`${HOST_VMS}/erp/operation/gps/page`, {params});
  14 +}
  15 +//查询外勤设备信息分页列表
  16 +export function getTripTableData(params?:any):PromiseResp<any> {
  17 + return request.get(`${HOST_VMS}/erp/operation/trip/page`, {params});
  18 +}
  19 +//运维轨迹查询
  20 +export function getPointsData(params:any):PromiseResp<any> {
  21 + return request.get(`${HOST_VMS}/erp/operation/track/message/query`, {params});
  22 +}
0 23 \ No newline at end of file
... ...
src/pages/vms/OperationAdministration/components/MapContent/index.tsx
1 1 import React, { useState, useEffect, useRef } from 'react';
  2 +import {message, Input, Button} from 'antd';
2 3 import AMapLoader from "@amap/amap-jsapi-loader";
  4 +import {getPointsData, getPointsDataMock} from '../../api';
  5 +import useUpdateEffect from '../useUpdateEffect';
  6 +import PlayBackPicker from '../PlayBackPicker';
3 7 import './style.less';
4 8  
  9 +interface searchParams<T>{
  10 + trid?:number | undefined;
  11 + date:Array<T>
  12 +}
  13 +interface DateParams {
  14 + startTime?: number;
  15 + endTime?:number;
  16 + trid?:number;
  17 +}
5 18 function MapContent(props:any) {
6   - console.log('MapContentprops', props);
  19 + const { trackParams, id} = props;
  20 + const trid = useRef<number | undefined>(undefined);
  21 + const date = useRef<Array<number | null>>([]);
  22 + const [searchParams, setSearchParams] = useState<searchParams<number | null>>({trid: trid.current, date: date.current});
  23 + //地图
7 24 const map = useRef<any>(null);
  25 + const amapCopy = useRef<any>(null);
  26 + const marker = useRef<Array<any>>([]);
  27 + const [tracksFilter, setTracksFilter] = useState<Array<any>>([]);
  28 + const lineArr= [
  29 + [116.478935, 39.997761],
  30 + [116.478939, 39.997825],
  31 + [116.478912, 39.998549],
  32 + [116.478912, 39.998549],
  33 + [116.478998, 39.998555],
  34 + [116.478998, 39.998555],
  35 + [116.479282, 39.99856],
  36 + [116.479658, 39.998528],
  37 + [116.480151, 39.998453],
  38 + [116.480784, 39.998302],
  39 + [116.480784, 39.998302],
  40 + [116.481149, 39.998184], [116.481573, 39.997997], [116.481863, 39.997846], [116.482072, 39.997718], [116.482362, 39.997718], [116.483633, 39.998935], [116.48367, 39.998968], [116.484648, 39.999861]];
8 41 useEffect(() => {
9   - initMap();
10   - return () => {
11   -
12   - };
  42 + initMap();
  43 + return () => {
  44 + };
13 45 }, []);
14   -
  46 + useEffect(() => {
  47 + if (!trackParams) return;
  48 + let dateParams ={} as DateParams;
  49 + const {trid, date} = searchParams;
  50 + if (trid) {
  51 + dateParams.trid = trid;
  52 + }
  53 + if (date[0] && date[1]) {
  54 + dateParams.startTime = date[0];
  55 + dateParams.endTime = date[1];
  56 + }
  57 + getPointsData({...trackParams, ...dateParams}).then(res => {
  58 + const {data: {data: tracksData}}=res;
  59 + if (res.data.errcode === 20000) {
  60 + message.warning('请选择24小时以内的时间段');
  61 + return;
  62 + }
  63 + const { tracks }= tracksData;
  64 + let tracksFilterData:Array<any> = [];
  65 + tracks?.forEach((item:any, index:any) => {
  66 + let tracksArr:Array<Array<number>> = [];
  67 + item.startPoint && tracksArr.unshift(item?.startPoint?.location.split(',').map(Number));
  68 + const points = filterPoint(item?.points);
  69 + tracksArr.push(...points);
  70 + item.endPoint && tracksArr.push(item?.endPoint?.location.split(',').map(Number));
  71 + tracksArr.length && tracksFilterData.push(tracksArr);
  72 + });
  73 + tracksFilterData.push(lineArr);
  74 + setTracksFilter(tracksFilterData);
  75 + mapPlayBack(tracksFilterData);
  76 + }).catch((e) => {
  77 + message.error('此时间段没有你想要的数据!');
  78 + });
  79 + }, [searchParams, trackParams]);
  80 +
  81 + /**
  82 + * @description: 地图轨迹展示
  83 + * @param {*}
  84 + * @return {*}
  85 + */
  86 + const mapPlayBack = (tracksData:Array<any>) => {
  87 + amapCopy.current.plugin('AMap.MoveAnimation', () => {
  88 + map.current = new amapCopy.current.Map(id, { //设置地图容器id
  89 + viewMode: "3D", //是否为3D地图模式
  90 + resizeEnable: true,
  91 + zoom: 8, //初始化地图级别
  92 + // center: tracksData[0][0], //初始化地图中心点位置
  93 + });
  94 + tracksData.forEach(tracks => {
  95 + //
  96 + const markerItem = new amapCopy.current.Marker({
  97 + map: map.current,
  98 + position: tracks[0], //轨迹起点
  99 + icon: "https://a.amap.com/jsapi_demos/static/demo-center-v2/car.png",
  100 + offset: new amapCopy.current.Pixel(-13, -26),
  101 + });
  102 + const polyline = new amapCopy.current.Polyline({
  103 + map: map.current,
  104 + path: tracks,
  105 + showDir: true,
  106 + strokeColor: "#28F", //线颜色
  107 + // strokeOpacity: 1, //线透明度
  108 + strokeWeight: 8, //线宽
  109 + lineJoin: 'round',
  110 + strokeStyle: "solid" //线样式
  111 + });
  112 + marker.current.push(markerItem);
  113 + map.current.add(markerItem);
  114 + map.current.add(polyline);
  115 + const passedPolyline = new amapCopy.current.Polyline({
  116 + map: map.current,
  117 + strokeColor: "#AF5", //线颜色
  118 + strokeWeight: 6, //线宽
  119 + });
  120 + markerItem.on('moving', (e:any) => {
  121 + passedPolyline.setPath(e.passedPath);
  122 + map.current.setCenter(e.target.getPosition(), true);
  123 + });
  124 + });
  125 + map.current.setFitView();
  126 + });
  127 + };
  128 + /**
  129 + * @description: 过滤坐标点
  130 + * @param {Array} points
  131 + * @return {*}
  132 + */
  133 + const filterPoint= (points:Array<any>):Array<any> => {
  134 + if (!points.length) return [];
  135 + const arr = points.map((item) => {
  136 + const {location }= item;
  137 + const locationarr = location.split(',').map(Number);
  138 + return locationarr;
  139 + });
  140 + return arr;
  141 + };
  142 +
  143 + /**
  144 + * @description: 开始回放
  145 + * @param {*}
  146 + * @return {*}
  147 + */
  148 + const startAnimation = () => {
  149 + console.log(1);
  150 + tracksFilter.forEach((item, index) => {
  151 + marker.current[index].moveAlong(item, {
  152 + // 每一段的时长
  153 + duration: 200, //可根据实际采集时间间隔设置
  154 + // JSAPI2.0 是否延道路自动设置角度在 moveAlong 里设置
  155 + autoRotation: true,
  156 + });
  157 + });
  158 + };
  159 +
  160 + /**
  161 + * @description: 暂停动画
  162 + * @param {*}
  163 + * @return {*}
  164 + */
  165 + const pauseAnimation = () => {
  166 + const {current} = marker;
  167 + current.forEach((item, index) => {
  168 + current[index].pauseMove();
  169 + });
  170 + };
  171 + /**
  172 + * @description: 继续动画
  173 + * @param {*}
  174 + * @return {*}
  175 + */
  176 + const resumeAnimation = () => {
  177 + const {current} = marker;
  178 + current.length && current.forEach((item, index) => {
  179 + current[index].resumeMove();
  180 + });
  181 + };
  182 + /**
  183 + * @description: 停止动画
  184 + * @param {*}
  185 + * @return {*}
  186 + */
  187 + const stopAnimation = () => {
  188 + const {current} = marker;
  189 + current.forEach((item, index) => {
  190 + current[index].stopMove();
  191 + });
  192 + };
15 193 /**
16 194 * @description: 初始化地图
17 195 */
... ... @@ -21,18 +199,70 @@ function MapContent(props:any) {
21 199 version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
22 200 plugins: ["AMap.Geolocation", "AMap.AutoComplete", "AMap.PlaceSearch"], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
23 201 }).then((AMap) => {
24   - map.current = new AMap.Map("container", { //设置地图容器id
  202 + amapCopy.current = AMap;
  203 + map.current = new AMap.Map(id, { //设置地图容器id
25 204 viewMode: "3D", //是否为3D地图模式
26   - zoom: 5, //初始化地图级别
27   - center: [105.602725, 37.076636], //初始化地图中心点位置
  205 + resizeEnable: true,
  206 + zoom: 10, //初始化地图级别
  207 + center: [104.06, 30.67], //初始化地图中心点位置
28 208 });
29 209 }).catch(e => {
30 210 console.log('e', e);
31 211 });
32 212 };
33 213  
  214 + /**
  215 + * @description: 手动获取时间
  216 + * @param {*}
  217 + * @return {*}
  218 + */
  219 + const handelDate = (val:Array<any>) => {
  220 + date.current = val;
  221 + };
34 222 return (
35   - <div id="container" className="map_main" />
  223 + <div className="map_box">
  224 + <div className="right_top">
  225 + <div className="top_input">
  226 + <Input
  227 + placeholder="轨迹ID"
  228 + onBlur={(event) => {
  229 + trid.current = parseInt(event.target.value, 10);
  230 + }}
  231 + />
  232 + </div>
  233 + <PlayBackPicker
  234 + handelDate={handelDate}
  235 + />
  236 + <div>
  237 + <Button
  238 + className="back_btn"
  239 + type="primary"
  240 + onClick={() => {
  241 + setSearchParams({trid: trid.current, date: date.current});
  242 + if (!trackParams)message.warning('请在列表中选择终端!');
  243 + }}
  244 + >
  245 + 查询
  246 + </Button>
  247 + </div>
  248 + </div>
  249 + <div id={id} className="map_main" />
  250 + {
  251 + tracksFilter.length && (
  252 + <div className="play_back_btn_box">
  253 + <div className="btn_item">
  254 + <Button type="primary" className="play_back_btn" onClick={startAnimation}>开始回放</Button>
  255 + <Button type="primary" className="play_back_btn" onClick={pauseAnimation}>暂停回放</Button>
  256 + </div>
  257 + <div className="btn_item">
  258 + <Button type="primary" className="play_back_btn" onClick={resumeAnimation}>继续回放</Button>
  259 + <Button type="primary" className="play_back_btn" onClick={stopAnimation}>停止回放</Button>
  260 + </div>
  261 + </div>
  262 + )
  263 + }
  264 +
  265 + </div>
36 266 );
37 267 }
38 268 export default MapContent;
... ...
src/pages/vms/OperationAdministration/components/MapContent/style.css
1   -#container {
  1 +.map_box {
  2 + position: relative;
  3 +}
  4 +.map_box .right_top {
  5 + margin-bottom: 10px;
  6 + display: flex;
  7 + justify-content: flex-start;
  8 + align-items: center;
  9 +}
  10 +.map_box .right_top .top_input {
  11 + margin-right: 25px;
  12 +}
  13 +.map_box .right_top .back_btn {
  14 + margin-left: 30px;
  15 +}
  16 +.map_box .map_main {
2 17 padding: 0px;
3 18 margin: 0px;
4 19 width: 100%;
  20 + height: 750px;
  21 +}
  22 +.map_box .play_back_btn_box {
  23 + position: absolute;
  24 + display: flex;
  25 + flex-direction: column;
  26 + z-index: 9999;
  27 + background-color: #fff;
  28 + padding: 20px;
  29 + border-radius: 8px;
  30 + right: 20px;
  31 + bottom: 20px;
  32 + box-shadow: 0 2px 6px 0 #FAAD14;
  33 +}
  34 +.map_box .play_back_btn_box .btn_item {
  35 + display: flex;
  36 + align-items: center;
  37 + justify-content: space-around;
  38 + width: 100%;
  39 +}
  40 +.map_box .play_back_btn_box .btn_item:first-child {
  41 + margin-bottom: 20px;
5 42 }
6   -.map_main {
7   - height: 700px;
  43 +.map_box .play_back_btn_box .btn_item .play_back_btn:first-child {
  44 + margin-right: 25px;
8 45 }
... ...
src/pages/vms/OperationAdministration/components/MapContent/style.less
1   -#container{
2   - padding: 0px;
3   - margin: 0px;
4   - width: 100%;
5   -}
6   -.map_main{
7   - height: 700px;
  1 +.map_box{
  2 + position: relative;
  3 + .right_top{
  4 + margin-bottom: 10px;
  5 + display:flex;
  6 + justify-content: flex-start;
  7 + align-items: center;
  8 + .top_input{
  9 + margin-right: 25px;
  10 + }
  11 + .back_btn{
  12 + margin-left: 30px;
  13 + }
  14 + }
  15 + #container{
  16 + }
  17 + .map_main{
  18 + padding: 0px;
  19 + margin: 0px;
  20 + width: 100%;
  21 + height: 750px;
  22 + }
  23 + .play_back_btn_box{
  24 + position: absolute;
  25 + display: flex;
  26 + flex-direction: column;
  27 + z-index: 9999;
  28 + background-color: #fff;
  29 + padding: 20px;
  30 + border-radius: 8px;
  31 + right: 20px;
  32 + bottom: 20px;
  33 + box-shadow: 0 2px 6px 0 #FAAD14;
  34 + .btn_item{
  35 + display: flex;
  36 + align-items: center;
  37 + justify-content: space-around;
  38 + width: 100%;
  39 + &:first-child{
  40 + margin-bottom: 20px;
  41 + }
  42 + .play_back_btn{
  43 + &:first-child{
  44 + margin-right: 25px;
  45 + }
  46 + }
  47 + }
  48 + }
8 49 }
9 50 \ No newline at end of file
... ...
src/pages/vms/OperationAdministration/components/PlayBack/index.tsx
1   -import React, { useState } from 'react';
  1 +import React, { useState, useEffect, useRef } from 'react';
2 2 import PlayBackTable from '../PlayBackTable';
3 3 import MapContent from '../MapContent';
4   -import moment from 'moment';
5   -import { Input, DatePicker as Picker, Space } from 'antd';
6 4 import './style.less';
7 5  
8   -const DatePicker:any = Picker;
9   -const {RangePicker} = DatePicker;
10   -function PlayBack() {
11   - const [tid, setTid] = useState<number | undefined>();
  6 +interface TrackParams {
  7 + tid: number;
  8 + entityName:string;
  9 +}
  10 +
  11 +function PlayBack(props:any) {
  12 + const {name, type} = props;
  13 + const [trackParams, setTrackParams] = useState<TrackParams | undefined>(undefined);
  14 + useEffect(() => {
  15 + }, []);
12 16 /**
13 17 * @description: 点击行
14 18 * @param {*}
15 19 * @return {*}
16 20 */
17   - const handelRow = (tid:number | undefined) => {
18   - console.log('tid==>', tid);
19   - setTid(tid);
  21 + const handelRow = (params:TrackParams) => {
  22 + setTrackParams(params);
20 23 };
21 24 return (
22 25 <div className="play_back">
23 26 <div className="left">
24 27 <PlayBackTable
25 28 handelRow={handelRow}
  29 + type={type}
26 30 />
27 31 </div>
28   - <div className="right">
29   - <div className="right_top">
30   - <div className="top_input">
31   - <Input
32   - placeholder="轨迹ID"
33   - />
34   - </div>
35   - <div>
36   - <RangePicker
37   - showTime
38   - />
39   - </div>
40   - </div>
41   -
42   - <MapContent />
  32 + <div className="right">
  33 + <MapContent
  34 + trackParams={trackParams}
  35 + id={name}
  36 + />
43 37 </div>
44 38 </div>
45 39 );
... ...
src/pages/vms/OperationAdministration/components/PlayBack/style.css
... ... @@ -8,7 +8,7 @@
8 8 padding: 0 10px;
9 9 }
10 10 .play_back .right {
11   - flex: 1 ;
  11 + flex: 1 1 ;
12 12 height: 100%;
13 13 }
14 14 .play_back .right .right_top {
... ... @@ -20,3 +20,6 @@
20 20 .play_back .right .right_top .top_input {
21 21 margin-right: 25px;
22 22 }
  23 +.play_back .right .right_top .back_btn {
  24 + margin-left: 30px;
  25 +}
... ...
src/pages/vms/OperationAdministration/components/PlayBack/style.less
... ... @@ -7,7 +7,7 @@
7 7 padding: 0 10px;
8 8 }
9 9 .right {
10   - flex: 1 ;
  10 + flex: 1 1 ;
11 11 height:100%;
12 12 .right_top{
13 13 margin-bottom: 10px;
... ... @@ -17,6 +17,9 @@
17 17 .top_input{
18 18 margin-right: 25px;
19 19 }
  20 + .back_btn{
  21 + margin-left: 30px;
  22 + }
20 23 }
21 24 }
22 25 }
23 26 \ No newline at end of file
... ...
src/pages/vms/OperationAdministration/components/PlayBackPicker/index.tsx 0 → 100644
  1 +import React, { useState, useEffect, useRef } from 'react';
  2 +import { DatePicker as Picker } from 'antd';
  3 +import moment from 'moment';
  4 +import type { Moment } from 'moment';
  5 +import './style.less';
  6 +
  7 +interface searchParams<T>{
  8 + trid?:number | undefined;
  9 + date?:Array<T>
  10 +}
  11 +const DatePicker:any = Picker;
  12 +const {RangePicker} = DatePicker;
  13 +type RangeValue = [Moment | undefined, Moment | undefined];
  14 +
  15 +function PlayBackPicker(props:any) {
  16 + const {handelDate} = props;
  17 +
  18 + const startTime = moment(new Date()).subtract(1, "days").startOf('days').valueOf();
  19 + const endTime = moment(new Date()).startOf('days').valueOf();
  20 + const date = useRef<Array<number | null>>([startTime, endTime]);
  21 + const [dateFlag, setDateFlag] = useState<RangeValue>([moment(new Date()).subtract(1, "days").startOf('days'), moment(new Date(), 'YYYY-MM-DD HH:mm:ss').startOf('days')]);
  22 + const [flag, setFlag] = useState<boolean>(true);
  23 +
  24 + useEffect(() => {
  25 + handelDate(date.current);
  26 + }, []);
  27 +
  28 + /**
  29 + * @description: 年月日时间选择
  30 + * @param {*}
  31 + * @return {*}
  32 + */
  33 + const disabledDate = (current: Moment) => {
  34 + if (flag) {
  35 + //禁用当天之后的时间
  36 + return current > moment().endOf('day');
  37 + }
  38 + //限制选择开始时间后的取值范围
  39 + const startHour = dateFlag[0] && dateFlag[0].hour();
  40 + const startMinute = dateFlag[0] && dateFlag[0].minute();
  41 + const startSecond = dateFlag[0] && dateFlag[0].second();
  42 + const beforeDate = dateFlag[0] && (current > moment().endOf('day') || moment(current).set({'hour': startHour, 'minute': startMinute, "second": startSecond}).diff(dateFlag[0], 'days') > 1);
  43 + //限制选择结束时间后的取值范围
  44 + const afterHour = dateFlag[1] && dateFlag[1].hour();
  45 + const afterMinute = dateFlag[1] && dateFlag[1].minute();
  46 + const afterSecond = dateFlag[1] && dateFlag[1].second();
  47 + const afterDate = dateFlag[1] && dateFlag[1].diff(moment(current).set({'hour': afterHour, 'minute': afterMinute, "second": afterSecond}), 'days')>1;
  48 + return !!beforeDate || !!afterDate;
  49 + };
  50 +
  51 + /**
  52 + * @description: 日期时分秒时间范围
  53 + * @param {any} date
  54 + * @param {any} type
  55 + * @return {*}
  56 + */
  57 + const disabledTracksTime = (date:any, type:any) => {
  58 + if (!date) return;
  59 + const {_d: checkDate, _i: nowDate} = date;
  60 + const checkYear = moment(checkDate).format('YYYY-MM-DD');
  61 + const nowYear = moment(nowDate).format('YYYY-MM-DD');
  62 + if (checkYear === nowYear) {
  63 + const nowHour = moment(nowDate).hour();
  64 + const nowMinute = moment(nowDate).minute();
  65 + const nowSecond = moment(nowDate).second();
  66 + return {
  67 + disabledHours: () => {
  68 + const disabledArr = timeArr(24).splice(nowHour, timeArr(24).length - nowHour);
  69 + return disabledArr;
  70 + },
  71 + disabledMinutes: () => {
  72 + const disabledArr = timeArr(60).splice(nowMinute, timeArr(60).length - nowMinute);
  73 + return disabledArr;
  74 + },
  75 + disabledSeconds: () => {
  76 + const disabledArr = timeArr(60).splice(nowSecond, timeArr(60).length - nowSecond);
  77 + return disabledArr;
  78 + },
  79 + };
  80 + }
  81 + };
  82 + /**
  83 + * @description: 时分秒时间数组
  84 + * @param {number} length
  85 + * @return {*}
  86 + */
  87 + const timeArr = (length:number):Array<number> => {
  88 + const arr = Array.from(Array(length), (value, index) => index);
  89 + return arr;
  90 + };
  91 + const onOpenChange = (type:boolean) => {
  92 + if (type) {
  93 + setDateFlag([undefined, undefined]);
  94 + if (date.current[0]!==null && date.current[1]!==null) {
  95 + date.current =[null, null];
  96 + handelDate([null, null]);
  97 + }
  98 + } else {
  99 + setFlag(true);
  100 + }
  101 + };
  102 + return (
  103 + <div>
  104 +
  105 + <RangePicker
  106 + format="YYYY-MM-DD HH:mm:ss"
  107 + allowClear={false}
  108 + value={dateFlag}
  109 + showTime={{
  110 + hideDisabledOptions: true,
  111 + }}
  112 + disabledDate={disabledDate}
  113 + disabledTime={disabledTracksTime}
  114 + onCalendarChange={
  115 + (value:any) => {
  116 + setDateFlag(value);
  117 + setFlag(false);
  118 + }
  119 + }
  120 + onOpenChange={onOpenChange}
  121 + onChange={(dateVal:Object, dateString:Array<string>) => {
  122 + const dateTimestamp = dateString.map(item => {
  123 + return moment(item).valueOf();
  124 + });
  125 + date.current = dateTimestamp;
  126 + handelDate(dateTimestamp);
  127 + }}
  128 + />
  129 + </div>
  130 + );
  131 +}
  132 +export default PlayBackPicker;
... ...
src/pages/vms/OperationAdministration/components/PlayBackPicker/style.less 0 → 100644
src/pages/vms/OperationAdministration/components/PlayBackTable/index.tsx
1   -import React, { useState } from 'react';
2   -import { Table } from 'antd';
  1 +import React, { useState, useEffect } from 'react';
  2 +import { Table, message} from 'antd';
  3 +import type { ColumnsType } from 'antd/es/table';
  4 +import {getGpsTableData, getTripTableData} from '../../api';
3 5  
4 6 import './style.less';
5 7  
6   -const data:Array<any> = [];
7   -for (let i=0; i<100; i++) {
8   - const item = {
9   - key: i,
10   - name: '胡彦斌',
11   - tid: i,
12   - address: '西湖区湖底公园1号',
13   - };
14   - data.push(item);
  8 +interface DataType {
  9 + tid: number;
  10 + trid: number;
  11 + entityName:string;
  12 + enable:boolean;
15 13 }
16   -
17   -const dataSource = data;
18 14  
19   - const columns = [
20   - {
21   - title: '姓名',
22   - dataIndex: 'name',
23   - key: 'name',
24   - },
  15 + const columns:ColumnsType<DataType> = [
25 16 {
26   - title: '设备id',
  17 + title: '终端id',
27 18 dataIndex: 'tid',
28 19 key: 'tid',
  20 + width: 100
  21 + },
  22 + {
  23 + title: '终端名称',
  24 + dataIndex: 'entityName',
  25 + key: 'entityName',
  26 + width: 100
  27 +
29 28 },
30 29 {
31   - title: '住址',
32   - dataIndex: 'address',
33   - key: 'address',
  30 + title: '轨迹id',
  31 + dataIndex: 'trid',
  32 + key: 'trid',
  33 + width: 100
  34 +
34 35 },
  36 + {
  37 + title: '设备状态',
  38 + dataIndex: 'enable',
  39 + key: 'enable',
  40 + width: 100
  41 +
  42 + }
35 43 ];
  44 +
36 45 function PlayBackTable(props:any) {
37   - console.log('props', props);
38   - const {handelRow} = props;
  46 + const {handelRow, type} = props;
  47 + const [tableData, setTableData] = useState<any>([]);
  48 + useEffect(() => {
  49 + //获取table数据
  50 + if (type === 1) {
  51 + getGpsTableData().then(res => {
  52 + const data = res?.data?.data.map((item:any) => {
  53 + if (item?.enable) item.enable = '启用'; else item.enable = '禁用';
  54 + return item;
  55 + });
  56 + setTableData(data);
  57 + }).catch((e) => {
  58 + message.error('查询数据失败!');
  59 + });
  60 + } else if (type === 2) {
  61 + getTripTableData().then(res => {
  62 + const data = res?.data?.data.map((item:any) => {
  63 + if (item?.enable) item.enable = '启用'; else item.enable = '禁用';
  64 + return item;
  65 + });
  66 + setTableData(data);
  67 + }).catch((e) => {
  68 + message.error('查询数据失败!');
  69 + });
  70 + }
  71 + }, []);
  72 +
39 73 return (
40 74 <div className="play_back_table">
41 75 <Table
42   - dataSource={dataSource}
  76 + dataSource={tableData}
43 77 columns={columns}
  78 + className="table_back"
  79 + rowKey={row => row.tid}
44 80 pagination={{
45 81 showQuickJumper: false,
46 82 showSizeChanger: true,
... ... @@ -50,7 +86,7 @@ function PlayBackTable(props:any) {
50 86 return {
51 87 //行点击
52 88 onClick: () => {
53   - handelRow(record.tid);
  89 + handelRow({tid: record?.tid, entityName: record?.entityName});
54 90 },
55 91 };
56 92 }
... ...
src/pages/vms/OperationAdministration/components/PlayBackTable/style.css
... ... @@ -2,3 +2,6 @@
2 2 width: 100%;
3 3 height: 100%;
4 4 }
  5 +.play_back_table .ant-table-cell {
  6 + max-width: 100px !important;
  7 +}
... ...
src/pages/vms/OperationAdministration/components/PlayBackTable/style.less
1 1 .play_back_table{
2 2 width: 100%;
3 3 height: 100%;
  4 + .ant-table-cell{
  5 + max-width: 100px !important;
  6 + }
4 7 }
5 8 \ No newline at end of file
... ...
src/pages/vms/OperationAdministration/components/useUpdateEffect.tsx 0 → 100644
  1 +import { useEffect, useRef } from "react";
  2 +
  3 +//模拟didupdate
  4 +const useUpdateEffect =(effect:Function, deps?:[any | null]) => {
  5 + const updateFlag = useRef(true);
  6 + useEffect(() => {
  7 + if (updateFlag.current) {
  8 + updateFlag.current =false;
  9 + } else {
  10 + effect();
  11 + }
  12 + }, deps);
  13 +};
  14 +export default useUpdateEffect;
0 15 \ No newline at end of file
... ...
src/pages/vms/OperationAdministration/index.tsx
... ... @@ -5,18 +5,22 @@ import PlayBack from &#39;./components/PlayBack&#39;;
5 5  
6 6 const TabPane = Tabs.TabPane;
7 7  
  8 +const gpsName = 'container1';
  9 +const tripName = 'container2';
  10 +const type=[1, 2];
8 11 function OperationAdministration() {
9   - // const [first, setfirst] = useState(1);
10 12 const items = [
11 13 {label: 'GPS轨迹回放', key: '1', children: PlayBack}
12 14 ];
13 15 return (
14 16 <PageHeaderWrapper title="轨迹回放">
15 17 <Card>
16   - {/* <Tabs items={items} /> */}
17 18 <Tabs>
18 19 <TabPane tab="GPS轨迹回放" key="1" className="tabsPanelScroll">
19   - <PlayBack />
  20 + <PlayBack name={gpsName} type={type[0]} />
  21 + </TabPane>
  22 + <TabPane tab="霏微出行" key="2" className="tabsPanelScroll">
  23 + <PlayBack name={tripName} type={type[1]} />
20 24 </TabPane>
21 25 </Tabs>
22 26 </Card>
... ...