李富豪 1 anno fa
parent
commit
4f41184c71

+ 28 - 0
Web/src/api/custom/index.ts

@@ -49,6 +49,16 @@ export type BatchDeletePictureApiParams = {
     id: string
 };
 
+export type FetchTrajectoryListApiParams = Partial<{
+    begin_time: number,
+    end_time: number,
+    template_type: number,
+    payload: number,
+    search_info: string,
+    page: number,
+    page_size: number,
+}>;
+
 // Api函数类型
 export type FetchPayloadListApi = () => Promise<any>;
 export type FetchFeedbackRecordListApi = (data: FetchFeedbackRecordListApiParams) => Promise<any>;
@@ -61,6 +71,8 @@ export type FetchFileDetailApi = (fileId: string) => Promise<any>;
 export type BatchDownloadFileApi = (params: BatchDownloadFileApiParams) => Promise<any>;
 export type UpdateFileNameApi = (fileId: string, data: { [key: string]: any }) => Promise<any>;
 export type BatchDeletePictureApi = (params: BatchDeletePictureApiParams) => Promise<any>;
+export type FetchTrajectoryListApi = (params: FetchTrajectoryListApiParams) => Promise<any>;
+export type FetchTrajectoryMapApi = (taskId: string) => Promise<any>;
 
 // 获取负载列表
 const fetchPayloadListApi: FetchPayloadListApi = async () => {
@@ -135,6 +147,20 @@ const batchDeletePictureApi: BatchDeletePictureApi = async (data) => {
     return res.data;
 };
 
+// 获取轨迹列表
+const fetchTrajectoryListApi: FetchTrajectoryListApi = async (params) => {
+    const url = `/map/api/v1/workspaces/${workspaceId}/flight-tasks`
+    const res = await request.get(url, { params: params });
+    return res.data;
+};
+
+// 获取轨迹地图
+const fetchTrajectoryMapApi: FetchTrajectoryMapApi = async (taskId) => {
+    const url = `/map/api/v1/workspaces/${workspaceId}/flight-task/${taskId}`
+    const res = await request.get(url);
+    return res.data;
+};
+
 export const apis = {
     fetchPayloadList: fetchPayloadListApi,
     fetchFeedbackRecordList: fetchFeedbackRecordListApi,
@@ -147,4 +173,6 @@ export const apis = {
     batchDownloadFile: batchDownloadFileApi,
     updateFileName: updateFileNameApi,
     batchDeletePicture: batchDeletePictureApi,
+    fetchTrajectoryList: fetchTrajectoryListApi,
+    fetchTrajectoryMap: fetchTrajectoryMapApi,
 };

File diff suppressed because it is too large
+ 0 - 0
Web/src/assets/icons/end.svg


File diff suppressed because it is too large
+ 0 - 0
Web/src/assets/icons/start.svg


+ 11 - 0
Web/src/components/GMap.vue

@@ -519,6 +519,7 @@ import { MapDoodleType, MapElementEnum } from '/@/constants/map'
 import { useGMapManage } from '/@/hooks/use-g-map'
 import { useGMapCover } from '/@/hooks/use-g-map-cover'
 import { useMouseTool } from '/@/hooks/use-mouse-tool'
+import { useGMapTrajectory } from '/@/hooks/use-g-map-trajectory'
 import { getApp, getRoot } from '/@/root'
 import { useMyStore } from '/@/store'
 import { GeojsonCoordinate } from '/@/types/map'
@@ -585,6 +586,7 @@ export default defineComponent({
     const useMouseToolHook = useMouseTool()
     const useGMapManageHook = useGMapManage()
     const deviceTsaUpdateHook = deviceTsaUpdate()
+
     const root = getRoot()
 
     const mouseMode = ref(false)
@@ -661,6 +663,15 @@ export default defineComponent({
       return 'color: red'
     })
 
+    watch(() => store.state.trajectoryList, (list: any) => {
+      setTimeout(() => {
+        if (list.length >= 2) {// 至少要有起点终点两个坐标才可以绘制轨迹
+          const trajectoryHook = useGMapTrajectory()
+          trajectoryHook.drawTrajectory(list);
+        }
+      }, 1000)
+    }, { deep: true })
+
     watch(() => store.state.deviceStatusEvent, (data: any) => {
       if (Object.keys(data.deviceOnline).length !== 0) {
         deviceTsaUpdateHook.initMarker(data.deviceOnline.domain, data.deviceOnline.device_callsign, data.deviceOnline.sn)

+ 51 - 0
Web/src/hooks/use-g-map-trajectory.ts

@@ -0,0 +1,51 @@
+import { getRoot } from '/@/root'
+import startSrc from '/@/assets/icons/start.svg'
+import endSrc from '/@/assets/icons/end.svg'
+
+export function useGMapTrajectory() {
+  const root = getRoot();
+  let AMap = root.$aMap;
+
+  // 绘制轨迹
+  const drawTrajectory = (paths: any[]) => {
+    // 绘制起点图标
+    const startPosition = paths[0];
+    const startIcon = new AMap.Icon({
+      size: new AMap.Size(40, 40),
+      image: startSrc,
+      imageSize: new AMap.Size(40, 40)
+    })
+    const startMarker = new AMap.Marker({
+      position: new AMap.LngLat(startPosition[0], startPosition[startPosition.length - 1]),
+      icon: startIcon,
+      offset: new AMap.Pixel(-20, -35)
+    })
+    // 绘制终点图标
+    const endPosition = paths[paths.length - 1];
+    const endIcon = new AMap.Icon({
+      size: new AMap.Size(40, 40),
+      image: endSrc,
+      imageSize: new AMap.Size(40, 40)
+    })
+    const endMarker = new AMap.Marker({
+      position: new AMap.LngLat(endPosition[0], endPosition[endPosition.length - 1]),
+      icon: endIcon,
+      offset: new AMap.Pixel(-20, -35)
+    })
+    // 绘制轨迹折线
+    const polyline = new AMap.Polyline({
+      path: paths,
+      strokeColor: '#2D8CF0',
+      strokeOpacity: 1,
+      strokeWeight: 2,
+      strokeStyle: 'solid',
+    })
+    root.$map.add([startMarker, endMarker, polyline]);
+    // 自动缩放地图到合适的视野级别
+    // root.$map.setFitView();
+  }
+
+  return {
+    drawTrajectory
+  }
+}

+ 21 - 1
Web/src/pages/page-web/projects/media/index/index.vue

@@ -197,7 +197,27 @@ const columns = [
     dataIndex: 'template_type',
     width: 150,
     customRender: ({ text }: any) => {
-      return text || '--';
+      let content = '--';
+      switch (text) {
+        case '0':
+          content = '航点航线';
+          break;
+        case '1':
+          content = '二维正射';
+          break;
+        case '2':
+          content = '倾斜摄影';
+          break;
+        case '3':
+          content = '带状航线';
+          break;
+        case '4':
+          content = '无';
+          break;
+        default:
+          break;
+      }
+      return content;
     }
   },
   {

+ 130 - 0
Web/src/pages/page-web/projects/trajectory/components/Search.vue

@@ -0,0 +1,130 @@
+<template>
+  <a-row style="margin-bottom: 20px;" justify="end">
+    <a-col>
+      <a-form ref="formRef" layout="inline" :model="formModel" :colon="false">
+        <a-form-item name="rangeDate">
+          <a-range-picker style="width: 250px;" v-model:value="formModel.rangeDate" />
+        </a-form-item>
+        <a-form-item name="template_type">
+          <a-select style="width: 200px;" placeholder="任务类型" v-model:value="formModel.template_type">
+            <a-select-option :value="0">
+              航点航线
+            </a-select-option>
+            <a-select-option :value="1">
+              二维正射
+            </a-select-option>
+            <a-select-option :value="2">
+              倾斜摄影
+            </a-select-option>
+            <a-select-option :value="3">
+              带状航线
+            </a-select-option>
+            <a-select-option :value="4">
+              无
+            </a-select-option>
+          </a-select>
+        </a-form-item>
+        <a-form-item name="payload">
+          <a-select style="width: 200px;" placeholder="拍摄负载" v-model:value="formModel.payload">
+            <a-select-option v-for="item in state.payloadList" :value="item.value">
+              {{ item.label }}
+            </a-select-option>
+          </a-select>
+        </a-form-item>
+        <a-form-item name="search_info">
+          <a-input style="width: 200px;" placeholder="计划名称" v-model:value="formModel.search_info" />
+        </a-form-item>
+        <a-form-item>
+          <a-button style="margin-right: 10px;" @click="handleClicSekarch">
+            <template #icon>
+              <SearchOutlined />
+            </template>
+          </a-button>
+          <a-button @click="handleClickReset">
+            <template #icon>
+              <ReloadOutlined />
+            </template>
+          </a-button>
+        </a-form-item>
+      </a-form>
+    </a-col>
+  </a-row>
+</template>
+
+<script lang="ts" setup>
+import { ref, reactive, onMounted } from 'vue';
+import { SearchOutlined, ReloadOutlined } from '@ant-design/icons-vue';
+import { apis } from '/@/api/custom';
+import moment from 'moment';
+
+interface Props {
+  onClickSearch: (query: any) => Promise<any>,
+  onClickReset: (query: any) => Promise<any>,
+};
+
+const props = withDefaults(defineProps<Props>(), {
+
+});
+
+const formRef = ref();
+
+const formModel = reactive({
+  rangeDate: [],
+  template_type: undefined,
+  payload: undefined,
+  search_info: undefined,
+})
+
+interface State {
+  payloadList: {
+    value: string,
+    label: string,
+  }[],
+};
+
+const state: State = reactive({
+  payloadList: [],
+})
+
+onMounted(async () => {
+  try {
+    const res = await apis.fetchPayloadList();
+    const list = res.data.map((item: any) => {
+      return {
+        value: item.payload_name,
+        label: item.payload_name,
+      }
+    })
+    state.payloadList = list;
+  } catch (e) {
+    console.error(e);
+  }
+})
+
+// 点击查询
+const handleClicSekarch = async () => {
+  const values = formRef.value?.getFieldsValue();
+  const data = {
+    ...values,
+  };
+  delete data.rangeDate;
+  if (values.rangeDate.length === 2) {
+    data.begin_time = moment(values.rangeDate[0]).valueOf();
+    data.end_time = moment(values.rangeDate[1]).valueOf();
+  }
+  await props.onClickSearch(data);
+}
+
+// 点击重置
+const handleClickReset = async () => {
+  formRef.value?.resetFields();
+  const values = formRef.value?.getFieldsValue();
+  const data = {
+    ...values,
+  };
+  delete data.rangeDate;
+  await props.onClickReset(data);
+}
+</script>
+
+<style lang="scss" scoped></style>

+ 187 - 0
Web/src/pages/page-web/projects/trajectory/index.vue

@@ -0,0 +1,187 @@
+<template>
+  <div class="trajectory">
+    <Search :onClickSearch="onClickSearch" :onClickReset="onClickReset" />
+    <div class="trajectory-table">
+      <a-table :scroll="{ x: '100%', y: 500 }" :childrenColumnName="null" rowKey="id" :loading="state.listLoading"
+        :columns="columns" @change="refreshData" :rowClassName="rowClassName" :dataSource="state.list"
+        :pagination="paginationConfig">
+        <!-- 操作 -->
+        <template #action="{ record }">
+          <a-tooltip title="查看轨迹">
+            <EnvironmentOutlined style="color: #2d8cf0;margin-right: 10px;" @click="onClickLookTrajectory(record.id)" />
+          </a-tooltip>
+        </template>
+      </a-table>
+    </div>
+  </div>
+</template>
+
+<script lang="ts" setup>
+import { reactive, onMounted } from 'vue';
+import { EnvironmentOutlined } from '@ant-design/icons-vue';
+import Search from './components/Search.vue';
+import { apis } from '/@/api/custom/index';
+import router from '/@/router';
+import { useMyStore } from '/@/store';
+
+const store = useMyStore()
+
+interface State {
+  listLoading: boolean,
+  list: any[],
+};
+
+const state: State = reactive({
+  listLoading: false,
+  list: [],
+});
+
+const paginationConfig = reactive({
+  pageSizeOptions: ['20', '50', '100'],
+  showQuickJumper: true,
+  showSizeChanger: true,
+  pageSize: 20,
+  current: 1,
+  total: 0
+})
+
+const fetchList = async (query?: any) => {
+  state.listLoading = true;
+  try {
+    const res = await apis.fetchTrajectoryList({
+      ...query,
+      page: paginationConfig.current,
+      page_size: paginationConfig.pageSize
+    });
+    if (res.code === 0) {
+      paginationConfig.total = res.data.pagination.total
+      paginationConfig.current = res.data.pagination.page
+      paginationConfig.pageSize = res.data.pagination.page_size
+    }
+    state.list = res.data.list;
+  } catch (e) {
+    console.error(e);
+  } finally {
+    state.listLoading = false;
+  }
+}
+
+onMounted(async () => {
+  await fetchList();
+})
+
+const columns = [
+  {
+    title: '计划名称',
+    dataIndex: 'task_name',
+    width: 250,
+    ellipsis: true,
+    sorter: (a: any, b: any) => a.task_name.localeCompare(b.task_name),
+  },
+  {
+    title: '拍摄负载',
+    dataIndex: 'payload',
+    width: 150,
+    ellipsis: true,
+  },
+  {
+    title: '创建时间',
+    dataIndex: 'create_time',
+    width: 200,
+    sorter: (a: any, b: any) => a.create_time.localeCompare(b.create_time),
+  },
+  {
+    title: '任务类型',
+    dataIndex: 'template_type',
+    width: 150,
+    customRender: ({ text }: any) => {
+      let content = '--';
+      switch (text) {
+        case '0':
+          content = '航点航线';
+          break;
+        case '1':
+          content = '二维正射';
+          break;
+        case '2':
+          content = '倾斜摄影';
+          break;
+        case '3':
+          content = '带状航线';
+          break;
+        case '4':
+          content = '无';
+          break;
+        default:
+          break;
+      }
+      return content;
+    }
+  },
+  {
+    title: '创建人',
+    dataIndex: 'username',
+    width: 150,
+  },
+  {
+    title: '操作',
+    dataIndex: 'actions',
+    fixed: 'right',
+    width: 80,
+    slots: { customRender: 'action' },
+  },
+]
+
+const rowClassName = (record: any, index: number) => {
+  const className = []
+  if ((index & 1) === 0) {
+    className.push('table-striped')
+  }
+  return className.toString().replaceAll(',', ' ')
+}
+
+const refreshData = async (page: any) => {
+  paginationConfig.current = page?.current!
+  paginationConfig.pageSize = page?.pageSize!
+  await fetchList();
+}
+
+// 点击搜索
+const onClickSearch = async (query: any) => {
+  await fetchList(query);
+}
+
+// 点击重置
+const onClickReset = async (query: any) => {
+  await fetchList(query);
+}
+
+// 点击查看轨迹
+const onClickLookTrajectory = async (id: string) => {
+  router.push({ path: '/workspace' });
+  const res = await apis.fetchTrajectoryMap(id);
+  const list = res.data.map((item: any) => {
+    return [item.longitude, item.latitude]
+  });
+  store.commit('SET_TRAJECTORY_LIST', list)
+}
+</script>
+
+<style lang="scss">
+.trajectory {
+  padding: 20px;
+}
+
+.ant-table {
+  border-top: 1px solid rgb(0, 0, 0, 0.06);
+  border-bottom: 1px solid rgb(0, 0, 0, 0.06);
+}
+
+.ant-table-tbody tr td {
+  border: 0;
+}
+
+.table-striped {
+  background-color: #f7f9fa;
+}
+</style>

+ 0 - 70
Web/src/pages/page-web/projects/trajectory/index/components/Search.vue

@@ -1,70 +0,0 @@
-<template>
-  <a-row style="margin-bottom: 20px;" justify="end">
-    <a-col>
-      <a-form ref="formRef" layout="inline" :model="formModel" :colon="false">
-        <a-form-item name="date">
-          <a-range-picker style="width: 250px;" v-model:value="formModel.date" />
-        </a-form-item>
-        <a-form-item name="device_name">
-          <a-select style="width: 200px;" placeholder="请选择拍摄负载" v-model:value="formModel.device_name">
-            <a-select-option value="1">
-              Mavic 3E Camera
-            </a-select-option>
-          </a-select>
-        </a-form-item>
-        <a-form-item name="keyword">
-          <a-input style="width: 200px;" placeholder="文件夹名称、计划名称" v-model:value="formModel.keyword" />
-        </a-form-item>
-        <a-form-item>
-          <a-button style="margin-right: 10px;" @click="handleClicSekarch">
-            <template #icon>
-              <SearchOutlined />
-            </template>
-          </a-button>
-          <a-button @click="handleClickReset">
-            <template #icon>
-              <ReloadOutlined />
-            </template>
-          </a-button>
-        </a-form-item>
-      </a-form>
-    </a-col>
-  </a-row>
-</template>
-
-<script lang="ts" setup>
-import { ref, reactive } from 'vue';
-import { SearchOutlined, ReloadOutlined } from '@ant-design/icons-vue';
-
-interface Props {
-  onClickSearch: (query: any) => Promise<any>,
-  onClickReset: (query: any) => Promise<any>,
-};
-
-const props = withDefaults(defineProps<Props>(), {
-
-});
-
-const formRef = ref();
-
-const formModel = reactive({
-  date: [],
-  device_name: undefined,
-  keyword: '',
-})
-
-// 点击查询
-const handleClicSekarch = async () => {
-  const values = formRef.value?.getFieldsValue();
-  await props.onClickSearch(values);
-}
-
-// 点击重置
-const handleClickReset = async () => {
-  formRef.value?.resetFields();
-  const values = formRef.value?.getFieldsValue();
-  await props.onClickReset(values);
-}
-</script>
-
-<style lang="scss" scoped></style>

+ 0 - 319
Web/src/pages/page-web/projects/trajectory/index/index.vue

@@ -1,319 +0,0 @@
-<template>
-  <div class="trajectoryList">
-    <Search :mode="state.mode" :selectedRowKeys="state.selectedRowKeys" :onClickDownload="onClickBatchDownload"
-      :onClickSearch="onClickSearch" :onClickReset="onClickReset" />
-    <div style="background: #FFFFFF;padding: 20px;">
-      <div class="trajectoryList-info">
-        <div>
-          轨迹回放文件
-        </div>
-        <div class="trajectoryList-info-right">
-          <div class="trajectoryList-info-right-text">
-            <div>
-              已选/全部:
-            </div>
-            <div>
-              {{ state.selectedRowKeys.length }}/{{ paginationConfig.total }}
-            </div>
-          </div>
-          <a-button style="padding:0 5px;" :type="state.mode === 'table' ? 'primary' : 'default'"
-            :ghost="state.mode === 'table'" size="small" @click="state.mode = 'table'">
-            <MenuOutlined />
-          </a-button>
-          <a-button style="padding:0 5px;" :type="state.mode === 'list' ? 'primary' : 'default'"
-            :ghost="state.mode === 'list'" size="small" @click="state.mode = 'list'">
-            <AppstoreOutlined />
-          </a-button>
-        </div>
-      </div>
-      <div>
-        <div class="trajectoryList-table" v-if="state.mode === 'table'">
-          <a-table :scroll="{ x: '100%', y: 500 }" :childrenColumnName="null" rowKey="id" :loading="state.listLoading"
-            :columns="columns" :dataSource="state.list" :rowClassName="rowClassName" :pagination="paginationConfig"
-            :rowSelection="{ selectedRowKeys: state.selectedRowKeys, onChange: onSelectChange }">
-            <!-- 文件夹名称 -->
-            <template #dir_name="{ record }">
-              <a-tooltip :title="record.dir_name">
-                <div class="fileName" @click="onClickFile(record)">
-                  <img :src="fileSrc">
-                  <div>
-                    {{ record.dir_name }}
-                  </div>
-                </div>
-              </a-tooltip>
-            </template>
-            <!-- 操作 -->
-            <template #action="{ record }">
-              <div class="flex-align-center flex-row" style="color: #2d8cf0">
-                <a-tooltip title="压缩下载">
-                  <DownloadOutlined style="margin-right: 10px;" @click="onClickDownload(record)" />
-                </a-tooltip>
-                <a-tooltip title="轨迹回放">
-                  <EnvironmentOutlined @click="onClickTrajectory" />
-                </a-tooltip>
-              </div>
-            </template>
-          </a-table>
-        </div>
-        <div class="trajectoryList-list" v-else>
-          <a-list :grid="{ gutter: 16, xs: 1, sm: 2, md: 3, lg: 4, xl: 8, xxl: 12 }" :loading="state.listLoading"
-            :dataSource="state.list" :pagination="paginationConfig">
-            <template #renderItem="{ item }">
-              <a-list-item>
-                <a-card hoverable @click="onClickFile(item)">
-                  <template #cover>
-                    <div style="display: flex;justify-content:center;align-items: center;">
-                      <img style="width: 70%;" :src="fileSrc" />
-                    </div>
-                  </template>
-                  <a-card-meta>
-                    <template #description>
-                      <a-tooltip placement="bottom" :title="item.dir_name">
-                        <div class="trajectoryList-list-name">
-                          {{ item.dir_name }}
-                        </div>
-                      </a-tooltip>
-                    </template>
-                  </a-card-meta>
-                </a-card>
-              </a-list-item>
-            </template>
-          </a-list>
-        </div>
-      </div>
-    </div>
-  </div>
-</template>
-
-<script lang="ts" setup>
-import { reactive, onMounted } from 'vue';
-import { MenuOutlined, AppstoreOutlined, DownloadOutlined, EnvironmentOutlined } from '@ant-design/icons-vue';
-import Search from './components/Search.vue';
-import fileSrc from '/@/assets/media/file.svg';
-import { apis } from '/@/api/custom';
-import router from '/@/router/index';
-
-interface State {
-  listLoading: boolean,
-  list: any[],
-  selectedRowKeys: string[],
-  mode: 'table' | 'list',
-};
-
-const state: State = reactive({
-  listLoading: false,
-  list: [],
-  selectedRowKeys: [],
-  mode: 'table',
-})
-
-const paginationConfig = reactive({
-  pageSizeOptions: ['20', '50', '100'],
-  showQuickJumper: true,
-  showSizeChanger: true,
-  pageSize: 20,
-  current: 1,
-  total: 0,
-  onChange: async (current: number) => {
-    paginationConfig.current = current;
-    await fetchList();
-  },
-  onShowSizeChange: async (current: number, pageSize: number) => {
-    paginationConfig.pageSize = pageSize;
-    await fetchList();
-  }
-})
-
-const fetchList = async () => {
-  state.listLoading = true;
-  try {
-    const res = await apis.fetchMediaFileList({ page: paginationConfig.current, page_size: paginationConfig.pageSize });
-    state.list = res.data.list;
-    paginationConfig.current = res.data.pagination.page;
-    paginationConfig.pageSize = res.data.pagination.page_size;
-    paginationConfig.total = res.data.pagination.total;
-  } catch (e) {
-    console.error(e);
-  } finally {
-    state.listLoading = false;
-  }
-}
-
-onMounted(async () => {
-  // await fetchList();
-})
-
-const columns = [
-  {
-    title: '文件夹名称',
-    dataIndex: 'dir_name',
-    width: 250,
-    ellipsis: true,
-    sorter: (a: any, b: any) => a.dir_name.localeCompare(b.dir_name),
-    slots: { customRender: 'dir_name' }
-  },
-  {
-    title: '设备型号',
-    dataIndex: 'device_name',
-    width: 150,
-    ellipsis: true,
-  },
-  {
-    title: '拍摄负载',
-    dataIndex: 'payload',
-    width: 150,
-    ellipsis: true,
-  },
-  {
-    title: '容量大小',
-    dataIndex: 'is_original',
-    width: 150,
-    ellipsis: true,
-    customRender: ({ text }: any) => {
-      return text || '--';
-    }
-  },
-  {
-    title: '创建时间',
-    dataIndex: 'create_time',
-    width: 200,
-    sorter: (a: any, b: any) => a.create_time.localeCompare(b.create_time),
-  },
-  {
-    title: '航线名称',
-    dataIndex: 'wayline_name',
-    width: 150,
-  },
-  {
-    title: '任务类型',
-    dataIndex: 'template_type',
-    width: 150,
-    customRender: ({ text }: any) => {
-      return text || '--';
-    }
-  },
-  {
-    title: '创建人',
-    dataIndex: 'username',
-    width: 150,
-  },
-  {
-    title: '操作',
-    dataIndex: 'actions',
-    fixed: 'right',
-    width: 80,
-    slots: { customRender: 'action' },
-  },
-]
-
-const rowClassName = (record: any, index: number) => {
-  const className = []
-  if ((index & 1) === 0) {
-    className.push('table-striped')
-  }
-  return className.toString().replaceAll(',', ' ')
-}
-
-// 点击批量下载
-const onClickBatchDownload = async () => {
-  console.log(state.selectedRowKeys, '点击批量下载');
-}
-
-// 点击搜索
-const onClickSearch = async () => {
-  console.log('点击搜索');
-}
-
-// 点击重置
-const onClickReset = async () => {
-  console.log('点击重置');
-}
-
-// 点击文件夹
-const onClickFile = (record: any) => {
-  router.push({ path: `/media/${record.id}` })
-}
-
-// 勾选
-const onSelectChange = (selectedRowKeys: string[]) => {
-  state.selectedRowKeys = selectedRowKeys;
-}
-
-// 点击下载
-const onClickDownload = async (record: any) => {
-  state.listLoading = true;
-  try {
-
-  } catch (e) {
-    console.error(e);
-  } finally {
-    state.listLoading = false;
-  }
-}
-
-// 点击轨迹回放
-const onClickTrajectory = () => {
-  router.push({ path: '/trajectory' })
-}
-</script>
-
-<style lang="scss">
-.trajectoryList {
-  padding: 20px;
-
-  &-info {
-    display: flex;
-    justify-content: space-between;
-    align-items: center;
-    margin-bottom: 20px;
-
-    &-right {
-      display: flex;
-      align-items: center;
-
-      &-text {
-        display: flex;
-        align-items: center;
-        margin-right: 20px;
-      }
-    }
-  }
-
-  .fileName {
-    display: flex;
-    align-items: center;
-    cursor: pointer;
-
-    img {
-      width: 36px;
-      height: 36px;
-      margin-right: 5px;
-    }
-  }
-
-  &-list {
-    &-name {
-      overflow: hidden;
-      text-overflow: ellipsis;
-      white-space: nowrap;
-    }
-  }
-}
-
-.ant-table {
-  border-top: 1px solid rgb(0, 0, 0, 0.06);
-  border-bottom: 1px solid rgb(0, 0, 0, 0.06);
-}
-
-.ant-table-tbody tr td {
-  border: 0;
-}
-
-.table-striped {
-  background-color: #f7f9fa;
-}
-
-.ant-card-body {
-  padding: 0 10px 10px;
-}
-</style>

+ 5 - 8
Web/src/pages/page-web/projects/tsa.vue

@@ -96,7 +96,7 @@
                           style="width: 18px; height: 16px; text-align: center;">
                           <span :style="hmsInfo[dock.sn].length > 99 ? 'font-size: 11px' : 'font-size: 12px'">{{
                             hmsInfo[dock.sn].length
-                          }}</span>
+                            }}</span>
                           <span class="fz10">{{ hmsInfo[dock.sn].length > 99 ? '+' : '' }}</span>
                         </div>
                         <a-popover trigger="click" placement="bottom" color="black"
@@ -229,9 +229,9 @@
       <a-button style="margin-right: 10px;" type="primary" @click="onClickGoHome">
         返回
       </a-button>
-      <a-button style="margin-right: 10px;" type="primary" @click="openLivestreamOthers">
+      <!-- <a-button style="margin-right: 10px;" type="primary" @click="openLivestreamOthers">
         测试直播
-      </a-button>
+      </a-button> -->
     </div>
   </div>
 </template>
@@ -292,15 +292,12 @@ onMounted(() => {
         if (data.deviceOnline.sn) {
           getUnreadHms(data.deviceOnline.sn)
         }
-      },
-      {
-        deep: true
-      }
+      }, { deep: true }
     )
     getOnlineDeviceHms()
   }, 3000)
   const element = document.getElementsByClassName('scrollbar').item(0) as HTMLDivElement
-  const parent = element?.parentNode as HTMLDivElement
+  const parent: any = element?.parentNode as HTMLDivElement
   scorllHeight.value = parent?.clientHeight - parent?.firstElementChild?.clientHeight
 })
 

+ 1 - 2
Web/src/router/index.ts

@@ -9,7 +9,6 @@ const routes: Array<RouteRecordRaw> = [
     path: '/',
     redirect: '/' + ERouterName.PROJECT
   },
-  // 首页
   {
     path: '/' + ERouterName.PROJECT,
     name: ERouterName.PROJECT,
@@ -60,7 +59,7 @@ const routes: Array<RouteRecordRaw> = [
       {
         path: '/' + ERouterName.TRAJECTORY,
         name: ERouterName.TRAJECTORY,
-        component: () => import('/@/pages/page-web/projects/trajectory/index/index.vue')
+        component: () => import('/@/pages/page-web/projects/trajectory/index.vue')
       },
       {
         path: '/' + ERouterName.MEMBER,

+ 4 - 0
Web/src/store/index.ts

@@ -8,6 +8,7 @@ import { WaylineFile } from '/@/types/wayline'
 import { DevicesCmdExecuteInfo } from '/@/types/device-cmd'
 
 const initStateFunc = () => ({
+  trajectoryList: [],// 轨迹列表
   mapClickId: '',
   Layers: [
     // {
@@ -100,6 +101,9 @@ export type RootStateType = ReturnType<typeof initStateFunc>
 const getters: GetterTree<RootStateType, RootStateType> = {
 }
 const mutations: MutationTree<RootStateType> = {
+  SET_TRAJECTORY_LIST(state, list) {
+    state.trajectoryList = list
+  },
   SET_MAP_CLICK_ID(state, id) {
     state.mapClickId = id
   },

Some files were not shown because too many files changed in this diff