forked from drone/command-center-dashboard

罗广辉
2025-04-07 0c24112327778616cd4e5ce2d98a6a4f9afa9782
feat: 历史任务里面地图
7 files modified
1 files deleted
1 files added
226 ■■■■ changed files
.env 4 ●●●● patch | view | raw | blame | history
package.json 1 ●●●● patch | view | raw | blame | history
pnpm-lock.yaml 70 ●●●●● patch | view | raw | blame | history
src/axios.js 2 ●●● patch | view | raw | blame | history
src/config/env.js 2 ●●●●● patch | view | raw | blame | history
src/main.js 7 ●●●●● patch | view | raw | blame | history
src/utils/cesium-tsa.js 12 ●●●●● patch | view | raw | blame | history
src/views/SignMachineNest/MachineRight/MachineTableDetails/DeviceJob/DeviceJobDetails/DeviceJobDetails.vue 31 ●●●● patch | view | raw | blame | history
src/views/SignMachineNest/MachineRight/MachineTableDetails/DeviceJob/DeviceJobDetails/DeviceJobDetailsMap.vue 97 ●●●●● patch | view | raw | blame | history
.env
@@ -5,3 +5,7 @@
#页面基础路径
VITE_APP_BASE = /command-center-dashboard/
#天地图token
VITE_APP_TDT_TOKEN = c6eea7dad4fa1e2d1e32ec0e7c9735db
#cesium token
VITE_APP_CESIUM_TOKEN = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJkYTZlNGNlYS01NTU1LTQ1MGEtYmNlZS0yNTE2NDk5YWM2MjEiLCJpZCI6MTc5Njk2LCJpYXQiOjE3MDA1NDcwMjV9.qcl4AH2731cfFd0-I1ZLUINPXqvglLkDFD-UGR2zU5M
package.json
@@ -31,6 +31,7 @@
    "js-base64": "^3.7.4",
    "js-cookie": "^3.0.0",
    "js-md5": "^0.7.3",
    "jszip": "^3.10.1",
    "lodash": "^4.17.21",
    "nprogress": "^0.2.0",
    "postcss-pxtorem": "^6.1.0",
pnpm-lock.yaml
@@ -68,6 +68,9 @@
      js-md5:
        specifier: ^0.7.3
        version: 0.7.3
      jszip:
        specifier: ^3.10.1
        version: 3.10.1
      lodash:
        specifier: ^4.17.21
        version: 4.17.21
@@ -1346,6 +1349,9 @@
    resolution: {integrity: sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==}
    engines: {node: '>=0.10.0'}
  core-util-is@1.0.3:
    resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==}
  cors@2.8.5:
    resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==}
    engines: {node: '>= 0.10'}
@@ -1817,6 +1823,9 @@
    engines: {node: '>=0.10.0'}
    hasBin: true
  immediate@3.0.6:
    resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==}
  immer@9.0.21:
    resolution: {integrity: sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==}
@@ -2023,6 +2032,9 @@
  jsonfile@6.1.0:
    resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==}
  jszip@3.10.1:
    resolution: {integrity: sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==}
  kdbush@4.0.2:
    resolution: {integrity: sha512-WbCVYJ27Sz8zi9Q7Q0xHC+05iwkm3Znipc2XTlrnJbsHMYktW4hPhXUE8Ys1engBrvffoSCqbil1JQAa7clRpA==}
@@ -2047,6 +2059,9 @@
  lerc@2.0.0:
    resolution: {integrity: sha512-7qo1Mq8ZNmaR4USHHm615nEW2lPeeWJ3bTyoqFbd35DLx0LUH7C6ptt5FDCTAlbIzs3+WKrk5SkJvw8AFDE2hg==}
  lie@3.3.0:
    resolution: {integrity: sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==}
  loader-utils@1.4.2:
    resolution: {integrity: sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==}
@@ -2256,6 +2271,9 @@
    resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==}
    engines: {node: '>= 0.4'}
  pako@1.0.11:
    resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==}
  pako@2.1.0:
    resolution: {integrity: sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==}
