业务配置页面+接口联调,弹窗修改路由跳转
This commit is contained in:
@@ -3,11 +3,8 @@ NODE_ENV = 'development'
|
||||
# 渔船点位
|
||||
VITE_WS_BASE_URL ='ws://220.185.188.222:8055/api/gisWs'
|
||||
|
||||
# VITE_APP_BASE_URL = 'http://125.124.131.105:6811/api'
|
||||
# 成彬本地
|
||||
VITE_APP_BASE_URL = 'http://100.95.100.2:6061/api'
|
||||
# VITE_APP_BASE_URL = 'http://100.95.236.218:6061/api'
|
||||
# VITE_APP_BASE_URL = 'http://119.167.138.11:6061/video-service'
|
||||
VITE_APP_BASE_URL = 'http://100.95.196.8:6061/api'
|
||||
|
||||
# 智能体访问地址
|
||||
# 宋凯忠本地
|
||||
|
||||
@@ -6,14 +6,50 @@ import request from '@/utils/request'
|
||||
* @param data
|
||||
* @returns {*}
|
||||
*/
|
||||
export const videoCameraFindPage = (data) => {
|
||||
export const dsVideoPage = (data) => {
|
||||
return request({
|
||||
url: '/videoCamera/findPage',
|
||||
url: '/fishingPort/dsVideo/page',
|
||||
method: 'post',
|
||||
data: data,
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
}
|
||||
data: data
|
||||
})
|
||||
}
|
||||
/**
|
||||
* 分页查询监控设备列表
|
||||
* 新增
|
||||
* @param data
|
||||
* @returns {*}
|
||||
*/
|
||||
export const dsVideoSave = (data) => {
|
||||
return request({
|
||||
url: '/fishingPort/dsVideo/save',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
/**
|
||||
* 分页查询监控设备列表
|
||||
* 修改
|
||||
* @param data
|
||||
* @returns {*}
|
||||
*/
|
||||
export const dsVideoUpdate = (data) => {
|
||||
return request({
|
||||
url: '/fishingPort/dsVideo/update',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
/**
|
||||
* 分页查询监控设备列表
|
||||
* 删除
|
||||
* @param data
|
||||
* @returns {*}
|
||||
*/
|
||||
export const dsVideoDelete = (data) => {
|
||||
return request({
|
||||
url: '/fishingPort/dsVideo/delete',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
/**
|
||||
|
||||
BIN
src/assets/images/common/icon_suffix.png
Normal file
BIN
src/assets/images/common/icon_suffix.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 204 B |
BIN
src/assets/images/map/devices/icon_monitor_bayonet.png
Normal file
BIN
src/assets/images/map/devices/icon_monitor_bayonet.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.0 KiB |
@@ -11,7 +11,7 @@
|
||||
v-model="model[item.prop]"
|
||||
:placeholder="item.placeholder ? item.placeholder : '请输入'"
|
||||
:clearable="item.clearable !== false"
|
||||
style="width: 110px">
|
||||
:style="{width: item.width || '110px'}">
|
||||
</el-input>
|
||||
<el-select
|
||||
v-if="item.type === 'select'"
|
||||
@@ -23,7 +23,7 @@
|
||||
:collapse-tags="item.collapseTags || false"
|
||||
:collapse-tags-tooltip="item.collapseTagsTooltip || false"
|
||||
@change="(val) => handle(item.event,val)"
|
||||
style="width: 90px"
|
||||
:style="{width: item.width || '90px'}"
|
||||
poper-class="filter-select"
|
||||
:empty-values="item.emptyValues || [ '', undefined]"
|
||||
:value-on-clear="item.valueOnClear || ''">
|
||||
|
||||
@@ -68,7 +68,6 @@ const initPlayer = () => {
|
||||
|
||||
timeoutId = setTimeout(() => {
|
||||
timeoutId = null
|
||||
console.log(retryCount, retryDelay, '重连次数......')
|
||||
if (retryCount <= MAX_RETRIES) {
|
||||
initPlayer() // 重新初始化播放器
|
||||
} else {
|
||||
@@ -76,7 +75,6 @@ const initPlayer = () => {
|
||||
if (player) {
|
||||
player = null
|
||||
}
|
||||
console.error('重试超过最大次数')
|
||||
}
|
||||
}, retryDelay)
|
||||
})
|
||||
|
||||
@@ -69,11 +69,11 @@
|
||||
]
|
||||
|
||||
const navRight = [
|
||||
// {
|
||||
// label: '识别记录',
|
||||
// path: '/screen/identification',
|
||||
// prop: 'identification'
|
||||
// },
|
||||
{
|
||||
label: '业务配置',
|
||||
path: '/setting',
|
||||
prop: 'identification'
|
||||
},
|
||||
{
|
||||
label: '插件下载',
|
||||
path: '',
|
||||
@@ -101,6 +101,8 @@
|
||||
const toggle = (nav) => {
|
||||
if(nav.prop === 'monitor') {
|
||||
window.open('/plugin/VideoWebPlugin.exe', '_blank')
|
||||
}else{
|
||||
router.push(nav.path)
|
||||
}
|
||||
}
|
||||
// 右上角时间
|
||||
@@ -250,7 +252,7 @@
|
||||
}
|
||||
.datetime{
|
||||
display: flex;
|
||||
gap: 14px;
|
||||
gap: 12px;
|
||||
color: #FFFFFF;
|
||||
text-align: left;
|
||||
height: 29px;
|
||||
@@ -284,7 +286,7 @@
|
||||
margin-left: 61px;
|
||||
}
|
||||
.right{
|
||||
gap:20px;
|
||||
gap:15px;
|
||||
margin-right: 40px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
@@ -1,130 +0,0 @@
|
||||
<template>
|
||||
<div :class="[{ 'expend-only': expend }, 'screen-map-server',toolBarStore.expand ? 'expand' : '']" @mouseenter="moveEnter" @mouseleave="moveLeave">
|
||||
|
||||
<img alt="ICON_MAP" class="icon-cover" :src="getAssetsFile(`icon-${active}-active.png`)">
|
||||
|
||||
<div v-for="(item, index) in list" class="screen-map-server-item" :key="index" :style="getStyle(item, index)"
|
||||
@click="toggle(item, index)">
|
||||
|
||||
<img v-show="(!expend && !index) || expend" alt="ICON_MAP" class="icon-map"
|
||||
:src="getAssetsFile(`icon-${item.prop}${item.prop == active ? '-active' : ''}.png`)">
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { getAssetsFile } from '@/utils/common'
|
||||
import useToolBarStore from '@/store/modules/toolbar'
|
||||
|
||||
const toolBarStore = useToolBarStore()
|
||||
const emit = defineEmits([ 'toggle' ])
|
||||
|
||||
const active = ref('satellite')
|
||||
const expend = ref(false)
|
||||
|
||||
const list = [
|
||||
{
|
||||
label: '遥感',
|
||||
prop: 'satellite'
|
||||
},
|
||||
{
|
||||
label: '海图',
|
||||
prop: 'sea'
|
||||
},
|
||||
{
|
||||
label: '浅色',
|
||||
prop: 'light'
|
||||
}
|
||||
]
|
||||
|
||||
/**
|
||||
* 动态改变当前图例的定位
|
||||
* @param e 当前图例信息
|
||||
* @param index 当前图例下标
|
||||
*/
|
||||
const getStyle = (e, index) => ({
|
||||
'background-color': !expend.value && e.color ? e.color : 'transparent', // 未展开样式
|
||||
'border-radius': expend.value ? '0px' : '5px', // 未展开样式
|
||||
right: expend.value ? `${index * 40 + (index + 1) * 4}px` : `${(index + 1) * 4}px`,
|
||||
'transition-duration': expend.value ? `${index * 0.2}s` : '0s',
|
||||
'z-index': e.index
|
||||
})
|
||||
|
||||
const moveEnter = () => {
|
||||
expend.value = true
|
||||
}
|
||||
|
||||
const moveLeave = () => {
|
||||
expend.value = false
|
||||
}
|
||||
|
||||
/**
|
||||
* 底图切换
|
||||
* @param e 当前图例信息
|
||||
*/
|
||||
const toggle = (e) => {
|
||||
active.value = e.prop
|
||||
emit('toggle', 'toggle-base', e.prop)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.screen-map-server {
|
||||
position: absolute;
|
||||
right: 30px;
|
||||
bottom: 112px;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
padding: 4px;
|
||||
border-radius: 5px;
|
||||
box-sizing: border-box;
|
||||
background-color: transparent;
|
||||
transition-duration: .3s;
|
||||
cursor: pointer;
|
||||
pointer-events: auto;
|
||||
|
||||
&.expend-only {
|
||||
height: 48px;
|
||||
width: 135px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(77, 151, 255, 0.5);
|
||||
|
||||
.icon-cover {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* COVER */
|
||||
.icon-cover {
|
||||
display: block;
|
||||
position: absolute;
|
||||
right: 4px;
|
||||
top: 4px;
|
||||
z-index: 9;
|
||||
}
|
||||
|
||||
/* ITEM */
|
||||
.screen-map-server-item {
|
||||
border-radius: 0;
|
||||
height: 40px;
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
width: 40px;
|
||||
z-index: 1;
|
||||
|
||||
.icon-map {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
.expand{
|
||||
right: 390px;
|
||||
}
|
||||
</style>
|
||||
@@ -23,14 +23,11 @@ import { monitors, uavs, stations, environmentals, fences, detailFences } from '
|
||||
import InfoWindowComponent from '@/components/Map/window/index.vue'
|
||||
import TrawlerInfoWindowComponent from '@/components/Map/window/trawler.vue'
|
||||
import { dsVideoList, findUavPage, getVideoInfo } from '@/api/device.js'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
const router = useRouter()
|
||||
const mapStore = useMapStore()
|
||||
const UAV = computed(() => mapStore.legend.UAV)
|
||||
const monitor = computed(() => mapStore.legend.monitor)
|
||||
const ais_station = computed(() => mapStore.legend.ais_station)
|
||||
const environmental = computed(() => mapStore.legend.environmental)
|
||||
const fence = computed(() => mapStore.legend.fence)
|
||||
const sector = computed(() => mapStore.sector)
|
||||
const legend = computed(() => mapStore.legend)
|
||||
const locateData = computed(() => mapStore.locate.data)
|
||||
let globalMap = null
|
||||
let vector = {}
|
||||
@@ -108,7 +105,7 @@ const addMonitorToMap = () => {
|
||||
},
|
||||
{
|
||||
id: item.id,
|
||||
symbol: $configs.getDevicePointSymbol('_monitor', { ...item, name: item.videoName }),
|
||||
symbol: $configs.getDevicePointSymbol('_monitor' + (item.beBayonet === 1 ? '_bayonet' : ''), { ...item, name: item.videoName }), // beBayonet 是否卡口1是 0否
|
||||
properties: item,
|
||||
zIndex: 2
|
||||
}
|
||||
@@ -118,21 +115,8 @@ const addMonitorToMap = () => {
|
||||
const pvalue = item.ptzcfg?.pValue || 0
|
||||
drawSector('_monitor', [ item.longitude, item.latitude ], visionDistance, item.id, (90 - pvalue) % 360)
|
||||
marker.on('click', (evt) => {
|
||||
// 先隐藏所有扇形
|
||||
changeSectorsInLayer('sectors_monitor', false)
|
||||
|
||||
// 确保扇形图层是可见的
|
||||
if (!vector.sectors_monitor.isVisible()) {
|
||||
vector.sectors_monitor.show()
|
||||
}
|
||||
|
||||
// 显示当前点击项的所有相关扇形(圆、椭圆、线)
|
||||
const baseId = `sector__monitor${item.id}`
|
||||
vector.sectors_monitor.getGeometryById(baseId + '_circle')?.show()
|
||||
vector.sectors_monitor.getGeometryById(baseId + '_ellipse')?.show()
|
||||
vector.sectors_monitor.getGeometryById(baseId + '_line')?.show()
|
||||
|
||||
mapStore.updateWindowInfo({ visible: true, type: '_monitor', data: { ...item } })
|
||||
mapStore.updateLocate({ ...item }) // 视频定位
|
||||
mapStore.updateWindowInfo({ visible: true, type: '_monitor', data: { ...item } }) // 打开监控视频弹窗
|
||||
})
|
||||
}
|
||||
})
|
||||
@@ -140,34 +124,17 @@ const addMonitorToMap = () => {
|
||||
}
|
||||
// 要素/视频定位
|
||||
const locateMoitor = (data) => {
|
||||
const name = 'locate-monitor'
|
||||
let layer = vector[name]
|
||||
if (!layer) {
|
||||
initLayerToMap('locate-monitor')
|
||||
layer = vector['locate-monitor']
|
||||
} else {
|
||||
layer.clear()
|
||||
}
|
||||
initLayerToMap('locate-monitor')
|
||||
const monitors = vector.monitor
|
||||
const marker = monitors.getGeometryById(data.id)
|
||||
if (marker) {
|
||||
const coordinates = marker.getCoordinates()
|
||||
geography.monitor.forEach((item) => {
|
||||
if (item.id === data.id) {
|
||||
// globalMap.map.animateTo(
|
||||
// {
|
||||
// center: [ coordinates.x, coordinates.y ]
|
||||
// },
|
||||
// {
|
||||
// duration: 1000 * 0.5,
|
||||
// easing: 'out'
|
||||
// }
|
||||
// )
|
||||
// 先隐藏所有扇形
|
||||
changeSectorsInLayer('sectors_monitor', false)
|
||||
getVideoInfo({ id: item.id }).then(res => {
|
||||
const visionDistance = item.visionDistance * 1000 || 5 * 1000 // 视角距离
|
||||
const pvalue = res.data.ptzcfg.pValue || 0 // 旋转角度
|
||||
const pvalue = res.data.ptzcfg?.pValue || 0 // 旋转角度
|
||||
drawSector('_monitor', [ item.longitude, item.latitude ], visionDistance, item.id, (90 - pvalue) % 360)
|
||||
|
||||
// 确保扇形图层是可见的
|
||||
@@ -369,7 +336,6 @@ const initUAV = () => {
|
||||
addUAVToMap()
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
const initMonitor = () => {
|
||||
const params = {}
|
||||
@@ -394,83 +360,60 @@ const initFence = () => {
|
||||
addFenceToMap('detailFence')
|
||||
}
|
||||
const toModel = () => {
|
||||
mapStore.updateDialog({ visible: true, type: 'largeModel' })
|
||||
router.push('/largeModel')
|
||||
}
|
||||
onMounted(() => {
|
||||
initMap()
|
||||
initFence()
|
||||
initUAV()
|
||||
initMonitor()
|
||||
initAisStation()
|
||||
initEnvironmental()
|
||||
// 监控设备图层初始化
|
||||
Object.values(layerMehods).forEach(initFunc => initFunc())
|
||||
// 渔船链接
|
||||
BoatUtil.init(mapStore)
|
||||
BoatUtil.getShip()
|
||||
// 轨迹图层
|
||||
initLayerToMap('track')
|
||||
})
|
||||
watch(() => UAV.value, () => {
|
||||
if(UAV.value) {
|
||||
initUAV()
|
||||
}else{
|
||||
vector.UAV?.hide()
|
||||
changeSectorsInLayer('sectors_UAV', false)
|
||||
}
|
||||
})
|
||||
watch(() => monitor.value, () => {
|
||||
if(monitor.value) {
|
||||
initMonitor()
|
||||
}else{
|
||||
vector.monitor?.hide()
|
||||
changeSectorsInLayer('sectors_monitor', false)
|
||||
const layerMehods = {
|
||||
UAV: initUAV,
|
||||
monitor: initMonitor,
|
||||
ais_station: initAisStation,
|
||||
environmental: initEnvironmental,
|
||||
fence: initFence
|
||||
}
|
||||
watch(() => Object.keys(layerMehods).reduce((obj, key) => {
|
||||
obj[key] = legend.value[key]
|
||||
return obj
|
||||
}, {}), (newVal, oldVal) => {
|
||||
Object.keys(layerMehods).forEach(key => {
|
||||
// 监听值变化进行更改
|
||||
if (newVal[key] !== oldVal[key]) {
|
||||
if (newVal[key]) {
|
||||
layerMehods[key]()
|
||||
} else {
|
||||
vector[key]?.hide()
|
||||
if (key === 'UAV' || key === 'monitor') { // 无人机和监控可视区域隐藏
|
||||
changeSectorsInLayer('sectors_' + key, false)
|
||||
} else if (key === 'fence') {
|
||||
vector.detailFence?.hide()
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}, { deep: true })
|
||||
const watchKeys = [ 'sectors_monitor', 'sectors_UAV' ]
|
||||
watch(() => ({ sectors_UAV: legend.value.sectors_UAV, sectors_monitor: legend.value.sectors_monitor }), (newVal, oldVal) => {
|
||||
watchKeys.forEach(key => {
|
||||
// 监听值变化进行更改
|
||||
if (newVal[key] !== oldVal[key]) {
|
||||
if (newVal[key]) {
|
||||
changeSectorsInLayer(key, true)
|
||||
} else {
|
||||
changeSectorsInLayer(key, false)
|
||||
}
|
||||
}
|
||||
})
|
||||
watch(() => ais_station.value, () => {
|
||||
if(ais_station.value) {
|
||||
initAisStation()
|
||||
}else{
|
||||
vector.ais_station?.hide()
|
||||
}
|
||||
})
|
||||
watch(() => environmental.value, () => {
|
||||
if(environmental.value) {
|
||||
initEnvironmental()
|
||||
}else{
|
||||
vector.environmental?.hide()
|
||||
}
|
||||
})
|
||||
watch(() => fence.value, () => {
|
||||
if(fence.value) {
|
||||
initFence()
|
||||
}else{
|
||||
vector.fence?.hide()
|
||||
vector.detailFence?.hide()
|
||||
}
|
||||
})
|
||||
watch(() => sector.value.monitor, (newVal) => {
|
||||
if(vector.sectors_monitor) {
|
||||
if(newVal) {
|
||||
// vector.sectors_monitor.show()
|
||||
changeSectorsInLayer('sectors_monitor', true)
|
||||
} else {
|
||||
// vector.sectors_monitor.hide()
|
||||
changeSectorsInLayer('sectors_monitor', false)
|
||||
}
|
||||
}
|
||||
})
|
||||
watch(() => sector.value.UAV, (newVal) => {
|
||||
if(vector.sectors_UAV) {
|
||||
if(newVal) {
|
||||
// vector.sectors_UAV.show()
|
||||
changeSectorsInLayer('sectors_UAV', true)
|
||||
} else {
|
||||
// vector.sectors_UAV.hide()
|
||||
changeSectorsInLayer('sectors_UAV', false)
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}, { deep: true })
|
||||
// 定位数据变化
|
||||
watch(() => locateData.value.videoCode, (newVal) => {
|
||||
watch(() => locateData.value.videoCode, () => {
|
||||
nextTick(() => {
|
||||
locateMoitor(locateData.value)
|
||||
})
|
||||
|
||||
@@ -184,7 +184,6 @@ const cleanupExpiredBoats = () => {
|
||||
|
||||
const getShip = () => {
|
||||
findByCurrent().then(res => {
|
||||
console.log('初始获取')
|
||||
addBoats(res.result)
|
||||
})
|
||||
// ----------船只数据------------------
|
||||
@@ -192,7 +191,6 @@ const getShip = () => {
|
||||
dynamicBoatInfoWebSocket.onopen(event => {
|
||||
})
|
||||
dynamicBoatInfoWebSocket.onmessage(event => {
|
||||
console.log('接收数据:', JSON.parse(event.data))
|
||||
if(Array.isArray(JSON.parse(event.data))) {
|
||||
addBoats(JSON.parse(event.data))
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
return
|
||||
}
|
||||
item.sector = !item.sector
|
||||
mapStore.updateSector(item.prop, item.sector)
|
||||
mapStore.updateLegend('sectors_' + item.prop, item.sector)
|
||||
}
|
||||
const toggleExpand = () => {
|
||||
isFold.value = !isFold.value
|
||||
@@ -86,7 +86,7 @@
|
||||
mapStore.updateLegend(item.prop, item.checked)
|
||||
if(!item.checked && (item.prop === 'monitor' || item.prop === 'UAV')) {
|
||||
item.sector = false
|
||||
mapStore.updateSector(item.prop, item.sector)
|
||||
mapStore.updateLegend('sectors_' + item.prop, item.sector)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -182,7 +182,7 @@ onUnmounted(() => {
|
||||
.content-wrapper{
|
||||
display: flex;
|
||||
position: relative;
|
||||
height: 100%;
|
||||
height: 800px;
|
||||
iframe{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
@@ -283,8 +283,6 @@ export default {
|
||||
});
|
||||
},
|
||||
uninit() {
|
||||
console.log(999);
|
||||
|
||||
let that = this;
|
||||
if (that.oWebControl != null) {
|
||||
that.oWebControl.JS_RequestInterface({
|
||||
|
||||
@@ -14,9 +14,7 @@ const routes = [
|
||||
auth: false,
|
||||
title: '首页'
|
||||
},
|
||||
component: () => import('@/views/business/index.vue'),
|
||||
children: [
|
||||
]
|
||||
component: () => import('@/views/business/index.vue')
|
||||
},
|
||||
{
|
||||
path: '/login',
|
||||
@@ -71,7 +69,7 @@ router.beforeEach((to, from, next) => {
|
||||
// 没有token
|
||||
if (whiteList.indexOf(to.path) !== -1) {
|
||||
// 在免登录白名单,直接进入
|
||||
next()
|
||||
next()
|
||||
} else {
|
||||
// next(`/login?redirect=${to.fullPath}`) // 否则全部重定向到登录页
|
||||
next('/login') // 否则全部重定向到登录页
|
||||
|
||||
@@ -6,29 +6,22 @@ const useMapStore = defineStore(
|
||||
state: () => ({
|
||||
legend: {
|
||||
UAV: true,
|
||||
sectors_UAV: false, // 无人机可视域开关
|
||||
monitor: true,
|
||||
sectors_monitor: false, // 监控可视域开关
|
||||
ais_station: true,
|
||||
environmental: true,
|
||||
fence: true
|
||||
},
|
||||
windowInfo: {
|
||||
visible: false,
|
||||
type: '',
|
||||
type: '', // 弹窗类型 _monitor/_UAV/_trawler_dynamic
|
||||
data: {}
|
||||
},
|
||||
sector: {
|
||||
'UAV': false, // 无人机可视域开关
|
||||
'monitor': false // 监控可视域开关
|
||||
},
|
||||
hik: { // 海康插件设备层级
|
||||
level: 1,
|
||||
data: {}
|
||||
},
|
||||
dialog: {
|
||||
visible: false,
|
||||
type: '', // 弹窗类型 alarm/CCTV/UAV/largeModel
|
||||
data: {}
|
||||
},
|
||||
// 无人机信息
|
||||
uavs: {
|
||||
data: {}
|
||||
@@ -48,20 +41,11 @@ const useMapStore = defineStore(
|
||||
this.windowInfo.type = type
|
||||
this.windowInfo.data = data
|
||||
},
|
||||
updateSector(type, checked) {
|
||||
this.sector[type] = checked
|
||||
},
|
||||
updateHik(option) {
|
||||
const { level = 1, data = {} } = option
|
||||
this.hik.level = level
|
||||
this.hik.data = data
|
||||
},
|
||||
updateDialog(option) {
|
||||
const { visible = false, type = '', data } = option
|
||||
this.dialog.visible = visible
|
||||
this.dialog.type = type
|
||||
this.dialog.data = data
|
||||
},
|
||||
updateUavData(option) {
|
||||
this.uavs.data = option
|
||||
},
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
import { defineStore } from 'pinia'
|
||||
|
||||
const useToolBarStore = defineStore(
|
||||
'toolbar',
|
||||
{
|
||||
state: () => ({
|
||||
expand: false, //地图图例位置
|
||||
trawler: {
|
||||
visible: false // 渔船动态详情收缩框显示
|
||||
}
|
||||
}),
|
||||
actions: {
|
||||
toogleExpand(expand) {
|
||||
this.expand = expand
|
||||
},
|
||||
toggleTrawlerVisible(visible) {
|
||||
this.trawler.visible = visible
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
export default useToolBarStore
|
||||
@@ -5,11 +5,11 @@
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import useMapStore from '@/store/modules/map'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
const mapStore = useMapStore()
|
||||
const router = useRouter()
|
||||
const handle = (type) => {
|
||||
mapStore.updateDialog({ visible: true, type })
|
||||
router.push({ path: '/wall', query: { type } })
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
|
||||
@@ -61,12 +61,12 @@
|
||||
</template>
|
||||
<script setup>
|
||||
import SubtitleComponent from '@/components/SubtItle/index.vue'
|
||||
import { reactive, ref } from 'vue'
|
||||
import useMapStore from '@/store/modules/map'
|
||||
import { ref } from 'vue'
|
||||
import { videoIdentificationPage } from '@/api/identification.js'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
const router = useRouter()
|
||||
const emit = defineEmits([ 'toggle-fold' ])
|
||||
const mapStore = useMapStore()
|
||||
const tabs = [
|
||||
{
|
||||
label: '无船号',
|
||||
@@ -120,7 +120,7 @@ const toggle = (index) => {
|
||||
const handle = (type, item) => {
|
||||
switch (type) {
|
||||
case 'more':
|
||||
mapStore.updateDialog({ visible: true, type: 'alarm', data: { isHasBoatName: current.value == 1 ? 1 : 2 } })
|
||||
router.push({ path: '/identification', query: { isHasBoatName: current.value == 1 ? 1 : 2 } })
|
||||
break
|
||||
default:
|
||||
break
|
||||
|
||||
@@ -28,6 +28,7 @@ const lock = ref(false)
|
||||
let timer = null
|
||||
let monitorIndex = 0
|
||||
const videoUrl = ref('')
|
||||
const time = ref(10000)
|
||||
|
||||
const handle = (index) => {
|
||||
if(index === 0) {
|
||||
@@ -57,33 +58,40 @@ const init = () => {
|
||||
const params = {}
|
||||
videoUrl.value = ''
|
||||
dsVideoList(params).then(res => {
|
||||
data.value = res.data.filter(i => i.videoUrl).sort((a, b) => a.playIndex - b.playIndex)
|
||||
videoUrl.value = data.value[monitorIndex].videoUrl
|
||||
mapStore.updateLocate(data.value[monitorIndex])
|
||||
clearTimer()
|
||||
handlePolling(true) // 开始轮询
|
||||
timer = setInterval(() => {
|
||||
if(lock.value) {
|
||||
return false
|
||||
}
|
||||
videoUrl.value = ''
|
||||
nextTick(() => {
|
||||
if(monitorIndex >= data.value.length - 1) {
|
||||
handlePolling(false) // 轮询结束
|
||||
monitorIndex = 0
|
||||
handlePolling(true) // 开始轮询
|
||||
}else{
|
||||
monitorIndex++
|
||||
}
|
||||
videoUrl.value = data.value[monitorIndex].videoUrl
|
||||
})
|
||||
mapStore.updateLocate(data.value[monitorIndex])
|
||||
}, 60 * 1000 * 0.5)
|
||||
data.value = res.data.filter(i => i.videoUrl && i.bePlay === 1).sort((a, b) => a.playIndex - b.playIndex)
|
||||
// 启动轮播定时器
|
||||
startPolling()
|
||||
})
|
||||
}
|
||||
const handlePolling = (flag) => {
|
||||
console.log(flag + '---轮询')
|
||||
|
||||
// 启动轮播
|
||||
const startPolling = () => {
|
||||
clearTimer()
|
||||
const runPolling = () => {
|
||||
if (!lock.value) {
|
||||
switchToNextVideo()
|
||||
}
|
||||
timer = setTimeout(runPolling, time.value)
|
||||
}
|
||||
runPolling()
|
||||
}
|
||||
|
||||
// 切换到下一个视频
|
||||
const switchToNextVideo = () => {
|
||||
videoUrl.value = ''
|
||||
time.value = data.value[monitorIndex].playTime * 1000 || 10 * 1000
|
||||
mapStore.updateLocate(data.value[monitorIndex])
|
||||
nextTick(() => {
|
||||
videoUrl.value = data.value[monitorIndex].videoUrl
|
||||
// 更新播放时间
|
||||
if (monitorIndex >= data.value.length - 1) {
|
||||
monitorIndex = 0 // 回到第一个
|
||||
} else {
|
||||
monitorIndex++
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 拖拽事件
|
||||
* @param e
|
||||
@@ -96,8 +104,7 @@ const drag = (e) => {
|
||||
document.querySelector('.monitor-container').style.width = i.width + 'px'
|
||||
})
|
||||
}else{
|
||||
dragEvent(e, 'monitor-container', () => {
|
||||
})
|
||||
dragEvent(e, 'monitor-container', () => { /* empty */ })
|
||||
}
|
||||
}
|
||||
onMounted(() => {
|
||||
|
||||
@@ -45,154 +45,8 @@ onMounted(() => {
|
||||
drone_sn: data.value.droneSn // 飞机 sn,按实际传入
|
||||
})
|
||||
}
|
||||
// // 使用轮询方式等待内容加载完成后再滚动
|
||||
// waitForContentAndScroll()
|
||||
})
|
||||
const waitForContentAndScroll = () => {
|
||||
let attempts = 0
|
||||
let previousScrollWidth = 0
|
||||
let stableCount = 0
|
||||
const maxAttempts = 30
|
||||
const checkAndScroll = () => {
|
||||
attempts++
|
||||
|
||||
if (Detail.value) {
|
||||
// 检查目标容器是否已加载内容
|
||||
const mapContainer = document.getElementById('map-app-global')
|
||||
|
||||
// 判断内容是否加载完成
|
||||
const isContentLoaded = mapContainer && mapContainer.children.length > 0
|
||||
// console.log('Content loaded:', isContentLoaded, mapContainer)
|
||||
// 获取当前尺寸
|
||||
const currentScrollWidth = Detail.value.scrollWidth
|
||||
const clientWidth = Detail.value.clientWidth
|
||||
|
||||
// console.log('Size check:', {
|
||||
// attempt: attempts,
|
||||
// scrollWidth: currentScrollWidth,
|
||||
// clientWidth: clientWidth,
|
||||
// isContentLoaded: isContentLoaded
|
||||
// })
|
||||
|
||||
// 检查尺寸是否稳定(连续几次尺寸相同)
|
||||
if (currentScrollWidth === previousScrollWidth && currentScrollWidth > clientWidth) {
|
||||
stableCount++
|
||||
} else {
|
||||
stableCount = 0
|
||||
}
|
||||
previousScrollWidth = currentScrollWidth
|
||||
// 当内容加载完成且尺寸稳定,或者达到最大尝试次数时执行滚动
|
||||
if (isContentLoaded && stableCount >= 2 && currentScrollWidth > clientWidth ||
|
||||
attempts >= maxAttempts) {
|
||||
|
||||
// 强制重新计算布局
|
||||
forceLayoutRecalculation(() => {
|
||||
executeScroll()
|
||||
})
|
||||
} else {
|
||||
// 内容未加载完成或尺寸不稳定,继续等待
|
||||
setTimeout(checkAndScroll, 300)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 开始检查
|
||||
setTimeout(checkAndScroll, 300)
|
||||
}
|
||||
const forceLayoutRecalculation = (callback) => {
|
||||
if (!Detail.value) {
|
||||
if (callback) {
|
||||
callback()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 方法1: 强制重排
|
||||
Detail.value.style.display = 'none'
|
||||
void Detail.value.offsetHeight // 强制重排
|
||||
Detail.value.style.display = 'flex'
|
||||
|
||||
// 方法2: 临时修改overflow触发重新计算
|
||||
const originalOverflow = Detail.value.style.overflow
|
||||
Detail.value.style.overflow = 'hidden'
|
||||
void Detail.value.offsetWidth
|
||||
Detail.value.style.overflow = originalOverflow
|
||||
|
||||
setTimeout(() => {
|
||||
if (callback) {
|
||||
callback()
|
||||
}
|
||||
}, 100)
|
||||
}
|
||||
|
||||
const executeScroll = () => {
|
||||
if (!Detail.value) {
|
||||
return
|
||||
}
|
||||
|
||||
// 重新获取准确的尺寸
|
||||
const scrollWidth = Detail.value.scrollWidth
|
||||
const clientWidth = Detail.value.clientWidth
|
||||
const maxScroll = scrollWidth - clientWidth
|
||||
|
||||
// console.log('Final size calculation:', {
|
||||
// scrollWidth,
|
||||
// clientWidth,
|
||||
// maxScroll
|
||||
// })
|
||||
|
||||
if (maxScroll > 0) {
|
||||
const targetPosition = 1388
|
||||
const scrollPosition = targetPosition > maxScroll ? maxScroll : targetPosition
|
||||
|
||||
// 修复:正确处理 scrollPosition 为 0 的情况
|
||||
const finalPosition = typeof scrollPosition === 'number' ? scrollPosition : 645
|
||||
|
||||
// 激活滚动机制后再执行滚动
|
||||
activateScrollMechanism(() => {
|
||||
Detail.value.scrollTo({
|
||||
left: finalPosition,
|
||||
behavior: 'smooth'
|
||||
})
|
||||
|
||||
// console.log('Scrolled to position:', finalPosition,
|
||||
// 'Max scroll:', maxScroll,
|
||||
// 'Container width:', clientWidth,
|
||||
// 'Scroll width:', scrollWidth)
|
||||
})
|
||||
} else {
|
||||
// console.log('No scrollable content, but content is loaded')
|
||||
// 即使没有滚动内容,也尝试激活滚动机制
|
||||
activateScrollMechanism(() => {
|
||||
Detail.value.scrollTo({
|
||||
left: 645,
|
||||
behavior: 'smooth'
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const activateScrollMechanism = (callback) => {
|
||||
if (!Detail.value) {
|
||||
if (callback) {
|
||||
callback()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 预激活滚动机制
|
||||
Detail.value.scrollTo({ left: 1, behavior: 'instant' })
|
||||
|
||||
setTimeout(() => {
|
||||
Detail.value.scrollTo({ left: 0, behavior: 'instant' })
|
||||
|
||||
setTimeout(() => {
|
||||
if (callback) {
|
||||
callback()
|
||||
}
|
||||
}, 50)
|
||||
}, 20)
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.fh2-container {
|
||||
|
||||
@@ -203,7 +203,6 @@ const rules = {
|
||||
model[key] = props.data[key]
|
||||
if(key === 'illegalType') {
|
||||
model[key] = props.data[key].map(i => i.label)
|
||||
console.log(model[key])
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -5,14 +5,6 @@
|
||||
<FilterCom ref="Filter" :filter-buttons="filterButtons" :filter-items="items" :filter-model="model" @handle="handle"/>
|
||||
<!-- 多选框筛选 -->
|
||||
<div class="Form">
|
||||
<!-- 暂时只支持单个类型的筛选 -->
|
||||
<!-- <el-checkbox-group v-model="illegalType" :max="1">
|
||||
<el-checkbox
|
||||
v-for="item in illegalTypes"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value" />
|
||||
</el-checkbox-group> -->
|
||||
<el-radio-group v-model="illegalType" @change="changeRadio">
|
||||
<el-radio v-for="item in illegalTypes"
|
||||
:key="item.value"
|
||||
@@ -98,9 +90,6 @@ import { useRoute } from 'vue-router'
|
||||
import DialogComponent from '@/components/Dialog/screen.vue'
|
||||
import DetailComponent from './detail.vue'
|
||||
|
||||
import useMapStore from '@/store/modules/map'
|
||||
const mapStore = useMapStore()
|
||||
|
||||
const route = useRoute()
|
||||
const illegalTypes = [
|
||||
{ value: '未封舱预警', label: '未封舱预警', prop: 'warning' },
|
||||
@@ -258,7 +247,6 @@ const columns = ref([
|
||||
])
|
||||
const config = {
|
||||
label: '操作',
|
||||
// width: 60
|
||||
width: 150
|
||||
}
|
||||
const operate = [
|
||||
@@ -344,7 +332,6 @@ const initData = () => {
|
||||
const params = new FormData()
|
||||
const obj = {
|
||||
...model,
|
||||
// illegalType: illegalType.value.join(','),
|
||||
illegalType: illegalType.value,
|
||||
beginTime: model.time && model.time[0] ? model.time[0] : '',
|
||||
endTime: model.time && model.time[1] ? model.time[1] : '',
|
||||
@@ -352,9 +339,6 @@ const initData = () => {
|
||||
pageSize: pagination.size
|
||||
}
|
||||
delete obj.time
|
||||
// Object.keys(obj).forEach((key) => {
|
||||
// params.append(key, obj[key])
|
||||
// })
|
||||
videoIdentificationPage(obj).then(res => {
|
||||
if (res.success) {
|
||||
tableData.value = res.result.records.map(i => {
|
||||
@@ -378,63 +362,6 @@ const initData = () => {
|
||||
}).finally(() => {
|
||||
loading.value = false
|
||||
})
|
||||
// tableData.value = [
|
||||
// {
|
||||
// 'aisStatus': '未开启',
|
||||
// 'belongPort': '',
|
||||
// 'boatCodePath': '',
|
||||
// 'boatName': '浙周田货0998',
|
||||
// 'boatNameEn': 'WUCHUANHAO',
|
||||
// 'cog': '0',
|
||||
// 'createAt': '2025-12-01 11:04:44',
|
||||
// 'createBy': '',
|
||||
// 'crossLineTime': null,
|
||||
// 'delFlag': 0,
|
||||
// 'distance': null,
|
||||
// 'draftMarks': null,
|
||||
// 'entryOut': '',
|
||||
// 'height': 0.00000000,
|
||||
// 'heightRange': '',
|
||||
// 'hkResult': '',
|
||||
// 'id': 76168,
|
||||
// 'identificationType': '',
|
||||
// 'illegalType': '未穿救生衣预警,未封舱预警,未悬挂国旗',
|
||||
// 'isCloseDoor': '否',
|
||||
// 'isHasAis': '否',
|
||||
// 'jacketStatus': '',
|
||||
// 'latitude': null,
|
||||
// 'length': 0.00000000,
|
||||
// 'longitude': null,
|
||||
// 'mmsi': '413823183',
|
||||
// 'shipType': '集装箱船',
|
||||
// 'sourcePicPath': 'http://198.16.74.209:6060/pic/2025-12-01/198.16.74.187/20251201_110559/ship_1_20251201_110559_644.jpg',
|
||||
// 'speed': null,
|
||||
// 'streetName': '',
|
||||
// 'sysShipName': '',
|
||||
// 'sysUpdateName': '',
|
||||
// 'systemResult': '',
|
||||
// 'takeTime': '2025-12-23 11:06:08',
|
||||
// 'takeType': '卡口',
|
||||
// 'trackerPicPath': 'http://198.16.74.209:6060/pic/2025-12-01/198.16.74.187/20251201_110559/ship_1_20251201_110559_644.jpg,http://198.16.74.209:6060/pic/2025-12-01/198.16.74.187/20251201_110559/ship_2_20251201_110603_161.jpg,http://198.16.74.209:6060/pic/2025-12-01/198.16.74.187/20251201_110559/ship_3_20251201_110605_535.jpg,http://198.16.74.209:6060/pic/2025-12-01/198.16.74.187/20251201_110559/ship_4_20251201_110608_298.jpg',
|
||||
// 'updateAt': '2025-12-01 11:04:44',
|
||||
// 'updateBy': '',
|
||||
// 'videoCode': 'fd3b45e1429a4e47bba873af602a9bed',
|
||||
// 'videoName': '卧旗--雷云一体机',
|
||||
// 'videoUrl': '',
|
||||
// 'width': 0.00000000
|
||||
// }, {}
|
||||
// ].map(i => {
|
||||
// return {
|
||||
// ...i,
|
||||
// illegalType: i.illegalType?.split(',').map(j => {
|
||||
// return {
|
||||
// value: illegalTypes.find(type => type.value === j)?.prop,
|
||||
// label: j
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
// })
|
||||
// handle('check', tableData.value.length > 0 ? tableData.value[0] : {})
|
||||
}
|
||||
const changeRadio = () => {
|
||||
nextTick(() => {
|
||||
@@ -526,17 +453,7 @@ const closeDetail = () => {
|
||||
initData()
|
||||
}
|
||||
onMounted(() => {
|
||||
model.isHasBoatName = mapStore.dialog.data.isHasBoatName
|
||||
console.log(model)
|
||||
if(Object.keys(route.query).length > 0 && route.query.type === 'alarm') {
|
||||
model.takeType = route.query.takeType
|
||||
illegalType.value = route.query.illegalType
|
||||
nextTick(() => {
|
||||
if (Filter.value && Filter.value.model) {
|
||||
Filter.value.model.takeType = route.query.takeType
|
||||
}
|
||||
})
|
||||
}
|
||||
model.isHasBoatName = route.query.isHasBoatName
|
||||
|
||||
initData()
|
||||
})
|
||||
|
||||
@@ -1,22 +1,18 @@
|
||||
<template>
|
||||
<!-- 识别记录页面 -->
|
||||
<DialogComponent :style="{ resize: 'both', overflow: 'auto' }" v-if="type === 'alarm'" title="识别记录" width="1800" :draggable="true" :modal="false" @close="close">
|
||||
<DialogComponent :style="{ resize: 'both', overflow: 'auto' }" title="识别记录" width="1800" :draggable="true" :modal="false" @close="close">
|
||||
<AlarmCom/>
|
||||
</DialogComponent>
|
||||
</template>
|
||||
<script setup>
|
||||
import { computed } from 'vue'
|
||||
import DialogComponent from '@/components/Dialog/screen.vue'
|
||||
import AlarmCom from './alarm/index.vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import useMapStore from '@/store/modules/map'
|
||||
|
||||
const mapStore = useMapStore()
|
||||
const router = useRouter()
|
||||
const type = computed(() => mapStore.dialog.type)
|
||||
|
||||
const close = () => {
|
||||
mapStore.updateDialog(false)
|
||||
router.push('/')
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
@@ -6,24 +6,13 @@
|
||||
<router-view></router-view>
|
||||
</div>
|
||||
<Alarm/>
|
||||
<LargeModelCom v-if="visible && type === 'largeModel'"/>
|
||||
<IdentificationCom v-if="visible && type === 'alarm'"/>
|
||||
<WallCom v-if="visible && (type==='CCTV'|| type==='UAV')"/>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import HeaderMenuComponent from '@/components/HeaderMenu/index.vue'
|
||||
import MapComponent from '@/components/Map/index.vue'
|
||||
import Alarm from '@/views/business/alarm/index.vue'
|
||||
import LargeModelCom from '@/views/business/largeModel/index.vue'
|
||||
import IdentificationCom from '@/views/business/identification/index.vue'
|
||||
import WallCom from '@/views/business/wall/index.vue'
|
||||
import useMapStore from '@/store/modules/map'
|
||||
import { computed } from 'vue'
|
||||
|
||||
const mapStore = useMapStore()
|
||||
const visible = computed(() => mapStore.dialog.visible)
|
||||
const type = computed(() => mapStore.dialog.type)
|
||||
window.name = 'business_window'
|
||||
</script>
|
||||
|
||||
@@ -202,7 +191,7 @@ window.name = 'business_window'
|
||||
position: absolute;
|
||||
right: 7px;
|
||||
i:not(.el-select__clear) {
|
||||
// background: url("@/assets/images/common/icon_suffix.png") center center no-repeat;
|
||||
background: url("@/assets/images/common/icon_suffix.png") center center no-repeat;
|
||||
background-size: 8px 6px;
|
||||
width: 8px;
|
||||
height: 6px;
|
||||
@@ -230,7 +219,7 @@ window.name = 'business_window'
|
||||
right: 7px;
|
||||
top: 13px;
|
||||
.el-input__suffix-inner{
|
||||
// background: url("@/assets/images/common/icon_suffix.png") center center no-repeat;
|
||||
background: url("@/assets/images/common/icon_suffix.png") center center no-repeat;
|
||||
background-size: 8px 6px;
|
||||
width: 8px;
|
||||
height: 6px;
|
||||
|
||||
@@ -256,13 +256,11 @@ const send = () => {
|
||||
additionalContent += '\n' + data.mp4_url.join(' ') + '\n'
|
||||
}
|
||||
if(data.rtsp_url && Array.isArray(data.rtsp_url)) {
|
||||
console.log('data.rtsp_url', data.rtsp_url)
|
||||
data.rtsp_url.forEach(item => {
|
||||
additionalContent += '\n' + JSON.stringify(item) + '\n'
|
||||
})
|
||||
}
|
||||
if(data.rtsp_data && Array.isArray(data.rtsp_data)) {
|
||||
console.log('data.rtsp_data', data.rtsp_data)
|
||||
data.rtsp_data.forEach(item => {
|
||||
additionalContent += '\n' + JSON.stringify(item) + '\n'
|
||||
})
|
||||
|
||||
@@ -54,7 +54,9 @@ import { dragEvent } from '@/utils/common'
|
||||
import { getVideoStream, doStartOrStopUavAlgorithm } from '@/api/uav'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import useMapStore from '@/store/modules/map'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
const router = useRouter()
|
||||
const mapStore = useMapStore()
|
||||
const uavData = computed(() => mapStore.uavs.data)
|
||||
const ModuleLeft = ref(null)
|
||||
@@ -105,7 +107,7 @@ const initList = () => {
|
||||
History.value.initList()
|
||||
}
|
||||
const close = () => {
|
||||
mapStore.updateDialog({ visible: false, type: 'largeModel' })
|
||||
router.push('/')
|
||||
}
|
||||
const openVideo = (data) => {
|
||||
visible.value = data.visible
|
||||
|
||||
@@ -70,7 +70,6 @@ const renderMedia = (url, text) => {
|
||||
if (!url) {
|
||||
return ''
|
||||
}
|
||||
console.log(url, 'url')
|
||||
// 监控
|
||||
if (url.startsWith('{') && url.includes('rtsp_url')) {
|
||||
const videoNameMatch = JSON.parse(url).video_name
|
||||
@@ -193,7 +192,29 @@ return ''
|
||||
// 监控视频查看
|
||||
const openVideoHandler = (index) => {
|
||||
const data = videoArr.value[index]
|
||||
codes.value = [ data.videoCode ]
|
||||
// 雷云一体机一个视频
|
||||
if(data.videoName.indexOf('雷云') !== -1) {
|
||||
const videos = videoArr.value.filter(i => i.videoName.indexOf('雷云') !== -1).sort((a, b) => {
|
||||
const index1 = a.videoName[a.videoName.length - 1]
|
||||
const index2 = b.videoName[b.videoName.length - 1]
|
||||
return index1 - index2
|
||||
})
|
||||
|
||||
codes.value = [ videos[0].videoCode ]
|
||||
}else{
|
||||
if(data.videoName.indexOf('球机') !== -1) {
|
||||
const videos = videoArr.value.filter(i => i.videoName.indexOf('球机') !== -1).sort((a, b) => {
|
||||
const index1 = a.videoName[a.videoName.length - 1]
|
||||
const index2 = b.videoName[b.videoName.length - 1]
|
||||
return index1 - index2
|
||||
})
|
||||
codes.value = videos.map((i, index) => {
|
||||
return i.previewUrl
|
||||
})
|
||||
}else{
|
||||
codes.value = [ data.videoCode ]
|
||||
}
|
||||
}
|
||||
nextTick(() => {
|
||||
setTimeout(() => {
|
||||
visible.value = true
|
||||
|
||||
85
src/views/business/setting/index.vue
Normal file
85
src/views/business/setting/index.vue
Normal file
@@ -0,0 +1,85 @@
|
||||
<template>
|
||||
<!-- 业务配置页面 -->
|
||||
<DialogComponent :style="{ resize: 'both', overflow: 'auto' }" title="业务配置" width="1800" :draggable="true" :modal="false" @close="close">
|
||||
<div class="tabs-container">
|
||||
<el-tabs v-model="type" tab-position="left" class="tabs">
|
||||
<el-tab-pane v-for="item in tabs"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:name="item.value">
|
||||
<template #label>
|
||||
<span class="custom-tabs-label">
|
||||
<span>{{item.label}}</span>
|
||||
<el-icon v-if="type == item.value"><CaretRight /></el-icon>
|
||||
</span>
|
||||
</template>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
<CCTVComponent v-if="type === 'cctv'"/>
|
||||
</div>
|
||||
</DialogComponent>
|
||||
</template>
|
||||
<script setup>
|
||||
import { CaretRight } from '@element-plus/icons-vue'
|
||||
import DialogComponent from '@/components/Dialog/screen.vue'
|
||||
import CCTVComponent from './monitor/index.vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { ref } from 'vue'
|
||||
|
||||
const router = useRouter()
|
||||
const tabs = ref([
|
||||
{
|
||||
value: 'cctv',
|
||||
label: 'CCTV'
|
||||
},
|
||||
{
|
||||
value: 'UAV',
|
||||
label: '无人机'
|
||||
}
|
||||
])
|
||||
const type = ref('cctv')
|
||||
|
||||
const close = () => {
|
||||
router.push('/')
|
||||
}
|
||||
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.tabs-container{
|
||||
display: flex;
|
||||
width: 100%;
|
||||
}
|
||||
.el-tabs {
|
||||
box-sizing: border-box;
|
||||
:deep(.el-tabs__header){
|
||||
&.is-left{
|
||||
margin-right: 20px !important;
|
||||
}
|
||||
.el-tabs__nav-wrap::after {
|
||||
background-color: rgba(0, 192, 255, 0.2) !important;
|
||||
}
|
||||
.el-tabs__item {
|
||||
width: 200px;
|
||||
color: rgba(68, 165, 255, 1);
|
||||
justify-content: center;
|
||||
&.is-active{
|
||||
color: #00C0FF;
|
||||
background: rgba(10, 169, 255, 0.15);
|
||||
.el-icon{
|
||||
position: absolute;
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
.el-tabs__item.is-disabled {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
.el-tabs__active-bar {
|
||||
background-color: #00C0FF;
|
||||
}
|
||||
}
|
||||
}
|
||||
.content{
|
||||
width: calc(100% - 220px);
|
||||
}
|
||||
</style>
|
||||
262
src/views/business/setting/monitor/detail.vue
Normal file
262
src/views/business/setting/monitor/detail.vue
Normal file
@@ -0,0 +1,262 @@
|
||||
<template>
|
||||
<el-form class="detail-form" ref="form" :model="model" label-width="auto" :rules="rules" label-suffix=":">
|
||||
<el-form-item v-for="(item,index) in items" :key="index" :label="item.label" :prop="item.prop" :style="`grid-column-start: span ${item.width || '1'};`">
|
||||
|
||||
<el-input v-if="item.type === 'input'" v-model="model[item.prop]" :readonly="type==='check'"/>
|
||||
<el-input v-if="item.type === 'textarea'" autosize v-model="model[item.prop]" :rows="item.rows || 2" type="textarea" :readonly="type==='check'"/>
|
||||
<el-input-number v-if="item.type === 'number'" v-model="model[item.prop]" :min="item.min || 0" style="width: 100%;" :readonly="type==='check'"/>
|
||||
|
||||
<el-select v-if="item.type === 'select'" v-model="model[item.prop]" :clearable="item.clearable" :disabled="type==='check'">
|
||||
<el-option v-for="(opt, index) in item.options" :key="index" :label="opt.label" :value="opt.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
|
||||
<el-date-picker v-if="item.type === 'datetime'" v-model="model[item.prop]" type="datetime"
|
||||
:placeholder="item.placeholder ? item.placeholder : '请选择时间'" value-format="YYYY-MM-DD HH:mm:ss"
|
||||
:clearable="item.clearable" style="width:100%" :readonly="type==='check'">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div class="button-wrapper" v-if="type !== 'check'">
|
||||
<el-button type="primary" @click="validate">提交</el-button>
|
||||
<el-button type="primary" @click="$emit('close')">取消</el-button>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref, reactive } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { dsVideoSave, dsVideoUpdate } from '@/api/device'
|
||||
|
||||
const emit = defineEmits([ 'close' ])
|
||||
const props = defineProps({
|
||||
data: {
|
||||
default() {
|
||||
return {}
|
||||
},
|
||||
required: false,
|
||||
type: Object
|
||||
},
|
||||
type: {
|
||||
default: '',
|
||||
required: false,
|
||||
type: String
|
||||
}
|
||||
})
|
||||
|
||||
const form = ref(null)
|
||||
|
||||
const model = reactive({
|
||||
videoCode: '',
|
||||
videoName: '',
|
||||
longitude: '',
|
||||
latitude: '',
|
||||
height: 0,
|
||||
visionDistance: 5,
|
||||
videoIp: '',
|
||||
videoPort: '',
|
||||
videoAccount: '',
|
||||
videoPassword: '',
|
||||
channelNo: '0',
|
||||
videoType: '云台',
|
||||
belongUnit: '',
|
||||
runStatus: '正常',
|
||||
beBayonet: 0,
|
||||
bePlay: 0,
|
||||
playIndex: 1,
|
||||
playTime: 5
|
||||
})
|
||||
|
||||
const items = ref([
|
||||
{
|
||||
label: '监控编号',
|
||||
prop: 'videoCode',
|
||||
type: 'input'
|
||||
},
|
||||
{
|
||||
label: '监控名称',
|
||||
prop: 'videoName',
|
||||
type: 'input'
|
||||
},
|
||||
{
|
||||
label: '经度',
|
||||
prop: 'longitude',
|
||||
type: 'input'
|
||||
},
|
||||
{
|
||||
label: '纬度',
|
||||
prop: 'latitude',
|
||||
type: 'input'
|
||||
},
|
||||
{
|
||||
label: '监控安装高度(米)',
|
||||
prop: 'height',
|
||||
type: 'number'
|
||||
},
|
||||
{
|
||||
label: '可视距离(公里)',
|
||||
prop: 'visionDistance',
|
||||
type: 'number'
|
||||
},
|
||||
{
|
||||
label: '设备ip',
|
||||
prop: 'videoIp',
|
||||
type: 'input'
|
||||
},
|
||||
{
|
||||
label: '设备端口号',
|
||||
prop: 'videoPort',
|
||||
type: 'input'
|
||||
},
|
||||
{
|
||||
label: '设备账号',
|
||||
prop: 'videoAccount',
|
||||
type: 'input'
|
||||
},
|
||||
{
|
||||
label: '设备密码',
|
||||
prop: 'videoPassword',
|
||||
type: 'input'
|
||||
},
|
||||
{
|
||||
label: '监控类型',
|
||||
prop: 'videoType',
|
||||
type: 'select',
|
||||
options: [
|
||||
{ value: '球机', label: '球机' },
|
||||
{ value: '云台', label: '云台' }
|
||||
]
|
||||
},
|
||||
{
|
||||
label: '运行状态',
|
||||
prop: 'runStatus',
|
||||
type: 'select',
|
||||
options: [
|
||||
{ value: '正常', label: '正常' },
|
||||
{ value: '故障', label: '故障' }
|
||||
]
|
||||
},
|
||||
{
|
||||
label: '是否卡口',
|
||||
prop: 'beBayonet',
|
||||
type: 'select',
|
||||
options: [
|
||||
{ value: 1, label: '是' },
|
||||
{ value: 0, label: '否' }
|
||||
]
|
||||
},
|
||||
{
|
||||
label: '是否轮询',
|
||||
prop: 'bePlay',
|
||||
type: 'select',
|
||||
options: [
|
||||
{
|
||||
value: 1,
|
||||
label: '是'
|
||||
},
|
||||
{
|
||||
value: 0,
|
||||
label: '否'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
label: '轮询顺序',
|
||||
prop: 'playIndex',
|
||||
type: 'number'
|
||||
},
|
||||
{
|
||||
label: '轮询时间(s)',
|
||||
prop: 'playTime',
|
||||
type: 'number'
|
||||
},
|
||||
{
|
||||
label: '通道号',
|
||||
prop: 'channelNo',
|
||||
type: 'input'
|
||||
},
|
||||
{
|
||||
label: '监管所属单位',
|
||||
prop: 'belongUnit',
|
||||
type: 'input'
|
||||
}
|
||||
])
|
||||
|
||||
const rules = {
|
||||
videoCode: [ { required: true, message: '监控编号 未填写', trigger: 'blur' } ],
|
||||
videoName: [ { required: true, message: '监控名称 未填写', trigger: 'blur' } ],
|
||||
longitude: [ { required: true, message: '经度 未填写', trigger: 'blur' } ],
|
||||
latitude: [ { required: true, message: '纬度 未填写', trigger: 'blur' } ],
|
||||
height: [ { required: true, message: '监控安装高度 未填写', trigger: 'blur' } ],
|
||||
visionDistance: [ { required: true, message: '可视距离 未填写', trigger: 'blur' } ],
|
||||
videoIp: [ { required: true, message: '设备ip 未填写', trigger: 'blur' } ],
|
||||
videoPort: [ { required: true, message: '设备端口号 未填写', trigger: 'blur' } ],
|
||||
videoAccount: [ { required: true, message: '设备账号 未填写', trigger: 'blur' } ],
|
||||
videoPassword: [ { required: true, message: '设备密码 未填写', trigger: 'blur' } ],
|
||||
videoType: [ { required: true, message: '监控类型 未填写', trigger: 'blur' } ],
|
||||
runStatus: [ { required: true, message: '运行状态 未填写', trigger: 'blur' } ],
|
||||
beBayonet: [ { required: true, message: '是否卡口 未填写', trigger: 'change' } ],
|
||||
bePlay: [ { required: true, message: '是否轮询 未填写', trigger: 'change' } ]
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化赋值
|
||||
*/
|
||||
const initData = () => {
|
||||
if (props.type !== 'add') {
|
||||
Object.keys(model).forEach((key) => {
|
||||
model[key] = props.data[key]
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 表单校验
|
||||
*/
|
||||
const validate = () => {
|
||||
form.value.validate().then((valid) => {
|
||||
if (valid) {
|
||||
submit()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 表单校验
|
||||
*/
|
||||
const submit = () => {
|
||||
const params = {
|
||||
...model
|
||||
}
|
||||
if(props.type === 'add') {
|
||||
dsVideoSave(params).then(() => {
|
||||
ElMessage.success('提交成功!')
|
||||
emit('close', true)
|
||||
})
|
||||
}else{
|
||||
dsVideoUpdate({ ...params, id: props.data.id }).then(() => {
|
||||
ElMessage.success('提交成功!')
|
||||
emit('close', true)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
initData()
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.detail-form{
|
||||
display: grid;
|
||||
box-sizing: border-box;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
column-gap: 20px;
|
||||
}
|
||||
|
||||
.button-wrapper{
|
||||
width: 100%;
|
||||
margin-top: 20px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 20px;
|
||||
}
|
||||
</style>
|
||||
263
src/views/business/setting/monitor/index.vue
Normal file
263
src/views/business/setting/monitor/index.vue
Normal file
@@ -0,0 +1,263 @@
|
||||
<template>
|
||||
<div class="content">
|
||||
<FilterComponent :filter-buttons="filterButtons" :filter-items="items" :filter-model="model" @handle="handle"/>
|
||||
<TableComponent style="height: 650px;" :loading="loading" :data="tableData" :columns="columns" :config="config" :operate="operate" @handle="handle"/>
|
||||
<el-pagination v-model:current-page="pagination.current" v-model:page-size="pagination.size"
|
||||
:total="pagination.total" :page-sizes="[10, 15, 20, 50]" layout="total, sizes, prev, pager, next, jumper"
|
||||
@size-change="initData" @current-change="initData"
|
||||
style="margin-top: 10px; justify-content: center;" />
|
||||
<DialogComponent v-if="detail.visible" :title="detail.title[detail.type]" :modal="true" width="800"
|
||||
@close="closeDetail">
|
||||
<DetailComponent :data="detail.data" :type="detail.type" @close="closeDetail" />
|
||||
</DialogComponent>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { reactive, ref } from 'vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import FilterComponent from '@/components/Filter/index.vue'
|
||||
import TableComponent from '@/components/Table/index2.vue'
|
||||
import DialogComponent from '@/components/Dialog/screen.vue'
|
||||
import DetailComponent from './detail.vue'
|
||||
import { dsVideoPage, dsVideoDelete } from '@/api/device'
|
||||
|
||||
const items = [
|
||||
{
|
||||
label: '监控名称',
|
||||
prop: 'videoName',
|
||||
width: '180px',
|
||||
type: 'input'
|
||||
},
|
||||
{
|
||||
label: '监控编号',
|
||||
prop: 'videoCode',
|
||||
width: '180px',
|
||||
type: 'input'
|
||||
},
|
||||
{
|
||||
label: '是否卡口',
|
||||
prop: 'beBayonet',
|
||||
type: 'select',
|
||||
width: '180px',
|
||||
options: [
|
||||
{ value: 1, label: '是' },
|
||||
{ value: 0, label: '否' }
|
||||
]
|
||||
},
|
||||
{
|
||||
label: '是否轮询',
|
||||
prop: 'bePlay',
|
||||
type: 'select',
|
||||
width: '180px',
|
||||
options: [
|
||||
{ value: 1, label: '是' },
|
||||
{ value: 0, label: '否' }
|
||||
]
|
||||
}
|
||||
]
|
||||
const filterButtons = ref([
|
||||
{
|
||||
name: '检索',
|
||||
prop: 'query',
|
||||
theme: 'primary',
|
||||
type: 'button'
|
||||
},
|
||||
{
|
||||
name: '新增',
|
||||
prop: 'add',
|
||||
theme: 'primary',
|
||||
type: 'button'
|
||||
}
|
||||
])
|
||||
let model = {
|
||||
videoName: '',
|
||||
videoCode: '',
|
||||
beBayonet: '',
|
||||
bePlay: ''
|
||||
}
|
||||
|
||||
const loading = ref(false)
|
||||
const tableData = ref([])
|
||||
|
||||
const columns = [
|
||||
{
|
||||
label: '监控编号',
|
||||
prop: 'videoCode',
|
||||
width: 290
|
||||
},
|
||||
{
|
||||
label: '监控名称',
|
||||
prop: 'videoName',
|
||||
width: 250
|
||||
},
|
||||
{
|
||||
label: '经度',
|
||||
prop: 'longitude',
|
||||
width: 100
|
||||
},
|
||||
{
|
||||
label: '纬度',
|
||||
prop: 'latitude',
|
||||
width: 100
|
||||
},
|
||||
|
||||
{
|
||||
label: '设备ip',
|
||||
prop: 'videoIp',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
label: '设备端口号',
|
||||
prop: 'videoPort',
|
||||
width: 90
|
||||
},
|
||||
{
|
||||
label: '通道号',
|
||||
prop: 'channelNo',
|
||||
width: 60
|
||||
},
|
||||
{
|
||||
label: '监控类型',
|
||||
prop: 'videoType',
|
||||
width: 80
|
||||
},
|
||||
{
|
||||
label: '运行状态',
|
||||
prop: 'runStatus',
|
||||
width: 80
|
||||
},
|
||||
{
|
||||
label: '是否卡口',
|
||||
prop: 'beBayonetF',
|
||||
width: 80
|
||||
},
|
||||
{
|
||||
label: '是否轮询',
|
||||
prop: 'bePlayF',
|
||||
width: 80
|
||||
}
|
||||
]
|
||||
|
||||
const config = {
|
||||
type: 'index',
|
||||
width: 110,
|
||||
align: 'center'
|
||||
}
|
||||
|
||||
const operate = [
|
||||
{
|
||||
label: '编辑',
|
||||
prop: 'edit',
|
||||
theme: 'success'
|
||||
},
|
||||
{
|
||||
label: '删除',
|
||||
prop: 'remove',
|
||||
theme: 'danger'
|
||||
}
|
||||
]
|
||||
|
||||
const pagination = {
|
||||
current: 1,
|
||||
size: 15,
|
||||
total: 0
|
||||
}
|
||||
|
||||
const detail = reactive({
|
||||
visible: false,
|
||||
title: {
|
||||
add: '监控信息新增',
|
||||
check: '监控信息查看',
|
||||
edit: '监控信息编辑'
|
||||
},
|
||||
type: 'add',
|
||||
data: {}
|
||||
})
|
||||
|
||||
const initData = () => {
|
||||
loading.value = true
|
||||
const data = {
|
||||
...model,
|
||||
pageNum: pagination.current,
|
||||
pageSize: pagination.size
|
||||
}
|
||||
dsVideoPage(data).then(res => {
|
||||
tableData.value = res.rows.map(i => {
|
||||
return {
|
||||
...i,
|
||||
beBayonetF: i.beBayonet === 1 ? '是' : '否',
|
||||
bePlayF: i.bePlay === 1 ? '是' : '否'
|
||||
}
|
||||
})
|
||||
pagination.total = res.total
|
||||
}).finally(() => {
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 按钮操作
|
||||
* @param type 操作类型
|
||||
* @param data 数据
|
||||
*/
|
||||
const handle = (type, data) => {
|
||||
|
||||
switch (type) {
|
||||
case 'query':
|
||||
model = { ...data }
|
||||
pagination.current = 1
|
||||
initData()
|
||||
break
|
||||
case 'add':
|
||||
detail.visible = true
|
||||
detail.type = 'add'
|
||||
detail.data = {}
|
||||
break
|
||||
case 'check':
|
||||
case 'edit':
|
||||
detail.visible = true
|
||||
detail.type = type
|
||||
detail.data = { ...data }
|
||||
break
|
||||
case 'remove': {
|
||||
ElMessageBox.confirm(
|
||||
'是否移除该条数据?',
|
||||
'提示',
|
||||
{
|
||||
confirmButtonText: '确认',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}
|
||||
).then(() => {
|
||||
const params = {
|
||||
id: data.id
|
||||
}
|
||||
dsVideoDelete(params).then(() => {
|
||||
ElMessage.success('移除成功!')
|
||||
initData()
|
||||
})
|
||||
}).catch(() => { /* empty */ })
|
||||
break
|
||||
}
|
||||
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭详情弹窗
|
||||
* @param refresh 是否刷新数据
|
||||
*/
|
||||
const closeDetail = (refresh) => {
|
||||
detail.visible = false
|
||||
if (refresh) {
|
||||
initData()
|
||||
}
|
||||
}
|
||||
initData()
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
</style>
|
||||
@@ -39,7 +39,7 @@
|
||||
import { nextTick, onUnmounted, ref } from 'vue'
|
||||
import HikPlayerComponent from '@/components/Player/HikPlayer.vue'
|
||||
import FlvPlayerComponent from '@/components/FlvPlayer/index.vue'
|
||||
import { getVideoStream, doStartOrStopUavAlgorithm } from '@/api/uav'
|
||||
import { getVideoStream } from '@/api/uav'
|
||||
|
||||
const control = ref([
|
||||
{ label: '1X1', value: 1 },
|
||||
@@ -93,7 +93,6 @@ const closeVideo = (data, item) => {
|
||||
const handleNodeClick = (node) => {
|
||||
if(props.videoType === 'CCTV' && node.videoCode) {
|
||||
let index = haikang.value.findIndex(i => !i)
|
||||
console.log(index, haikang.value, 'value')
|
||||
if(index !== -1) {
|
||||
haikang.value[index] = { codes: node.videoCode }
|
||||
}
|
||||
|
||||
@@ -12,13 +12,12 @@ import { computed, nextTick, ref, watch } from 'vue'
|
||||
import DialogComponent from '@/components/Dialog/screen.vue'
|
||||
import TreeCom from './tree.vue'
|
||||
import GridCom from './grid.vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import useMapStore from '@/store/modules/map'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { dragEvent, resizeEvent } from '@/utils/common'
|
||||
|
||||
const mapStore = useMapStore()
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const type = computed(() => mapStore.dialog.type)
|
||||
const type = computed(() => route.query.type)
|
||||
const Tree = ref(null)
|
||||
const Grid = ref(null)
|
||||
|
||||
@@ -32,7 +31,7 @@ const handle = (node) => {
|
||||
Grid.value.handleNodeClick(node)
|
||||
}
|
||||
const close = () => {
|
||||
mapStore.updateDialog(false)
|
||||
router.push('/')
|
||||
}
|
||||
watch(() => type.value, () => {
|
||||
if(type.value) {
|
||||
@@ -48,8 +47,8 @@ watch(() => type.value, () => {
|
||||
*
|
||||
*/
|
||||
const drag = (e) => {
|
||||
if(e.target.className.includes('el-dialog-title')) {
|
||||
dragEvent(e, 'el-dialog-title', () => {
|
||||
if(e.target.className.includes('el-dialog-title') || e.target.className.includes('el-dialog__title')) {
|
||||
dragEvent(e, 'el-dialog', () => {
|
||||
if(Grid.value.videoPreview) {
|
||||
Grid.value.videoPreview.forEach(i => {
|
||||
i.initResize(false)
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
import { findVideoLevelList, findUavPage, findEnvPage, dsVideoList } from '@/api/device.js'
|
||||
import { ref } from 'vue'
|
||||
import { findVideoLevelList, findUavPage } from '@/api/device.js'
|
||||
|
||||
const emit = defineEmits([ 'handle' ])
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
</el-breadcrumb>
|
||||
<div class="title">千帆智瞰</div>
|
||||
<div class="user">
|
||||
<!-- <el-button :icon="Monitor" @click="goBusiness">业务系统</el-button> -->
|
||||
<el-button :icon="Monitor" @click="goHome">返回门户</el-button>
|
||||
<el-avatar :icon="UserFilled" :size="28"/>
|
||||
<el-dropdown @command="handle">
|
||||
@@ -150,12 +149,6 @@ const validate = () => {
|
||||
}
|
||||
})
|
||||
}
|
||||
/**
|
||||
* 跳转到系统设置
|
||||
*/
|
||||
const goBusiness = () => {
|
||||
window.open('/', 'business_window')
|
||||
}
|
||||
const goHome = () => {
|
||||
window.open('/', 'business_window')
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user