15 files modified
4 files deleted
4 files added
| | |
| | | # @LastEditors : yuan |
| | | # @LastEditTime : 2025-07-29 16:15:31 |
| | | # @FilePath : \.env.development |
| | | # @Description : |
| | | # Copyright 2025 OBKoro1, All Rights Reserved. |
| | | # @Description : |
| | | # Copyright 2025 OBKoro1, All Rights Reserved. |
| | | # 2025-07-29 15:59:42 |
| | | ### |
| | | ### |
| | | NODE_ENV = 'development' |
| | | |
| | | #开发环境配置 |
| | |
| | | VITE_APP_AREA_NAME = https://wrj.shuixiongit.com |
| | | |
| | | # ws地址 |
| | | VITE_APP_WS_API_URL = wss://wrj.shuixiongit.com |
| | | VITE_APP_WS_API_URL = wss://wrj.shuixiongit.com/drone-wss/api/v1/ws |
| | | |
| | | # 航线文件地址 |
| | | VITE_APP_AIRLINE_URL = https://wrj.shuixiongit.com/minio/cloud-bucket |
| | |
| | | VITE_APP_DASHBOARD_URL = 'http://192.168.253.121:8080/command-center-dashboard/' |
| | | |
| | | # ws地址 |
| | | VITE_APP_WS_API_URL = ws://192.168.253.121:8080 |
| | | VITE_APP_WS_API_URL = ws://192.168.253.121:8080/drone-wss/api/v1/ws |
| | | |
| | | # 航线文件地址 |
| | | VITE_APP_AIRLINE_URL = http://192.168.253.121:9000/cloud-bucket |
| | |
| | | VITE_APP_DEVICE_IP = '139.196.74.78:1883' |
| | | |
| | | VITE_APP_TDT_TOKEN = e110584a27d506da2740edca951683f4 |
| | | VITE_APP_CESIUM_TOKEN = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJkYTZlNGNlYS01NTU1LTQ1MGEtYmNlZS0yNTE2NDk5YWM2MjEiLCJpZCI6MTc5Njk2LCJpYXQiOjE3MDA1NDcwMjV9.qcl4AH2731cfFd0-I1ZLUINPXqvglLkDFD-UGR2zU5M |
| | | VITE_APP_CESIUM_TOKEN = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJkYTZlNGNlYS01NTU1LTQ1MGEtYmNlZS0yNTE2NDk5YWM2MjEiLCJpZCI6MTc5Njk2LCJpYXQiOjE3MDA1NDcwMjV9.qcl4AH2731cfFd0-I1ZLUINPXqvglLkDFD-UGR2zU5M |
| | |
| | | VITE_APP_AREA_NAME = http://192.168.1.227:80 |
| | | |
| | | # ws地址 |
| | | VITE_APP_WS_API_URL = wss://192.168.1.227:80 |
| | | VITE_APP_WS_API_URL = wss://192.168.1.227:80/drone-wss/api/v1/ws |
| | | |
| | | # 航线文件地址 |
| | | VITE_APP_AIRLINE_URL = http://192.168.1.227:80/minio/cloud-bucket |
| | |
| | | VITE_APP_DASHBOARD_URL = 'https://aisky.org.cn/command-center-dashboard/' |
| | | |
| | | # ws地址 |
| | | VITE_APP_WS_API_URL = wss://aisky.org.cn |
| | | VITE_APP_WS_API_URL = wss://aisky.org.cn/drone-wss/api/v1/ws |
| | | |
| | | # 航线文件地址 |
| | | VITE_APP_AIRLINE_URL = https://wrj.shuixiongit.com/aiskyminio/cloud-bucket |
| | |
| | | VITE_APP_AREA_NAME = https://wrj.shuixiongit.com |
| | | |
| | | # ws地址 |
| | | VITE_APP_WS_API_URL = wss://wrj.shuixiongit.com |
| | | VITE_APP_WS_API_URL = wss://wrj.shuixiongit.com/drone-wss/api/v1/ws |
| | | |
| | | # 航线文件地址 |
| | | VITE_APP_AIRLINE_URL = https://wrj.shuixiongit.com/minio/cloud-bucket |
| | |
| | | <router-view /> |
| | | </template> |
| | | |
| | | |
| | | <script setup> |
| | | import { useDownloadWs } from '@/page/index/useDownloadWs'; |
| | | useDownloadWs() |
| | | </script> |
| | | |
| | | <style> |
| | |
| | | data |
| | | }) |
| | | } |
| | | |
| | | // 查询下载状态 |
| | | export const getDownloadStatusApi = (data) => { |
| | | return request({ |
| | | url: `/blade-resource/attach/getDownloadStatus`, |
| | | method: 'post', |
| | | data |
| | | }) |
| | | } |
| | | // 取消下载 |
| | | export const cancelDownloadApi = (data) => { |
| | | return request({ |
| | | url: `/blade-resource/attach/cancelDownload`, |
| | | method: 'post', |
| | | data |
| | | }) |
| | | } |
| | | // 地图 |
| | | export const getMapInfoAPI = (jobId) => { |
| | | return request({ |
| | |
| | | <!-- <wechat></wechat> --> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import index from '@/mixins/index' |
| | | import wechat from './wechat.vue' |
| New file |
| | |
| | | import { getWebsocketUrl } from '@/utils/websocket/config' |
| | | import { useConnectWebSocket } from '@/utils/websocket/connect-websocket' |
| | | import { useStore } from 'vuex' |
| | | import dayjs from 'dayjs' |
| | | import { aLinkDownloadUtil } from '@/utils/util' |
| | | import EventBus from '@/utils/eventBus' |
| | | import { computed, onBeforeUnmount, onMounted } from 'vue'; |
| | | import { setStore,getStore } from '@/utils/store'; |
| | | import { getDownloadStatusApi } from '@/api/dataCenter/dataCenter'; |
| | | |
| | | export const useDownloadWs = () => { |
| | | const store = useStore() |
| | | const loginUserInfo = computed(() => store.state.user.userInfo) |
| | | const downloadProgress = computed(() => store.state.common.downloadProgress) |
| | | let currentWebSocket = null |
| | | function messageHandler(payload) { |
| | | const {type,status,progress,download_url} = payload |
| | | const setProgress = status === 'CANCELLED' |
| | | ? 100 |
| | | : (status !== 'COMPLETED' && progress === 100) ? 99 : progress |
| | | store.commit('setDownloadProgress', { |
| | | ...downloadProgress.value, |
| | | [type]: setProgress, |
| | | }) |
| | | if (status === 'COMPLETED' && ['htsjzx','htlsrwxq'].includes(type)) { |
| | | const name = `数据中心-${dayjs().format('YYYYMMDDHHmmss')}.zip` |
| | | const currentUrl = getStore({name: 'downloadUrl'}) |
| | | if (currentUrl === download_url && download_url!== undefined) return |
| | | aLinkDownloadUtil(download_url, name) |
| | | setStore({ name: 'downloadUrl', content: download_url }) |
| | | } |
| | | } |
| | | |
| | | onMounted(() => { |
| | | let webSocketUrl = getWebsocketUrl() + `&model_type=3&workspace-id=${loginUserInfo.value.user_id}` |
| | | currentWebSocket = useConnectWebSocket((result)=>{ |
| | | const payload = JSON.parse(result) |
| | | messageHandler(payload.data) |
| | | }, webSocketUrl) |
| | | EventBus.on('useDownloadWs-messageHandler',messageHandler) |
| | | }) |
| | | |
| | | onBeforeUnmount(() => { |
| | | currentWebSocket?.close() |
| | | EventBus.off('useDownloadWs-messageHandler',messageHandler) |
| | | }) |
| | | return {} |
| | | } |
| | |
| | | lockPasswd: getStore({ name: 'lockPasswd' }) || '', |
| | | website: website, |
| | | setting: website.setting, |
| | | downloadProgress:{ |
| | | htsjzx: 100, //数据中心 |
| | | htlsrwxq: 100, //历史任务详情 |
| | | } |
| | | }, |
| | | mutations: { |
| | | setDownloadProgress(state, data) { |
| | | state.downloadProgress = data |
| | | }, |
| | | SET_LANGUAGE: (state, language) => { |
| | | state.language = language; |
| | | setStore({ |
| | |
| | | } |
| | | } |
| | | return newObj |
| | | } |
| | | } |
| | | |
| | | // a链接直接下载 |
| | | export const aLinkDownloadUtil = (url, name) => { |
| | | let a = document.createElement('a') |
| | | a.style.display = 'none' |
| | | a.href = url |
| | | a.download = name |
| | | document.body.appendChild(a) |
| | | a.click() |
| | | document.body.removeChild(a) |
| | | a = null |
| | | } |
| New file |
| | |
| | | import { getToken } from '@/utils/auth'; |
| | | |
| | | export function getWebsocketUrl() { |
| | | const token = getToken() || ''; |
| | | return import.meta.env.VITE_APP_WS_API_URL + '?x-auth-token=' + encodeURI(token); |
| | | } |
| | | // AI 指令飞行 |
| | | export function getAIWebsocketUrl() { |
| | | const token = getToken() || '' |
| | | return `${import.meta.env.VITE_APP_WS_API_URL}?x-auth-token=${encodeURI(token)}`; |
| | | } |
| New file |
| | |
| | | import ConnectWebSocket from '@/utils/websocket/index' |
| | | import { getWebsocketUrl } from '@/utils/websocket/config' |
| | | |
| | | /** |
| | | * 接收一个message函数 |
| | | * @param messageHandler |
| | | * @param url |
| | | */ |
| | | export function useConnectWebSocket(messageHandler, url) { |
| | | const webSocket = new ConnectWebSocket(url || getWebsocketUrl()) |
| | | |
| | | webSocket?.registerMessageHandler(messageHandler) |
| | | webSocket?.initSocket() |
| | | |
| | | return webSocket |
| | | } |
| New file |
| | |
| | | import ReconnectingWebSocket from 'reconnecting-websocket' |
| | | |
| | | /** |
| | | * ConnectWebSocket 类 |
| | | * TODO: 优化messageHandler: EventEmitter。暂时传入回调函数 |
| | | */ |
| | | |
| | | class ConnectWebSocket { |
| | | _url |
| | | _socket |
| | | _hasInit |
| | | _messageHandler |
| | | |
| | | constructor(url) { |
| | | this._url = url |
| | | this._socket = null |
| | | this._hasInit = false |
| | | this._messageHandler = null |
| | | } |
| | | |
| | | initSocket() { |
| | | if (this._hasInit) { |
| | | return |
| | | } |
| | | if (!this._url) { |
| | | return |
| | | } |
| | | // 会自动重连,无需处理重连逻辑 |
| | | this._socket = new ReconnectingWebSocket(this._url, [], { |
| | | maxReconnectionDelay: 20000, // 断开后最大的重连时间: 20s,每多一次重连,会增加 1.3 倍,5 * 1.3 * 1.3 * 1.3... |
| | | minReconnectionDelay: 5000, // 断开后最短的重连时间: 5s |
| | | maxRetries: 5, |
| | | }) |
| | | this._hasInit = true |
| | | |
| | | this._socket.addEventListener('open', this._onOpen.bind(this)) |
| | | this._socket.addEventListener('close', this._onClose.bind(this)) |
| | | this._socket.addEventListener('error', this._onError.bind(this)) |
| | | this._socket.addEventListener('message', this._onMessage.bind(this)) |
| | | } |
| | | |
| | | _onOpen() { |
| | | console.log('ws连接成功') |
| | | } |
| | | |
| | | _onClose() { |
| | | console.log('ws连接已断开') |
| | | } |
| | | |
| | | _onError() { |
| | | console.log('ws连接 error') |
| | | } |
| | | |
| | | registerMessageHandler(messageHandler) { |
| | | this._messageHandler = messageHandler |
| | | } |
| | | |
| | | _onMessage(msg) { |
| | | // const data = JSON.parse(msg.data); |
| | | this._messageHandler && this._messageHandler(msg.data) |
| | | } |
| | | |
| | | sendMessage = message => { |
| | | // 目前只供AI聊天使用 |
| | | this._socket?.send(message) |
| | | // this._socket?.send(JSON.stringify(message.data)); |
| | | } |
| | | |
| | | close() { |
| | | this._socket?.close() |
| | | this._messageHandler = null |
| | | this._socket = null |
| | | } |
| | | } |
| | | |
| | | export default ConnectWebSocket |
| | |
| | | </div> |
| | | <div class="search-first"> |
| | | <div class="search-btn"> |
| | | <el-button type="primary" icon="el-icon-download" @click="allDownloadFun" |
| | | >全部下载</el-button |
| | | > |
| | | <el-button type="success" plain icon="el-icon-download" @click="downloadFun" |
| | | >下载</el-button |
| | | > |
| | | <!-- <el-button type="primary" icon="el-icon-download" @click="allDownloadFun"--> |
| | | <!-- >全部下载</el-button--> |
| | | <!-- >--> |
| | | <div class="downloadBtn" @click="htsjzx === 100 && downloadFun()"> |
| | | <el-progress v-if="htsjzx !== 100" :percentage="htsjzx" :show-text="false" striped striped-flow :duration="1" /> |
| | | <div class="downloadBtnText"> |
| | | <span v-if="htsjzx === 100">下载</span> |
| | | <template v-else> |
| | | 处理中<el-icon @click="cancelDownload"><CircleClose /></el-icon> |
| | | </template> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </el-form> |
| | |
| | | import { useStore } from 'vuex'; |
| | | import { getRegionTreeAll, getDeviceRegion, deptsByAreaCode } from '@/api/job/task'; |
| | | import { watch } from 'vue'; |
| | | import { cancelDownloadApi, getDownloadStatusApi } from '@/api/dataCenter/dataCenter'; |
| | | import EventBus from '@/utils/eventBus'; |
| | | const store = useStore(); |
| | | const userAreaCode = computed(() => store.getters.userInfo.detail.areaCode); |
| | | const selectedAreaCode = computed(() => store.state.user.selectedAreaCode); |
| | | const htsjzx = computed(() => store.state.common.downloadProgress?.htsjzx || 100) |
| | | |
| | | const emit = defineEmits(['search', 'downFun', 'allDownFun']); |
| | | const startTime = dayjs().subtract(6, 'day').startOf('day'); |
| | | const endTime = dayjs().endOf('day'); |
| | |
| | | { |
| | | value: '5', |
| | | label: '全景', |
| | | |
| | | |
| | | }, |
| | | { |
| | | value: '4', |
| | |
| | | const allDownloadFun = () => { |
| | | emit('allDownFun'); |
| | | }; |
| | | |
| | | function cancelDownload() { |
| | | cancelDownloadApi({ type:'htsjzx' }).then(res =>{ |
| | | ElMessage.success('取消成功') |
| | | }) |
| | | } |
| | | |
| | | onMounted(() => { |
| | | requestDockInfo(); |
| | | getDownloadStatusApi({type: 'htsjzx'}).then(res =>{ |
| | | if (!['CANCELLED','COMPLETED'].includes(res.data.data?.status || 'COMPLETED')){ |
| | | EventBus.emit('useDownloadWs-messageHandler',res.data.data) |
| | | } |
| | | }) |
| | | }); |
| | | </script> |
| | | |
| | |
| | | |
| | | .search-btn { |
| | | margin-right: 32px; |
| | | |
| | | .downloadBtn{ |
| | | position: relative; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | height: 28px; |
| | | padding: 0 15px; |
| | | background: rgb(239.8,248.9,235.3); |
| | | border-radius: 4px 4px 4px 4px; |
| | | border: 1px solid rgb(179,224.5,156.5); |
| | | cursor: pointer; |
| | | color: #67c23a; |
| | | font-size: 14px; |
| | | |
| | | .downloadBtnText{ |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 5px; |
| | | z-index: 5; |
| | | } |
| | | .el-progress{ |
| | | height: 100%; |
| | | position: absolute; |
| | | left: 0; |
| | | top: 0; |
| | | width: 100%; |
| | | |
| | | :deep(){ |
| | | .el-progress-bar__outer{ |
| | | height: 26px !important; |
| | | border-radius: 0 !important; |
| | | background: transparent !important; |
| | | |
| | | .el-progress-bar__inner{ |
| | | border-radius: 0 !important; |
| | | background-color: #e5ffd9; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | } |
| | | |
| | | } |
| | | .time-card { |
| | | text-align: center; |
| | |
| | | deleteFileMultipleApi, |
| | | downloadApi, |
| | | updataTitleApi, |
| | | getOrthoimageInfo, |
| | | getOrthoimageInfo, getDownloadStatusApi |
| | | } from '@/api/dataCenter/dataCenter'; |
| | | import { getShowImg, getSmallImg, getzsSmallImg } from '@/utils/util'; |
| | | import { onMounted, watch } from 'vue'; |
| | |
| | | a.click(); |
| | | document.body.removeChild(a); |
| | | } |
| | | const fileDownload = () => { |
| | | const fileDownload = async () => { |
| | | const list = selectedRows.value.filter(i => i.checked); |
| | | if (!list?.length) return ElMessage.warning('请选择文件'); |
| | | if (list.length === 1) { |
| | |
| | | jobName: '', |
| | | resultType: '', |
| | | startTime: '', |
| | | wayLineJobIds: [], |
| | | type:'htsjzx' |
| | | }; |
| | | |
| | | downloadApi(aaa).then(res => { |
| | | aLinkDownload(res.data.data, `sjzx-file-pack-${dayjs().format('YYYYMMDDHHmmss')}.zip`); |
| | | const res = await getDownloadStatusApi({type: 'htsjzx'}) |
| | | if (!['CANCELLED','COMPLETED'].includes(res.data.data?.status || 'COMPLETED')){ |
| | | loading.close() |
| | | return ElMessage.warning('还有正在处理的') |
| | | } |
| | | downloadApi(aaa).finally(res => { |
| | | loading.close(); |
| | | }); |
| | | } |
| | |
| | | import { getLazyTree } from '@/api/base/region' |
| | | |
| | | import { mapGetters } from 'vuex' |
| | | import { getWebsocketUrl } from '@/websocket/util/config' |
| | | import ConnectWebSocket from '@/websocket' |
| | | import { $Clipboard } from "@smallwei/avue" |
| | | |
| | | |
| | |
| | | import FirmwareManage from './components/firmwareManage.vue' |
| | | import DevicePerShare from './components/devicePerShare.vue' |
| | | import DockControlPanel from './components/DockControlPanel.vue' |
| | | import { getWebsocketUrl } from '@/websocket/util/config' |
| | | import ConnectWebSocket from '@/websocket' |
| | | import { getWebsocketUrl } from '@/utils/websocket/config'; |
| | | import ConnectWebSocket from '@/utils/websocket'; |
| | | export default { |
| | | components: { |
| | | FirmwareManage, |
| | |
| | | this.webSocketIdSet.add(webSocketId) |
| | | const webSorketUrl = getWebsocketUrl() + '&workspace-id=' + data.workspace_id |
| | | // 监听ws 消息 |
| | | this.useConnectWebSocket(webSocketId, webSorketUrl) |
| | | this.useConnectWebSocket1(webSocketId, webSorketUrl) |
| | | } |
| | | }, |
| | | useConnectWebSocket (webSocketId, url) { |
| | | useConnectWebSocket1 (webSocketId, url) { |
| | | const websocket = new ConnectWebSocket(url) |
| | | // 加入 webscoket map |
| | | this.websocketMap.set(webSocketId, websocket) |
| | |
| | | |
| | | <script setup> |
| | | import { ElMessage } from 'element-plus'; |
| | | import EventBus from '@/event-bus' |
| | | import { EBizCode, ELocalStorageKey, ERouterName } from '@/types' |
| | | import { useConnectWebSocket } from '@/hooks/use-connect-websocket' |
| | | import { getWebsocketUrl } from '@/websocket/util/config' |
| | | import { defineProps, ref, watch, reactive } from 'vue' |
| | | import { cmdList as baseCmdList } from '@/types/device-cmd' |
| | | import { useDockControl } from './use-dock-control' |
| | |
| | | import { setThermalCurrentPaletteStyle, setPhotoStorageSet, setVideoStorageSet, getLiveStatus, setStreamsSwitch, photoAndVideoCmd } from '@/api/device-setting' |
| | | |
| | | import Store from '@/store' |
| | | import { useConnectWebSocket } from '@/utils/websocket/connect-websocket'; |
| | | import { getWebsocketUrl } from '@/utils/websocket/config'; |
| | | import EventBus from '@/utils/eventBus'; |
| | | |
| | | const valueStyle = ref(0) |
| | | const cameraModeValue = ref(0) |
| | |
| | | } |
| | | ) |
| | | onMounted(() => { |
| | | const webSorketUrl = getWebsocketUrl() + '&workspace-id=' + props.deviceInfo.workspace_id |
| | | // 监听ws 消息 |
| | | useConnectWebSocket(messageHandler, webSorketUrl) |
| | | getLiveStatuss() |
| | | }); |
| | | |
| | |
| | | action: cmdItem.action, |
| | | } |
| | | const success = await sendDockControlCmd(params, true) |
| | | if (success) { |
| | | updateDeviceSingleCmdInfo(cmdList.value[index]) |
| | | } |
| | | } |
| | | |
| | | // webSocket 监听 |
| | | const messageHandler = async payload => { |
| | | payload = JSON.parse(payload) |
| | | if (!payload) { |
| | | return |
| | | } |
| | |
| | | } |
| | | } |
| | | |
| | | const webSorketUrl = getWebsocketUrl() + '&workspace-id=' + props.deviceInfo.workspace_id |
| | | // 监听ws 消息 |
| | | useConnectWebSocket(messageHandler, webSorketUrl) |
| | | |
| | | // 添加 changs 方法 |
| | | async function changs(value, item) { |
| | |
| | | } |
| | | } |
| | | } |
| | | </style> |
| | | </style> |