徐景良 6 days ago
commit 77abcbadf6

@ -43,13 +43,13 @@
<!-- 引入青犀插件内容 -->
<!-- <script type="text/javascript" src="./public/monitor/monitorQX/EasyPlayer-element.min.js"></script> -->
<!-- 引入大华算法 -->
<link rel="stylesheet" href="./public/smartJs/css/layui.css">
<link rel="stylesheet" href="./public/smartJs/theme.css">
<link rel="stylesheet" href="./public/smartJs/smart-style.css">
<script src="./public/smartJs/runtime.js"></script>
<script src="./public/smartJs/layui.js"></script>
<script src="./public/smartJs/xm-select.js"></script>
<script src="./public/smartJs/smart.js"></script>
<link rel="stylesheet" href="/smartJs/css/layui.css">
<link rel="stylesheet" href="/smartJs/theme.css">
<link rel="stylesheet" href="/smartJs/smart-style.css">
<script src="/smartJs/runtime.js"></script>
<script src="/smartJs/layui.js"></script>
<script src="/smartJs/xm-select.js"></script>
<script src="/smartJs/smart.js"></script>
</head>

@ -106,6 +106,7 @@
"fabric": "^4.6.0",
"fast-xml-parser": "^5.2.5",
"file-saver": "^2.0.5",
"flv.js": "^1.6.2",
"highlight.js": "^11.9.0",
"js-base64": "3.7.7",
"js-md5": "^0.8.3",

