徐景良 6 days ago
commit 77abcbadf6

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

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

@ -7,6 +7,8 @@ enum Api {
AddAlgorithmsRepository = '/api/AlgorithmsRepository/AddAlgorithmsRepository', AddAlgorithmsRepository = '/api/AlgorithmsRepository/AddAlgorithmsRepository',
// 修改算法 // 修改算法
UpdateAlgorithmsRepository = '/api/AlgorithmsRepository/UpdateAlgorithmsRepository', UpdateAlgorithmsRepository = '/api/AlgorithmsRepository/UpdateAlgorithmsRepository',
// 删除算法
DeleteAlgorithmsRepository = '/api/AlgorithmsRepository/DeleteAlgorithmsRepository'
} }
export const GetAlgorithmsRepositoryList = (params) => defHttp.get({ export const GetAlgorithmsRepositoryList = (params) => defHttp.get({
@ -20,4 +22,8 @@ export const AddAlgorithmsRepository = (params) => defHttp.post({
export const UpdateAlgorithmsRepository = (params) => defHttp.post({ export const UpdateAlgorithmsRepository = (params) => defHttp.post({
url: Api.UpdateAlgorithmsRepository, url: Api.UpdateAlgorithmsRepository,
params, 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"> <div ref="scrollBox" class="show-image-div">
<a-image-preview-group> <a-image-preview-group>
<a-image <a-image
v-for="value in props.showInfoData.aiAchievementDetailList" v-for="(value, index) in props.showInfoData.aiAchievementDetailList"
:key="value" :key="index"
:width="232" :width="232"
:height="140" :height="140"
style="border-radius: 10px;" style="border-radius: 10px;"
class="image-item" class="image-item"
:src="`${value.image}`" :src="`${value.image}`"
:img-props="{ loading: 'lazy' }"
/> />
</a-image-preview-group> </a-image-preview-group>
</div> </div>
@ -47,7 +48,7 @@ onMounted(() => {
.show-image-div { .show-image-div {
width: calc(100% - 417px); width: calc(100% - 417px);
height: 185px; height: 185px;
padding: 23px 25px 22px 25px; padding: 23px 25px 0px 25px;
position: absolute; position: absolute;
bottom: 0px; bottom: 0px;
left: 417px; left: 417px;
@ -56,7 +57,7 @@ onMounted(() => {
/* 核心:横向滚动 */ /* 核心:横向滚动 */
display: flex; display: flex;
overflow-x: auto; // overflow-x: auto;
overflow-y: hidden; overflow-y: hidden;
white-space: nowrap; white-space: nowrap;
gap: 22px; gap: 22px;
@ -70,6 +71,22 @@ onMounted(() => {
border-radius: 10px; 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 { .image-item {
border-radius: 10px; border-radius: 10px;

@ -3,14 +3,19 @@
<div class="left-menu-title">AI成果</div> <div class="left-menu-title">AI成果</div>
<div class="left-menu-search-div"> <div class="left-menu-search-div">
<a-select <a-select
v-model:value="type"
:allowClear="true"
placeholder="选择分类" placeholder="选择分类"
popupClassName="ai-achievement-classify-dropdown" popupClassName="ai-achievement-classify-dropdown"
class="classify-select" class="classify-select"
:options="classifyOptions" :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>
<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-outer ${selectItemId == item.id?'list-item-outer-select' : ''}`" v-for="(item,index) in dataList" >
<div class="list-item-inner"> <div class="list-item-inner">
<img class="item-image" :src="`${item.cover}`" > <img class="item-image" :src="`${item.cover}`" >
@ -31,33 +36,102 @@
</div> </div>
</div> </div>
</div> </div>
<div v-if="loading" class="loading-text">...</div>
<div v-else-if="dataList.length >= total" class="loading-text">没有更多数据了</div>
</div> </div>
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref, onMounted } from 'vue'; 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 { GetAiAchievementList } from '@/api/demo/aiachievement'
import { getAppEnvConfig } from '@/utils/env'; import { GetAlgorithmsRepositoryList } from '@/api/demo/ailist'
const { VITE_GLOB_API_URL } = getAppEnvConfig(); import dayjs from 'dayjs';
const emits = defineEmits([ const emits = defineEmits([
'changeLeftMenuShow' 'changeLeftMenuShow'
]); ]);
onMounted(() => { onMounted(() => {
GetAiAchievementList({page:1,limit:999}).then(res => { GetAlgorithmsRepositoryList({page: 1,limit: 999,}).then(res => {
console.log('res',res) total.value = res.total
dataList.value = res.items 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 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([ 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){ function showInfo(item){
selectItemId.value = item.id selectItemId.value = item.id
emits('changeLeftMenuShow',item); emits('changeLeftMenuShow',item);
@ -97,6 +171,9 @@
::v-deep(.ant-select-selection-placeholder) { ::v-deep(.ant-select-selection-placeholder) {
color: rgba(255, 255, 255, 0.15); color: rgba(255, 255, 255, 0.15);
} }
:deep(.ant-select-clear){
background: #252525;
}
} }
.date-select{ .date-select{
width: 269px; width: 269px;
@ -281,4 +358,10 @@
background-color: #37383d !important; background-color: #37383d !important;
} }
} }
.loading-text {
text-align: center;
color: #aaa;
font-size: 12px;
padding: 10px 0;
}
</style> </style>

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

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

@ -23,7 +23,7 @@
<div class="item-list" v-for="item in dataList"> <div class="item-list" v-for="item in dataList">
<div class="image-div"> <div class="image-div">
<img class="image-item" :src="`${VITE_GLOB_API_URL}/${item.cover}`"> <img class="image-item" :src="`${VITE_GLOB_API_URL}/${item.cover}`">
<div class="image-icon">盖板缺失</div> <!--<div class="image-icon">盖板缺失</div> -->
</div> </div>
<div class="show-info-div"> <div class="show-info-div">
<div class="info-title-div"> <div class="info-title-div">
@ -31,36 +31,22 @@
<div class="info-title-inner"> <div class="info-title-inner">
<div class="info-title">{{ item.name }}</div> <div class="info-title">{{ item.name }}</div>
<div style="display: flex;justify-content: space-between;"> <div style="display: flex;justify-content: space-between;">
<div class="info-subtitle">{{ item.description }}</div> <div class="info-subtitle">{{ item.description? item.description: '暂无描述' }}</div>
<a-popover overlayClassName="instance-show-more-info-popover" trigger="click" placement="topRight"> </div>
<template #content> </div>
<div class="show-more-content"> </div>
<div class="content-raw"> <div class="info-content-div">
<div class="content-label">关联事件</div> <div class="content-div">
<div class="content-value"> <div style="width: 153px;margin-right: 14px;">
<div>-</div> <div class="content-title-div">关联算法</div>
</div> <div class="content-info" v-html="getContentStr(item.algoIds)"></div>
</div> </div>
<div class="content-raw"> <div class="button-div">
<div class="content-label">关联算法</div> <a-button class="delete-button" @click="delData(item)"></a-button>
<div class="content-value"> <a-button class="show-info-button" type="primary" @click="showInfo(item)"></a-button>
<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> </div>
</div> </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> </div>
</div> </div>
@ -87,7 +73,7 @@
placement="right" placement="right"
rootClassName="instance-show-info-drawer" rootClassName="instance-show-info-drawer"
> >
<ShowInfoDrawer :showInfoData="showInfoData" @changeDrawerModal="changeDrawerModal" @changeAddModal="changeAddModal"/> <ShowInfoDrawer :showInfoData="showInfoData" :algorithmOptions="algorithmOptions" @changeDrawerModal="changeDrawerModal" @changeAddModal="changeAddModal"/>
</a-drawer> </a-drawer>
</div> </div>
</a-spin> </a-spin>
@ -172,6 +158,7 @@ const delData = (item) => {
icon: createVNode(ExclamationCircleOutlined), icon: createVNode(ExclamationCircleOutlined),
okText: '确认', okText: '确认',
cancelText: '取消', cancelText: '取消',
centered: true,
onOk() { onOk() {
return DeleteAlgoInstance({id: item.id}).then(res => { return DeleteAlgoInstance({id: item.id}).then(res => {
message.success("删除成功") 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> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.page-out{ .page-out{
padding: 16px 30px 53px 17px; padding: 16px 30px 33px 17px;
width: 100%; width: 100%;
height: calc(100vh - 80px); height: calc(100vh - 80px);
.title{ .title{
@ -264,7 +256,7 @@ const delData = (item) => {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
gap: 20px; gap: 20px;
padding-bottom: 55px; padding-bottom: 20px;
overflow: auto; overflow: auto;
scrollbar-width: none; scrollbar-width: none;
::-webkit-scrollbar{ ::-webkit-scrollbar{
@ -273,7 +265,7 @@ const delData = (item) => {
} }
.item-list{ .item-list{
width: 300px; width: 300px;
height: 291px; height: 321px;
background: #FFFFFF; background: #FFFFFF;
box-shadow: 5px 18px 32px 0px rgba(28,29,34,0.1); box-shadow: 5px 18px 32px 0px rgba(28,29,34,0.1);
border-radius: 10px; border-radius: 10px;
@ -323,7 +315,7 @@ const delData = (item) => {
margin-right: 5px; margin-right: 5px;
} }
.info-title-inner{ .info-title-inner{
width: 100%; width: calc(100% - 8px);
.info-title{ .info-title{
font-family: PingFangSC-Medium; font-family: PingFangSC-Medium;
font-weight: 500; font-weight: 500;
@ -331,6 +323,9 @@ const delData = (item) => {
color: #1C1D22; color: #1C1D22;
line-height: 20px; line-height: 20px;
margin-bottom: 5px; margin-bottom: 5px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
} }
.info-subtitle{ .info-subtitle{
font-family: PingFangSC-Regular; font-family: PingFangSC-Regular;
@ -338,6 +333,9 @@ const delData = (item) => {
font-size: 11px; font-size: 11px;
color: rgba(28,29,34,0.5); color: rgba(28,29,34,0.5);
line-height: 15px; line-height: 15px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
} }
.show-more-info{ .show-more-info{
@ -362,62 +360,75 @@ const delData = (item) => {
} }
} }
.info-content-div{ .info-content-div{
width: 100%; display: flex;
height: 66px; .content-div{
background-image: url('/public/instance/instance_list_item_info_content.png');
padding-top: 8px;
padding-left: 12px;
margin-bottom: 13px;
.content-raw{
display: flex; 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-family: PingFangSC-Regular;
font-weight: 400; font-weight: 400;
font-size: 12px; font-size: 10px;
color: #1C1D22; color: #1C1D22;
line-height: 17px; line-height: 14px;
margin-right: 11px;
} }
.content-value{ .content-info{
font-family: PingFangSC-Medium; font-family: PingFangSC-Regular;
font-weight: 500; font-weight: 400;
font-size: 12px; font-size: 10px;
color: #1C1D22; 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="interval"></div>
<div class="footer"> <div class="footer">
<a-button class="cancel-button" @click="emits('changeAddModal',false)"></a-button> <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> <a-button class="save-button" type="primary" @click="submit"></a-button>
</div> </div>
</a-spin> </a-spin>
@ -100,14 +101,14 @@
</template> </template>
<script setup lang="ts"> <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 { 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 SelectImageModal from "./SelectImageModal.vue";
import { ModelLabelsType } from './utils' import { ModelLabelsType } from './utils'
import { getAppEnvConfig } from '@/utils/env'; import { getAppEnvConfig } from '@/utils/env';
import { AddAlgorithmsRepository, UpdateAlgorithmsRepository } from '@/api/demo/ailist' import { AddAlgorithmsRepository, UpdateAlgorithmsRepository, DeleteAlgorithmsRepository } from '@/api/demo/ailist'
import { message } from "ant-design-vue"; import { message, Modal } from "ant-design-vue";
const { VITE_GLOB_API_URL } = getAppEnvConfig(); const { VITE_GLOB_API_URL } = getAppEnvConfig();
const props = defineProps(['modalType', 'algorithmInfo']) const props = defineProps(['modalType', 'algorithmInfo'])
const emits = defineEmits(['changeAddModal', 'query']) 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> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@ -550,6 +567,20 @@ const submit = () => {
text-shadow: 0px 10px 30px rgba(0,0,6,0.15); text-shadow: 0px 10px 30px rgba(0,0,6,0.15);
margin-right: 14px; 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{ .save-button{
width: 146px; width: 146px;
height: 40px; height: 40px;

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

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

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

@ -558,7 +558,8 @@
} }
}; };
onMounted(() => { 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('keydown', handleKeyDown);
document.addEventListener('keyup', handleKeyUp); document.addEventListener('keyup', handleKeyUp);

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

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

Loading…
Cancel
Save