@@ -2350,6 +2368,9 @@
    resolution: {integrity: sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==}
    engines: {node: '>=6'}
  process-nextick-args@2.0.1:
    resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==}
  protobufjs@7.4.0:
    resolution: {integrity: sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==}
    engines: {node: '>=12.0.0'}
@@ -2378,6 +2399,9 @@
  rbush@3.0.1:
    resolution: {integrity: sha512-XRaVO0YecOpEuIvbhbpTrZgoiI6xBlz6hnlr6EHhd+0x9ase6EmeN+hdwwUaJvLcsFFQ8iWVF1GAK1yB0BWi0w==}
  readable-stream@2.3.8:
    resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==}
  readable-stream@3.6.2:
    resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==}
@@ -2443,6 +2467,9 @@
    resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==}
    engines: {node: '>=0.4'}
  safe-buffer@5.1.2:
    resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==}
  safe-buffer@5.2.1:
    resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
@@ -2489,6 +2516,9 @@
  set-value@2.0.1:
    resolution: {integrity: sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==}
    engines: {node: '>=0.10.0'}
  setimmediate@1.0.5:
    resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==}
  side-channel-list@1.0.0:
    resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==}
@@ -2602,6 +2632,9 @@
  string.prototype.trimstart@1.0.8:
    resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==}
    engines: {node: '>= 0.4'}
  string_decoder@1.1.1:
    resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==}
  string_decoder@1.3.0:
    resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==}
@@ -4549,6 +4582,8 @@
  copy-descriptor@0.1.1: {}
  core-util-is@1.0.3: {}
  cors@2.8.5:
    dependencies:
      object-assign: 4.1.1
@@ -5154,6 +5189,8 @@
  image-size@0.5.5: {}
  immediate@3.0.6: {}
  immer@9.0.21: {}
  immutable@5.1.1: {}
@@ -5350,6 +5387,13 @@
    optionalDependencies:
      graceful-fs: 4.2.11
  jszip@3.10.1:
    dependencies:
      lie: 3.3.0
      pako: 1.0.11
      readable-stream: 2.3.8
      setimmediate: 1.0.5
  kdbush@4.0.2: {}
  kind-of@3.2.2:
@@ -5367,6 +5411,10 @@
  ktx-parse@1.0.0: {}
  lerc@2.0.0: {}
  lie@3.3.0:
    dependencies:
      immediate: 3.0.6
  loader-utils@1.4.2:
    dependencies:
@@ -5586,6 +5634,8 @@
      object-keys: 1.1.1
      safe-push-apply: 1.0.0
  pako@1.0.11: {}
  pako@2.1.0: {}
  pascalcase@0.1.1: {}
@@ -5671,6 +5721,8 @@
  prismjs@1.30.0: {}
  process-nextick-args@2.0.1: {}
  protobufjs@7.4.0:
    dependencies:
      '@protobufjs/aspromise': 1.1.2
@@ -5708,6 +5760,16 @@
  rbush@3.0.1:
    dependencies:
      quickselect: 2.0.0
  readable-stream@2.3.8:
    dependencies:
      core-util-is: 1.0.3
      inherits: 2.0.4
      isarray: 1.0.0
      process-nextick-args: 2.0.1
      safe-buffer: 5.1.2
      string_decoder: 1.1.1
      util-deprecate: 1.0.2
  readable-stream@3.6.2:
    dependencies:
@@ -5798,6 +5860,8 @@
      has-symbols: 1.1.0
      isarray: 2.0.5
  safe-buffer@5.1.2: {}
  safe-buffer@5.2.1: {}
  safe-push-apply@1.0.0:
@@ -5861,6 +5925,8 @@
      is-extendable: 0.1.1
      is-plain-object: 2.0.4
      split-string: 3.1.0
  setimmediate@1.0.5: {}
  side-channel-list@1.0.0:
    dependencies:
@@ -5999,6 +6065,10 @@
      define-properties: 1.2.1
      es-object-atoms: 1.1.1
  string_decoder@1.1.1:
    dependencies:
      safe-buffer: 5.1.2
  string_decoder@1.3.0:
    dependencies:
      safe-buffer: 5.2.1
