Quellcode durchsuchen

Merge remote-tracking branch 'origin/dev' into dev

# Conflicts:
#	src/views/globalMap/RightMenu/Helicopter.vue
#	src/views/globalMap/RightMenu/MobileUnmannedVehicle.vue
yangyuxuan vor 5 Monaten
Ursprung
Commit
e9b47cffa7

+ 17 - 12
src/components/HKVideo/index.vue

@@ -15,7 +15,7 @@
           <div class="err_inner_box">
             <div class="err_icon"></div>
             <div class="err_text">视频解析错误</div>
-            <div class="refresh_btn" @click="play_now">刷新</div>
+            <div class="refresh_btn" @click="play">刷新</div>
           </div>
         </div>
       </div>
@@ -88,7 +88,7 @@ watch(
     nextTick(() => {
       if (props.autoplay) {
         reload.value = false;
-        play_now();
+        play_now(true);
       }
     });
   },
@@ -96,16 +96,21 @@ watch(
     deep: true
   }
 );
-const play_now = async () => {
-  console.log('play_now');
+const play_now = async (check?: boolean) => {
   posterVisible.value = false;
-  errBKVisible.value = false;
-  isPlaying.value = true;
-  // 视频监控数据
-  getVideoUrlById(props.dot_data.video_code).then((res) => {
-    wsUrl.value = res.data;
-    videoPlayer.value.play(wsUrl.value);
-  });
+  // if (check === true && props.dot_data.status === '离线') {
+  //   errBKVisible.value = true;
+  //   isPlaying.value = false;
+  // } else {
+    errBKVisible.value = false;
+    isPlaying.value = true;
+    // 视频监控数据
+    getVideoUrlById(props.dot_data.video_code).then((res) => {
+      wsUrl.value = res.data;
+      videoPlayer.value.play(wsUrl.value);
+    });
+  // }
+  console.log('play_now');
 };
 
 const stop_now = async () => {
@@ -130,7 +135,7 @@ defineExpose({
 });
 onMounted(() => {
   if (!!props.autoplay) {
-    play_now();
+    play_now(true);
   }
 });
 </script>

+ 17 - 0
src/types/components.d.ts

@@ -21,6 +21,7 @@ declare module 'vue' {
     ElBreadcrumb: typeof import('element-plus/es')['ElBreadcrumb']
     ElBreadcrumbItem: typeof import('element-plus/es')['ElBreadcrumbItem']
     ElButton: typeof import('element-plus/es')['ElButton']
+    ElCard: typeof import('element-plus/es')['ElCard']
     ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
     ElCol: typeof import('element-plus/es')['ElCol']
     ElColorPicker: typeof import('element-plus/es')['ElColorPicker']
@@ -37,20 +38,34 @@ declare module 'vue' {
     ElIcon: typeof import('element-plus/es')['ElIcon']
     ElImage: typeof import('element-plus/es')['ElImage']
     ElInput: typeof import('element-plus/es')['ElInput']
+    ElLink: typeof import('element-plus/es')['ElLink']
     ElMenu: typeof import('element-plus/es')['ElMenu']
     ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
     ElOption: typeof import('element-plus/es')['ElOption']
     ElPagination: typeof import('element-plus/es')['ElPagination']
+    ElPopover: typeof import('element-plus/es')['ElPopover']
+    ElRadio: typeof import('element-plus/es')['ElRadio']
+    ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
     ElRow: typeof import('element-plus/es')['ElRow']
     ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
     ElSelect: typeof import('element-plus/es')['ElSelect']
+    ElSkeleton: typeof import('element-plus/es')['ElSkeleton']
+    ElSkeletonItem: typeof import('element-plus/es')['ElSkeletonItem']
     ElSlider: typeof import('element-plus/es')['ElSlider']
+    ElStep: typeof import('element-plus/es')['ElStep']
+    ElSteps: typeof import('element-plus/es')['ElSteps']
     ElSubMenu: typeof import('element-plus/es')['ElSubMenu']
     ElSwitch: typeof import('element-plus/es')['ElSwitch']
+    ElTable: typeof import('element-plus/es')['ElTable']
+    ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
+    ElTabPane: typeof import('element-plus/es')['ElTabPane']
+    ElTabs: typeof import('element-plus/es')['ElTabs']
     ElText: typeof import('element-plus/es')['ElText']
     ElTimeline: typeof import('element-plus/es')['ElTimeline']
     ElTimelineItem: typeof import('element-plus/es')['ElTimelineItem']
+    ElTooltip: typeof import('element-plus/es')['ElTooltip']
     ElTree: typeof import('element-plus/es')['ElTree']
+    ElTreeSelect: typeof import('element-plus/es')['ElTreeSelect']
     ElUpload: typeof import('element-plus/es')['ElUpload']
     FileUpload: typeof import('./../components/FileUpload/index.vue')['default']
     FooterSection: typeof import('./../components/FooterSection/index.vue')['default']
@@ -61,6 +76,7 @@ declare module 'vue' {
     HikvisionPlayer: typeof import('./../components/HKVideo/hikvision-player.vue')['default']
     HKVideo: typeof import('./../components/HKVideo/index.vue')['default']
     IconSelect: typeof import('./../components/IconSelect/index.vue')['default']
+    IEpUploadFilled: typeof import('~icons/ep/upload-filled')['default']
     IFrame: typeof import('./../components/iFrame/index.vue')['default']
     ImagePreview: typeof import('./../components/ImagePreview/index.vue')['default']
     ImageUpload: typeof import('./../components/ImageUpload/index.vue')['default']
@@ -98,6 +114,7 @@ declare module 'vue' {
     VideoContainer2: typeof import('./../components/HKVideo/video-container2.vue')['default']
     VideoTagEdit: typeof import('./../components/VideoTagEdit/index.vue')['default']
     YMap: typeof import('./../components/Map/YMap.vue')['default']
+    YMapold: typeof import('./../components/Map/YMapold.vue')['default']
     YztMap: typeof import('./../components/Map/YztMap/index.vue')['default']
   }
   export interface ComponentCustomProperties {

+ 2 - 1
src/utils/index.ts

@@ -378,7 +378,8 @@ export const getRgba = (rgbaString) => {
   };
 };
 
-export const hexToRgba = (hex, alpha) => {
+export const hexToRgba = (hex, alpha = 1) => {
+  if (!hex) return '';
   // 确保输入是一个有效的十六进制颜色值,并以 # 开头
   hex = hex.replace(/^#/, '');
   // 如果十六进制颜色值是3位的简写形式(如 #f80),则扩展为6位

+ 56 - 67
src/utils/olMap/olMap.ts

@@ -94,6 +94,9 @@ export class olMap {
   // 自定义绘制结束调用方法
   private drawEndMethod;
   private selectedFeature;
+  private drawing;
+  private path;
+  private anyLine;
 
   constructor(options) {
     this.options = options;
@@ -357,7 +360,8 @@ export class olMap {
         }
         this.closeDraw();
         if (newOptions.graphicsType === 'anyLine') {
-          this.drawAnyLine();
+          this.drawOptions.fillOpacity = 0;
+          this.drawAnyLine(this.drawOptions);
         } else {
           // 创建绘制交互
           let style = new Style({
@@ -485,74 +489,59 @@ export class olMap {
     data.id = id;
     return { text, data };
   }
-  drawAnyLine() {
-    document.addEventListener('touchend', this.handleTouchEnd);
-    this.map.on('pointerdown', this.handleTouchStart);
-    this.map.on('pointermove', this.handleTouchMove.bind(null, this.options));
-    document.addEventListener('mouseup', this.handleTouchEnd.bind(null, this.options));
-  }
-  handleTouchStart(e) {
-    this.drawing = true;
-    const interactions = this.map.getInteractions();
-    interactions.forEach((interaction) => {
-      if (interaction instanceof DragPan || interaction instanceof DoubleClickZoom) {
-        interaction.setActive(false); // 修改为需要的值,true或false
-      }
-    });
+  drawAnyLine(drawOptions) {
+    const handleTouchStart = (e) => {
+      this.drawing = true;
+      const interactions = this.map.getInteractions();
+      interactions.forEach((interaction) => {
+        if (interaction instanceof DragPan || interaction instanceof DoubleClickZoom) {
+          interaction.setActive(false); // 修改为需要的值,true或false
+        }
+      });
 
-    this.path = [e.lnglat];
-    // if (this.anyLine) {
-    //   map.remove(anyLine);
-    // }
-  }
-  handleTouchMove(options, e) {
-    if (!this.drawing) return;
-    this.path.push(e.lnglat);
-    // if (anyLine) {
-    //   map.remove(anyLine);
-    // }
-    this.anyLine = new Feature({
-      geometry: new LineString(this.path) // path为坐标数组,如[[x1,y1], [x2,y2]]
-    });
-    const lineStyle = new Style({
-      stroke: new Stroke({
-        color: hexToRgba(options.strokeColor, options.strokeOpacity), // 合并颜色与透明度
-        width: options.strokeWeight,
-        lineJoin: 'round' // 线段连接处圆角
-      })
-    });
-    this.anyLine.setStyle(lineStyle);
-    //   new AMap.Polyline({
-    //   path: path,
-    //   strokeColor: options.strokeColor,
-    //   strokeOpacity: options.strokeOpacity,
-    //   strokeWeight: options.strokeWeight,
-    //   strokeStyle: options.strokeStyle,
-    //   lineJoin: 'round'
-    // });
-    this.drawVector.getSource().addFeature(this.anyLine);
-  }
-  handleTouchEnd(options) {
-    // drawing = false;
-    // map.setStatus({
-    //   showIndoorMap: true,
-    //   dragEnable: true,
-    //   keyboardEnable: true,
-    //   doubleClickZoom: true,
-    //   zoomEnable: true,
-    //   rotateEnable: true
-    // });
-    // map.off('touchstart', handleTouchStart);
-    // map.on('touchmove', handleTouchMove.bind(null, options));
-    // document.addEventListener('touchend', handleTouchEnd.bind(null, options));
-    // map.off('mousedown', handleTouchStart);
-    // map.off('mousemove', handleTouchMove);
-    // document.removeEventListener('mouseup', handleTouchEnd);
-    // if (!!drawEndMethod) {
-    //   drawEndMethod(options, anyLine);
-    // }
-    // anyLine = null;
+      this.path = [e.coordinate];
+      // 移除旧的线段
+      if (this.anyLine) {
+        this.drawVector.getSource().removeFeature(this.anyLine);
+      }
+    };
+    const handleTouchMove = (e) => {
+      if (!this.drawing) return;
+      this.path.push(e.coordinate);
+      // 移除旧的线段
+      if (this.anyLine) {
+        this.drawVector.getSource().removeFeature(this.anyLine);
+      }
+      this.anyLine = new Feature({
+        geometry: new LineString(this.path)
+      });
+      const lineStyle = new Style({
+        stroke: new Stroke({
+          color: hexToRgba(this.drawOptions.strokeColor, this.drawOptions.strokeOpacity), // 合并颜色与透明度
+          width: this.drawOptions.strokeWeight,
+          lineJoin: 'round' // 线段连接处圆角
+        })
+      });
+      this.anyLine.setStyle(lineStyle);
+      this.drawVector.getSource().addFeature(this.anyLine);
+    };
+    const handleTouchEnd = () => {
+      this.drawing = false;
+      document.removeEventListener('touchend', handleTouchEnd);
+      this.map.un('pointerdown', handleTouchStart);
+      this.map.un('pointermove', handleTouchMove);
+      document.removeEventListener('mouseup', handleTouchEnd);
+      if (!!this.drawEndMethod) {
+        this.drawEndMethod(drawOptions, this.anyLine);
+      }
+      this.anyLine = null;
+    };
+    document.addEventListener('touchend', handleTouchEnd);
+    this.map.on('pointerdown', handleTouchStart);
+    this.map.on('pointermove', handleTouchMove);
+    document.addEventListener('mouseup', handleTouchEnd);
   }
+
   // 关闭绘制
   closeDraw() {
     if (!this.drawTool) return;

+ 0 - 2
src/views/emergencyCommandMap/LeftSection/VideoMonitorEdit.vue

@@ -12,10 +12,8 @@
               class="custom-select"
               popper-class="custom-select-popper"
               :teleported="false"
-              placeholder="全部"
               style="width: 450px"
             >
-              <el-option label="全部" value="" />
               <el-option v-for="item in video_type" :key="item.value" :label="item.label" :value="item.value" />
             </el-select>
           </el-form-item>

+ 86 - 16
src/views/globalMap/RightMenu/Helicopter.vue

@@ -18,15 +18,26 @@
 <!--        <div class="td" style="width: 220px; flex: unset">操作</div>-->
       </div>
       <div class="table-content">
-        <div v-for="(item, index) in dataList" :key="item.id" class="tr">
+        <div v-for="item in dataList" :key="item.id" class="tr">
           <div class="td">{{ item.helicopter_name }}</div>
 <!--          <div class="td" style="width: 220px; flex: unset">-->
-<!--            <div class="text" @click="handleConnect(index, item)">连线</div>-->
+<!--            <div class="text" @click="handleConnect">连线</div>-->
 <!--            &lt;!&ndash;            <div class="text" @click="handleCollaborate(index, item)">协同</div>&ndash;&gt;-->
 <!--            <div class="text" @click="handleTrack(item)">轨迹</div>-->
 <!--          </div>-->
         </div>
       </div>
+      <div class="footer">
+        <el-pagination
+          background
+          :hide-on-single-page="true"
+          layout="total, prev, pager, next"
+          :total="total"
+          :page-size="queryParams.size"
+          :current-current="queryParams.current"
+          @current-change="handleChangePage"
+        />
+      </div>
     </div>
   </div>
 </template>
@@ -34,34 +45,40 @@
 <script setup lang="ts">
 import { Search } from '@element-plus/icons-vue';
 import { onMounted, reactive } from 'vue';
-import { getHelicopterList, getHelicopterTrajectory } from "@/api/globalMap/Helicopter";
+import { getHelicopterList, getHelicopterTrajectory } from '@/api/globalMap/Helicopter';
 const trackPlayback = inject('trackPlayback');
 // 数据列表,直接定义为数组
-const dataList = reactive([]);
+const dataList = ref([]);
 //入参
 const queryParams = reactive({
+  current: 1,
+  size: 10,
   keywords: ''
 });
+const total = ref(0);
 //调接口
 const initData = () => {
   getHelicopterList({
+    current: queryParams.current,
+    size: queryParams.size,
     query: {
       keywords: queryParams.keywords
     }
   }).then((res) => {
-    if (res.code === 0 && Array.isArray(res.rows)) {
-      dataList.splice(0, dataList.length, ...res.rows); // 使用 splice 替换数组内容,保持响应性
-    } else {
-      console.error('Invalid response from server:', res);
-      // 可以选择清空数据列表或显示错误消息
-      dataList.splice(0, dataList.length); // 清空数据列表
-    }
+    dataList.value = res.rows;
+    total.value = res.total;
   });
 };
 
+const handleChangePage = (newNum) => {
+  queryParams.current = newNum;
+  initData();
+};
+
 // 取消按钮的逻辑,搜索框清空并重新加载数据
 const handleCancel = () => {
   queryParams.keywords = '';
+  queryParams.current = 1;
   initData();
 };
 const handleConnect = () => {};
@@ -125,13 +142,12 @@ onMounted(() => {
 
 .custom-table {
   width: 100%;
-  height: 1030px;
-  overflow-y: auto;
-  overflow-x: hidden;
+  height: 1120px;
+  display: flex;
+  flex-direction: column;
   .table-content {
-    height: 880px;
+    flex: 1;
     overflow-y: auto;
-    overflow-x: hidden;
   }
   .th {
     width: 100%;
@@ -203,4 +219,58 @@ onMounted(() => {
   font-size: 32px; /* 根据需要设置字体大小 */
   line-height: 1; /* 确保行高一致 */
 }
+
+.footer {
+  height: 64px;
+  display: flex;
+  justify-content: flex-end;
+  margin-top: 25px;
+  .pagination-container {
+    height: 64px;
+    margin: 0;
+  }
+  :deep(.el-pagination__total) {
+    color: #a7ccdf;
+    font-size: 32px;
+  }
+  :deep(.el-pagination) {
+    .btn-next,
+    .btn-prev {
+      background-color: transparent;
+      border: none;
+      .el-icon {
+        font-size: 22px;
+        color: #a7ccdf;
+      }
+    }
+    .btn-prev:disabled,
+    .btn-next:disabled {
+      background-color: transparent;
+      border: none;
+    }
+    .el-pager li {
+      width: 64px;
+      height: 64px;
+      line-height: 64px;
+      text-align: center;
+      font-size: 38px;
+      color: #a7ccdf;
+      background-color: #0e3064;
+      border: 1px solid #0c57a7;
+      margin: 0 6px;
+      &:hover {
+        background-color: #038dff;
+        border: 1px solid #038dff;
+      }
+    }
+    .el-pager li.is-active {
+      background-color: #038dff;
+      border: 1px solid #038dff;
+    }
+    .el-pagination__goto {
+      font-size: 38px;
+      color: #a7ccdf;
+    }
+  }
+}
 </style>

+ 86 - 22
src/views/globalMap/RightMenu/MobileUnmannedVehicle.vue

@@ -14,7 +14,7 @@
     </div>
     <div class="flex-container">
       <div class="text-item">机动无人机</div>
-      <div class="button-item common-btn-primary2 edit-icon" style="margin-top: -20px" @click="showMoreVideos">全部播放</div>
+      <div class="button-item common-btn-primary2 edit-icon" @click="showMoreVideos">全部播放</div>
     </div>
     <div class="custom-table">
       <div class="th">
@@ -22,7 +22,7 @@
 <!--        <div class="td" style="width: 220px; flex: unset">操作</div>-->
       </div>
       <div class="table-content">
-        <div v-for="(item, index) in dataList" :key="item.id" class="tr">
+        <div v-for="item in dataList" :key="item.id" class="tr">
           <div class="td">{{ item.drone_name }}</div>
 <!--          <div class="td" style="width: 220px; flex: unset">-->
 <!--            <div class="text" @click="handleConnect(index, item)">视频</div>-->
@@ -31,6 +31,17 @@
 <!--          </div>-->
         </div>
       </div>
+      <div class="footer">
+        <el-pagination
+          background
+          :hide-on-single-page="true"
+          layout="total, prev, pager, next"
+          :total="total"
+          :page-size="queryParams.size"
+          :current-current="queryParams.current"
+          @current-change="handleChangePage"
+        />
+      </div>
     </div>
   </div>
 </template>
@@ -38,44 +49,44 @@
 <script setup lang="ts">
 import { Search } from '@element-plus/icons-vue';
 import { onMounted, reactive } from 'vue';
-import {
-  getDroneResourcesList,
-  getDroneResourcesTrajectory,
-  getDroneResourcesVideo
-} from "@/api/globalMap/MobileUnmannedVehicle";
+import { getDroneResourcesList, getDroneResourcesTrajectory, getDroneResourcesVideo } from '@/api/globalMap/MobileUnmannedVehicle';
 const getDataMethod = ref(null);
 const showMoreVideos = () => {
   getDataMethod.value = () => getDroneResourcesVideo(id);
 };
-
-
 const trackPlayback = inject('trackPlayback');
 // 数据列表,直接定义为数组
-const dataList = reactive([]);
+const dataList = ref([]);
 //入参
 const queryParams = reactive({
+  current: 1,
+  size: 10,
   keywords: ''
 });
+const total = ref(0);
 //调接口
 const initData = () => {
   getDroneResourcesList({
+    current: queryParams.current,
+    size: queryParams.size,
     query: {
       keywords: queryParams.keywords
     }
   }).then((res) => {
-    if (res.code === 0 && Array.isArray(res.rows)) {
-      dataList.splice(0, dataList.length, ...res.rows); // 使用 splice 替换数组内容,保持响应性
-    } else {
-      console.error('Invalid response from server:', res);
-      // 可以选择清空数据列表或显示错误消息
-      dataList.splice(0, dataList.length); // 清空数据列表
-    }
+    dataList.value = res.rows;
+    total.value = res.total;
   });
 };
 
+const handleChangePage = (newNum) => {
+  queryParams.current = newNum;
+  initData();
+};
+
 // 取消按钮的逻辑,搜索框清空并重新加载数据
 const handleCancel = () => {
   queryParams.keywords = '';
+  queryParams.current = 1;
   initData();
 };
 const handleConnect = () => {};
@@ -139,13 +150,12 @@ onMounted(() => {
 
 .custom-table {
   width: 100%;
-  height: 1030px;
-  overflow-y: auto;
-  overflow-x: hidden;
+  height: 1015px;
+  display: flex;
+  flex-direction: column;
   .table-content {
-    height: 880px;
+    flex: 1;
     overflow-y: auto;
-    overflow-x: hidden;
   }
   .th {
     width: 100%;
@@ -207,6 +217,7 @@ onMounted(() => {
   display: flex;
   justify-content: space-between; /* 左右两端对齐 */
   align-items: center; /* 垂直居中对齐 */
+  margin: 15px 0;
 }
 .text-item {
   font-size: 32px; /* 根据需要设置字体大小 */
@@ -217,4 +228,57 @@ onMounted(() => {
   font-size: 32px; /* 根据需要设置字体大小 */
   line-height: 1; /* 确保行高一致 */
 }
+.footer {
+  height: 64px;
+  display: flex;
+  justify-content: flex-end;
+  margin-top: 25px;
+  .pagination-container {
+    height: 64px;
+    margin: 0;
+  }
+  :deep(.el-pagination__total) {
+    color: #a7ccdf;
+    font-size: 32px;
+  }
+  :deep(.el-pagination) {
+    .btn-next,
+    .btn-prev {
+      background-color: transparent;
+      border: none;
+      .el-icon {
+        font-size: 22px;
+        color: #a7ccdf;
+      }
+    }
+    .btn-prev:disabled,
+    .btn-next:disabled {
+      background-color: transparent;
+      border: none;
+    }
+    .el-pager li {
+      width: 64px;
+      height: 64px;
+      line-height: 64px;
+      text-align: center;
+      font-size: 38px;
+      color: #a7ccdf;
+      background-color: #0e3064;
+      border: 1px solid #0c57a7;
+      margin: 0 6px;
+      &:hover {
+        background-color: #038dff;
+        border: 1px solid #038dff;
+      }
+    }
+    .el-pager li.is-active {
+      background-color: #038dff;
+      border: 1px solid #038dff;
+    }
+    .el-pagination__goto {
+      font-size: 38px;
+      color: #a7ccdf;
+    }
+  }
+}
 </style>

+ 25 - 14
src/views/globalMap/RightMenu/OnlinePlotting/index.vue

@@ -623,20 +623,31 @@ const handleEndDraw = (options, obj) => {
   mouseToolState.value.graphicsType = '';
   drawTool.setDrawEndMethod();
   const id = nanoid();
-  obj._opts.extData = {
-    id: id
-  };
-  const data: any = deepClone(options);
-  data.id = id;
-  if (data.type === 'anyLine') {
-    const path = obj.getPath();
-    // 将AMap.LngLat对象数组转换为经纬度数组
-    const pathArr = path.map((lngLat) => {
-      // 返回经度和纬度的数组
-      return [lngLat.lng, lngLat.lat];
-    });
-    pathArr.push(pathArr[0]);
-    data.path = pathArr;
+  let data;
+  if (AMapType.includes(props.activeMap)) {
+    obj._opts.extData = {
+      id: id
+    };
+    data = deepClone(options);
+    data.id = id;
+    if (data.type === 'anyLine') {
+      const path = obj.getPath();
+      // 将AMap.LngLat对象数组转换为经纬度数组
+      const pathArr = path.map((lngLat) => {
+        // 返回经度和纬度的数组
+        return [lngLat.lng, lngLat.lat];
+      });
+      pathArr.push(pathArr[0]);
+      data.path = pathArr;
+    }
+  } else {
+    obj.set('id', id);
+    data = deepClone(options);
+    data.id = id;
+    if (data.type === 'anyLine') {
+      const path = obj.getGeometry().getCoordinates();
+      data.path = path;
+    }
   }
   overlays.push(obj);
   overlaysData.push(data);

+ 86 - 17
src/views/globalMap/RightMenu/SatellitePhone.vue

@@ -18,16 +18,27 @@
         <div class="td" style="width: 330px; flex: unset">操作</div>
       </div>
       <div class="table-content">
-        <div v-for="(item, index) in dataList" :key="item.id" class="tr">
+        <div v-for="item in dataList" :key="item.id" class="tr">
           <div class="td">{{ item.name }}</div>
           <div class="td">{{ item.unit_name }}</div>
           <div class="td" style="width: 330px; flex: unset">
-            <div class="text" @click="handleConnect(index, item)">连线</div>
-            <div class="text" size="small" @click="handleCollaborate(index, item)">电话</div>
+            <div class="text" @click="handleConnect">连线</div>
+            <div class="text" size="small" @click="handleCollaborate">电话</div>
             <div class="text" size="small" @click="handleTrack(item)">轨迹</div>
           </div>
         </div>
       </div>
+      <div class="footer">
+        <el-pagination
+          background
+          :hide-on-single-page="true"
+          layout="total, prev, pager, next"
+          :total="total"
+          :page-size="queryParams.size"
+          :current-current="queryParams.current"
+          @current-change="handleChangePage"
+        />
+      </div>
     </div>
   </div>
 </template>
@@ -35,38 +46,44 @@
 <script setup lang="ts">
 import { Search } from '@element-plus/icons-vue';
 import { onMounted, reactive } from 'vue';
-import { getSatellitePhoneList, getSatellitePhoneTrajectory } from "@/api/globalMap/SatellitePhone";
+import { getSatellitePhoneList, getSatellitePhoneTrajectory } from '@/api/globalMap/SatellitePhone';
 
 const trackPlayback = inject('trackPlayback');
 
 // 数据列表,直接定义为数组
-const dataList = reactive([]);
+const dataList = ref([]);
 //入参
 const queryParams = reactive({
+  current: 1,
+  size: 10,
   keywords: '',
   unit_name: ''
 });
+const total = ref(0);
 //调接口
 const initData = () => {
   getSatellitePhoneList({
+    current: queryParams.current,
+    size: queryParams.size,
     query: {
       keywords: queryParams.keywords,
       unit_name: queryParams.unit_name
     }
   }).then((res) => {
-    if (res.code === 0 && Array.isArray(res.rows)) {
-      dataList.splice(0, dataList.length, ...res.rows); // 使用 splice 替换数组内容,保持响应性
-    } else {
-      console.error('Invalid response from server:', res);
-      // 可以选择清空数据列表或显示错误消息
-      dataList.splice(0, dataList.length); // 清空数据列表
-    }
+    dataList.value = res.rows;
+    total.value = res.total;
   });
 };
 
+const handleChangePage = (newNum) => {
+  queryParams.current = newNum;
+  initData();
+};
+
 // 取消按钮的逻辑,搜索框清空并重新加载数据
 const handleCancel = () => {
   queryParams.keywords = '';
+  queryParams.current = 1;
   initData();
 };
 
@@ -132,13 +149,12 @@ onMounted(() => {
 
 .custom-table {
   width: 100%;
-  height: 1030px;
-  overflow-y: auto;
-  overflow-x: hidden;
+  height: 1120px;
+  display: flex;
+  flex-direction: column;
   .table-content {
-    height: 880px;
+    flex: 1;
     overflow-y: auto;
-    overflow-x: hidden;
   }
   .th {
     width: 100%;
@@ -195,4 +211,57 @@ onMounted(() => {
     margin-right: 0;
   }
 }
+.footer {
+  height: 64px;
+  display: flex;
+  justify-content: flex-end;
+  margin-top: 25px;
+  .pagination-container {
+    height: 64px;
+    margin: 0;
+  }
+  :deep(.el-pagination__total) {
+    color: #a7ccdf;
+    font-size: 32px;
+  }
+  :deep(.el-pagination) {
+    .btn-next,
+    .btn-prev {
+      background-color: transparent;
+      border: none;
+      .el-icon {
+        font-size: 22px;
+        color: #a7ccdf;
+      }
+    }
+    .btn-prev:disabled,
+    .btn-next:disabled {
+      background-color: transparent;
+      border: none;
+    }
+    .el-pager li {
+      width: 64px;
+      height: 64px;
+      line-height: 64px;
+      text-align: center;
+      font-size: 38px;
+      color: #a7ccdf;
+      background-color: #0e3064;
+      border: 1px solid #0c57a7;
+      margin: 0 6px;
+      &:hover {
+        background-color: #038dff;
+        border: 1px solid #038dff;
+      }
+    }
+    .el-pager li.is-active {
+      background-color: #038dff;
+      border: 1px solid #038dff;
+    }
+    .el-pagination__goto {
+      font-size: 38px;
+      color: #a7ccdf;
+    }
+  }
+}
 </style>