Pārlūkot izejas kodu

feat: 添加地图更新页面&地图更新统计页面&地图续扫提醒阈值弹框

LingxinMeng 10 mēneši atpakaļ
vecāks
revīzija
924229b0c2
4 mainītis faili ar 817 papildinājumiem un 95 dzēšanām
  1. 10 0
      src/router/index.ts
  2. 345 0
      src/views/MapUpdateView.vue
  3. 132 95
      src/views/ReportView.vue
  4. 330 0
      src/views/UpdateStatView.vue

+ 10 - 0
src/router/index.ts

@@ -17,6 +17,16 @@ const router = createRouter({
             // this generates a separate chunk (About.[hash].js) for this route
             // which is lazy-loaded when the route is visited.
             component: () => import('../views/AboutView.vue')
+        },
+        {
+            path: '/map_update',
+            name: 'map_update',
+            component: () => import('../views/MapUpdateView.vue')
+        },
+        {
+            path: '/update_stat',
+            name: 'update_stat',
+            component: () => import('../views/UpdateStatView.vue')
         }
     ]
 })

+ 345 - 0
src/views/MapUpdateView.vue

@@ -0,0 +1,345 @@
+<template>
+  <div class="common-layout">
+    <el-container>
+      <el-header
+          style="height: 250px; background-color: rgba(255,0,0,50%); display: flex; flex-direction: column; justify-content: center; align-items: center;">
+        <div class="demo-image" style="text-align: center;"> <!-- 注意这里添加了 text-align: center; 但对于块级元素这不是必需的 -->
+          <img src="../assets/pji-logo.jpg" alt="" style="max-width: 100%; height: auto;">
+          <!-- 推荐使用 max-width 保持图片比例 -->
+        </div>
+      </el-header>
+      <el-main style="background-color:white;">
+        <div class="topbar">
+          <el-button type="primary" @click="dialogVisible = true" style="float: right; margin-bottom: 20px;">将地图更新至机器人端</el-button>
+          <el-dialog
+              v-model="dialogVisible"
+              title="提示"
+              width="300"
+              :before-close="handleClose"
+          >
+            <span>请确认是否进行地图更新</span>
+            <template #footer>
+              <div class="dialog-footer">
+                <el-button @click="dialogVisible = false">取消</el-button>
+                <el-button type="primary" @click="dialogVisible = false">
+                  确认
+                </el-button>
+              </div>
+            </template>
+          </el-dialog>
+        </div>
+
+        <el-table stripe style="background-color: rgba(255,0,0,99%);width: 100%" border :data="tableData"
+                  fixed ref="multipleTableRef" :cell-style="{ textAlign: 'center'}" :header-cell-style="{ textAlign: 'center'}">
+          <el-table-column type="selection" width="55"/>
+          <el-table-column prop="mapId" label="地图id"/>
+          <el-table-column prop="beforePgm" label="更新前pgm"/>
+          <el-table-column prop="afterPgm" label="更新后pgm"/>
+          <el-table-column prop="mapUpdateRate" label="地图更新率" :formatter="mapUpdateRateFormatter"/>
+        </el-table>
+
+<!--        <p></p> &lt;!&ndash;空行&ndash;&gt;-->
+<!--        <el-pagination-->
+<!--            v-model:current-page="currentPage"-->
+<!--            v-model:page-size="pageSize"-->
+<!--            :page-sizes="[10]"-->
+<!--            :small="small"-->
+<!--            :disabled="disabled"-->
+<!--            :background="true"-->
+<!--            layout="total, sizes, prev, pager, next, jumper"-->
+<!--            :total="total"-->
+<!--            @size-change="handleSizeChange"-->
+<!--            @current-change="handleCurrentChange"-->
+<!--        />-->
+<!--        &lt;!&ndash;        <el-pagination background layout="prev, pager, next" :total="1000"/>&ndash;&gt;-->
+      </el-main>
+      <!--      <el-footer style="background-color: rgba(255,0,0,99%)">国家智能网联汽车创新中心</el-footer>-->
+    </el-container>
+  </div>
+</template>
+
+<script lang="ts" setup>
+import {onBeforeMount, ref} from "vue";
+import axios from "axios";
+import {reactive} from 'vue'
+import {ElTable} from "element-plus";
+import {useRouter} from 'vue-router'; // 导入 Vue Router 的 useRouter 钩子
+
+
+const router = useRouter();
+const gazeboState = ref(false)
+const rvizState = ref(false)
+const multipleTableRef = ref<InstanceType<typeof ElTable>>
+
+const dialogVisible = ref(false)
+
+const handleClose = (done: () => void) => {
+  done()
+}
+
+// do not use same name with ref
+const form = reactive({
+  sudoPassword: '',
+  tag: '',
+  // date1: '',
+  // date2: '',
+  // delivery: false,
+  // type: [],
+  // resource: '',
+  // desc: '',
+})
+const currentTag = ref('')
+
+
+const algorithmImport = async () => {
+  dialogVisible.value = false
+  try {
+    const result = await window.electronAPI.openFileManager();
+    console.log('用户选择的文件路径为:', result, ',版本为:', form.tag);
+    window.electronAPI.dockerImport(form.sudoPassword, result, form.tag)
+  } catch (error) {
+    console.error('打开文件管理器时出错:', error);
+  }
+};
+
+const goToDetail = () => {
+  router.push('/about')
+}
+
+// 数据容量单位从B转成MB
+const dataSizeFormatter = (row, column, cellValue, index) => {
+  // 假设 1MB = 1024 * 1024 字节
+  if (cellValue) {
+    const mb = (cellValue / (1024 * 1024)).toFixed(2); // 保留两位小数
+    return `${mb}MB`;
+  }
+  return cellValue; // 如果cellValue为null或undefined,则返回原值或你想要的默认值
+}
+
+const mapUpdateRateFormatter = (row, column, cellValue, index) => {
+  // 假设 1MB = 1024 * 1024 字节
+  if (cellValue) {
+    const percentValue = (cellValue * 100).toFixed(1); // 保留两位小数
+    return `${percentValue}%`;
+  }
+  return cellValue; // 如果cellValue为null或undefined,则返回原值或你想要的默认值
+}
+
+const gazebo = () => {
+  if (gazeboState.value) {
+    if (window.electronAPI) {
+      window.electronAPI.openGazebo(); // 关闭 gazebo
+    } else {
+      console.error('electronAPI is not defined');
+    }
+    // gazeboState.value = false
+  } else {
+    if (window.electronAPI) {
+      window.electronAPI.closeGazebo();
+    } else {
+      console.error('electronAPI is not defined');
+    }
+    // gazeboState.value = true
+  }
+}
+
+const rviz = () => {
+  if (rvizState.value) {
+    if (window.electronAPI) {
+      window.electronAPI.openRviz();
+    } else {
+      console.error('electronAPI is not defined');
+    }
+  } else {
+    if (window.electronAPI) {
+      window.electronAPI.closeRviz();
+    } else {
+      console.error('electronAPI is not defined');
+    }
+  }
+}
+
+
+const downloadPdf = (index: number, row: any) => {
+  console.log(index, row)
+  axios.post('http://36.110.106.142:12341/web_server/exam/report',
+      {
+        "id": row.id,
+        "teamName": row.teamName,
+        "scoreOnline": row.scoreOnline,
+        "beginTime": row.beginTime,
+        "endTime": row.endTime
+      },
+      {
+        headers: {
+          "Authorization": "U9yKpD6kZZDDe4LFKK6myAxBUT1XRrDM"
+        },
+        responseType: 'blob' // 设置响应类型为二进制流
+      }
+  ).then(function (response) {
+    const url = window.URL.createObjectURL(new Blob([response.data]));
+    const link = document.createElement('a');
+    link.href = url;
+    link.setAttribute('download', row.topic + "-" + row.teamName + "-评分报告.pdf"); // 设置下载的文件名
+    document.body.appendChild(link);
+    link.click();
+  }).catch(function (error) {
+    console.log(error);
+  });
+}
+
+
+const openPdf = (index: number, row: any) => {
+  console.log(index, row)
+  axios.post('http://36.110.106.142:12341/web_server/exam/report',
+      {
+        "id": row.id,
+        "teamName": row.teamName,
+        "scoreOnline": row.scoreOnline,
+        "beginTime": row.beginTime,
+        "endTime": row.endTime
+      },
+      {
+        headers: {
+          "Authorization": "U9yKpD6kZZDDe4LFKK6myAxBUT1XRrDM"
+        },
+        responseType: 'blob' // 设置响应类型为二进制流
+      }
+  ).then(function (response) {
+    const url = window.URL.createObjectURL(new Blob([response.data], {type: 'application/pdf'}));
+    window.open(url, '_blank');
+  }).catch(function (error) {
+    console.log(error);
+  });
+}
+
+
+const queryLine = reactive({
+  dataName: '',
+  equipmentName: '',
+  equipmentTypeName: '',
+  triggerName: '',
+  triggerTypeName: '',
+})
+
+const onSubmit = () => {
+  page()
+}
+
+let total = ref(0)
+let tableData = ref([{
+  'mapId': 1,
+  'beforePgm': 'url1',
+  'afterPgm': 'url1_1',
+  'mapUpdateRate': 0.201
+},
+{
+  'mapId': 2,
+  'beforePgm': 'url2',
+  'afterPgm': 'url2_1',
+  'mapUpdateRate': 0.21
+}
+]);
+
+onBeforeMount(() => {
+  page()
+})
+
+function page() {
+  axios.get('http://1.202.169.139:8081/open/scene/list?page=' + currentPage.value + '&size=' + pageSize.value,
+      {
+        headers: {
+          "Authorization": "4773hd92ysj54paflw2jem3onyhywxt2"
+        }
+      }
+  ).then(function (response) {
+    // tableData.value = response.data.data.content
+    total.value = response.data.data.totalElements
+    // total.value = tableData.value.length
+    // console.log(tableData);
+    // console.log(response.data.data);
+  }).catch(function (error) {
+    console.log(error);
+  });
+}
+
+const currentPage = ref(1)
+const pageSize = ref(10)
+const small = ref(false)
+const disabled = ref(false)
+
+const handleSizeChange = (val: number) => {
+  pageSize.value = val
+  page()
+  if (tableData.value.length == 0) {
+    page()
+  }
+}
+const handleCurrentChange = (val: number) => {
+  currentPage.value = val
+  page()
+}
+const handleClick = () => {
+  console.log('click')
+}
+
+
+</script>
+<style scoped>
+
+
+.demo-pagination-block + .demo-pagination-block {
+  margin-top: 10px;
+}
+
+.demo-pagination-block .demonstration {
+  margin-bottom: 16px;
+}
+
+
+.demo-form-inline .el-input {
+  --el-input-width: 200px;
+}
+
+.demo-form-inline .el-select {
+  --el-select-width: 400px;
+}
+
+.demo-image .block {
+  padding: 30px 0;
+  text-align: center;
+  border-right: solid 1px var(--el-border-color);
+  display: inline-block;
+  width: 20%;
+  box-sizing: border-box;
+  vertical-align: top;
+}
+
+.demo-image .block:last-child {
+  border-right: none;
+}
+
+.demo-image .demonstration {
+  display: block;
+  color: var(--el-text-color-secondary);
+  font-size: 14px;
+  margin-bottom: 20px;
+}
+
+.topbar {
+  margin-bottom: 15px;
+}
+
+/* 假设 .el-pager__item 是分页按钮的类名,这可能需要你根据实际的 Element UI 版本和源码进行调整 */
+.el-pager__item {
+  background-color: rgba(255, 0, 0, 50%) !important; /* 修改背景色 */
+  color: #fff; /* 可能需要修改文本颜色以在红色背景上可见 */
+  border-color: transparent; /* 如果需要,修改边框颜色 */
+}
+
+/* 修改当前选中页码的按钮样式 */
+.el-pager__item.is-active {
+  background-color: rgba(255, 0, 0, 70%) !important; /* 选中时的背景色 */
+  color: #fff; /* 选中时的文本颜色 */
+}
+</style>

