代码优化

main
石超 2026-02-11 10:23:01 +08:00
parent b6a37cb957
commit bb3166b732
29 changed files with 3862 additions and 1960 deletions

36
.env.development Normal file
View File

@ -0,0 +1,36 @@
# Whether to open mock
VITE_USE_MOCK = true
# public path
VITE_PUBLIC_PATH = /
# Basic interface address SPA
#基础框架
VITE_GLOB_API_URL = http://192.168.10.163:9024
VITE_GLOB_UPLOAD_URL = http://192.168.10.163:9024
VITE_GLOB_INFO_IMAGE_URL = http://192.168.10.163:9024
VITE_GLOB_APP_TITLE = 天网慧眼低空态势感知平台
VITE_GLOB_APP_EN_TITLE = Tianwang Huiyan Low-altitude Situation Awareness Platform
VITE_GLOB_APP_LOGO = /logo.png
VITE_GLOB_APP_MANAGEMENT_UNIT = 管理单位:山东慧创信息科技有限公司
VITE_GLOB_APP_TECHINICAL_SUPPORT = 技术⽀持:山东慧创信息科技有限公司
VITE_GLOB_APP_VERSIONS = 系统版本V1.0
VITE_GLOB_API_URL_PREFIX=
VITE_GLOB_MEDIALIBRARY_IMAGE_URL = http://175.27.168.120:6013/test/
VITE_GLOB_APP_HEADER_TITLE = 低空数智平台
VITE_GLOB_PY_URL = http://192.168.10.131:9309
VITE_MQTT_URL =
VITE_MQTT_PORT =

49
.env.dikongganzhi Normal file
View File

@ -0,0 +1,49 @@
# Whether to open mock
VITE_USE_MOCK = true
# public path
VITE_PUBLIC_PATH = /
# Whether to enable gzip or brotli compression
# Optional: gzip | brotli | none
# If you need multiple forms, you can use `,` to separate
VITE_BUILD_COMPRESS = 'none'
# Basic interface address SPA
# 低空数智
VITE_GLOB_API_URL=https://ssl.hopetrytech.com:6034
VITE_GLOB_INFO_IMAGE_URL=https://ssl.hopetrytech.com:6034
# File upload address optional
# It can be forwarded by nginx or write the actual address directly
VITE_GLOB_UPLOAD_URL=https://ssl.hopetrytech.com:6034
# Interface prefix
VITE_GLOB_API_URL_PREFIX=
VITE_GLOB_APP_TITLE = 低空数智态势感知平台
VITE_GLOB_APP_EN_TITLE = Tianwang Huiyan Low-altitude Situation Awareness Platform
VITE_GLOB_APP_LOGO = /logo.png
VITE_GLOB_APP_MANAGEMENT_UNIT = 管理单位:山东慧创信息科技有限公司
VITE_GLOB_APP_TECHINICAL_SUPPORT = 技术⽀持:山东慧创信息科技有限公司
VITE_GLOB_APP_VERSIONS = 系统版本V1.0
VITE_GLOB_YINGXIANG_SERVER = http://192.168.31.205:8080/geoserver/ne/wms?service=WMS&version=1.1.0&request=GetMap&layers=ne:linyitif&styles=&bbox={bbox-epsg-3857}&width=256&height=256&srs=EPSG:3857&format=image/png&TRANSPARENT=TRUE
VITE_GLOB_FILE_PREVIEW = http://120.222.154.7:6081
VITE_GLOB_MEDIALIBRARY_IMAGE_URL = http://175.27.168.120:6013/test/
VITE_GLOB_APP_HEADER_TITLE = 低空数智平台
VITE_GLOB_PY_URL = http://123.132.248.154:9309
# VITE_GLOB_PY_URL = http://192.168.10.131:9309

10
.gitignore vendored
View File

@ -14,11 +14,11 @@ tests/server/static/upload
.env.local
.env.*.local
.eslintcache
.env
.env.analyze
.env.development
.env.dikongganzhi
.env.production
# .env
# .env.analyze
# .env.development
# .env.dikongganzhi
# .env.production
# Log files
npm-debug.log*
yarn-debug.log*

View File