src/axios.js
@@ -16,9 +16,9 @@
import NProgress from 'nprogress' // progress bar
import 'nprogress/nprogress.css' // progress bar style
import { Base64 } from 'js-base64'
import { baseUrl } from '@/config/env'
import crypto from '@/utils/crypto'
let baseUrl = import.meta.env.VITE_APP_API
// 全局未授权错误提示状态,只提示一次
let isErrorShown = false
// 全局锁机制相关变量
src/config/env.js
File was deleted
src/main.js
@@ -19,6 +19,8 @@
import 'animate.css'
import dayjs from 'dayjs'
import 'styles/common.scss'
import * as Cesium from 'cesium'
// 系统组件
import debug from './debug'
import VueClipboard from 'vue3-clipboard'
@@ -44,6 +46,11 @@
window.$crudCommon = crudCommon
debug()
window.axios = axios
const { VITE_APP_BASE,VITE_APP_CESIUM_TOKEN } = import.meta.env
window.CESIUM_BASE_URL = `${VITE_APP_BASE}cesiumPu`
Cesium.Ion.defaultAccessToken = VITE_APP_CESIUM_TOKEN
const app = createApp(App)
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
    app.component(key, component)
src/utils/cesium-tsa.js
@@ -3,10 +3,6 @@
import store from '@/store'
import { Terrain } from 'cesium'
// vite env
const { VITE_APP_BASE } = import.meta.env
window.CESIUM_BASE_URL = `${VITE_APP_BASE}cesiumPu`
// 定义全局的viewer变量防止重复生成
let viewer = null
let globalBaseMapLayers = []
@@ -20,9 +16,9 @@
let handlerEvents = {
  handler: null,
}
let TDT_Token = import.meta.env.VITE_APP_TDT_TOKEN
export default function cesiumOperation () {
  const TDT_Token = 'c6eea7dad4fa1e2d1e32ec0e7c9735db'
  // 天地图地图
  const TDT_IMG_C =
    'https://{s}.tianditu.gov.cn/img_c/wmts?service=wmts&request=GetTile&version=1.0.0' +
@@ -154,13 +150,7 @@
    tilingScheme: new AmapMercatorTilingScheme(),
    minimumLevel: 3,
  })
  Cesium.Ion.defaultAccessToken =
    'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJkMzg4MDk5YS05MWEzLTQ3NTYtOTYzNS04Yzk4MjU2MjI5N2YiLCJpZCI6MjE3OTM4LCJpYXQiOjE3MTY3NzIzOTR9.q1rzR7SRtIulQKTtJuv5HPUbp1av5E9RaOe-6voPDGc'
  const _init = async id => {
    const cesiumToken =
      'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJkYTZlNGNlYS01NTU1LTQ1MGEtYmNlZS0yNTE2NDk5YWM2MjEiLCJpZCI6MTc5Njk2LCJpYXQiOjE3MDA1NDcwMjV9.qcl4AH2731cfFd0-I1ZLUINPXqvglLkDFD-UGR2zU5M'
    Cesium.Ion.defaultAccessToken = cesiumToken
    Cesium.Camera.DEFAULT_VIEW_FACTOR = -0.45
    // 西南东北,默认显示中国
    Cesium.Camera.DEFAULT_VIEW_RECTANGLE = Cesium.Rectangle.fromDegrees(66, 4, 135, 53.55)
src/views/SignMachineNest/MachineRight/MachineTableDetails/DeviceJob/DeviceJobDetails/DeviceJobDetails.vue
@@ -33,7 +33,7 @@
                    />
                </div>
            </div>
            <div class="contentRight">map</div>
            <DeviceJobDetailsMap class="contentRight" :detailsData="detailsData"/>
        </div>
    </el-dialog>
</template>
@@ -42,6 +42,7 @@
import { pxToRem } from '@/utils/rem'
import JobRelatedEvents from './JobRelatedEvents.vue'
import { getJobDetails, getJobInfoFiles } from '@/api/home/task'
import DeviceJobDetailsMap from './DeviceJobDetailsMap.vue'
const isShow = defineModel('show')
@@ -59,19 +60,19 @@
])
const detailsData = ref({
    id: 19,
    remark: '测试测试',
    is_monitoring: 0,
    industry_type_str: '综合类、公安类',
    area_code: '360103',
    ai_type_str: '识别火情、车牌识别',
    begin_time: '2025/04/02 16:00',
    end_time: '2025/04/01 15:59',
    device_names: '赣县-夏潭机场',
    create_time: '2025-04-01T07:35:19.000+00:00',
    name: '夏弹机场测试',
    event_number: 2,
    creator_name: '管理员',
    id: null,
    remark: null,
    is_monitoring: null,
    industry_type_str: null,
    area_code: null,
    ai_type_str: null,
    begin_time: null,
    end_time: null,
    device_names: null,
    create_time: null,
    name: null,
    event_number: null,
    creator_name: null,
    way_lines: [],
})
@@ -95,8 +96,8 @@
watch(isShow, (newValue, oldValue) => {
    if (newValue) {
        getAchievement()
        getDetails()
        getAchievement()
    }
})
</script>
src/views/SignMachineNest/MachineRight/MachineTableDetails/DeviceJob/DeviceJobDetails/DeviceJobDetailsMap.vue
New file
@@ -0,0 +1,97 @@
<template>
    <div id="deviceJobDetailsMap" />
