无人机管理后台前端(已迁走)
罗广辉
2025-09-13 634ee52cd4997cd50688ef5eda6c2cc86ea03cb4
Merge branch 'feature/v6.0/6.0.1' into prod
8 files modified
177 ■■■■■ changed files
src/api/device/device.js 8 ●●●●● patch | view | raw | blame | history
src/api/home/aggregation.js 14 ●●●● patch | view | raw | blame | history
src/api/job/task.js 8 ●●●● patch | view | raw | blame | history
src/utils/cesium/createRouteLine.js 35 ●●●●● patch | view | raw | blame | history
src/views/device/airport.vue 57 ●●●● patch | view | raw | blame | history
src/views/device/components/devicePerShare.vue 44 ●●●● patch | view | raw | blame | history
src/views/job/components/TaskIntermediateContent/TaskIntermediateContent.vue 9 ●●●● patch | view | raw | blame | history
src/views/job/components/TaskTop/TaskIndustry.vue 2 ●●● patch | view | raw | blame | history
src/api/device/device.js
@@ -159,4 +159,12 @@
    method: 'post',
    data: param
  })
}
export const devicesUpAndDown = (param) => {
  return request({
    url: `/drone-device-core/manage/api/v1/devices/upAndDown`,
    method: 'post',
    data: param
  })
}
src/api/home/aggregation.js
@@ -8,19 +8,11 @@
    })
}
export const getDeviceRegion = params => {
export const getDeviceRegion = data => {
    return request({
        url: '/drone-device-core/manage/api/v1/devices/getDeviceRegion',
        method: 'get',
        params,
    })
}
export const getDeviceRegionByPost = data => {
    return request({
        url: '/drone-device-core/manage/api/v1/devices/getDeviceRegion',
        method: 'post',
        data,
    method: 'post',
    data:{ hidden_flag:0, ...data },
    })
}
src/api/job/task.js
@@ -190,11 +190,11 @@
    })
}
export const getDeviceRegion = params => {
export const getDeviceRegion = data => {
    return request({
        url: '/drone-device-core/manage/api/v1/devices/getDeviceRegion',
        method: 'get',
        params,
        method: 'post',
        data:{ hidden_flag:0, ...data },
    })
}
@@ -255,4 +255,4 @@
        method: 'post',
        data: data,
    })
}
}
src/utils/cesium/createRouteLine.js
@@ -36,6 +36,34 @@
    speed: 5
})
let arrowLineMaterialPropertyOrange = new ArrowLineMaterialProperty({
    color: new Cesium.Color(255 / 255, 185 / 255, 58 / 255, 1),
    directionColor: new Cesium.Color(1, 1, 1, 1),
    outlineColor: new Cesium.Color(1, 1, 1, 1),
    outlineWidth: 0,
    speed: 5,
})
let arrowLineMaterialPropertyGreen = new ArrowLineMaterialProperty({
    color: new Cesium.Color(6 / 255, 217 / 255, 87 / 255, 1),
    directionColor: new Cesium.Color(1, 1, 1, 1),
    outlineColor: new Cesium.Color(1, 1, 1, 1),
    outlineWidth: 0,
    speed: 5,
})
// 记录index
let indexLog = 0
// 颜色
function getLineColor(lineNumber) {
    // 颜色顺序: 蓝(0), 黄(1), 绿(2)
    const colors = [arrowLineMaterialProperty, arrowLineMaterialPropertyOrange, arrowLineMaterialPropertyGreen]
    // 计算颜色索引 (从0开始)
    const colorIndex = (lineNumber - 1) % 3
    // 返回对应颜色
    return colors[colorIndex]
}
let runningLineMaterial = new LineTrailMaterial({
    color: Cesium.Color.fromCssColorString('#1FFF69'),
    opacity: 1,
@@ -94,6 +122,7 @@
     * @param {*} viewer 
     */
    initCreateRoute (viewer) {
        indexLog = 0
        this.viewer = viewer
    }
@@ -469,7 +498,7 @@
     */
    async drawPointRoute (lineObj, missionConfig, dronePosition, data, startPoint, isShowDock, isShowPointBillboard, wayline_type) {
        const { positionArray, filePositions } = this.disposeData(lineObj, missionConfig, dronePosition, data, startPoint, wayline_type)
        const droneTransformPosition = Cesium.Cartesian3.fromDegrees(
            Number(dronePosition.longitude),
            Number(dronePosition.latitude),
@@ -478,6 +507,7 @@
        // 路径线
        let polyline
        if (this.type === 'clusterScheduling') {
            filePositions.forEach((item, index) => {
@@ -630,7 +660,7 @@
                polyline: {
                    width: 4,
                    positions: positionArray,
                    material: arrowLineMaterialProperty,
                    material: getLineColor(indexLog),
                    clampToGround: false,
                },
@@ -681,6 +711,7 @@
     * @returns {} {positionArray: 带拼接点位置, filePositions:光航线点位置}
     */
    disposeData (lineObj, missionConfig, dronePosition, data, startPoint, wayline_type) {
        indexLog = indexLog + 1
        const { device_sn } = data
        const executeHeightMode = lineObj.executeHeightMode === "WGS84"
src/views/device/airport.vue
@@ -57,7 +57,7 @@
      </template>
      <template #menu="scope">
        <el-dropdown>
              <el-button type="primary" text icon="el-icon-folder-opened" v-if="permission.oss_set">更 多</el-button>
          <el-button type="primary" text v-if="permission.oss_set"><el-icon><MoreFilled /></el-icon>更多</el-button>
              <template #dropdown v-if="scope.row.domain == 3">
                <el-dropdown-menu teleported>
                  <el-dropdown-item command="a">
@@ -126,11 +126,12 @@
      <el-input v-model="operate_password" disabled></el-input>
    </el-dialog>
    <el-dialog title="注销" append-to-body v-model="cancenOperate" width="460px">
      <div style="display: flex;justify-content: end;">注销 <span style="color:cornflowerblue;">{{ cancelSNName }}</span> 设备可能会影响相关数据,确认注销吗?</div>
      <div style="display: flex;justify-content: end;">
        <div><el-checkbox v-model="deleteFlag"></el-checkbox>删除相关图片、视频、事件</div>
      </div>
    <el-dialog title="注销" class="zx-cancel" append-to-body v-model="cancenOperate" width="460px">
      <div style="display: flex;justify-content: center;margin-bottom: 10px;">注销
        <span style="color:cornflowerblue;font-weight: bolder;margin: 0px 4px;">
          {{ cancelSNName }}
        </span> 设备可能会影响相关数据,确认注销吗?</div>
        <div style="display: flex;justify-content: center;color:red;font-size: 12px;">*删除相关图片、视频、事件</div>
      <template #footer>
        <span class="dialog-footer" style="display: flex;justify-content: center;">
          <el-button @click="cancenOperate = false">取 消</el-button>
@@ -211,7 +212,8 @@
  getDeviceFirmwareList,
  getDevices,
  deviceOffline,
  devicesUpdate
  devicesUpdate,
  devicesUpAndDown
} from '@/api/device/device'
import { deleteByOssId, addOrUpdate as addOrUpdateOssBind } from '@/api/device/ossBind'
import { getListPage as getOssList } from '@/api/resource/oss'
@@ -247,6 +249,7 @@
      }
    }
    return {
      treeResolveMap: new Map(),
      rules: {
        password: [{ required: true, validator: validatePass, trigger: 'blur' }],
        password2: [{ required: true, validator: validatePass2, trigger: 'blur' }],
@@ -532,7 +535,7 @@
            endPlaceholder: '保险结束日期',
            rules: [
              {
                required: true,
                required: false,
                message: '请选择保险有效期',
                trigger: 'blur',
              },
@@ -850,6 +853,7 @@
    },
  },
  destroyed () {
    this.treeResolveMap.clear()
    this.websocketMap.forEach((k, v) => {
      if (null != v) {
        v.close()
@@ -963,10 +967,9 @@
    },
    cancenOperateDo () {
      console.log('333')
      this.cancenOperate = false
      this.deleteFlag = false
      deviceOffline(this.cancenOperateRow.device_sn, this.deleteFlag).then(res => {
      deviceOffline(this.cancenOperateRow.device_sn, true).then(res => {
        ElMessage.success('注销成功')
        
        this.init()
@@ -1009,7 +1012,7 @@
      })
        .then(() => {
          let hidden_flag = row.hidden_flag === 1?0:1
          devicesUpdate({id:row.id, hiddenFlag:hidden_flag})
          devicesUpAndDown({id:row.id, hiddenFlag:hidden_flag})
            .then(res => {
              ElMessage.success(`${txt}成功`)
              this.init()
@@ -1295,8 +1298,8 @@
      const submitData = {
        ...row,
        area_code: row.area_code.split(',').pop(),
        insure_start_time: row.duration_of_insurance[0],
        insure_expired_time: row.duration_of_insurance[1],
        insure_start_time: row.duration_of_insurance[0] || null,
        insure_expired_time: row.duration_of_insurance[1] || null,
        deptId: row.dept_id,
        areaCode: row.area_code.split(',').pop(),
      }
@@ -1307,7 +1310,25 @@
      update(submitData).then(
        () => {
          this.onLoad(this.page)
          if (row.domain === 0) {
            // 获取保存的 resolve 函数
            const resolve = this.treeResolveMap.get(row.device_sn)
            if (resolve) {
              // 重新加载子节点数据
              var params = {
                childSn: row.device_sn,
              }
              getList(1, 10, params).then(res => {
                const data = res.data.data.records
                data.forEach(e => {
                  e.duration_of_insurance = [e.insure_start_time || '', e.insure_expired_time || '']
                })
                resolve(data)
              })
            }
          } else {
            this.onLoad(this.page)
          }
          this.$message({
            type: 'success',
            message: '操作成功!',
@@ -1459,6 +1480,8 @@
      })
    },
    treeLoad (tree, treeNode, resolve) {
      // 保存resolve
      this.treeResolveMap.set(tree.child_sn, resolve)
      var params = {
        childSn: tree.child_sn,
      }
@@ -1605,5 +1628,11 @@
  right: 0;
}
:deep(.avue-crud__pagination) {
  position: fixed;
  bottom: 10px;
  right: 30px;
}
</style>
src/views/device/components/devicePerShare.vue
@@ -89,28 +89,28 @@
              },
            ],
          },
          {
            label: '授权功能',
            prop: 'devicePerMenuId',
            labelWidth: 130,
            type: 'tree',
            dicUrl: '/blade-system/manage/api/v1/devicePerMenu/selectDeviceList',
            props: {
              label: 'name',
              value: 'id',
            },
            multiple: true,
            dataType: 'string',
            span: 24,
            row: true,
            rules: [
              {
                required: true,
                message: '请输入授权功能',
                trigger: 'blur',
              },
            ],
          },
          // {
          //   label: '授权功能',
          //   prop: 'devicePerMenuId',
          //   labelWidth: 130,
          //   type: 'tree',
          //   dicUrl: '/blade-system/manage/api/v1/devicePerMenu/selectDeviceList',
          //   props: {
          //     label: 'name',
          //     value: 'id',
          //   },
          //   multiple: true,
          //   dataType: 'string',
          //   span: 24,
          //   row: true,
          //   rules: [
          //     {
          //       required: true,
          //       message: '请输入授权功能',
          //       trigger: 'blur',
          //     },
          //   ],
          // },
          {
            label: '授权时间',
            prop: 'createTime',
src/views/job/components/TaskIntermediateContent/TaskIntermediateContent.vue
@@ -169,9 +169,14 @@
const jobId = ref('')
const handleDetail = row => {
    if (!row.device_sns.length) return ElMessage.warning('没有device_sns')
    if (row.device_sns.length !== 1) return ElMessage.success('即将跳转到集群调度')
    rowData.value = row ? row : {}
jobId.value = rowData.value?.job_id
    if (row.device_sns.length > 1 && (row.status === 2 || row.status === 1)) {
        const adminUrl = `${import.meta.env.VITE_APP_AREA_NAME}/command-center-dashboard/#/clusterScheduling`
        const targetPath = `taskNo=${encodeURIComponent(rowData.value.job_info_num)}`
        window.open(`${adminUrl}?${targetPath}`, '_blank')
        return
    }
    jobId.value = rowData.value?.job_id
    if (row.status === 2 || row.status === 1) {
        // isShowCurrentTaskDetails.value = true
        // 跳转大屏当前任务详情
src/views/job/components/TaskTop/TaskIndustry.vue
@@ -1,7 +1,7 @@
<!-- 任务算法统计 -->
<template>
    <div class="task-industry">
        <div class="title">机巢事件前五数量占比</div>
        <div class="title">机巢事件数量占比</div>
        <div class="chart" ref="chartRef"></div>
    </div>
</template>