@ -1,8 +1,8 @@
/**
* Mars3D mars3d
*
* v3.10.1
* 2025-08-04 14:14
* v3.10.12
* 2026-01-11 17:26
* Copyright by http://mars3d.cn
* 使 2025-08-04
*/
@ -80,6 +80,9 @@
top: 0;
left: 0;
}
.mars3d-contextmenu-ul .mars3d-contextmenu-item ::marker {
content: "";
}
.mars3d-contextmenu-ul .mars3d-contextmenu-line {
position: absolute;
left: 2%;
@ -140,7 +143,7 @@
min-width: 100px;
padding: 2px 5px;
font-size: 11px;
z-index: 1000;
z-index: 20170825;
opacity: 0.8;
-khtml-opacity: 0.8;
-moz-opacity: 0.8;
@ -903,7 +906,6 @@
}
.mars3d-popup-content {
margin: 10px;
line-height: 1.4;
font-size: 13px;
max-width: 700px;
min-width: 50px;
@ -1021,6 +1023,10 @@
.mars3d-template-content textarea::placeholder {
color: #cdcdcd;
}
.mars3d-popup-iframe {
overflow: auto;
margin: 0;
}
/*****tooltip弹出框样式******/
.mars3d-tooltip {
padding: 6px;
@ -1205,9 +1211,9 @@
/** 按钮工具栏修改定位:"top-left"上侧靠左 */
.cesium-viewer-toolbar-top-left {
top: 10px;
bottom: auto;
bottom: auto !important;
left: 10px;
right: auto;
right: auto !important;
/**帮助 弹出面板*/
/**底图切换 弹出面板*/
}
@ -1221,9 +1227,9 @@
/** 修改定位:"left-top"左侧靠上 */
.cesium-viewer-toolbar-left-top {
top: 10px;
bottom: auto;
bottom: auto !important;
left: 10px;
right: auto;
right: auto !important;
/**底图切换 弹出面板*/
/**帮助 弹出面板*/
/**二维三维切换*/
@ -1259,10 +1265,10 @@
}
/** 修改定位:"left-bottom"左侧靠下 */
.cesium-viewer-toolbar-left-bottom {
top: auto;
top: auto !important;
bottom: 60px;
left: 10px;
right: auto;
right: auto !important;
/**底图切换 弹出面板*/
/**帮助 弹出面板*/
/**二维三维切换*/
@ -1301,9 +1307,9 @@
/** 修改定位:"right-top"右侧靠上 */
.cesium-viewer-toolbar-right-top {
top: 10px;
bottom: auto;
bottom: auto !important;
right: 10px;
left: auto;
left: auto !important;
/**底图切换 弹出面板*/
/**帮助 弹出面板*/
/**二维三维切换*/
@ -1340,10 +1346,10 @@
}
/** 修改定位:"right-bottom"右侧靠下 */
.cesium-viewer-toolbar-right-bottom {
top: auto;
top: auto !important;
bottom: 60px;
right: 10px;
left: auto;
left: auto !important;
/**底图切换 弹出面板*/
/**帮助 弹出面板*/
/**二维三维切换*/

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,6 @@
{
"name": "mars3d",
"version": "3.10.1",
"version": "3.10.11",
"description": "Mars3D三维可视化平台",
"main": "./mars3d.js",
"types": "./mars3d.d.ts",

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

@ -147,53 +147,14 @@
map = initMap();
map.on('load', () => {
// map.addLayer({
// 'id': 'wms-test-layer',
// 'type': 'raster',
// 'source': {
// 'type': 'raster',
// 'tiles': [
// // "http://175.27.168.120:8080/geoserver/feixian/wms?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&FORMAT=image%2Fjpeg&TRANSPARENT=true&LAYERS=feixian%3Ayingxiang_17&exceptions=application%2Fvnd.ogc.se_inimage&SRS=EPSG%3A4548&STYLES=&WIDTH=728&HEIGHT=768&BBOX=586801.5388788335%2C3908183.1422136417%2C590270.7583843566%2C3911848.0123377703",
// // "http://175.27.168.120:8080/geoserver/feixian/wms?service=WMS&version=1.1.0&request=GetMap&layers=feixian:yingxiang_17&styles=&bbox={bbox-epsg-3857}&width=256&height=256&srs=EPSG:3857&format=image/png&TRANSPARENT=TRUE"
// "http://60.213.14.14:8060/geoserver/feixian/wms?service=WMS&version=1.1.0&request=GetMap&layers=feixian:yingxiang&styles=&bbox={bbox-epsg-3857}&width=256&height=256&srs=EPSG:3857&format=image/png&TRANSPARENT=TRUE"
// ],
// 'tileSize': 256
// },
// 'paint': {}
// });
map.addSource('radar', {
'type': 'image',
// 'url': 'http://175.27.168.120:8080/geoserver/feixian/wms?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&FORMAT=image%2Fjpeg&TRANSPARENT=true&LAYERS=feixian%3Ayingxiang_17&exceptions=application%2Fvnd.ogc.se_inimage&SRS=EPSG%3A4548&STYLES=&WIDTH=728&HEIGHT=768&BBOX=586801.5388788335%2C3908183.1422136417%2C590270.7583843566%2C3911848.0123377703',
// 'url':"http://175.27.168.120:8080/geoserver/feixian/wms?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&FORMAT=image%2Fjpeg&TRANSPARENT=true&LAYERS=feixian%3Ayingxiang_17&exceptions=application%2Fvnd.ogc.se_inimage&SRS=EPSG%3A4548&STYLES=&WIDTH=727&HEIGHT=768&BBOX=591035.9133569683%2C3908525.08342436%2C591469.2675472646%2C3908982.893941982",
'url':"http://60.213.14.14:8060/geoserver/feixian/wms?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&FORMAT=image%2Fjpeg&TRANSPARENT=true&LAYERS=feixian%3Ayingxiang&exceptions=application%2Fvnd.ogc.se_inimage&SRS=EPSG%3A4527&STYLES=&WIDTH=1024&HEIGHT=1024&BBOX=39591762.54875996%2C3908085.3169043385%2C39592654.90645946%2C3909001.5344353705",
'coordinates': [
// EPSG:4548
// [118.00090749819051,35.30579563806707],
// [118.0057224793592,35.30579563806707],
// [118.0057224793592,35.30170937770571],
// [118.00090749819051,35.30170937770571],
// EPSG:4527
// [118.00884630303432,35.3058545162185],
// [118.01875909202998,35.3058545162185],
// [118.01875909202998,35.29767983003392],
// [118.00884630303432,35.29767983003392],
[118.00884630303432,35.30585451621851],
[118.01875909202998,35.30585451621851],
[118.01875909202998,35.297679830033914],
[118.00884630303432,35.297679830033914],
// [39591762.54875996,3909001.5344353705],
// [39592654.90645946,3909001.5344353705],
// [39592654.90645946,3908085.3169043385],
// [39591762.54875996,3908085.3169043385],
]
});
map.addLayer({

View File

@ -1,9 +1,10 @@
import mqtt from 'mqtt';
import { getAppEnvConfig } from '@/utils/env';
const { VITE_MQTT_URL, VITE_MQTT_PORT } = getAppEnvConfig();
const connection = {
protocol: 'ws',
host: '175.27.168.120',
port: 6010,
host: VITE_MQTT_URL,
port: VITE_MQTT_PORT,
endpoint: '/mqtt',
clean: true,
connectTimeout: 30 * 1000, // ms
@ -49,7 +50,7 @@ const destroyConnection = () => {
};
// 订阅事件
const clientSubscribe = (topic: string) => {
client.subscribe(topic, { qos: 0 }, () => {});
client.subscribe(topic, { qos: 0 }, () => { });
};
// 发送消息
// 定义一个函数clientPublish用于发布消息

View File

@ -23,10 +23,6 @@ export const airPortStore = defineStore({
rtmp: 'rtmp://175.27.168.120:6019/live/',
url: 'http://175.27.168.120:6012/live/',
getUrl: 'http://175.27.168.120:5005/',
// rtmp: 'rtmp://box.wisestcity.com:1935/live/',
// url: 'http://box.wisestcity.com:8081/live/',
// rtmp: 'http://175.27.168.120:5005/rtc/v1/whip/?app=live&stream=',
// url: 'http://175.27.168.120:5005/rtc/v1/whep/?app=live&stream=',
},
gateway: null,
typeId: null,
@ -37,6 +33,8 @@ export const airPortStore = defineStore({
name: null,
type: null,
},
aiLiveUrl: null,
isAiVideo: false,
}),
getters: {
getAirport(state) {
@ -66,6 +64,12 @@ export const airPortStore = defineStore({
getCamera(state) {
return state.camera;
},
getAiLiveUrl(state) {
return state.aiLiveUrl;
},
getIsAiVideo(state) {
return state.isAiVideo;
},
},
actions: {
setAirPort(item: any, value: any) {
@ -131,5 +135,11 @@ export const airPortStore = defineStore({
setCamera(item: any, value: any) {
this.camera[item] = value;
},
setAiLiveUrl(value: any) {
this.aiLiveUrl = value;
},
setIsAiVideo(value: any) {
this.isAiVideo = value;
},
},
});

View File

@ -44,6 +44,8 @@ export function getAppEnvConfig() {
VITE_GLOB_FILE_PREVIEW,
VITE_GLOB_APP_HEADER_TITLE,
VITE_GLOB_PY_URL,
VITE_MQTT_URL,
VITE_MQTT_PORT,
} = ENV;
let { VITE_GLOB_API_URL } = ENV;
if (localStorage.getItem(API_ADDRESS)) {
@ -65,6 +67,8 @@ export function getAppEnvConfig() {
VITE_GLOB_FILE_PREVIEW,
VITE_GLOB_APP_HEADER_TITLE,
VITE_GLOB_PY_URL,
VITE_MQTT_URL,
VITE_MQTT_PORT,
};
}

View File

@ -6,14 +6,16 @@ import { timestampToFormattedDate } from '@/utils/index';
const userStore = useUserStore();
const userInfo = userStore.getUserInfo;
import { getAppEnvConfig } from '@/utils/env';
const { VITE_MQTT_URL, VITE_MQTT_PORT } = getAppEnvConfig();
const { createMessage } = useMessage();
const seizeClientId = 'mqtt_client_1581F8HGX254V00A0BUY_seize';
const connection = {
protocol: 'ws',
host: '175.27.168.120',
host: VITE_MQTT_URL,
// server less服务器只有两种协议mqtts: 8883; wss: 8084
port: 6010,
port: VITE_MQTT_PORT,
endpoint: '/mqtt',
// for more options, please refer to https://github.com/mqttjs/MQTT.js#mqttclientstreambuilder-options
clean: true,
@ -73,7 +75,7 @@ const createConnection = (callback?) => {
addOrUpdateRedisUser(querys);
}
const { protocol, host, port, endpoint, ...options } = connection;
console.log("options123",options);
console.log("options123", options);
const connectUrl = `${protocol}://${host}:${port}${endpoint}`;
client = mqtt.connect(connectUrl, options);
client.on('connect', () => {
@ -129,7 +131,7 @@ const clientSubscribe = (topic: string, options?: any) => {
// if (!client || !client.connected) {
// createConnection();
// }
getClient().subscribe(topic, { qos: 0 }, (error, res) => {});
getClient().subscribe(topic, { qos: 0 }, (error, res) => { });
};
// 取消订阅事件
const clientUnSubscribe = (topic: string) => {

View File

@ -348,7 +348,6 @@
extendsData: [],
mediaType: 'image', // video--image-- 使video 使imageimagUrl
imagUrl: './test.png', // url base64
// imagUrl: 'http://175.27.168.120:6013/test/4b90d8ca-390e-4320-a29b-0a879733f36d/69c91c81-5267-45f9-b8c2-fb77808c14fe/DJI_202508151432_002_69c91c81-5267-45f9-b8c2-fb77808c14fe/DJI_20250815143510_0035_V.jpeg',
version: '1.0',
});
const demoInit = () => {

View File

@ -57,7 +57,6 @@
extendsData: [],
mediaType: 'image', // video--image-- 使video 使imageimagUrl
imagUrl: './test.png', // url base64
// imagUrl: 'http://175.27.168.120:6013/test/4b90d8ca-390e-4320-a29b-0a879733f36d/69c91c81-5267-45f9-b8c2-fb77808c14fe/DJI_202508151432_002_69c91c81-5267-45f9-b8c2-fb77808c14fe/DJI_20250815143510_0035_V.jpeg',
version: '1.0',
});
const demoInit = () => {

File diff suppressed because it is too large Load Diff

View File

@ -1,42 +1,47 @@
<template>
<!-- 智能巡检配置组件 -->
<div>
<div class="shade-container" v-if="drawarea"></div>
<!-- 遮罩层当绘制区域时显示 -->
<div class="shade-container" v-if="drawArea"></div>
<!-- 机场信息配置面板 -->
<div class="airport-information">
<div class="title">选择AI算法实例 <span> 航飞要求 </span></div>
<div class="content">
<div class="content-edit instantiate" @click="instantiateVisible = !instantiateVisible">
<!-- AI算法实例选择 -->
<div class="content-edit instantiate" @click="algoInstanceMenuVisible = !algoInstanceMenuVisible">
<div class="input-result">
<span :style="{ backgroundColor: instantiateItem.displayColor }">
{{ instantiateItem.displayScheme }}</span
>
{{ instantiateItem.name }}
<span :style="{ backgroundColor: selectedAlgoInstance.displayColor }">
{{ selectedAlgoInstance.displayScheme }}</span>
{{ selectedAlgoInstance.name }}
</div>
<UpOutlined v-if="instantiateVisible" />
<UpOutlined v-if="algoInstanceMenuVisible" />
<DownOutlined v-else />
<div class="select-result" v-if="instantiateVisible">
<div
v-for="(item, index) in instantiateOptions"
:key="index"
@click="instantiateSelect(item)"
>
<!-- 算法实例选择列表 -->
<div class="select-result" v-if="algoInstanceMenuVisible">
<div v-for="(item, index) in algoInstanceOptions" :key="index" @click="selectAlgoInstance(item)">
<span :style="{ backgroundColor: item.displayColor }">{{ item.displayScheme }}</span>
{{ item.name }}
</div>
</div>
</div>
<!-- 空间约束范围配置 -->
<div class="content-edit space">
<span>空间约束范围</span>
<div class="space-content">
<span>导入KML</span>
<span @click="drawarea = true"><PlusOutlined />新增</span>
<span @click="drawArea = true">
<PlusOutlined />新增
</span>
</div>
</div>
<!-- 识别时间范围配置 -->
<div class="content-title">
<span>识别时间范围</span>
</div>
<div class="content-edit">
<a-select v-model:value="data.time" :options="timeOptions" />
</div>
<!-- 触发动作配置 -->
<div class="content-title">
<span>触发动作</span>
</div>
@ -46,367 +51,488 @@
<a-radio-button value="2">等待接管</a-radio-button>
</a-radio-group>
</div>
<!-- 警告提示标题配置 -->
<div class="content-title">
<span>警告提示标题</span>
</div>
<div class="content-edit">
<a-input v-model:value="data.code" placeholder="异常提示" />
</div>
<!-- 警告提示内容配置 -->
<div class="content-title">
<span>警告提示内容</span>
</div>
<div class="content-edit">
<a-textarea v-model:value="data.desc" placeholder="识别到异常目标" />
</div>
<!-- 操作按钮 -->
<div class="content-button">
<a-button type="primary" style="background: #3a57e8" @click="emits('changePatrol')"
>取消</a-button
>
<a-button type="primary" style="background: #0a99eb; margin-left: 20px" @click="submit"
>确定</a-button
>
<a-button type="primary" style="background: #3a57e8" @click="emits('changePatrol')"></a-button>
<a-button type="primary" style="background: #0a99eb; margin-left: 20px" @click="submit"></a-button>
</div>
</div>
</div>
<div class="patrol-map" v-if="drawarea">
<!-- 绘制区域面板 -->
<div class="patrol-map" v-if="drawArea">
<div class="title">绘制范围</div>
<div class="map-container">
<div class="map-container-content">
<Map :drawArea="drawarea" @areaData="getAreaData" />
<Map :drawArea="drawArea" @areaData="getAreaData" />
</div>
</div>
<div class="content-button">
<a-button type="primary" style="background: #3a57e8" @click="drawarea = false"
>取消</a-button
>
<a-button
type="primary"
style="background: #0a99eb; margin-left: 20px"
@click="patrolMapConfirm"
>确定</a-button
>
<a-button type="primary" style="background: #3a57e8" @click="drawArea = false">取消</a-button>
<a-button type="primary" style="background: #0a99eb; margin-left: 20px" @click="patrolMapConfirm"></a-button>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { reactive, ref, watch, onMounted } from 'vue';
import { useMessage } from '@/hooks/web/useMessage';
import {
InfoCircleOutlined,
DownOutlined,
UpOutlined,
PlusOutlined,
} from '@ant-design/icons-vue';
import { Map } from '../index';
import { GetAlgoInstanceList } from '@/api/demo/aiinstance';
import { airPortStore } from '@/store/modules/airport';
import { callAiModel } from '@/api/workmanagement/droneDock';
import { EventBus } from '@/utils/eventBus';
// Vue
import { reactive, ref, onMounted } from 'vue';
//
import { useMessage } from '@/hooks/web/useMessage';
//
import {
DownOutlined,
UpOutlined,
PlusOutlined,
} from '@ant-design/icons-vue';
//
import { Map } from '../index';
// API
import { GetAlgoInstanceList } from '@/api/demo/aiinstance';
import { callAiModel } from '@/api/workmanagement/droneDock';
//
import { airPortStore } from '@/store/modules/airport';
const airPortStoreVal = airPortStore();
const { createMessage } = useMessage();
const emits = defineEmits(['changePatrol']);
const data = reactive({
instantiate: null,
code: '',
desc: '',
action: '1',
time: 'day',
area: null,
});
const bgOptions = ref(['#6909B2', '#09B284', '#B2AA09', '#E240BD', '#E24040']);
const instantiateVisible = ref(false);
const instantiateOptions = ref([
{
label: '疑似违停车辆识别',
type: '违停车辆',
value: '1',
bgColor: bgOptions.value[0],
},
{
label: '疑似违停车辆识别',
type: '违停车辆',
value: '1',
bgColor: bgOptions.value[2],
},
]);
const timeOptions = ref([
{
label: '全天',
value: 'day',
},
]);
const instantiateItem = ref({});
const instantiateSelect = (val) => {
data.instantiate = val.id;
instantiateItem.value = val;
};
const drawarea = ref(false);
const getAreaData = (val) => {
console.log(val);
data.area = val;
};
const patrolMapConfirm = () => {
if (!data.area) {
createMessage.warning('请绘制区域');
return;
}
drawarea.value = false;
};
const getList = () => {
//
const airPortStoreVal = airPortStore();
//
const { createMessage } = useMessage();
//
const emits = defineEmits(['changePatrol', 'taskSubmitted']);
//
const data = reactive({
instantiate: null, // AIID
code: '', //
desc: '', //
action: '1', // 1-2-
time: 'day', //
area: null, //
});
//
const bgOptions = ref(['#6909B2', '#09B284', '#B2AA09', '#E240BD', '#E24040']);
//
const algoInstanceMenuVisible = ref(false);
//
const algoInstanceOptions = ref([]);
//
const timeOptions = ref([
{
label: '全天',
value: 'day',
},
]);
//
const selectedAlgoInstance = ref({});
//
const drawArea = ref(false);
//
const liveCode = ref(airPortStoreVal.getUAV.sn);
const live_info = airPortStoreVal.getLiveInfo;
//
//
// item -
const selectAlgoInstance = (item) => {
data.instantiate = item.id;
selectedAlgoInstance.value = item;
};
//
//
// val -
const getAreaData = (val) => {
console.log('区域数据:', val);
data.area = val;
};
//
//
const patrolMapConfirm = () => {
if (!data.area) {
createMessage.warning('请绘制区域');
//
airPortStoreVal.setflyLog({
type: 'error',
title: '区域绘制',
content: '请绘制区域'
});
return;
}
drawArea.value = false;
};
//
// APIAI
const getList = () => {
try {
GetAlgoInstanceList({
page: 1,
limit: 999,
}).then((res) => {
console.log(res);
instantiateOptions.value = res.items;
console.log('算法实例列表:', res);
if (res && res.items) {
algoInstanceOptions.value = res.items;
} else {
console.error('获取算法实例列表失败: 响应数据格式错误');
createMessage.error('获取算法实例列表失败: 响应数据格式错误');
algoInstanceOptions.value = [];
}
}).catch((error) => {
console.error('获取算法实例列表失败:', error);
createMessage.error('获取算法实例列表失败: ' + (error.message || '网络错误'));
algoInstanceOptions.value = [];
});
};
const liveCode = ref(airPortStoreVal.getUAV.sn);
const live_info = airPortStoreVal.getLiveInfo;
} catch (error) {
console.error('获取算法实例列表异常:', error);
createMessage.error('获取算法实例列表异常: ' + (error.message || '未知错误'));
algoInstanceOptions.value = [];
}
};
const submit = () => {
liveCode.value = airPortStoreVal.getUAV.sn;
if (!instantiateItem.value.id) {
createMessage.warning('请选择AI算法实例');
//
// API
const submit = () => {
try {
//
liveCode.value = airPortStoreVal.getUAV?.sn || '';
//
if (!selectedAlgoInstance.value.id) {
// createMessage.warning('AI');
//
airPortStoreVal.setflyLog({
type: 'error',
title: '算法实例',
content: '请选择AI算法实例'
});
return;
}
// if (!data.code) {
// createMessage.warning('');
// return;
// }
// if (!data.desc) {
// createMessage.warning('');
// return;
// }
if (!airPortStoreVal.getTaskId) {
// createMessage.warning('ID');
//
airPortStoreVal.setflyLog({
type: 'error',
title: '任务ID',
content: '任务ID不存在'
});
return;
}
if (!airPortStoreVal.getUAV?.sn) {
// createMessage.warning('SN');
//
airPortStoreVal.setflyLog({
type: 'error',
title: '无人机信息',
content: '无人机SN不存在'
});
return;
}
if (!live_info.rtmp) {
// createMessage.warning('URL');
//
airPortStoreVal.setflyLog({
type: 'error',
title: '直播配置',
content: '直播URL不存在'
});
return;
}
//
const querys = {
taskId: airPortStoreVal.getTaskId,
algoInstanceId: instantiateItem.value.id,
algoInstanceId: selectedAlgoInstance.value.id,
rtmpUrl: live_info.rtmp + liveCode.value,
warningTitle: data.code,
warningContent: data.desc,
warningTitle: data.code || '智能巡检异常',
warningContent: data.desc || '识别到异常目标',
uavSn: airPortStoreVal.getUAV.sn,
};
// API
callAiModel(querys).then((res) => {
console.log(res);
createMessage.success('操作成功');
emits('changePatrol');
console.log('智能巡检任务提交结果:', res);
if (res && res.code === 200) {
createMessage.success('操作成功');
// AI
if (res.data && res.data.push_url) {
airPortStoreVal.setAiLiveUrl(res.data.push_url);
airPortStoreVal.setflyLog({
type: 'success',
title: 'AI视频流',
content: '已获取AI识别视频流地址'
});
}
// socket
emits('taskSubmitted', {
taskId: airPortStoreVal.getTaskId,
algoInstanceId: selectedAlgoInstance.value.id,
success: true
});
emits('changePatrol');
} else {
airPortStoreVal.setflyLog({
type: 'error',
title: '操作失败',
content: '操作失败: ' + (res?.message || '未知错误')
});
// createMessage.error(': ' + (res?.message || ''));
}
}).catch((error) => {
airPortStoreVal.setflyLog({
type: 'error',
title: '提交智能巡检任务失败',
content: ('提交智能巡检任务失败: ' + (error.message || '网络错误'))
});
// console.error(':', error);
// createMessage.error(': ' + (error.message || ''));
});
};
onMounted(() => {
getList();
});
} catch (error) {
airPortStoreVal.setflyLog({
type: 'error',
title: '提交智能巡检配置异常',
content: ('操作异常: ' + (error.message || '未知错误'))
});
// console.error(':', error);
// createMessage.error(': ' + (error.message || ''));
}
};
//
onMounted(() => {
//
getList();
});
</script>
<style lang="less" scoped>
.shade-container {
width: 100vw;
height: 100vh;
background: rgba(0, 0, 0, 0.3);
position: fixed;
top: 0;
left: 0;
z-index: 1000;
.shade-container {
width: 100vw;
height: 100vh;
background: rgba(0, 0, 0, 0.3);
position: fixed;
top: 0;
left: 0;
z-index: 1000;
}
.title {
width: 100%;
padding: 10px 0;
box-shadow: 0px 10px 30px 0px rgba(0, 0, 6, 0.15);
border-bottom: 1px solid #4e5778;
display: flex;
justify-content: space-between;
align-items: center;
span {
color: #f2762d;
font-size: 12px;
border-radius: 10px;
border: 1px solid #f2762d;
display: inline-block;
padding: 4px 6px;
}
.title {
width: 100%;
padding: 10px 0;
box-shadow: 0px 10px 30px 0px rgba(0, 0, 6, 0.15);
border-bottom: 1px solid #4e5778;
}
.content-button {
margin-top: 10px;
display: flex;
align-items: center;
justify-content: flex-end;
}
.airport-information {
position: absolute;
top: 0;
right: 5px;
width: 290px;
padding: 10px;
margin: 10px 0 0 10px;
border-radius: 6px;
backdrop-filter: blur(3px);
color: #fff;
.content-edit {
display: flex;
align-items: center;
justify-content: space-between;
align-items: center;
span {
color: #f2762d;
font-size: 12px;
border-radius: 10px;
border: 1px solid #f2762d;
display: inline-block;
padding: 4px 6px;
}
}
.content-button {
border: 1px solid #4e5778;
margin-top: 10px;
display: flex;
align-items: center;
justify-content: flex-end;
}
.airport-information {
position: absolute;
top: 0;
right: 5px;
width: 290px;
padding: 10px;
// background: #0d0e15;
margin: 10px 0 0 10px;
// box-shadow:
// 0px 10px 30px 0px rgba(0, 0, 6, 0.15),
// inset 0px 0px 36px 0px rgba(58, 87, 232, 0.73);
border-radius: 6px;
backdrop-filter: blur(3px);
color: #fff;
padding: 2px 10px;
border-radius: 4px;
font-size: 12px;
.content-item {
display: flex;
align-items: center;
border-bottom: 1px solid #4e5778;
padding: 10px 0;
.item-div {
width: 49%;
cursor: pointer;
img {
width: 20px;
}
}
}
.content-edit {
display: flex;
align-items: center;
justify-content: space-between;
border: 1px solid #4e5778;
margin-top: 10px;
padding: 2px 10px;
border-radius: 4px;
input {
background: none;
border: none;
color: #fff;
font-size: 12px;
input {
background: none;
border: none;
color: #fff;
font-size: 12px;
}
textarea {
background: none;
color: #fff;
border: none;
}
::v-deep .ant-select {
width: 100%;
}
::v-deep .ant-select-selector {
background: none;
width: 100%;
border: none;
text-align: center;
color: #fff;
font-size: 12px;
}
textarea {
background: none;
color: #fff;
border: none;
}
::v-deep .ant-select {
width: 100%;
}
::v-deep .ant-select-selector {
background: none;
width: 100%;
border: none;
text-align: center;
color: #fff;
font-size: 12px;
}
}
.instantiate {
padding: 4px 6px;
cursor: pointer;
position: relative;
div {
span {
margin-right: 6px;
}
}
.instantiate {
padding: 4px 6px;
cursor: pointer;
position: relative;
div {
span {
margin-right: 6px;
}
.input-result {
span {
padding: 6px;
border-radius: 6px;
display: inline-block;
}
.input-result {
}
.select-result {
position: absolute;
top: 40px;
left: -2%;
width: 104%;
background: #0d0e15;
box-shadow:
0px 5px 15px 0px rgba(0, 0, 6, 0.15),
inset 0px 0px 18px 0px rgba(58, 87, 232, 0.73);
height: 300px;
overflow: auto;
z-index: 2;
border: 1px solid #4e5778;
div {
padding: 10px 6px;
border-bottom: 1px solid #1c1c1c;
span {
padding: 6px;
border-radius: 6px;
display: inline-block;
}
}
.select-result {
position: absolute;
top: 40px;
left: -2%;
width: 104%;
background: #0d0e15;
box-shadow:
0px 5px 15px 0px rgba(0, 0, 6, 0.15),
inset 0px 0px 18px 0px rgba(58, 87, 232, 0.73);
height: 300px;
overflow: auto;
z-index: 2;
border: 1px solid #4e5778;
div {
padding: 10px 6px;
border-bottom: 1px solid #1c1c1c;
span {
padding: 6px;
border-radius: 6px;
display: inline-block;
}
}
}
}
.space {
padding: 10px 4px;
font-size: 14px;
.space-content {
> span {
color: #f2762d;
border: 1px solid #f2762d;
padding: 4px 8px;
border-radius: 18px;
font-size: 12px;
cursor: pointer;
}
}
> span:last-child {
margin-left: 10px;
color: #0377f6;
border: 1px solid #0377f6;
}
}
}
.content-title {
padding-top: 10px;
.anticon {
margin-left: 4px;
.space {
padding: 10px 4px;
font-size: 14px;
.space-content {
>span {
color: #f2762d;
border: 1px solid #f2762d;
padding: 4px 8px;
border-radius: 18px;
font-size: 12px;
cursor: pointer;
}
}
::v-deep .ant-radio-group {
width: 100%;
margin: 2px;
}
::v-deep .ant-radio-button-wrapper {
border: none;
width: 50%;
text-align: center;
background: #0b234d;
color: #fff;
box-shadow:
0px 10px 30px 0px rgba(0, 0, 6, 0.15),
0px 10px 30px 0px rgba(0, 0, 6, 0.15),
inset 0px -1px 5px 0px rgba(213, 220, 255, 0.73);
border-radius: 4px;
}
::v-deep .ant-radio-button-wrapper-checked {
background: #0377f6;
box-shadow:
0px 10px 30px 0px rgba(0, 0, 6, 0.15),
0px 10px 30px 0px rgba(0, 0, 6, 0.15),
inset 0px -1px 5px 0px rgba(213, 220, 255, 0.73);
>span:last-child {
margin-left: 10px;
color: #0377f6;
border: 1px solid #0377f6;
}
}
}
.patrol-map {
position: absolute;
top: 80px;
right: calc(50% - 400px);
width: 800px;
height: 600px;
padding: 10px;
background: #0d0e15;
margin: 10px 0 0 10px;
.content-title {
padding-top: 10px;
.anticon {
margin-left: 4px;
cursor: pointer;
}
}
::v-deep .ant-radio-group {
width: 100%;
margin: 2px;
}
::v-deep .ant-radio-button-wrapper {
border: none;
width: 50%;
text-align: center;
background: #0b234d;
color: #fff;
box-shadow:
0px 10px 30px 0px rgba(0, 0, 6, 0.15),
inset 0px 0px 36px 0px rgba(58, 87, 232, 0.73);
border-radius: 6px;
backdrop-filter: blur(3px);
color: #fff;
z-index: 1001;
.map-container {
width: 100%;
height: calc(100% - 80px);
}
.map-container-content {
height: calc(100% - 10px);
}
inset 0px -1px 5px 0px rgba(213, 220, 255, 0.73);
border-radius: 4px;
}
::v-deep .ant-radio-button-wrapper-checked {
background: #0377f6;
box-shadow:
0px 10px 30px 0px rgba(0, 0, 6, 0.15),
inset 0px -1px 5px 0px rgba(213, 220, 255, 0.73);
}
}
.patrol-map {
position: absolute;
top: 80px;
right: calc(50% - 400px);
width: 800px;
height: 600px;
padding: 10px;
background: #0d0e15;
margin: 10px 0 0 10px;
box-shadow:
0px 10px 30px 0px rgba(0, 0, 6, 0.15),
inset 0px 0px 36px 0px rgba(58, 87, 232, 0.73);
border-radius: 6px;
backdrop-filter: blur(3px);
color: #fff;
z-index: 1001;
.map-container {
width: 100%;
height: calc(100% - 80px);
}
.map-container-content {
height: calc(100% - 10px);
}
}
</style>

File diff suppressed because it is too large Load Diff

View File

@ -51,25 +51,10 @@
<img src="@/assets/images/monitoring/nine.png" alt="" />
<span>九分屏</span>
</div>
<!-- <el-button :type="state.classtype1" @click="selecttype('classtype1', 1, 24)"
>单屏</el-button
>
<el-button :type="state.classtype2" @click="selecttype('classtype2', 4, 12)"
>四分屏</el-button
>
<el-button :type="state.classtype3" @click="selecttype('classtype3', 9, 8)"
>九分屏</el-button
> -->
<!-- <el-button :type="state.classtype4" @click="selecttype('classtype4', 16, 6)"
>十六分屏</el-button
>
<el-button :type="state.classtype5" @click="selecttype('classtype5', 36, 4)"
>三十二分屏</el-button
> -->
</div>
<div class="main">
<div class="conter" ref="box">
<el-row :gutter="10">
<el-row :gutter="16">
<el-col
v-for="(n, index) in state.fornum"
:key="index"
@ -78,33 +63,46 @@
:md="state.clonum"
:lg="state.clonum"
:xl="state.clonum"
:class="state.videoclass"
>
<div
class="player-wrapper"
element-loading-text="加载中..."
element-loading-background="#000"
>
<div class="video-title">
<div class="video-icon">
<img src="@/assets/images/monitoring/monitor-icon.png" alt="" />
<div class="video-container">
<div class="video-header">
<div class="video-title">
<div class="video-icon">
<img src="@/assets/images/monitoring/monitor-icon.png" alt="" />
</div>
<span>DJ大疆无人机3H</span>
</div>
<div class="video-controls">
<button class="control-btn" title="全屏">
<i class="el-icon-full-screen"></i>
</button>
<button class="control-btn" title="音量">
<i class="el-icon-video-camera"></i>
</button>
<button class="control-btn" title="设置">
<i class="el-icon-setting"></i>
</button>
</div>
</div>
<div class="video-content">
<flv-player
style="width: 100%; height: 100%;"
src="http://175.27.168.120:6012/live/8UUXN5400A079H.flv"
/>
</div>
<span>1212121212</span>
</div>
<flv-player
style="
width: 80%;
margin-bottom: 10px;
padding: 0 6px 6px 6px;
background: #292932;
border-radius: 0 0 10px 10px;
"
src="http://175.27.168.120:6012/live/8UUXN5400A079H.flv"
/>
</div>
</el-col>
</el-row>
</div>
<div class="status-bar">
<span>最后更新2025/12/30 14:55:32 系统运行正常</span>
</div>
</div>
</div>
</div>
@ -119,59 +117,58 @@
{
id: 1,
status: 1,
name: '监控1',
name: 'DJ大疆无人机A9H',
},
{
id: 2,
status: 2,
name: '监控2',
},
{
id: 1,
status: 1,
name: '监控1',
name: 'DJ大疆无人机A9H',
},
{
id: 2,
status: 2,
name: '监控2',
},
{
id: 2,
status: 2,
name: '监控2',
},
{
id: 1,
id: 3,
status: 1,
name: '监控1',
name: 'DJ大疆无人机A9H',
},
{
id: 1,
status: 1,
name: '监控1',
},
{
id: 2,
id: 4,
status: 2,
name: '监控2',
name: 'DJ大疆无人机A9H',
},
{
id: 1,
id: 5,
status: 1,
name: '监控1',
name: 'DJ大疆无人机A9H',
},
{
id: 2,
status: 2,
name: '监控2',
id: 6,
status: 1,
name: 'DJ大疆无人机A9H',
},
{
id: 7,
status: 1,
name: 'DJ大疆无人机A9H',
},
{
id: 8,
status: 1,
name: 'DJ大疆无人机A9H',
},
{
id: 9,
status: 1,
name: 'DJ大疆无人机A9H',
},
{
id: 10,
status: 1,
name: 'DJ大疆无人机A9H',
},
]);
const state = reactive({
fullscreen: false,
fornum: 1,
clonum: 24,
videoclass: 'padding-bottom: 50%; position: relative; margin: 0px auto;',
classtype1: '',
classtype2: 'primary',
classtype3: '',
@ -224,29 +221,35 @@
<style scoped lang="less">
.video-contain {
display: flex;
background: #1c1c24;
background: #0f0f13;
height: calc(100vh - 83px);
width: 99.6%;
width: 100%;
}
.video-left {
width: 16%;
background: #1c1c24;
background: #16161a;
display: flex;
flex-direction: column;
align-items: center;
border-right: 1px solid #232328;
.left-title {
font-weight: 500;
font-size: 24px;
font-size: 18px;
color: #ffffff;
padding: 20px 0 10px 0;
padding: 20px 0 15px 0;
width: 90%;
text-align: left;
margin-left: 20px;
}
.monitor-status {
width: 220px;
height: 70px;
background: #21212a;
width: 90%;
height: 50px;
background: #1a1a20;
color: #fff;
display: flex;
align-items: center;
border-radius: 6px;
margin-bottom: 20px;
.on-line {
width: 49%;
text-align: center;
@ -258,11 +261,14 @@
display: inline-block;
margin-right: 6px;
}
span {
font-size: 14px;
}
}
.line {
width: 1px;
height: 30px;
background: #92929d;
background: #2a2a33;
opacity: 0.8;
}
.under-line {
@ -276,26 +282,36 @@
margin-right: 6px;
display: inline-block;
}
span {
font-size: 14px;
}
}
}
}
.video-right {
width: 84%;
background: #0f0f13;
display: flex;
flex-direction: column;
.split-screen {
display: flex;
align-items: center;
padding: 20px;
background: #16161a;
border-bottom: 1px solid #232328;
.split-item {
display: flex;
align-items: center;
justify-content: center;
width: 120px;
height: 30px;
width: 100px;
height: 36px;
color: #fff;
cursor: pointer;
font-size: 14px;
transition: all 0.3s ease;
img {
width: 16px;
margin-right: 6px;
margin-right: 8px;
}
span {
font-size: 14px;
@ -303,63 +319,136 @@
}
.active {
background: #1e75ff;
color: #ffffff;
}
.split-item:first-child {
border: 1px solid #34343e;
border: 1px solid #2a2a33;
border-radius: 6px 0 0 6px;
}
.split-item:nth-child(2) {
border-top: 1px solid #34343e;
border-bottom: 1px solid #34343e;
border-top: 1px solid #2a2a33;
border-bottom: 1px solid #2a2a33;
}
.split-item:last-child {
border: 1px solid #34343e;
border: 1px solid #2a2a33;
border-radius: 0 6px 6px 0;
}
}
}
.main {
flex: 1;
padding: 20px;
overflow: auto;
}
.player-wrapper {
height: 100%;
min-height: 200px;
}
.video-container {
background: #16161a;
border-radius: 6px;
overflow: hidden;
height: 100%;
display: flex;
flex-direction: column;
}
.video-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 16px;
background: #1a1a20;
border-bottom: 1px solid #232328;
}
.video-title {
color: #92929d;
background: #292932;
width: 80%;
padding: 10px 20px;
border-radius: 6px 6px 0 0;
display: flex;
align-items: center;
img {
width: 20px;
}
span {
font-size: 14px;
}
.video-icon {
margin-right: 6px;
border-radius: 34px;
width: 34px;
height: 34px;
border: 1px solid #34343e;
width: 32px;
height: 32px;
border-radius: 4px;
background: #1e75ff;
display: flex;
align-items: center;
justify-content: center;
margin-right: 10px;
img {
width: 18px;
height: 18px;
}
}
span {
font-size: 14px;
color: #ffffff;
font-weight: 400;
}
}
.video-controls {
display: flex;
align-items: center;
}
.control-btn {
width: 28px;
height: 28px;
border: none;
background: transparent;
color: #92929d;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
border-radius: 4px;
margin-left: 8px;
transition: all 0.3s ease;
&:hover {
background: #25252f;
color: #ffffff;
}
i {
font-size: 16px;
}
}
.video-content {
flex: 1;
background: #0f0f13;
position: relative;
min-height: 150px;
}
.status-bar {
margin-top: 20px;
padding: 12px 20px;
background: #16161a;
border-radius: 6px;
text-align: right;
span {
font-size: 14px;
color: #92929d;
}
}
.monitor-list {
width: 100%;
width: 90%;
margin-top: 10px;
.monitor-item {
color: #fff;
font-size: 14px;
display: flex;
align-items: center;
margin-left: 20px;
margin-top: 20px;
padding: 12px 16px;
margin-bottom: 8px;
background: #1a1a20;
border-radius: 6px;
transition: all 0.3s ease;
&:hover {
background: #1e1e26;
}
.item-img {
width: 30px;
height: 30px;
width: 36px;
height: 36px;
border-radius: 6px;
display: flex;
align-items: center;
justify-content: center;
margin-right: 6px;
margin-right: 12px;
img {
width: 20px;
}
@ -368,27 +457,119 @@
background: #1e75ff;
}
.underline {
background: #2b2b40;
background: #25252f;
}
.item-content {
width: 70%;
flex: 1;
min-width: 0;
span {
display: block;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-size: 14px;
color: #ffffff;
}
}
.online-i {
width: 8px;
height: 8px;
border-radius: 8px;
border-radius: 50%;
background: #4bd884;
display: inline-block;
margin-right: 6px;
margin-left: 12px;
position: relative;
&:after {
content: '';
position: absolute;
top: -2px;
left: -2px;
right: -2px;
bottom: -2px;
border-radius: 50%;
background: #4bd884;
opacity: 0.5;
animation: pulse 2s infinite;
}
}
.underline-i {
width: 8px;
height: 8px;
border-radius: 8px;
border-radius: 50%;
background: #fe4848;
display: inline-block;
margin-right: 6px;
margin-left: 12px;
}
}
}
@keyframes pulse {
0% {
transform: scale(0.8);
opacity: 0.5;
}
70% {
transform: scale(1.2);
opacity: 0;
}
100% {
transform: scale(0.8);
opacity: 0;
}
}
/* 响应式布局调整 */
@media screen and (max-width: 1200px) {
.video-left {
width: 20%;
}
.video-right {
width: 80%;
}
.main {
padding: 15px;
}
}
@media screen and (max-width: 992px) {
.video-left {
width: 25%;
}
.video-right {
width: 75%;
}
.left-title {
font-size: 16px !important;
}
.split-screen {
padding: 15px;
}
.split-item {
width: 90px !important;
height: 32px !important;
}
}
@media screen and (max-width: 768px) {
.video-contain {
flex-direction: column;
}
.video-left {
width: 100%;
border-right: none;
border-bottom: 1px solid #232328;
max-height: 300px;
}
.video-right {
width: 100%;
}
.monitor-list {
max-height: 200px;
overflow-y: auto;
}
.main {
padding: 10px;
}
}
</style>

View File

@ -218,50 +218,7 @@
axios.get(VITE_GLOB_PY_URL + '/api/tasks').then((res) => {
console.log(res.data.data);
const data = res.data.data;
// const data = {
// active: 1,
// models_count: 1,
// tasks: [
// {
// algoInstancesName: '',
// config: {
// enable_push: true,
// push_url: 'rtmp://175.27.168.120:1935/live/1581F6Q8X24BT00G01GZ1',
// rtmp_url: 'rtmp://175.27.168.120:6019/live/1581F6Q8X24BT00G01GZ',
// taskname: ' 20260112132523',
// },
// created_at: '2026-01-12T13:38:38.827486',
// models: [
// {
// color: null,
// conf_thres: 1,
// enabled: true,
// encrypted: true,
// id: 0,
// key_provided: true,
// name: '59e9f6069e5c3fa4',
// path: 'encrypted_models/59e9f6069e5c3fa4.enc',
// },
// ],
// stats: {
// avg_fps: 0,
// detections: 0,
// encrypted_models: 1,
// key_validated: true,
// key_validation_required: true,
// models_loaded: 1,
// start_time: 1768196318.8275044,
// total_frames: 0,
// validation_time: 1768196318.8275054,
// },
// status: 'running',
// task_id: '4097e184-6429-458d-8a52-bc3324b7b617',
// uavType: 'M3TD',
// },
// ],
// total: 1,
// };
const arr = [];
const arr:any = [];
data.tasks.forEach((element) => {
arr.push({
task_id: element.task_id,

View File

@ -3189,7 +3189,7 @@
}
// //
let position = [props.homeAirport.longitude, props.homeAirport.latitude, 70];
console.log(1111111111111111111, position, props.homeAirport);
// console.log(1111111111111111111, position, props.homeAirport);
let airportImg =
props.homeAirport.mode_code == 4
? '/projecthome/work_airport.png'

5
types/config.d.ts vendored
View File

@ -168,4 +168,9 @@ export interface GlobEnvConfig {
VITE_GLOB_APP_MANAGEMENT_UNIT?: string;
VITE_GLOB_APP_TECHINICAL_SUPPORT?: string;
VITE_GLOB_APP_VERSIONS?: string;
VITE_GLOB_FILE_PREVIEW?: string;
VITE_GLOB_APP_HEADER_TITLE?: string;
VITE_GLOB_PY_URL?: string;
VITE_MQTT_URL?: string;
VITE_MQTT_PORT?: number;
}