@ -7,6 +7,8 @@ enum Api {
AddAlgorithmsRepository = '/api/AlgorithmsRepository/AddAlgorithmsRepository',
// 修改算法
UpdateAlgorithmsRepository = '/api/AlgorithmsRepository/UpdateAlgorithmsRepository',
// 删除算法
DeleteAlgorithmsRepository = '/api/AlgorithmsRepository/DeleteAlgorithmsRepository'
}
export const GetAlgorithmsRepositoryList = (params) => defHttp.get({
@ -20,4 +22,8 @@ export const AddAlgorithmsRepository = (params) => defHttp.post({
export const UpdateAlgorithmsRepository = (params) => defHttp.post({
url: Api.UpdateAlgorithmsRepository,
params,
});
export const DeleteAlgorithmsRepository = (params) => defHttp.post({
url: `${Api.DeleteAlgorithmsRepository}?id=${params.id}`,
params,
});

@ -2,13 +2,14 @@
<div ref="scrollBox" class="show-image-div">
<a-image-preview-group>
<a-image
v-for="value in props.showInfoData.aiAchievementDetailList"
:key="value"
v-for="(value, index) in props.showInfoData.aiAchievementDetailList"
:key="index"
:width="232"
:height="140"
style="border-radius: 10px;"
class="image-item"
:src="`${value.image}`"
:img-props="{ loading: 'lazy' }"
/>
</a-image-preview-group>
</div>
@ -47,7 +48,7 @@ onMounted(() => {
.show-image-div {
width: calc(100% - 417px);
height: 185px;
padding: 23px 25px 22px 25px;
padding: 23px 25px 0px 25px;
position: absolute;
bottom: 0px;
left: 417px;
@ -56,7 +57,7 @@ onMounted(() => {
/* 核心:横向滚动 */
display: flex;
overflow-x: auto;
// overflow-x: auto;
overflow-y: hidden;
white-space: nowrap;
gap: 22px;
@ -70,6 +71,22 @@ onMounted(() => {
border-radius: 10px;
}
}
.show-image-div::-webkit-scrollbar {
height: 12px; /* 横向滚动条高度 */
}
.show-image-div::-webkit-scrollbar-track {
background: transparent; /* 滚动条轨道背景 */
}
.show-image-div::-webkit-scrollbar-thumb {
background-color: rgb(255, 255, 255); /* 滚动条颜色 */
border-radius: 4px;
}
.show-image-div::-webkit-scrollbar-thumb:hover {
background-color: rgb(255, 255, 255);
}
.image-item {
border-radius: 10px;

@ -3,14 +3,19 @@
<div class="left-menu-title">AI成果</div>
<div class="left-menu-search-div">
<a-select
v-model:value="type"
:allowClear="true"
placeholder="选择分类"
popupClassName="ai-achievement-classify-dropdown"
class="classify-select"
:options="classifyOptions"
@change="changeType"
/>
<a-range-picker class="date-select" />
<a-range-picker v-model:value="searchTime" class="date-select" :format="dateFormatList"
@change="changeSearchTime"
/>
</div>
<div class="show-list-div">
<div class="show-list-div" ref="scrollBox" @scroll="handleScroll">
<div :class="`list-item-outer ${selectItemId == item.id?'list-item-outer-select' : ''}`" v-for="(item,index) in dataList" >
<div class="list-item-inner">
<img class="item-image" :src="`${item.cover}`" >
@ -31,33 +36,102 @@
</div>
</div>
</div>
<div v-if="loading" class="loading-text">...</div>
<div v-else-if="dataList.length >= total" class="loading-text">没有更多数据了</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref, onMounted } from 'vue';
import { UpdateWorkArea, UpdateAnnotation } from '@/api/demo/mediaLibrary';
import { useMessage } from '@/hooks/web/useMessage';
import { GetAiAchievementList } from '@/api/demo/aiachievement'
import { getAppEnvConfig } from '@/utils/env';
const { VITE_GLOB_API_URL } = getAppEnvConfig();
import { GetAlgorithmsRepositoryList } from '@/api/demo/ailist'
import dayjs from 'dayjs';
const emits = defineEmits([
'changeLeftMenuShow'
]);
onMounted(() => {
GetAiAchievementList({page:1,limit:999}).then(res => {
console.log('res',res)
dataList.value = res.items
GetAlgorithmsRepositoryList({page: 1,limit: 999,}).then(res => {
total.value = res.total
classifyOptions.value = res.items.map(item => {
return {
label: item.name,
value: item.id
}
})
}).finally(() => {
loading.value = false
})
fetchData()
})
const dateFormatList = ['YYYY-MM-DD', 'YYYY-MM-DD']
const selectItemId = ref()
const dataList = ref([])
const dataList = ref<any>([])
const type = ref()
const searchTime = ref()
const startTime = ref()
const endTime = ref()
const page = ref(1)
const limit = ref(10)
const total = ref(0)
const loading = ref(false)
const scrollBox = ref<HTMLDivElement>()
const classifyOptions = ref([
{label:'1231231', value:'123123123'},
{label:'222', value:'222'},
{label:'333', value:'333'},
])
async function fetchData() {
if (loading.value) return
loading.value = true
try {
const res = await GetAiAchievementList({
page: page.value,
limit:limit.value,
type: type.value,
startTime: startTime.value,
endTime: endTime.value
})
total.value = res.total
dataList.value = [...dataList.value, ...res.items]
page.value++
} finally {
loading.value = false
}
}
async function searchFetchData() {
if (loading.value) return
loading.value = true
try {
page.value = 1
const res = await GetAiAchievementList({
page: page.value,
limit:limit.value,
type: type.value,
startTime: startTime.value,
endTime: endTime.value
})
total.value = res.total
dataList.value = [...res.items]
page.value++
} finally {
loading.value = false
}
}
function handleScroll(e: Event) {
const el = e.target as HTMLElement
if (el.scrollTop + el.clientHeight >= el.scrollHeight - 10) {
if (dataList.value.length < total.value) {
fetchData()
}
}
}
const changeSearchTime = (value, dateString: [string, string]) => {
console.log('value',value)
console.log('dateFormat',dateString)
startTime.value = dateString[0]
endTime.value = dateString[1]
searchFetchData()
}
const changeType = () => {
searchFetchData()
}
function showInfo(item){
selectItemId.value = item.id
emits('changeLeftMenuShow',item);
@ -97,6 +171,9 @@
::v-deep(.ant-select-selection-placeholder) {
color: rgba(255, 255, 255, 0.15);
}
:deep(.ant-select-clear){
background: #252525;
}
}
.date-select{
width: 269px;
@ -281,4 +358,10 @@
background-color: #37383d !important;
}
}
.loading-text {
text-align: center;
color: #aaa;
font-size: 12px;
padding: 10px 0;
}
</style>

@ -56,6 +56,7 @@
style="margin-bottom: 6px;"
class="item-select item-multiple-select"
mode="multiple"
placeholder="请选择算法"
v-model:value="algoIdsList"
:options="props.algorithmOptions"
@change="changeSelectAlgorithm"
@ -268,7 +269,6 @@ const recognitionCoverageFirst = ref('')
const recognitionCoverageLast = ref('')
const selectImageModal = ref(false)
const selectEventsOptions = ref([
{ label: 'aaa', value: 'aaa' }
])
const items = ref([
{ title: '基础信息', },

@ -32,7 +32,7 @@
<div class="content-item">
<div class="item-label">AI算法</div>
<div class="item-value">
<div v-for="algoName in props.showInfoData.algoNames">{{ `${algoName}` }}</div>
<div v-html="getContentStr(props.showInfoData.algoIds)"></div>
</div>
</div>
<div class="content-interval"></div>
@ -64,8 +64,13 @@ import { defineProps, defineEmits } from "vue"
import { EditOutlined, CloseOutlined } from '@ant-design/icons-vue'
import { getAppEnvConfig } from '@/utils/env';
const { VITE_GLOB_API_URL } = getAppEnvConfig();
const props = defineProps(['showInfoData'])
const props = defineProps(['showInfoData','algorithmOptions'])
const emits = defineEmits(['changeDrawerModal','changeAddModal'])
const getContentStr = (listId: string) => {
let idList = listId.split(',')
const names = idList.map(id => `#${props.algorithmOptions.find(item => item.value === id)?.label}`).join('<br/>')
return names
}
</script>
<style lang="scss" scoped>
@ -109,6 +114,13 @@ const emits = defineEmits(['changeDrawerModal','changeAddModal'])
}
}
.drawer-content{
height: calc(100vh - 63px);
overflow: auto;
scrollbar-width: none;
::-webkit-scrollbar{
width: 0;
height: 0;
}
padding: 30px;
.content-image{
width: 300px;
@ -164,7 +176,7 @@ const emits = defineEmits(['changeDrawerModal','changeAddModal'])
}
.item-description-value{
width: 294px;
height: 27px;
// height: 27px;
// background: rgba(216, 216, 216, 0.34);
padding-left: 28px;
font-family: PingFangSC-Medium;
@ -174,6 +186,11 @@ const emits = defineEmits(['changeDrawerModal','changeAddModal'])
line-height: 20px;
display: flex;
align-items: center;
// display: -webkit-box;
// -webkit-box-orient: vertical;
// -webkit-line-clamp: ;
// overflow: hidden;
// text-overflow: ellipsis;
}
}
.content-item{

@ -23,7 +23,7 @@
<div class="item-list" v-for="item in dataList">
<div class="image-div">
<img class="image-item" :src="`${VITE_GLOB_API_URL}/${item.cover}`">
<div class="image-icon">盖板缺失</div>
<!--<div class="image-icon">盖板缺失</div> -->
</div>
<div class="show-info-div">
<div class="info-title-div">
@ -31,36 +31,22 @@
<div class="info-title-inner">
<div class="info-title">{{ item.name }}</div>
<div style="display: flex;justify-content: space-between;">
<div class="info-subtitle">{{ item.description }}</div>
<a-popover overlayClassName="instance-show-more-info-popover" trigger="click" placement="topRight">
<template #content>
<div class="show-more-content">
<div class="content-raw">
<div class="content-label">关联事件</div>
<div class="content-value">
<div>-</div>
</div>
</div>
<div class="content-raw">
<div class="content-label">关联算法</div>
<div class="content-value">
<div v-for="algoName in item.algoNames">{{ `#${algoName}` }}</div>
</div>
</div>
</div>
</template>
<div class="show-more-info">
<div class="show-more-span">展开更多</div>
<div class="show-more-icon"></div>
</div>
</a-popover>
<div class="info-subtitle">{{ item.description? item.description: '暂无描述' }}</div>
</div>
</div>
</div>
<div class="info-content-div">
<div class="content-div">
<div style="width: 153px;margin-right: 14px;">
<div class="content-title-div">关联算法</div>
<div class="content-info" v-html="getContentStr(item.algoIds)"></div>
</div>
<div class="button-div">
<a-button class="delete-button" @click="delData(item)"></a-button>
<a-button class="show-info-button" type="primary" @click="showInfo(item)"></a-button>
</div>
</div>
</div>
</div>
<div class="item-footer">
<a-button class="item-del" @click="delData(item)"></a-button>
<a-button class="item-show" type="primary" @click="showInfo(item)"></a-button>
</div>
</div>
</div>
@ -87,7 +73,7 @@
placement="right"
rootClassName="instance-show-info-drawer"
>
<ShowInfoDrawer :showInfoData="showInfoData" @changeDrawerModal="changeDrawerModal" @changeAddModal="changeAddModal"/>
<ShowInfoDrawer :showInfoData="showInfoData" :algorithmOptions="algorithmOptions" @changeDrawerModal="changeDrawerModal" @changeAddModal="changeAddModal"/>
</a-drawer>
</div>
</a-spin>
@ -172,6 +158,7 @@ const delData = (item) => {
icon: createVNode(ExclamationCircleOutlined),
okText: '确认',
cancelText: '取消',
centered: true,
onOk() {
return DeleteAlgoInstance({id: item.id}).then(res => {
message.success("删除成功")
@ -180,11 +167,16 @@ const delData = (item) => {
},
});
}
const getContentStr = (listId: string) => {
let idList = listId.split(',')
const names = idList.map(id => `#${algorithmOptions.value.find(item => item.value === id)?.label}`).join('<br/>')
return names
}
</script>
<style lang="scss" scoped>
.page-out{
padding: 16px 30px 53px 17px;
padding: 16px 30px 33px 17px;
width: 100%;
height: calc(100vh - 80px);
.title{
@ -264,7 +256,7 @@ const delData = (item) => {
display: flex;
flex-wrap: wrap;
gap: 20px;
padding-bottom: 55px;
padding-bottom: 20px;
overflow: auto;
scrollbar-width: none;
::-webkit-scrollbar{
@ -273,7 +265,7 @@ const delData = (item) => {
}
.item-list{
width: 300px;
height: 291px;
height: 321px;
background: #FFFFFF;
box-shadow: 5px 18px 32px 0px rgba(28,29,34,0.1);
border-radius: 10px;
@ -323,7 +315,7 @@ const delData = (item) => {
margin-right: 5px;
}
.info-title-inner{
width: 100%;
width: calc(100% - 8px);
.info-title{
font-family: PingFangSC-Medium;
font-weight: 500;
@ -331,6 +323,9 @@ const delData = (item) => {
color: #1C1D22;
line-height: 20px;
margin-bottom: 5px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.info-subtitle{
font-family: PingFangSC-Regular;
@ -338,6 +333,9 @@ const delData = (item) => {
font-size: 11px;
color: rgba(28,29,34,0.5);
line-height: 15px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.show-more-info{
@ -362,62 +360,75 @@ const delData = (item) => {
}
}
.info-content-div{
width: 100%;
height: 66px;
background-image: url('/public/instance/instance_list_item_info_content.png');
padding-top: 8px;
padding-left: 12px;
margin-bottom: 13px;
.content-raw{
display: flex;
.content-div{
display: flex;
.content-label{
width: 100%;
margin-top: 4px;
padding-top: 8px;
border-top: 1px dashed rgba(151, 151, 151, 0.37);
.content-title-div{
display: flex;
align-items: center;
justify-content: center;
width: 47px;
height: 19px;
background: rgba(216, 216, 216,0.34);
border-radius: 2px;
font-family: PingFangSC-Regular;
font-weight: 400;
font-size: 12px;
font-size: 10px;
color: #1C1D22;
line-height: 17px;
margin-right: 11px;
line-height: 14px;
}
.content-value{
font-family: PingFangSC-Medium;
font-weight: 500;
font-size: 12px;
.content-info{
font-family: PingFangSC-Regular;
font-weight: 400;
font-size: 10px;
color: #1C1D22;
line-height: 17px;
line-height: 14px;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
text-overflow: ellipsis;
}
.button-div{
padding-top: 23px;
display: flex;
.delete-button{
display: flex;
align-items: center;
justify-content: center;
width: 54px;
height: 23px;
border-radius: 2px;
border: 1px solid #0B60BD;
font-family: PingFangSC-Regular;
font-weight: 400;
font-size: 11px;
color: #0B60BD;
line-height: 15px;
margin-right: 6px;
}
.show-info-button{
display: flex;
align-items: center;
justify-content: center;
width: 54px;
height: 23px;
background: #0B60BD;
border-radius: 2px;
border: 1px solid #0B60BD;
font-family: PingFangSC-Regular;
font-weight: 400;
font-size: 11px;
color: #FFFFFF;
line-height: 15px;
}
}
}
}
}
.item-footer{
width: 100%;
height: 23px;
display: flex;
align-items: center;
justify-content: end;
padding-right: 12px;
.item-del{
width: 54px;
height: 23px;
border-radius: 2px;
border: 1px solid #F2F2F2;
margin-right: 7px;
font-family: PingFangSC-Regular;
font-weight: 400;
font-size: 11px;
color: #E3150E;
line-height: 15px;
}
.item-show{
width: 54px;
height: 23px;
background: #0B60BD;
border-radius: 2px;
border: 1px solid #0B60BD;
font-family: PingFangSC-Regular;
font-weight: 400;
font-size: 11px;
color: #FFFFFF;
line-height: 15px;
}
}
}

@ -91,6 +91,7 @@
<div class="interval"></div>
<div class="footer">
<a-button class="cancel-button" @click="emits('changeAddModal',false)"></a-button>
<a-button v-if="props.modalType == 'update'" class="delete-button" type="primary" @click="delData"></a-button>
<a-button class="save-button" type="primary" @click="submit"></a-button>
</div>
</a-spin>
@ -100,14 +101,14 @@
</template>
<script setup lang="ts">
import { ref, h, defineEmits, defineProps, onMounted } from "vue"
import { ref, h, defineEmits, defineProps, onMounted, createVNode } from "vue"
import { uploadFile } from '@/api/formrender/index';
import { PlusOutlined, } from '@ant-design/icons-vue';
import { ExclamationCircleOutlined, PlusOutlined, } from '@ant-design/icons-vue';
import SelectImageModal from "./SelectImageModal.vue";
import { ModelLabelsType } from './utils'
import { getAppEnvConfig } from '@/utils/env';
import { AddAlgorithmsRepository, UpdateAlgorithmsRepository } from '@/api/demo/ailist'
import { message } from "ant-design-vue";
import { AddAlgorithmsRepository, UpdateAlgorithmsRepository, DeleteAlgorithmsRepository } from '@/api/demo/ailist'
import { message, Modal } from "ant-design-vue";
const { VITE_GLOB_API_URL } = getAppEnvConfig();
const props = defineProps(['modalType', 'algorithmInfo'])
const emits = defineEmits(['changeAddModal', 'query'])
@ -226,6 +227,22 @@ const submit = () => {
})
}
}
const delData = () => {
Modal.confirm({
title: `确认删除该算法吗?`,
icon: createVNode(ExclamationCircleOutlined),
okText: '确认',
cancelText: '取消',
centered: true,
onOk() {
return DeleteAlgorithmsRepository({id: id.value}).then(res => {
message.success("删除成功")
emits('query')
emits('changeAddModal',false)
})
},
});
}
</script>
<style lang="scss" scoped>
@ -550,6 +567,20 @@ const submit = () => {
text-shadow: 0px 10px 30px rgba(0,0,6,0.15);
margin-right: 14px;
}
.delete-button{
width: 146px;
height: 40px;
background: #ed6f6f;
box-shadow: 0px 10px 30px 0px rgba(0,0,6,0.15);
border-radius: 4px;
font-family: PingFangSC-Medium;
font-weight: 500;
font-size: 16px;
color: #FFFFFF;
line-height: 33px;
text-shadow: 0px 10px 30px rgba(0,0,6,0.15);
margin-right: 14px;
}
.save-button{
width: 146px;
height: 40px;

@ -127,7 +127,7 @@
groupIndex.value = index;
}
//
const graffitiColor = ref('');
const graffitiColor = ref('#ffffff');
function chooseGraffitiColor(color) {
graffitiColor.value = color;
}

@ -483,6 +483,7 @@
}
//
if (tableType.value === 'table') {
let showTableDataClone = cloneDeep(showTableData.value);
reload().then((res) => {
tableTypeAfterShow.value = tableType.value;
// -
@ -501,7 +502,7 @@
});
}
//
let selectRowsIdArray = showTableData.value.filter((item) => item.checked);
let selectRowsIdArray = showTableDataClone.filter((item) => item.checked);
setSelectedRows(selectRowsIdArray);
});
}
@ -1222,7 +1223,7 @@
width: 165px;
height: 130px;
outline: 1px solid #000000;
margin: 16px;
margin: 14px;
display: flex;
align-items: center;

@ -73,16 +73,17 @@
@changeCameraType="changeCameraType"
/>
<div class="intelligent-patrol" v-if="taskId">
<div @click="patrolVisible = true">
<div @click="patrolClick">
<span> <RadarChartOutlined /> </span>
<span>智能巡检</span>
<span v-if="stopPatrolVisible"></span>
<span v-else></span>
</div>
<div @click="reportVisible = true">
<!-- <div @click="reportVisible = true">
<span> <AlertOutlined /></span>
<span>上报事件</span>
</div>
</div> -->
</div>
<Patrol :taskId="taskId" v-if="patrolVisible" @changePatrol="patrolVisible = false" />
<Patrol :taskId="taskId" v-if="patrolVisible" @changePatrol="changePatrol" :zIndex="zIndex" />
<Report @changeReport="reportVisible = false" v-if="reportVisible" />
</div>
</template>
@ -111,7 +112,10 @@
import { drcUpTopic, setTopic } from '@/utils/debugging/remote';
import { airPortStore } from '@/store/modules/airport';
import { AlertOutlined, RadarChartOutlined } from '@ant-design/icons-vue';
import { endHandFlyTask } from '@/api/workmanagement/droneDock';
import io from 'socket.io-client';
let socket;
const zIndex = ref(0);
const airPortStoreVal = airPortStore();
const airPortInfo = airPortStoreVal.getAirport;
@ -139,7 +143,40 @@
const topicUAVUrl = computed(() => {
return 'thing/product/' + UAVinfo.sn + '/osd';
});
const taskId = ref(airPortStoreVal.getTaskId);
const patrolClick = () => {
console.log('patrolClick', airPortStoreVal.getTaskId);
if (airPortStoreVal.getTaskId) {
endHandFlyTask({
taskid: airPortStoreVal.getTaskId,
}).then((res) => {
if (res) {
if (socket) {
socket.disconnect();
}
airPortStoreVal.setTaskId(null);
}
});
} else {
zIndex.value++;
patrolVisible.value = true;
}
};
const stopPatrolVisible = ref(false);
console.log('airPortStoreVal', airPortStoreVal.getTaskId);
if (airPortStoreVal.getTaskId) {
stopPatrolVisible.value = true;
}
const changePatrol = (val) => {
if (val) {
stopPatrolVisible.value = true;
}
patrolVisible.value = false;
};
onMounted(() => {
// socket = io('http://192.168.10.131:9025');
socket = io('http://123.132.248.154:9309');
destroyConnection();
createConnection(connectCallback);
setTimeout(() => {
@ -225,7 +262,6 @@
flyToFormVisible.value = true;
zIndex.value++;
};
const taskId = ref('');
const changeTakeOffForm = (val) => {
takeOffFormVisible.value = false;
if (val) {

@ -558,7 +558,8 @@
}
};
onMounted(() => {
socket = io('http://192.168.10.131:9025');
// socket = io('http://192.168.10.131:9025');
socket = io('http://123.132.248.154:9309');
//
document.addEventListener('keydown', handleKeyDown);
document.addEventListener('keyup', handleKeyUp);

@ -1,93 +1,106 @@
<template>
<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">
<div class="input-result">
<span :style="{ backgroundColor: instantiateItem.displayColor }">
{{ instantiateItem.displayScheme }}</span
>
{{ instantiateItem.name }}
<VueDragResize
:w="width"
:h="height"
:x="left"
:y="top"
:z="zIndex"
:isActive="true"
:parentLimitation="true"
:isResizable="false"
>
<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">
<div class="input-result">
<span :style="{ backgroundColor: instantiateItem.displayColor }">
{{ instantiateItem.displayScheme }}</span
>
{{ instantiateItem.name }}
</div>
<UpOutlined v-if="instantiateVisible" />
<DownOutlined v-else />
<div class="select-result" v-if="instantiateVisible">
<div
v-for="(item, index) in instantiateOptions"
:key="index"
@click="instantiateSelect(item)"
>
<span :style="{ backgroundColor: item.displayColor }">{{
item.displayScheme
}}</span>
{{ item.name }}
</div>
</div>
</div>
<UpOutlined v-if="instantiateVisible" />
<DownOutlined v-else />
<div class="select-result" v-if="instantiateVisible">
<div
v-for="(item, index) in instantiateOptions"
:key="index"
@click="instantiateSelect(item)"
>
<span :style="{ backgroundColor: item.displayColor }">{{ item.displayScheme }}</span>
{{ item.name }}
<div class="content-edit space">
<span>空间约束范围</span>
<div class="space-content">
<span>导入KML</span>
<span @click="drawarea = true"><PlusOutlined />新增</span>
</div>
</div>
</div>
<div class="content-edit space">
<span>空间约束范围</span>
<div class="space-content">
<span>导入KML</span>
<span @click="drawarea = true"><PlusOutlined />新增</span>
<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>
<div class="content-edit" style="border: none">
<a-radio-group v-model:value="data.action" button-style="solid">
<a-radio-button value="1">关闭</a-radio-button>
<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
>
</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>
<div class="content-edit" style="border: none">
<a-radio-group v-model:value="data.action" button-style="solid">
<a-radio-button value="1">关闭</a-radio-button>
<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="patrol-map" v-if="drawarea">
<div class="title">绘制范围</div>
<div class="map-container">
<div class="map-container-content">
<Map :drawArea="drawarea" @areaData="getAreaData" />
</div>
</div>
<div class="content-button">
<a-button type="primary" style="background: #3a57e8" @click="emits('changePatrol')"
<a-button type="primary" style="background: #3a57e8" @click="drawarea = false"
>取消</a-button
>
<a-button type="primary" style="background: #0a99eb; margin-left: 20px" @click="submit"
<a-button
type="primary"
style="background: #0a99eb; margin-left: 20px"
@click="patrolMapConfirm"
>确定</a-button
>
</div>
</div>
</div>
<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" />
</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
>
</div>
</div>
</div>
</VueDragResize>
</template>
<script setup lang="ts">
import { reactive, ref, watch, onMounted } from 'vue';
@ -103,6 +116,7 @@
import { airPortStore } from '@/store/modules/airport';
import { callAiModel } from '@/api/workmanagement/droneDock';
import { EventBus } from '@/utils/eventBus';
import VueDragResize from 'vue-drag-resize/src';
const airPortStoreVal = airPortStore();
@ -111,7 +125,14 @@
const props = defineProps({
taskId: String,
type: String,
zIndex: Number,
});
const pageWidth = document.documentElement.clientWidth;
const width = ref(300);
const height = ref(550);
const left = ref(pageWidth - 620);
const top = ref(100);
const zIndex = ref(props.zIndex);
const data = reactive({
instantiate: null,
code: '',
@ -177,14 +198,14 @@
createMessage.warning('请选择AI算法实例');
return;
}
if (!data.code) {
createMessage.warning('警告提示标题不能为空');
return;
}
if (!data.desc) {
createMessage.warning('警告提示内容不能为空');
return;
}
// if (!data.code) {
// createMessage.warning('');
// return;
// }
// if (!data.desc) {
// createMessage.warning('');
// return;
// }
if (props.type == 'plan') {
const querys = {
algoInstanceId: instantiateItem.value.id,
@ -206,7 +227,7 @@
console.log(res);
createMessage.success('操作成功');
airPortStoreVal.setTaskId(props.taskId);
emits('changePatrol');
emits('changePatrol', true);
});
};
onMounted(() => {
@ -248,8 +269,8 @@
}
.airport-information {
position: absolute;
top: 100px;
right: 140px;
top: 0;
right: 5px;
width: 290px;
padding: 10px;
background: #0d0e15;

@ -54,7 +54,8 @@
function connectWebSocket() {
console.log('connectWebSocket');
// Socket
socket = io('http://192.168.10.131:9025');
// socket = io('http://192.168.10.131:9025');
socket = io('http://123.132.248.154:9309');
//
socket.on('connect', () => {

@ -0,0 +1,158 @@
<template>
<div class="video-stream-container">
<div class="original-video">
<div class="title">
<VideoCameraOutlined />
原始视频流
<RedoOutlined title="刷新" @click="reloadLive" />
</div>
<div class="player">
<video
id="player-container-original-live"
width="480"
height="340"
preload="auto"
playsinline
webkit-playsinline
>
</video>
</div>
</div>
<div class="testing-video">
<div class="title">
<VideoCameraOutlined />
检测后视频流
<RedoOutlined title="刷新" @click="reloadTestingLive" />
</div>
<div class="player">
<video
id="player-container-testing-live"
width="480"
height="340"
preload="auto"
playsinline
webkit-playsinline
>
</video>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import TCPlayer from 'tcplayer.js';
import 'tcplayer.js/dist/tcplayer.min.css'; //
import { airPortStore } from '@/store/modules/airport';
import { onMounted, watch, onBeforeUnmount } from 'vue';
import { VideoCameraOutlined, RedoOutlined } from '@ant-design/icons-vue';
const props = defineProps({
statisData: {
type: Array,
default: () => [],
},
});
const airPortStoreVal = airPortStore();
const live_info = airPortStoreVal.getLiveInfo;
//
let player;
const liveCode = live_info.url + '7.flv';
const playVideo = () => {
player = TCPlayer('player-container-original-live', {
sources: [
{
src: liveCode, //
},
],
licenseUrl: liveCode, // license license licenseUrl
});
};
//
let playerTesting;
const testingCode = live_info.url + '11.flv';
const testingPlayVideo = () => {
player = TCPlayer('player-container-testing-live', {
sources: [
{
src: testingCode, //
},
],
licenseUrl: testingCode, // license license licenseUrl
});
};
const reloadLive = () => {
player.src(liveCode);
player.play();
};
const reloadTestingLive = () => {
if (playerTesting) {
playerTesting.src(testingCode);
playerTesting.play();
}
};
onMounted(() => {
playVideo();
testingPlayVideo();
setTimeout(() => {
if (player) {
player.play();
}
if (playerTesting) {
playerTesting.play();
}
}, 1000);
});
watch(
() => props.statisData,
(val) => {
reloadLive();
reloadTestingLive();
},
);
//
onBeforeUnmount(() => {
if (player) {
player.dispose();
player = null;
}
if (playerTesting) {
playerTesting.dispose();
playerTesting = null;
}
});
</script>
<style lang="scss" scoped>
.video-stream-container {
width: 500px;
margin-left: 20px;
.original-video {
height: 40vh;
background: linear-gradient(180deg, rgba(13, 25, 45, 0.87) 0%, #182f4e 100%);
box-shadow: 0px 10px 30px 0px rgba(0, 0, 6, 0.15);
border-radius: 6px;
backdrop-filter: blur(3.62969752520624px);
}
.testing-video {
margin-top: 10px;
height: 40vh;
background: linear-gradient(180deg, rgba(13, 25, 45, 0.87) 0%, #182f4e 100%);
box-shadow: 0px 10px 30px 0px rgba(0, 0, 6, 0.15);
border-radius: 6px;
backdrop-filter: blur(3.62969752520624px);
}
.title {
color: #fff;
padding: 10px 0;
margin: 0 20px;
border-bottom: 1px solid #4e5778;
}
.player {
height: 80%;
video {
margin-left: 10px;
}
}
}
</style>

@ -7,15 +7,9 @@
<RedoOutlined title="刷新" @click="reloadLive" />
</div>
<div class="player">
<video
id="player-container-original-live"
width="480"
height="340"
preload="auto"
playsinline
webkit-playsinline
>
</video>
<div class="video-content">
<video id="player-container-original-live" class="video-player" controls></video>
</div>
</div>
</div>
<div class="testing-video">
@ -25,25 +19,18 @@
<RedoOutlined title="刷新" @click="reloadTestingLive" />
</div>
<div class="player">
<video
id="player-container-testing-live"
width="480"
height="340"
preload="auto"
playsinline
webkit-playsinline
>
</video>
<div class="video-content">
<video id="player-container-testing-live" class="video-player" controls></video>
</div>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import TCPlayer from 'tcplayer.js';
import 'tcplayer.js/dist/tcplayer.min.css'; //
import { airPortStore } from '@/store/modules/airport';
import { onMounted, watch, onBeforeUnmount } from 'vue';
import { VideoCameraOutlined, RedoOutlined } from '@ant-design/icons-vue';
import flvjs from 'flv.js';
const props = defineProps({
statisData: {
@ -58,38 +45,57 @@
let player;
const liveCode = live_info.url + '7.flv';
const playVideo = () => {
player = TCPlayer('player-container-original-live', {
sources: [
{
src: liveCode, //
},
],
licenseUrl: liveCode, // license license licenseUrl
var originalElement = document.getElementById('player-container-original-live');
var player = flvjs.createPlayer({
type: 'flv',
url: liveCode,
});
player.attachMediaElement(originalElement);
player.load();
player.play();
};
//
let playerTesting;
const testingCode = live_info.url + '11.flv';
const testingPlayVideo = () => {
player = TCPlayer('player-container-testing-live', {
sources: [
{
src: testingCode, //
},
],
licenseUrl: testingCode, // license license licenseUrl
var testingElement = document.getElementById('player-container-testing-live');
var playerTesting = flvjs.createPlayer({
type: 'flv',
url: testingCode,
});
playerTesting.attachMediaElement(testingElement);
playerTesting.load();
playerTesting.play();
};
const reloadLive = () => {
player.src(liveCode);
player.play();
var originalElement = document.getElementById('player-container-original-live');
if (player) {
player.detachMediaElement(); //
player.destroy(); //
player = flvjs.createPlayer({
type: 'flv',
url: liveCode,
});
player.attachMediaElement(originalElement); // video
player.load(); //
player.play(); //
}
};
const reloadTestingLive = () => {
var testingElement = document.getElementById('player-container-testing-live');
if (playerTesting) {
playerTesting.src(testingCode);
playerTesting.play();
playerTesting.detachMediaElement(); //
player.destroy(); //
playerTesting = flvjs.createPlayer({
type: 'flv',
url: testingCode,
});
playerTesting.attachMediaElement(testingElement); // video
playerTesting.load(); //
playerTesting.play(); //
}
};
onMounted(() => {
@ -155,4 +161,9 @@
}
}
}
.video-player {
margin: 6px;
width: 100%;
height: 32vh;
}
</style>

Loading…
Cancel
Save