+ 132 - 95
src/views/ReportView.vue

@@ -9,98 +9,123 @@
         </div>
       </el-header>
       <el-main style="background-color:white;">
-        <el-form style=" background-color: rgba(0,0,0,0%);" :inline="true" :model="queryLine"
-                 class="demo-form-inline">
-          <el-form-item label="数据名称">
-            <el-input v-model="queryLine.dataName" placeholder="请输入数据名称" clearable/>
-          </el-form-item>
-          <!--          <el-form-item label="数据标签">-->
-          <!--            <el-input v-model="queryLine.teamName" placeholder="请输入数据标签" clearable/>-->
-          <!--          </el-form-item>-->
-          <el-form-item label="设备名称">
-            <el-input v-model="queryLine.equipmentName" placeholder="请输入设备名称" clearable/>
-          </el-form-item>
-          <el-form-item label="设备类型">
-            <el-input v-model="queryLine.equipmentTypeName" placeholder="请输入设备类型" clearable/>
-          </el-form-item>
-          <el-form-item label="触发器名称">
-            <el-input v-model="queryLine.triggerName" placeholder="请输入触发器名称" clearable/>
-          </el-form-item>
-          <el-form-item label="触发器类型">
-            <el-input v-model="queryLine.triggerTypeName" placeholder="请输入触发器类型" clearable/>
-          </el-form-item>
-          <el-form-item>
-            <el-button type="danger" @click="onSubmit">查询</el-button>
-          </el-form-item>
-          <el-form-item>
-            <el-button type="danger" @click="onSubmit">重置</el-button>
-          </el-form-item>
-        </el-form>
-        <el-button type="primary" @click="algorithmImport">地图更新</el-button>
-        <el-button type="primary" @click="algorithmImport">地图更新统计</el-button>
-        <el-button type="primary" @click="algorithmImport">地图续扫提醒阈值</el-button>
-        <el-button type="primary" @click="algorithmImport">地图续扫提醒</el-button>
-        <el-button type="primary" @click="dialogVisible = true">算法镜像导入</el-button>
-        <el-dialog
-            v-model="dialogVisible"
-            title="请输入算法版本"
-            width="300"
-            :before-close="handleClose"
-        >
-          <template #footer>
-            <div class="dialog-footer">
-              <el-form :model="form" label-width="auto">
-                <el-form-item style="margin-bottom: 10px" label="sudo密码:">
-                  <el-input v-model="form.sudoPassword"/>
-                </el-form-item>
-                <el-form-item style="margin-bottom: 10px" label="算法版本:">
-                  <el-input v-model="form.tag"/>
-                </el-form-item>
-              </el-form>
-              <!--            -->
-              <!--            <el-button @click="dialogVisible = false">取消</el-button>-->
-              <el-button type="primary" @click="algorithmImport">选择镜像文件</el-button>
-            </div>
-          </template>
-        </el-dialog>
-        <el-button style="margin-left: 10px;"  type="primary" @click="onSubmit">算法镜像选择</el-button>
-        <el-switch
-            style="margin-left: 10px;"
-            v-model="value"
-            size="large"
-            inactive-text="算法容器"
-        />
-<!--        <el-switch-->
-<!--            v-model="algorithmContainerState"-->
-<!--            class="ml-2"-->
-<!--            inline-prompt-->
-<!--            style="margin-left: 100px;&#45;&#45;el-switch-on-color: #13ce66; &#45;&#45;el-switch-off-color: #ff4949"-->
-<!--            active-text="算法容器已开启"-->
-<!--            inactive-text="算法容器已关闭"-->
-<!--        />-->
-  <!--        <el-switch-->
-  <!--            v-model="gazeboState"-->
-  <!--            class="ml-2"-->
-  <!--            inline-prompt-->
-  <!--            style="margin-left: 100px; &#45;&#45;el-switch-on-color: #13ce66; &#45;&#45;el-switch-off-color: #ff4949"-->
-  <!--            active-text="Gazebo 已开启"-->
-  <!--            inactive-text="Gazebo 已关闭"-->
-  <!--            @click="gazebo"-->
-  <!--        />-->
-  <!--        <el-switch-->
-  <!--            v-model="rvizState"-->
-  <!--            class="ml-2"-->
-  <!--            inline-prompt-->
-  <!--            style="margin-left: 100px;&#45;&#45;el-switch-on-color: #13ce66; &#45;&#45;el-switch-off-color: #ff4949"-->
-  <!--            active-text="Rviz 已开启"-->
-  <!--            inactive-text="Rviz 已关闭"-->
-  <!--            @click="rviz"-->
-  <!--        />-->
-        <el-button style="margin-left: 100px;" type="primary" @click="onSubmit">仿真测试记录</el-button>
-        <br>
-        <br>
+        <div class="topbar">
+          <el-form style=" background-color: rgba(0,0,0,0%);" :inline="true" :model="queryLine"
+                   class="demo-form-inline">
+            <el-form-item label="数据名称">
+              <el-input v-model="queryLine.dataName" placeholder="请输入数据名称" clearable/>
+            </el-form-item>
+            <!--          <el-form-item label="数据标签">-->
+            <!--            <el-input v-model="queryLine.teamName" placeholder="请输入数据标签" clearable/>-->
+            <!--          </el-form-item>-->
+            <el-form-item label="设备名称">
+              <el-input v-model="queryLine.equipmentName" placeholder="请输入设备名称" clearable/>
+            </el-form-item>
+            <el-form-item label="设备类型">
+              <el-input v-model="queryLine.equipmentTypeName" placeholder="请输入设备类型" clearable/>
+            </el-form-item>
+            <el-form-item label="触发器名称">
+              <el-input v-model="queryLine.triggerName" placeholder="请输入触发器名称" clearable/>
+            </el-form-item>
+            <el-form-item label="触发器类型">
+              <el-input v-model="queryLine.triggerTypeName" placeholder="请输入触发器类型" clearable/>
+            </el-form-item>
+            <el-form-item>
+              <el-button type="danger" @click="onSubmit">查询</el-button>
+            </el-form-item>
+            <el-form-item>
+              <el-button type="danger" @click="onSubmit">重置</el-button>
+            </el-form-item>
+          </el-form>
+          <el-button type="primary" @click="goToMapUpdate">地图更新</el-button>
+          <el-button type="primary" @click="goToUpdateStat">地图更新统计</el-button>
+          <el-button type="primary" @click="mapDialogVisible = true">地图续扫提醒阈值</el-button>
+          <el-button type="primary" @click="algorithmImport">地图续扫提醒</el-button>
+          <el-button type="primary" @click="algorithmDialogVisible = true">算法镜像导入</el-button>
+          <el-dialog
+              v-model="algorithmDialogVisible"
+              title="请输入算法版本"
+              width="300"
+              :before-close="handleClose"
+          >
+            <template #footer>
+              <div class="dialog-footer">
+                <el-form :model="form" label-width="auto">
+                  <el-form-item style="margin-bottom: 10px" label="sudo密码:">
+                    <el-input v-model="form.sudoPassword"/>
+                  </el-form-item>
+                  <el-form-item style="margin-bottom: 10px" label="算法版本:">
+                    <el-input v-model="form.tag"/>
+                  </el-form-item>
+                </el-form>
+                <!--            -->
+                <!--            <el-button @click="algorithmDialogVisible = false">取消</el-button>-->
+                <el-button type="primary" @click="algorithmImport">选择镜像文件</el-button>
+              </div>
+            </template>
+          </el-dialog>
+
+          <el-dialog
+              v-model="mapDialogVisible"
+              title="地图续扫提醒"
+              width="400"
+              :before-close="handleClose"
+          >
+            <el-form :model="form">
+              <el-form-item label="请输入地图续扫提醒阈值" label-width="170">
+                <el-input v-model="form.name">
+                  <template #suffix>
+                    <i slot="suffix" style="color: #181818">%</i>
+                  </template>
+                </el-input>
+              </el-form-item>
+
+            </el-form>
+            <template #footer>
+              <div class="dialog-footer">
+                <el-button type="primary" @click="mapDialogVisible = false">
+                  确认
+                </el-button>
+              </div>
+            </template>
+          </el-dialog>
+          <el-button style="margin-left: 10px;"  type="primary" @click="onSubmit">算法镜像选择</el-button>
+          <el-switch
+              style="margin-left: 10px;"
+              v-model="value"
+              size="large"
+              inactive-text="算法容器"
+          />
+          <!--        <el-switch-->
+          <!--            v-model="algorithmContainerState"-->
+          <!--            class="ml-2"-->
+          <!--            inline-prompt-->
+          <!--            style="margin-left: 100px;&#45;&#45;el-switch-on-color: #13ce66; &#45;&#45;el-switch-off-color: #ff4949"-->
+          <!--            active-text="算法容器已开启"-->
+          <!--            inactive-text="算法容器已关闭"-->
+          <!--        />-->
+          <!--        <el-switch-->
+          <!--            v-model="gazeboState"-->
+          <!--            class="ml-2"-->
+          <!--            inline-prompt-->
+          <!--            style="margin-left: 100px; &#45;&#45;el-switch-on-color: #13ce66; &#45;&#45;el-switch-off-color: #ff4949"-->
+          <!--            active-text="Gazebo 已开启"-->
+          <!--            inactive-text="Gazebo 已关闭"-->
+          <!--            @click="gazebo"-->
+          <!--        />-->
+          <!--        <el-switch-->
+          <!--            v-model="rvizState"-->
+          <!--            class="ml-2"-->
+          <!--            inline-prompt-->
+          <!--            style="margin-left: 100px;&#45;&#45;el-switch-on-color: #13ce66; &#45;&#45;el-switch-off-color: #ff4949"-->
+          <!--            active-text="Rviz 已开启"-->
+          <!--            inactive-text="Rviz 已关闭"-->
+          <!--            @click="rviz"-->
+          <!--        />-->
+          <el-button style="margin-left: 100px;" type="primary" @click="onSubmit">仿真测试记录</el-button>
+        </div>
         <el-table stripe style="background-color: rgba(255,0,0,99%);width: 100%" border :data="tableData"