</template>
<script setup>
import { Terrain, Viewer } from 'cesium'
import * as Cesium from 'cesium'
import AmapMercatorTilingScheme from '@/utils/cesium/AmapMercatorTilingScheme'
import { analyzeKmzFile, XMLToJSON } from '@/utils/cesium/kmz'
const props = defineProps(['detailsData'])
const imageryProvider_ammapSL = new Cesium.UrlTemplateImageryProvider({
    url: 'https://webrd02.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}',
    layer: 'tdtVecBasicLayer',
    style: 'default',
    format: 'image/png',
    tileMatrixSetID: 'GoogleMapsCompatible',
    subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'],
    maximumLevel: 18,
    tilingScheme: new AmapMercatorTilingScheme(),
    credit: 'amap_SL',
})
const init = () => {
    const viewer = new Viewer('deviceJobDetailsMap', {
        terrain: Terrain.fromWorldTerrain(),
        infoBox: false, // 禁用沙箱,解决控制台报错
        animation: false, // 左下角的动画仪表盘
        baseLayerPicker: false, // 右上角的图层选择按钮
        geocoder: false, // 搜索框
        homeButton: false, // home按钮
        sceneModePicker: false, // 模式切换按钮
        timeline: false, // 底部的时间轴
        navigationHelpButton: false, // 右上角的帮助按钮,
        selectionIndicator: false, // 是否显示选择指示器
        baseLayer: false,
        fullscreenButton: false,
        sceneMode: Cesium.SceneMode.COLUMBUS_VIEW,
    })
    viewer.imageryLayers.addImageryProvider(imageryProvider_ammapSL)
    // viewer.scene.morphTo2D(0)
}
const drawLine = () => {
    props.detailsData.way_lines.forEach(item => {
        analyzeKmzFile(`${item.url}?_t=${new Date().getTime()}`).then(async res => {
            const templateXML = await res.fileInfoObj['wpmz/template.kml']
            const templateXMLJSON = XMLToJSON(templateXML)?.['Document']
            console.log(templateXMLJSON,66969969)
        })
    })
}
watch(() => props.detailsData, (newValue, oldValue) => {
    if(newValue){
        drawLine()
    }
})
onMounted(() => {
    nextTick(() => {
        init()
    })
})
</script>
<style scoped lang="scss">
#deviceJobDetailsMap {
    height: 100%;
    :deep() {
        .cesium-viewer {
            height: 100%;
            overflow: hidden;
            .cesium-viewer-cesiumWidgetContainer {
                width: 100%;
                height: 100%;
                .cesium-widget {
                    width: 100%;
                    height: 100%;
                    canvas {
                        width: 100%;
                        height: 100%;
                    }
                }
            }
        }
        .cesium-viewer-bottom {
            display: none;
        }
    }
}
</style>