-                  fixed ref="multipleTableRef">
+                  fixed ref="multipleTableRef" :cell-style="{ textAlign: 'center'}" :header-cell-style="{ textAlign: 'center'}">
           <el-table-column type="selection" width="55"/>
           <el-table-column prop="dataName" label="数据名称"/>
           <el-table-column prop="dataSize" label="数据容量" :formatter="dataSizeFormatter"/>
@@ -110,7 +135,7 @@
           <el-table-column prop="triggerTypeName" label="触发器类型"/>
           <el-table-column prop="callbackTime" label="上报时间"/>
           <el-table-column prop="dataStateName" label="数据状态"/>
-          <el-table-column width="100" fixed="right" label="操作">
+          <el-table-column width="300" fixed="right" label="操作">
             <el-button size="small" type="danger" @click="goToDetail">生成world</el-button>
             <el-button size="small" type="danger" @click="goToDetail">仿真测试</el-button>
             <!--            <el-button size="small" type="danger" @click="goToDetail">算法评价</el-button>-->
@@ -152,7 +177,8 @@ const gazeboState = ref(false)
 const rvizState = ref(false)
 const multipleTableRef = ref<InstanceType<typeof ElTable>>
 
-const dialogVisible = ref(false)
+const algorithmDialogVisible = ref(false)
+const mapDialogVisible = ref(false)
 
 const handleClose = (done: () => void) => {
   done()
@@ -173,7 +199,7 @@ const currentTag = ref('')
 
 
 const algorithmImport = async () => {
-  dialogVisible.value = false
+  algorithmDialogVisible.value = false
   try {
     const result = await window.electronAPI.openFileManager();
     console.log('用户选择的文件路径为:', result, ',版本为:', form.tag);
@@ -187,6 +213,14 @@ const goToDetail = () => {
   router.push('/about')
 }
 
+const goToMapUpdate = () => {
+  router.push('/map_update')
+}
+
+const goToUpdateStat = () => {
+  router.push('/update_stat')
+}
+
 // 数据容量单位从B转成MB
 const dataSizeFormatter = (row, column, cellValue, index) => {
   // 假设 1MB = 1024 * 1024 字节
@@ -346,7 +380,6 @@ const handleClick = () => {
 </script>
 <style scoped>
 
-
 .demo-pagination-block + .demo-pagination-block {
   margin-top: 10px;
 }
@@ -385,6 +418,10 @@ const handleClick = () => {
   margin-bottom: 20px;
 }
 
+.topbar {
+  margin-bottom: 15px;
+}
+
 /* 假设 .el-pager__item 是分页按钮的类名,这可能需要你根据实际的 Element UI 版本和源码进行调整 */
 .el-pager__item {
   background-color: rgba(255, 0, 0, 50%) !important; /* 修改背景色 */

+ 330 - 0
src/views/UpdateStatView.vue

@@ -0,0 +1,330 @@
+<template>
+  <div class="common-layout">
+    <el-container>
+      <el-header
+          style="height: 250px; background-color: rgba(255,0,0,50%); display: flex; flex-direction: column; justify-content: center; align-items: center;">
+        <div class="demo-image" style="text-align: center;"> <!-- 注意这里添加了 text-align: center; 但对于块级元素这不是必需的 -->
+          <img src="../assets/pji-logo.jpg" alt="" style="max-width: 100%; height: auto;">
+          <!-- 推荐使用 max-width 保持图片比例 -->
+        </div>
+      </el-header>
+      <el-main style="background-color:white;">
+        <div class="topbar">
+          <el-form style=" background-color: rgba(0,0,0,0%);" :inline="true" :model="queryLine"
+                   class="demo-form-inline">
+
+            <el-form-item label="设备名称">
+              <el-input v-model="queryLine.equipmentName" placeholder="请输入设备名称" clearable/>
+            </el-form-item>
+            <el-form-item label="设备类型">
+              <el-input v-model="queryLine.equipmentTypeName" placeholder="请输入设备类型" clearable/>
+            </el-form-item>
+            <el-form-item>
+              <el-button type="danger" @click="onSubmit">查询</el-button>
+            </el-form-item>
+            <el-form-item>
+              <el-button type="danger" @click="onSubmit">重置</el-button>
+            </el-form-item>
+          </el-form>
+        </div>
+        <el-table stripe style="background-color: rgba(255,0,0,99%);width: 100%" border :data="tableData"
+                  fixed ref="multipleTableRef" :cell-style="{ textAlign: 'center'}" :header-cell-style="{ textAlign: 'center'}">
+          <el-table-column type="selection" width="55"/>
+          <el-table-column prop="equipmentName" label="设备名称"/>
+          <el-table-column prop="equipmentTypeName" label="设备类型"/>
+          <el-table-column prop="mapId" label="地图id"/>
+          <el-table-column prop="originalPgm" label="原始pgm"/>
+          <el-table-column prop="updateTime" label="地图更新时间"/>
+          <el-table-column prop="cumulativeUpdateRate" label="累积地图更新率"/>
+          <el-table-column prop="currentPgm" label="当前pgm"/>
+        </el-table>
+
+        <p></p> <!--空行-->
+        <el-pagination
+            v-model:current-page="currentPage"
+            v-model:page-size="pageSize"
+            :page-sizes="[10]"
+            :small="small"
+            :disabled="disabled"
+            :background="true"
+            layout="total, sizes, prev, pager, next, jumper"
+            :total="total"
+            @size-change="handleSizeChange"
+            @current-change="handleCurrentChange"
+        />
+        <!--        <el-pagination background layout="prev, pager, next" :total="1000"/>-->
+      </el-main>
+      <!--      <el-footer style="background-color: rgba(255,0,0,99%)">国家智能网联汽车创新中心</el-footer>-->
+    </el-container>
+  </div>
+</template>
+
+<script lang="ts" setup>
+import {onBeforeMount, ref} from "vue";
+import axios from "axios";
+import {reactive} from 'vue'
+import {ElTable} from "element-plus";
+import {useRouter} from 'vue-router'; // 导入 Vue Router 的 useRouter 钩子
+
+
+const value = ref(true)
+const router = useRouter();
+const algorithmContainerState = ref(false)
+const gazeboState = ref(false)
+const rvizState = ref(false)
+const multipleTableRef = ref<InstanceType<typeof ElTable>>
+
+const dialogVisible = ref(false)
+
+const handleClose = (done: () => void) => {
+  done()
+}
+
+// do not use same name with ref
+const form = reactive({
+  sudoPassword: '',
+  tag: '',
+  // date1: '',
+  // date2: '',
+  // delivery: false,
+  // type: [],
+  // resource: '',
+  // desc: '',
+})
+const currentTag = ref('')
+
+
+const algorithmImport = async () => {
+  dialogVisible.value = false
+  try {
+    const result = await window.electronAPI.openFileManager();
+    console.log('用户选择的文件路径为:', result, ',版本为:', form.tag);
+    window.electronAPI.dockerImport(form.sudoPassword, result, form.tag)
+  } catch (error) {
+    console.error('打开文件管理器时出错:', error);
+  }
+};
+
+const goToDetail = () => {
+  router.push('/about')
+}
+
+const goToMapUpdate = () => {
+  router.push('/map_update')
+}
+
+
+// 数据容量单位从B转成MB
+const dataSizeFormatter = (row, column, cellValue, index) => {
+  // 假设 1MB = 1024 * 1024 字节
+  if (cellValue) {
+    const mb = (cellValue / (1024 * 1024)).toFixed(2); // 保留两位小数
+    return `${mb}MB`;
+  }
+  return cellValue; // 如果cellValue为null或undefined,则返回原值或你想要的默认值
+}
+
+const gazebo = () => {
+  if (gazeboState.value) {
+    if (window.electronAPI) {
+      window.electronAPI.openGazebo(); // 关闭 gazebo
+    } else {
+      console.error('electronAPI is not defined');
+    }
+    // gazeboState.value = false
+  } else {
+    if (window.electronAPI) {
+      window.electronAPI.closeGazebo();
+    } else {
+      console.error('electronAPI is not defined');
+    }
+    // gazeboState.value = true
+  }
+}
+
+const rviz = () => {
+  if (rvizState.value) {
+    if (window.electronAPI) {
+      window.electronAPI.openRviz();
+    } else {
+      console.error('electronAPI is not defined');
+    }
+  } else {
+    if (window.electronAPI) {
+      window.electronAPI.closeRviz();
+    } else {
+      console.error('electronAPI is not defined');
+    }
+  }
+}
+
+
+const downloadPdf = (index: number, row: any) => {
+  console.log(index, row)
+  axios.post('http://36.110.106.142:12341/web_server/exam/report',
+      {
+        "id": row.id,
+        "teamName": row.teamName,
+        "scoreOnline": row.scoreOnline,
+        "beginTime": row.beginTime,
+        "endTime": row.endTime
+      },
+      {
+        headers: {
+          "Authorization": "U9yKpD6kZZDDe4LFKK6myAxBUT1XRrDM"
+        },
+        responseType: 'blob' // 设置响应类型为二进制流
+      }
+  ).then(function (response) {
+    const url = window.URL.createObjectURL(new Blob([response.data]));
+    const link = document.createElement('a');
+    link.href = url;
+    link.setAttribute('download', row.topic + "-" + row.teamName + "-评分报告.pdf"); // 设置下载的文件名
+    document.body.appendChild(link);
+    link.click();
+  }).catch(function (error) {
+    console.log(error);
+  });
+}
+
+
+const openPdf = (index: number, row: any) => {
+  console.log(index, row)
+  axios.post('http://36.110.106.142:12341/web_server/exam/report',
+      {
+        "id": row.id,
+        "teamName": row.teamName,
+        "scoreOnline": row.scoreOnline,
+        "beginTime": row.beginTime,
+        "endTime": row.endTime
+      },
+      {
+        headers: {
+          "Authorization": "U9yKpD6kZZDDe4LFKK6myAxBUT1XRrDM"
+        },
+        responseType: 'blob' // 设置响应类型为二进制流
+      }
+  ).then(function (response) {
+    const url = window.URL.createObjectURL(new Blob([response.data], {type: 'application/pdf'}));
+    window.open(url, '_blank');
+  }).catch(function (error) {
+    console.log(error);
+  });
+}
+
+
+const queryLine = reactive({
+  dataName: '',
+  equipmentName: '',
+  equipmentTypeName: '',
+  triggerName: '',
+  triggerTypeName: '',
+})
+
+const onSubmit = () => {
+  page()
+}
+
+let total = ref(0)
+let tableData = ref([]);
+onBeforeMount(() => {
+  page()
+})
+
+function page() {
+  axios.get('http://1.202.169.139:8081/open/scene/list?page=' + currentPage.value + '&size=' + pageSize.value,
+      {
+        headers: {
+          "Authorization": "4773hd92ysj54paflw2jem3onyhywxt2"
+        }
+      }
+  ).then(function (response) {
+    tableData.value = response.data.data.content
+    total.value = response.data.data.totalElements
+    // total.value = tableData.value.length
+    // console.log(tableData);
+    // console.log(response.data.data);
+  }).catch(function (error) {
+    console.log(error);
+  });
+}
+
+const currentPage = ref(1)
+const pageSize = ref(10)
+const small = ref(false)
+const disabled = ref(false)
+
+const handleSizeChange = (val: number) => {
+  pageSize.value = val
+  page()
+  if (tableData.value.length == 0) {
+    page()
+  }
+}
+const handleCurrentChange = (val: number) => {
+  currentPage.value = val
+  page()
+}
+const handleClick = () => {
+  console.log('click')
+}
+
+
+</script>
+<style scoped>
+
+.demo-pagination-block + .demo-pagination-block {
+  margin-top: 10px;
+}
+
+.demo-pagination-block .demonstration {
+  margin-bottom: 16px;
+}
+
+
+.demo-form-inline .el-input {
+  --el-input-width: 200px;
+}
+
+.demo-form-inline .el-select {
+  --el-select-width: 400px;
+}
+
+.demo-image .block {
+  padding: 30px 0;
+  text-align: center;
+  border-right: solid 1px var(--el-border-color);
+  display: inline-block;
+  width: 20%;
+  box-sizing: border-box;
+  vertical-align: top;
+}
+
+.demo-image .block:last-child {
+  border-right: none;
+}
+
+.demo-image .demonstration {
+  display: block;
+  color: var(--el-text-color-secondary);
+  font-size: 14px;
+  margin-bottom: 20px;
+}
+
+.topbar {
+  margin-bottom: 15px;
+}
+
+/* 假设 .el-pager__item 是分页按钮的类名,这可能需要你根据实际的 Element UI 版本和源码进行调整 */
+.el-pager__item {
+  background-color: rgba(255, 0, 0, 50%) !important; /* 修改背景色 */
+  color: #fff; /* 可能需要修改文本颜色以在红色背景上可见 */
+  border-color: transparent; /* 如果需要,修改边框颜色 */
+}
+
+/* 修改当前选中页码的按钮样式 */
+.el-pager__item.is-active {
+  background-color: rgba(255, 0, 0, 70%) !important; /* 选中时的背景色 */
+  color: #fff; /* 选中时的文本颜色 */
+}
+</style>