智慧装备添加锚点,右侧一级二级展示,以及点击锚点弹框
@ -549,3 +549,28 @@ export function getFlowDischargeList(code: string, data: any) {
|
|||||||
data
|
data
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 智慧装备 - 动物 鸟类
|
||||||
|
export function getAnimalList(data: any) {
|
||||||
|
return request({
|
||||||
|
url: '/wte/anml/run/GetKendoListCust',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// 智慧装备 - 钓鱼、违章监测、漂浮物识别装置、叠梁门运行识别装置
|
||||||
|
export function getWarningList(data: any) {
|
||||||
|
return request({
|
||||||
|
url: '/warn/ai/com/GetKendoListCust',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// 智慧装备 - 鱼类调查装置 鱼类智能识别装置 智能分拣装置
|
||||||
|
export function getFishList(data: any) {
|
||||||
|
return request({
|
||||||
|
url: '/wte/fp/ai/GetKendoListCust',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
@ -69,7 +69,15 @@ export function stbprpGetStbprpYsByStcd(data: any) {
|
|||||||
return request({
|
return request({
|
||||||
url: '/wq/stbprp/GetStbprpYsByStcd',
|
url: '/wq/stbprp/GetStbprpYsByStcd',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params:data
|
params: data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
//水质监测工作开展情况 - wte接口
|
||||||
|
export function vmsstbprptGetKendoListWte(data: any) {
|
||||||
|
return request({
|
||||||
|
url: '/wte/vmsstbprpt/GetKendoList',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
//表格数据获取函数
|
//表格数据获取函数
|
||||||
@ -87,3 +95,11 @@ export function NodataGetKendoListCust(data: any) {
|
|||||||
data
|
data
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
// 各基地社保统计
|
||||||
|
export function imeBaseDeviceStat(data: any) {
|
||||||
|
return request({
|
||||||
|
url: '/ime/base/device/stat',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
23
frontend/src/assets/legend/map-dlmsb.svg
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 22.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg width="20" height="23" version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 20 23" style="enable-background:new 0 0 20 23;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:#0AC266;}
|
||||||
|
.st1{fill:#00A050;}
|
||||||
|
.st2{fill:#FFFFFF;}
|
||||||
|
</style>
|
||||||
|
<title>map-qixidi</title>
|
||||||
|
<g id="页面-1_9_">
|
||||||
|
<g id="map-qixidi_9_">
|
||||||
|
<path id="路径_20_" class="st0" d="M10,0c5.5,0,10,4.5,10,10c0,4.6-3.1,8.4-7.3,9.6c-0.6,0.6-1.2,1.3-1.7,2l-0.6,1
|
||||||
|
C10.3,23,10,23,9.7,22.9c-0.1,0-0.1-0.1-0.2-0.2l-0.6-1c-0.5-0.8-1-1.4-1.7-2C3.1,18.5,0,14.6,0,10.1C0,4.5,4.5,0,10,0z"/>
|
||||||
|
<path id="路径_19_" class="st1" d="M10,1c-5,0-9,4-9,9c0,4,2.6,7.4,6.3,8.6l0.5,0.1L7.9,19c0.6,0.6,1.2,1.2,1.6,1.9l0.2,0.4
|
||||||
|
l0.2,0.3l0.2-0.3c0.4-0.7,1-1.4,1.6-2L12,19l0.2-0.2l0.2-0.1c3.8-1.1,6.5-4.6,6.5-8.7C19,5.1,15,1,10,1z"/>
|
||||||
|
<path class="st2" d="M14.3,11H5.9v1.9h3l0.1,0l1.2,0.5l1.1-0.5l0.1,0h3V11z M14.3,8H5.9v1.5h3l0.1,0l1.2,0.5l1.1-0.5l0.1,0h3
|
||||||
|
C14.3,9.5,14.3,8,14.3,8z M14.3,5.5c0-0.4,0.3-0.8,0.7-0.8c0.1,0,0.2,0,0.3,0.1c0.1,0,0.1,0.1,0.1,0.2v10.5c0,0.1,0,0.1-0.1,0.2
|
||||||
|
c-0.1,0-0.2,0.1-0.3,0.1c-0.4,0-0.7-0.3-0.7-0.8v-0.6H5.9V15c0,0.4-0.3,0.8-0.7,0.8c-0.1,0-0.2,0-0.3-0.1c-0.1,0-0.1-0.1-0.1-0.2
|
||||||
|
V5c0-0.1,0-0.1,0.1-0.2c0.1,0,0.2-0.1,0.3-0.1c0.4,0,0.7,0.3,0.7,0.8v0.9h3l0.1,0L10.1,7l1.1-0.6l0.1,0h3V5.5L14.3,5.5z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.5 KiB |
47
frontend/src/assets/legend/map-dwsb.svg
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 22.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg width="20" height="23" version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 20 23" style="enable-background:new 0 0 20 23;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:#0AC266;}
|
||||||
|
.st1{fill:#00A050;}
|
||||||
|
.st2{fill:#FFFFFF;}
|
||||||
|
</style>
|
||||||
|
<title>map-qixidi</title>
|
||||||
|
<g id="页面-1_12_">
|
||||||
|
<g id="map-qixidi_12_">
|
||||||
|
<path id="路径_26_" class="st0" d="M10,0c5.5,0,10,4.5,10,10c0,4.6-3.1,8.4-7.3,9.6c-0.6,0.6-1.2,1.3-1.7,2l-0.6,1
|
||||||
|
C10.3,23,10,23,9.7,22.9c-0.1,0-0.1-0.1-0.2-0.2l-0.6-1c-0.5-0.8-1-1.4-1.7-2C3.1,18.5,0,14.6,0,10.1C0,4.5,4.5,0,10,0z"/>
|
||||||
|
<path id="路径_25_" class="st1" d="M10,1c-5,0-9,4-9,9c0,4,2.6,7.4,6.3,8.6l0.5,0.1L8,19c0.6,0.6,1.2,1.2,1.6,1.9l0.2,0.4
|
||||||
|
l0.2,0.3l0.2-0.3c0.4-0.7,1-1.4,1.6-2l0.3-0.3l0.2-0.2l0.2-0.1c3.8-1.1,6.5-4.6,6.5-8.7C19,5.1,15,1,10,1z"/>
|
||||||
|
<g>
|
||||||
|
<path class="st2" d="M7.8,10.6c0-0.5-0.4-0.9-0.7-1.2C7,9.3,6.9,9.1,6.8,9C6.7,8.8,6.5,8.6,6.4,8.6c0-0.2-0.1-0.4-0.2-0.7
|
||||||
|
C6,8.1,5.9,8.2,5.9,8.4h0c0,0.1,0,0.2,0,0.3c-0.4,0.2-0.5,0.9-0.5,1.6c0,0.9,0.7,1.5,1.2,1.5C7.3,11.8,7.8,11.3,7.8,10.6z
|
||||||
|
M6.1,10.3c0-0.5,0-0.8,0.1-0.9l0,0c0.2,0.2,0.3,0.4,0.4,0.5c0.3,0.3,0.5,0.5,0.5,0.7c0,0.2,0,0.3-0.1,0.4
|
||||||
|
c-0.1,0.1-0.2,0.1-0.4,0.1c-0.1,0-0.2-0.1-0.3-0.2C6.2,10.8,6.1,10.6,6.1,10.3z"/>
|
||||||
|
<path class="st2" d="M8.6,9.6c0.7,0,1.2-0.5,1.2-1.2c0-0.7-0.3-1.5-0.5-1.9C9.2,6.2,9.1,6.1,8.9,6c0,0,0,0,0,0
|
||||||
|
c0-0.2-0.1-0.4-0.2-0.7C8.5,5.4,8.4,5.6,8.4,5.7c0,0.1,0,0.2,0,0.2c-0.7,0.2-1,1.2-1,1.9C7.4,8.8,7.8,9.6,8.6,9.6z M8.3,7
|
||||||
|
c0.1-0.2,0.2-0.3,0.2-0.3c0.1,0,0.1,0,0.1,0c0,0,0,0,0,0.1C8.8,7,8.9,7.2,9,7.5C9,7.8,9.1,8.1,9.1,8.4c0,0.2,0,0.3-0.1,0.4
|
||||||
|
C8.9,8.8,8.7,8.9,8.6,8.9c-0.1,0-0.2-0.1-0.3-0.2C8.2,8.5,8.1,8.2,8.1,7.9C8.1,7.6,8.2,7.3,8.3,7z"/>
|
||||||
|
<path class="st2" d="M11.8,9.6c0.7,0,1.2-1,1.2-1.7c0-0.7-0.5-1.9-1.2-1.9c0-0.1,0-0.2,0-0.2c0-0.2-0.1-0.3-0.2-0.5
|
||||||
|
c-0.1,0.3-0.2,0.6-0.2,0.8c-0.2,0.1-0.4,0.3-0.5,0.6c-0.2,0.4-0.5,1-0.5,1.7C10.3,9.1,11.1,9.6,11.8,9.6z M11.2,7.7
|
||||||
|
c0.1-0.2,0.2-0.4,0.3-0.6c0.1-0.2,0.2-0.3,0.2-0.3c0,0,0,0,0.1,0c0,0,0,0,0,0C11.9,6.8,12,6.9,12.1,7c0.2,0.3,0.3,0.6,0.3,0.9
|
||||||
|
c0,0.3-0.1,0.5-0.2,0.7c-0.1,0.2-0.2,0.2-0.3,0.2c-0.2,0-0.4-0.1-0.6-0.2c-0.1-0.1-0.2-0.2-0.2-0.3C11.1,8.2,11.1,7.9,11.2,7.7z"
|
||||||
|
/>
|
||||||
|
<path class="st2" d="M14.4,8.7c0-0.1,0-0.2,0-0.3h0c0-0.2-0.1-0.3-0.2-0.5c-0.1,0.3-0.2,0.5-0.2,0.8c-0.1,0.1-0.3,0.2-0.5,0.4
|
||||||
|
c-0.2,0.2-1,1-0.7,1.7c0.2,0.7,0.7,1,1.2,1c0.5,0,1.2-1,1.2-1.7C15.1,9.5,14.7,8.9,14.4,8.7z M14,10.8C14,10.9,13.9,11,13.8,11
|
||||||
|
l0,0c-0.2,0-0.4-0.2-0.5-0.5c-0.1-0.2,0.1-0.5,0.6-1h0C14,9.5,14,9.5,14.1,9.4c0,0,0,0,0.1,0.1c0.1,0.2,0.2,0.4,0.2,0.6
|
||||||
|
C14.3,10.3,14.2,10.5,14,10.8z"/>
|
||||||
|
<path class="st2" d="M13.1,11.9c-0.1-0.1-0.2-0.1-0.2-0.2c-0.7-1.2-1.2-2.2-2.7-2.2c-1,0-1.5,0.5-1.7,1c-0.2,0.3-0.5,1-1.5,1.7
|
||||||
|
c-1.2,1.2-0.5,2.4,0.5,2.7c1.3,0.2,1.9-0.1,2.3-0.3c0.2-0.1,0.4-0.2,0.7-0.2c0.2,0,0.5,0.1,0.8,0.2c0.4,0.1,0.7,0.3,1.1,0.3h0
|
||||||
|
c0.6,0,1.4,0,1.8-1C14.5,13,13.5,12.3,13.1,11.9z M13.2,13.6c-0.1,0.2-0.2,0.3-0.3,0.3c-0.1,0-0.3,0.1-0.6,0.1h0
|
||||||
|
c-0.1,0-0.4-0.1-0.8-0.2c-0.5-0.2-0.9-0.3-1.2-0.3c-0.3,0-0.7,0.1-1.1,0.3C9,13.9,8.8,13.9,8.6,14h0C8.3,14,8,14,7.5,14
|
||||||
|
c-0.2-0.1-0.3-0.2-0.3-0.3c-0.1-0.2,0-0.4,0.3-0.7c0.8-0.6,1.3-1.2,1.7-2v0c0.1-0.3,0.4-0.4,0.9-0.4c0.4,0,0.7,0.1,0.9,0.3
|
||||||
|
c0.2,0.2,0.5,0.6,0.9,1.2l0.1,0.2l0.1,0.1l0.1,0.1c0.1,0.1,0.2,0.2,0.3,0.3C13,13.1,13.2,13.4,13.2,13.6z"/>
|
||||||
|
<path class="st2" d="M5.6,7H4.7V5.6c0-0.4,0.3-0.7,0.7-0.7h1.4v0.8H5.7c-0.1,0-0.1,0.1-0.1,0.1V7z M15,4.9h-1.4v0.8h1.2
|
||||||
|
c0.1,0,0.1,0.1,0.1,0.1V7h0.8V5.6C15.7,5.2,15.4,4.9,15,4.9z M5.6,14.9v-1.2H4.7v1.4c0,0.4,0.3,0.7,0.7,0.7h1.4V15H5.7
|
||||||
|
C5.6,15,5.6,15,5.6,14.9z M14.9,14.9c0,0.1-0.1,0.1-0.1,0.1h-1.2v0.8H15c0.4,0,0.7-0.3,0.7-0.7v-1.4h-0.8V14.9z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 3.8 KiB |
30
frontend/src/assets/legend/map-dy.svg
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 22.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg width="20" height="23" version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 20 23" style="enable-background:new 0 0 20 23;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:#0AC266;}
|
||||||
|
.st1{fill:#00A050;}
|
||||||
|
.st2{fill:#FFFFFF;}
|
||||||
|
</style>
|
||||||
|
<title>map-qixidi</title>
|
||||||
|
<g id="页面-1_5_">
|
||||||
|
<g id="map-qixidi_5_">
|
||||||
|
<path id="路径_12_" class="st0" d="M10,0c5.5,0,10,4.5,10,10c0,4.6-3.1,8.4-7.3,9.6c-0.6,0.6-1.2,1.3-1.7,2l-0.6,1
|
||||||
|
C10.3,23,10,23,9.8,22.9c-0.1,0-0.1-0.1-0.2-0.2l-0.6-1c-0.5-0.8-1-1.4-1.7-2C3.1,18.5,0,14.6,0,10C0,4.5,4.5,0,10,0z"/>
|
||||||
|
<path id="路径_11_" class="st1" d="M10,1c-5,0-9,4-9,9c0,4,2.6,7.4,6.3,8.6l0.5,0.1L8,19c0.6,0.6,1.2,1.2,1.6,1.9l0.2,0.4
|
||||||
|
l0.2,0.3l0.2-0.3c0.4-0.7,1-1.4,1.6-2l0.3-0.3l0.2-0.2l0.2-0.1c3.8-1.1,6.5-4.6,6.5-8.7C19,5.1,15,1,10,1z"/>
|
||||||
|
<g>
|
||||||
|
<path class="st2" d="M16.2,11.4H14c-0.3,0-0.7,0.2-0.9,0.4l-0.9,0.9l-0.5-0.5c-0.9-0.9-2-1.3-3.1-1.3c-1.1,0-2.3,0.4-3.1,1.3
|
||||||
|
l-1.2,1.2l1.2,1.2c0.9,0.9,2,1.3,3.1,1.3c1.2,0,2.3-0.5,3.1-1.3l0.5-0.5l0.9,0.9c0.2,0.2,0.6,0.4,0.9,0.4h2.3l-0.5-2L16.2,11.4z
|
||||||
|
M11,13.9c-0.6,0.6-1.5,1-2.4,1c-0.9,0-1.8-0.4-2.4-1l-0.5-0.5l0.5-0.5c0.6-0.6,1.5-1,2.4-1c0.9,0,1.8,0.4,2.4,1l0.5,0.5L11,13.9
|
||||||
|
L11,13.9z M15,14.4h-1c0,0-0.1,0-0.2-0.1l-0.9-0.9l0.9-0.9c0,0,0.1-0.1,0.2-0.1l1,0l-0.3,1L15,14.4z"/>
|
||||||
|
<path class="st2" d="M8,13.4c0,0.3-0.2,0.5-0.5,0.5c0,0,0,0,0,0c-0.3,0-0.5-0.2-0.5-0.5c0,0,0,0,0,0c0-0.3,0.2-0.5,0.5-0.5
|
||||||
|
c0,0,0,0,0,0C7.8,12.9,8,13.1,8,13.4C8,13.4,8,13.4,8,13.4z M7,8.6h0.8c0,0.4-0.3,0.7-0.8,0.7c-0.4,0-0.7-0.3-0.7-0.7V6.8
|
||||||
|
c0.6-0.2,1-0.8,1-1.4c0-0.8-0.7-1.5-1.5-1.5S4.2,4.6,4.2,5.4c0,0.7,0.4,1.2,1,1.4v1.8c0,1,0.8,1.8,1.7,1.8c1,0,1.8-0.8,1.8-1.7
|
||||||
|
V6.9L7,8.6z M5.7,5.9c-0.3,0-0.5-0.2-0.5-0.5c0-0.3,0.2-0.5,0.5-0.5c0,0,0,0,0,0c0.3,0,0.5,0.2,0.5,0.5C6.2,5.7,6,5.9,5.7,5.9z"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.0 KiB |
54
frontend/src/assets/legend/map-hdsb.svg
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 22.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg width="20" height="23" version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 20 23" style="enable-background:new 0 0 20 23;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:#0AC266;}
|
||||||
|
.st1{fill:#00A050;}
|
||||||
|
.st2{fill:#FFFFFF;}
|
||||||
|
</style>
|
||||||
|
<title>map-qixidi</title>
|
||||||
|
<g id="页面-1_4_">
|
||||||
|
<g id="map-qixidi_4_">
|
||||||
|
<path id="路径_10_" class="st0" d="M10,0c5.5,0,10,4.5,10,10c0,4.6-3.1,8.4-7.3,9.6c-0.6,0.6-1.2,1.3-1.7,2l-0.6,1
|
||||||
|
c-0.1,0.2-0.5,0.3-0.7,0.2c-0.1,0-0.1-0.1-0.2-0.2l-0.6-1c-0.5-0.8-1-1.4-1.7-2C3.1,18.5,0,14.6,0,10C0,4.5,4.5,0,10,0z"/>
|
||||||
|
<path id="路径_9_" class="st1" d="M10,1c-5,0-9,4-9,9c0,4,2.6,7.4,6.3,8.6l0.5,0.1L8,18.9c0.6,0.6,1.2,1.2,1.6,1.9l0.2,0.4
|
||||||
|
l0.2,0.3l0.2-0.3c0.4-0.7,1-1.4,1.6-2l0.3-0.3l0.2-0.2l0.2-0.1c3.8-1.1,6.5-4.6,6.5-8.7C19,5.1,15,1,10,1z"/>
|
||||||
|
<g>
|
||||||
|
<path class="st2" d="M8.8,15.9c-0.1,0-0.2,0-0.2-0.1l-0.1-0.1c-0.1-0.1-0.1-0.3,0-0.5s0.3-0.1,0.5,0L9,15.3
|
||||||
|
c0.1,0.1,0.1,0.3,0,0.5C8.9,15.9,8.8,15.9,8.8,15.9z M7.8,15c-0.1,0-0.2,0-0.2-0.1l-0.2-0.2c-0.1-0.1-0.1-0.3,0-0.5
|
||||||
|
c0.1-0.1,0.3-0.1,0.5,0l0,0l0.2,0.2c0.1,0.1,0.1,0.3,0,0.5C8,14.9,7.9,15,7.8,15L7.8,15z M7,13.3L7,13.3c-0.2,0-0.3-0.2-0.3-0.3
|
||||||
|
c0-0.1,0-0.1,0-0.2c0-0.2,0.2-0.3,0.4-0.3c0.2,0,0.3,0.2,0.3,0.4c0,0,0,0.1,0,0.1C7.3,13.2,7.2,13.3,7,13.3L7,13.3z M7.5,12.1
|
||||||
|
c-0.2,0-0.3-0.1-0.3-0.3c0-0.1,0-0.1,0.1-0.2c0.1-0.1,0.2-0.2,0.3-0.3c0.1-0.1,0.3-0.1,0.5,0c0.1,0.1,0.1,0.3,0,0.4
|
||||||
|
c-0.1,0.1-0.1,0.1-0.2,0.2C7.7,12.1,7.6,12.1,7.5,12.1L7.5,12.1z M8.4,10.5L8.4,10.5c-0.2,0-0.3-0.2-0.3-0.3V10
|
||||||
|
c0-0.2,0.1-0.3,0.3-0.3c0.2,0,0.3,0.1,0.3,0.3l0,0v0.2C8.7,10.3,8.6,10.5,8.4,10.5L8.4,10.5z M8.1,9.2C8,9.2,7.9,9.2,7.8,9.1
|
||||||
|
C7.8,9,7.7,9,7.6,8.9c-0.1-0.1-0.1-0.3,0-0.5c0.1-0.1,0.3-0.1,0.5,0c0,0,0,0,0,0c0.1,0.1,0.2,0.2,0.2,0.3
|
||||||
|
c0.1,0.1,0.1,0.3-0.1,0.4C8.2,9.2,8.1,9.2,8.1,9.2z M7.1,7.6c-0.2,0-0.3-0.1-0.3-0.3c0-0.1,0-0.1,0-0.2C6.7,7,6.8,6.8,7,6.8
|
||||||
|
c0.2,0,0.3,0.1,0.4,0.3c0,0,0,0,0,0c0,0,0,0.1,0,0.1C7.4,7.4,7.3,7.6,7.1,7.6C7.1,7.6,7.1,7.6,7.1,7.6L7.1,7.6z M7.3,6.4
|
||||||
|
c-0.2,0-0.3-0.1-0.3-0.3c0-0.1,0-0.1,0-0.2C7,5.8,7.1,5.7,7.2,5.6c0.1-0.1,0.3-0.2,0.5-0.1C7.8,5.6,7.8,5.8,7.7,6
|
||||||
|
C7.6,6.1,7.6,6.1,7.5,6.2C7.5,6.3,7.4,6.4,7.3,6.4L7.3,6.4z M8.6,5C8.4,5,8.3,4.9,8.3,4.7c0-0.1,0-0.2,0.1-0.2l0.1-0.1
|
||||||
|
C8.7,4.2,8.9,4.3,9,4.4c0.1,0.1,0.1,0.3,0,0.4L8.8,4.9C8.8,5,8.7,5,8.6,5L8.6,5z M13.2,16.1c-0.2,0-0.3-0.1-0.3-0.3c0,0,0,0,0,0
|
||||||
|
c0-0.2,0.1-0.3,0.3-0.3c0.1,0,0.2,0,0.2,0.1c0.1,0.1,0.1,0.3,0,0.5C13.3,16.1,13.2,16.1,13.2,16.1z M12.3,15.3
|
||||||
|
c-0.1,0-0.2,0-0.2-0.1l-0.6-0.6c0,0-0.1-0.1-0.1-0.2c-0.1-0.1-0.1-0.3,0-0.5c0,0,0,0,0,0c0.1-0.1,0.3-0.1,0.5,0
|
||||||
|
c0,0,0.1,0.1,0.1,0.1l0.6,0.6c0.1,0.1,0.1,0.3,0,0.5C12.5,15.3,12.4,15.3,12.3,15.3L12.3,15.3z M11.2,13.4
|
||||||
|
c-0.2,0-0.3-0.1-0.3-0.3c0-0.2,0.1-0.3,0.3-0.3c0.2,0,0.3,0.1,0.3,0.3C11.5,13.3,11.4,13.4,11.2,13.4L11.2,13.4L11.2,13.4z
|
||||||
|
M11.5,12.4c-0.1,0-0.1,0-0.2,0c-0.2-0.1-0.2-0.3-0.1-0.4c0.1-0.2,0.3-0.4,0.5-0.6c0.1-0.1,0.1-0.1,0.2-0.2
|
||||||
|
c0.1-0.1,0.3-0.1,0.5,0c0.1,0.1,0.1,0.3,0,0.5c-0.1,0.1-0.2,0.2-0.2,0.2c-0.1,0.1-0.3,0.3-0.4,0.4C11.7,12.3,11.6,12.4,11.5,12.4
|
||||||
|
z M12.6,10.5L12.6,10.5c-0.1,0-0.2,0-0.2-0.1c-0.1-0.1-0.1-0.1-0.1-0.2c0-0.2,0.2-0.3,0.3-0.3c0.2,0,0.3,0.2,0.3,0.3
|
||||||
|
C12.9,10.3,12.7,10.5,12.6,10.5z M12.3,9.4c-0.1,0-0.2-0.1-0.3-0.2c-0.1-0.1-0.2-0.3-0.3-0.4l-0.2-0.2l-0.1-0.1
|
||||||
|
c-0.1-0.1-0.1-0.3,0-0.5c0.1-0.1,0.3-0.1,0.5,0L12,8.2l0.2,0.2c0.2,0.2,0.3,0.3,0.4,0.5c0.1,0.2,0,0.4-0.1,0.4c0,0,0,0,0,0
|
||||||
|
C12.4,9.4,12.4,9.4,12.3,9.4L12.3,9.4z M11.2,7.5c-0.2,0-0.3-0.1-0.3-0.3c0-0.1,0-0.2,0.1-0.2c0.1-0.1,0.1-0.1,0.2-0.1
|
||||||
|
c0.2,0,0.3,0.1,0.4,0.3C11.5,7.3,11.4,7.5,11.2,7.5C11.2,7.5,11.2,7.5,11.2,7.5L11.2,7.5L11.2,7.5z M11.4,6.4c-0.1,0-0.1,0-0.2,0
|
||||||
|
c-0.2-0.1-0.2-0.3-0.1-0.4c0.1-0.3,0.3-0.5,0.5-0.7l0.2-0.2C12,5,12.2,5,12.3,5.1c0.1,0.1,0.1,0.3,0,0.5l-0.2,0.2
|
||||||
|
c-0.2,0.1-0.3,0.3-0.4,0.5C11.7,6.3,11.5,6.4,11.4,6.4L11.4,6.4z M13,4.8c-0.1,0-0.2,0-0.2-0.1c-0.1-0.1-0.1-0.1-0.1-0.2
|
||||||
|
c0-0.1,0-0.2,0.1-0.2c0.1-0.1,0.3-0.1,0.5,0c0.1,0.1,0.1,0.3,0,0.5C13.2,4.8,13.1,4.8,13,4.8L13,4.8z"/>
|
||||||
|
<path class="st2" d="M13.9,14.1c-0.6-0.6-0.6-1.5,0-2.1c0,0,0.1-0.1,0.1-0.1c1-0.9,1.2-2.5,0.3-3.5c0-0.1-0.1-0.1-0.1-0.2
|
||||||
|
l-0.2-0.2c-0.6-0.6-0.6-1.5,0-2.1c0,0,0.1-0.1,0.1-0.1l1.9-1.7h-1.5l-1.1,0.9c-1,0.9-1.1,2.5-0.2,3.5c0,0,0.1,0.1,0.1,0.1
|
||||||
|
l0.2,0.2c0.6,0.6,0.6,1.5,0,2.1c0,0-0.1,0.1-0.1,0.1c-1,0.9-1.2,2.5-0.3,3.5c0,0,0.1,0.1,0.1,0.1l1.4,1.4h1.4L13.9,14.1z M5.8,13
|
||||||
|
c0-0.4,0.2-0.8,0.5-1.1c1-0.9,1.1-2.5,0.3-3.5c0-0.1-0.1-0.1-0.1-0.1L6.2,8.1c-0.6-0.6-0.6-1.5,0-2.1c0,0,0.1-0.1,0.1-0.1
|
||||||
|
l1.9-1.7H6.8L5.7,5.1C4.6,6,4.5,7.6,5.4,8.6c0,0,0.1,0.1,0.1,0.1l0.2,0.2c0.6,0.6,0.6,1.5,0,2.1c0,0-0.1,0.1-0.1,0.1
|
||||||
|
c-1,0.9-1.2,2.5-0.3,3.5c0,0,0.1,0.1,0.1,0.1l1.4,1.4h1.4l-2.1-2.1C5.9,13.8,5.8,13.4,5.8,13z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 4.8 KiB |
35
frontend/src/assets/legend/map-nlsb.svg
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 22.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg width="20" height="23" version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 20 23" style="enable-background:new 0 0 20 23;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:#0AC266;}
|
||||||
|
.st1{fill:#00A050;}
|
||||||
|
.st2{fill:#FFFFFF;}
|
||||||
|
</style>
|
||||||
|
<title>map-qixidi</title>
|
||||||
|
<g id="页面-1_13_">
|
||||||
|
<g id="map-qixidi_13_">
|
||||||
|
<path id="路径_28_" class="st0" d="M10,0c5.5,0,10,4.5,10,10c0,4.6-3.1,8.4-7.3,9.6c-0.6,0.6-1.2,1.3-1.7,2l-0.6,1
|
||||||
|
C10.3,23,10,23,9.7,22.9c-0.1,0-0.1-0.1-0.2-0.2l-0.6-1c-0.5-0.8-1-1.4-1.7-2C3.1,18.5,0,14.6,0,10.1C0,4.5,4.5,0,10,0z"/>
|
||||||
|
<path id="路径_27_" class="st1" d="M10,1c-5,0-9,4-9,9c0,4,2.6,7.4,6.3,8.6l0.5,0.1L8,19c0.6,0.6,1.2,1.2,1.6,1.9l0.2,0.4
|
||||||
|
l0.2,0.3l0.2-0.3c0.4-0.7,1-1.4,1.6-2l0.3-0.3l0.2-0.2l0.2-0.1c3.8-1.1,6.5-4.6,6.5-8.7C19,5.1,15,1,10,1z"/>
|
||||||
|
<path class="st2" d="M5.5,14.6h1.2v0.8H5.3c-0.4,0-0.7-0.3-0.7-0.7v-1.4h0.8v1.2C5.4,14.5,5.5,14.6,5.5,14.6z M5.4,5.4
|
||||||
|
c0-0.1,0.1-0.1,0.1-0.1h1.2V4.5H5.3c-0.4,0-0.7,0.3-0.7,0.7v1.4h0.8V5.4z M14.8,4.5h-1.4v0.8h1.2c0.1,0,0.1,0.1,0.1,0.1v1.2h0.8
|
||||||
|
V5.2C15.6,4.8,15.2,4.5,14.8,4.5z M14.7,14.5c0,0.1-0.1,0.1-0.1,0.1h-1.2v0.8h1.4c0.4,0,0.7-0.3,0.7-0.7v-1.4h-0.8V14.5z"/>
|
||||||
|
<path class="st2" d="M14.9,8.1c0,0.1-0.1,0.2-0.2,0.3l-0.9,0.5c-0.2,0.1-0.3,0-0.4-0.1c-0.1-0.2,0-0.3,0.1-0.4L14,8.1l-0.4-0.2
|
||||||
|
c-0.1,0-0.1-0.1-0.1-0.2c-0.2-0.5-0.5-0.7-1-0.8c-0.5,0-0.9,0.2-1.2,0.6l-0.2,0.3c0,0,0,0.1,0,0.1c0.8,2.1,0.1,3.3-0.8,3.8
|
||||||
|
c-0.3,0.1-0.6,0.2-0.9,0.2c-0.7,0-1.4-0.4-1.7-1.1c-0.1-0.2,0-0.3,0.1-0.4c0.2-0.1,0.3,0,0.4,0.1c0.4,0.7,1.2,0.8,1.7,0.6
|
||||||
|
c0.6-0.3,1.1-1.1,0.7-2.5c-0.3,0.4-0.7,0.7-1.3,1C9.1,9.7,9,9.7,8.9,9.8c-0.8,0.4-1.6,0.8-2.4-0.2L6.3,9.4
|
||||||
|
C6.2,9.3,5.8,8.8,5.6,8.7c0,0.1,0,0.2,0,0.4c0,0.8,0.9,1.6,1.6,1.8c0.1,0,0.2,0.1,0.2,0.3c0.3,1.6,1.7,2.3,3,2.1
|
||||||
|
c1.3-0.1,2.9-1.2,2.9-3.8c0-0.2,0.1-0.3,0.3-0.3c0.2,0,0.3,0.1,0.3,0.3c0,3-1.9,4.3-3.5,4.4c-0.1,0-0.2,0-0.3,0
|
||||||
|
c-0.2,0-0.4,0-0.6,0l-0.2,0.6h0.3c0.2,0,0.3,0.1,0.3,0.3c0,0.2-0.1,0.3-0.3,0.3H9c-0.1,0-0.2,0-0.3-0.1c-0.1-0.1-0.1-0.2-0.1-0.3
|
||||||
|
l0.3-1c-1-0.3-1.8-1.1-2.1-2.3c-0.9-0.3-1.9-1.3-1.9-2.3c0-0.4,0-0.9,0.4-1c0.5-0.2,1,0.5,1.5,1L7,9.1c0.5,0.6,0.9,0.5,1.7,0.1
|
||||||
|
C8.7,9.1,8.9,9.1,9,9c0.9-0.4,1.1-0.8,1.6-1.5l0.2-0.3c0.4-0.6,1.1-1,1.8-0.9c0.6,0.1,1.2,0.4,1.5,1.1l0.8,0.4
|
||||||
|
C14.9,7.9,14.9,8,14.9,8.1z M12.2,7.6c-0.1,0.1-0.1,0.2-0.1,0.3c0,0.1,0,0.2,0.1,0.3c0.1,0.1,0.2,0.1,0.3,0.1c0.1,0,0.2,0,0.3-0.1
|
||||||
|
c0.1-0.1,0.1-0.2,0.1-0.3c0-0.1-0.1-0.2-0.1-0.3C12.6,7.4,12.4,7.4,12.2,7.6z M11.3,14.5H11l0-0.1c0-0.2-0.1-0.3-0.2-0.4
|
||||||
|
c-0.2,0-0.3,0.1-0.4,0.2l-0.1,0.5c0,0.1,0,0.2,0.1,0.3c0.1,0.1,0.2,0.1,0.3,0.1h0.7c0.2,0,0.3-0.1,0.3-0.3
|
||||||
|
C11.6,14.6,11.5,14.5,11.3,14.5z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.8 KiB |
31
frontend/src/assets/legend/map-pfwsb.svg
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 22.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg width="20" height="23" version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 20 23" style="enable-background:new 0 0 20 23;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:#0AC266;}
|
||||||
|
.st1{fill:#00A050;}
|
||||||
|
.st2{fill:#FFFFFF;}
|
||||||
|
</style>
|
||||||
|
<title>map-qixidi</title>
|
||||||
|
<g id="页面-1_10_">
|
||||||
|
<g id="map-qixidi_10_">
|
||||||
|
<path id="路径_22_" class="st0" d="M10,0c5.5,0,10,4.5,10,10c0,4.6-3.1,8.4-7.3,9.6c-0.6,0.6-1.2,1.3-1.7,2l-0.6,1
|
||||||
|
c-0.1,0.2-0.5,0.3-0.7,0.2c-0.1,0-0.1-0.1-0.2-0.2l-0.6-1c-0.5-0.8-1-1.4-1.7-2C3.1,18.5,0,14.6,0,10C0,4.5,4.5,0,10,0z"/>
|
||||||
|
<path id="路径_21_" class="st1" d="M10,1c-5,0-9,4-9,9c0,4,2.6,7.4,6.3,8.6l0.5,0.1L8,18.9c0.6,0.6,1.2,1.2,1.6,1.9l0.2,0.4
|
||||||
|
l0.2,0.3l0.2-0.3c0.4-0.7,1-1.4,1.6-2l0.3-0.3l0.2-0.2l0.2-0.1c3.8-1.1,6.5-4.6,6.5-8.7C19,5.1,15,1,10,1z"/>
|
||||||
|
<path class="st2" d="M4.2,9.3c0-0.3,0.2-0.6,0.5-0.6h11.1c0.3,0,0.5,0.3,0.5,0.6c0,0.3-0.2,0.6-0.5,0.6H4.6
|
||||||
|
C4.4,9.9,4.2,9.7,4.2,9.3z M16.2,11.1C16.2,11.1,16.2,11.1,16.2,11.1c0-0.2-0.2-0.4-0.4-0.3c0,0-1,0.9-2.3,0.9
|
||||||
|
c-1,0-1.8-0.9-2.7-0.9c-1.4,0-2.3,0.9-3.2,0.9c-0.9,0-2.3-1.2-2.3-1.2c-0.2-0.2-0.3,0.1-0.4,0.2c0,0,0,0.1,0,0.1v0.4
|
||||||
|
c0,0.1,0.1,0.3,0.2,0.4c0,0,1.4,1.2,2.5,1.2c0.9,0,1.9-0.9,3.2-0.9c1,0,1.6,0.9,2.7,0.9c1.2,0,2.3-0.9,2.3-0.9
|
||||||
|
c0.3-0.1,0.4-0.4,0.4-0.5v0c0,0,0,0,0,0v0c0,0,0,0,0,0v0c0,0,0,0,0,0v0c0,0,0,0,0,0v0c0,0,0,0,0,0v0c0,0,0,0,0,0v0c0,0,0,0,0,0v0
|
||||||
|
C16.2,11.2,16.2,11.2,16.2,11.1L16.2,11.1C16.2,11.2,16.2,11.2,16.2,11.1L16.2,11.1C16.2,11.1,16.2,11.1,16.2,11.1L16.2,11.1
|
||||||
|
L16.2,11.1z M16.2,13.5C16.2,13.5,16.2,13.5,16.2,13.5c0-0.2-0.2-0.4-0.4-0.3c0,0-1,0.9-2.3,0.9c-1,0-1.8-0.9-2.7-0.9
|
||||||
|
c-1.4,0-2.3,0.9-3.2,0.9c-0.9,0-2.3-1.2-2.3-1.2c-0.2-0.2-0.3,0.1-0.4,0.2c0,0,0,0.1,0,0.1v0.4c0,0.1,0.1,0.3,0.2,0.4
|
||||||
|
c0,0,1.4,1.2,2.5,1.2c0.9,0,1.9-0.9,3.2-0.9c1,0,1.6,0.9,2.7,0.9c1.2,0,2.3-0.9,2.3-0.9c0.3-0.1,0.4-0.4,0.4-0.5v0c0,0,0,0,0,0v0
|
||||||
|
c0,0,0,0,0,0v0c0,0,0,0,0,0v0c0,0,0,0,0,0v0c0,0,0,0,0,0v0c0,0,0,0,0,0v0c0,0,0,0,0,0v0C16.2,13.6,16.2,13.6,16.2,13.5L16.2,13.5
|
||||||
|
C16.2,13.6,16.2,13.6,16.2,13.5L16.2,13.5C16.2,13.6,16.2,13.5,16.2,13.5L16.2,13.5L16.2,13.5z M6.7,4.5l1.5,1.5L6.7,7.6L5.1,6.1
|
||||||
|
L6.7,4.5z M10.1,4.5l1.5,1.5l-1.5,1.5L8.6,6.1L10.1,4.5z M13.6,4.5l1.5,1.5l-1.5,1.5L12,6.1L13.6,4.5z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.4 KiB |
49
frontend/src/assets/legend/map-yldc.svg
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 22.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg width="20" height="23" version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 20 23" style="enable-background:new 0 0 20 23;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:#0AC266;}
|
||||||
|
.st1{fill:#00A050;}
|
||||||
|
.st2{fill:#FFFFFF;}
|
||||||
|
</style>
|
||||||
|
<title>map-qixidi</title>
|
||||||
|
<g id="页面-1_1_">
|
||||||
|
<g id="map-qixidi_1_">
|
||||||
|
<path id="路径_4_" class="st0" d="M10,0c5.5,0,10,4.5,10,10c0,4.6-3.1,8.4-7.3,9.6c-0.6,0.6-1.2,1.3-1.7,2l-0.6,1
|
||||||
|
C10.3,23,10,23,9.7,22.9c-0.1,0-0.1-0.1-0.2-0.2l-0.6-1c-0.5-0.8-1-1.4-1.7-2C3.1,18.5,0,14.6,0,10.1C0,4.5,4.5,0,10,0z"/>
|
||||||
|
<path id="路径_3_" class="st1" d="M10,1c-5,0-9,4-9,9c0,4,2.6,7.4,6.3,8.6l0.5,0.1L8,19c0.6,0.6,1.2,1.2,1.6,1.9l0.2,0.4
|
||||||
|
l0.2,0.3l0.2-0.3c0.4-0.7,1-1.4,1.6-2L12,19l0.2-0.2l0.2-0.1c3.8-1.1,6.5-4.6,6.5-8.7C19,5.1,15,1,10,1z"/>
|
||||||
|
<g>
|
||||||
|
<path class="st2" d="M16.4,12.8L16.4,12.8c-0.7-0.8-1.5-1.1-2.4-1c-0.2,0-0.4,0.1-0.6,0.1c-0.1-0.7-0.1-1.3-0.3-1.8
|
||||||
|
C13.5,9.1,13.5,8,13.1,7c-0.2-0.5-0.5-0.9-0.8-1.3C12.2,5.4,12,5.2,11.8,5L11.8,5c0,0-0.1-0.1-0.2-0.1c-0.4-0.1-0.8,0-1.3,0.2
|
||||||
|
c-0.2,0.1-0.4,0.2-0.6,0.4L9.6,5.5c0,0,0,0,0,0c-1.3-0.6-2.6-0.7-4-0.6c-0.2,0-0.4,0.2-0.4,0.4l0,0.5L5,5.7c0,0,0,0,0,0
|
||||||
|
C4.8,5.7,4.6,5.8,4.5,6l0,0c-0.1,1.5,0.1,3.1,0.9,4.4c0.1,0.1,0.1,0.2,0.2,0.3c-0.1,0.4,0,0.9,0,1.3c0.1,0.5,0.3,1,0.5,1.5
|
||||||
|
c0.2,0.3,0.3,0.4,0.4,0.6c0.3,0.3,0.8,0.1,0.7-0.3l0,0c0-0.2,0-0.4,0.1-0.6c0.1-0.2,0.2-0.3,0.3-0.4c1,0.6,2.3,0.9,3.9,1.1
|
||||||
|
c0,0.2-0.1,0.4-0.1,0.6c-0.1,0.9,0.2,1.8,1,2.4c0.2,0.1,0.4,0.1,0.6,0c0.1-0.1,0.1-0.1,0.1-0.2l0-0.1l0-0.1l0,0
|
||||||
|
c0-0.2,0.1-0.4,0.1-0.6c0.1-0.3,0.2-0.6,0.3-0.9c0.1-0.2,0.2-0.3,0.3-0.4c0.1-0.1,0.2-0.2,0.4-0.3c0.2-0.1,0.6-0.3,0.9-0.3
|
||||||
|
c0.2-0.1,0.4-0.1,0.6-0.1l0.1,0c0,0,0.1,0,0.1,0c0.2,0,0.4-0.2,0.4-0.5C16.5,13,16.4,12.9,16.4,12.8z M12.5,8.6
|
||||||
|
C12.6,8.5,12.6,8.5,12.5,8.6c0,0,0,0.1,0,0.2C12.6,8.7,12.5,8.6,12.5,8.6C12.5,8.6,12.5,8.6,12.5,8.6z M12.4,7.4L12.4,7.4
|
||||||
|
c0.1,0.1,0.1,0.2,0.1,0.3c0,0-0.1,0-0.1,0.1c-0.1,0-0.1,0.1-0.2,0.1c0,0,0,0,0,0C12.1,7.8,12,7.7,12,7.6l0,0c0,0,0.1,0,0.1-0.1
|
||||||
|
L12.4,7.4z M11.8,6.5l0.1,0c0,0.1,0.1,0.1,0.1,0.2c-0.1,0-0.2,0.1-0.3,0.1l-0.1,0.1l-0.1,0.1c-0.1-0.1-0.1-0.1-0.2-0.2
|
||||||
|
C11.5,6.7,11.7,6.6,11.8,6.5z M10.6,5.8c0.2-0.1,0.4-0.2,0.6-0.2l0.1,0l0,0c0,0,0.1,0.1,0.1,0.1c-0.2,0.1-0.3,0.1-0.5,0.2
|
||||||
|
c-0.1,0-0.2,0.1-0.3,0.1c-0.1-0.1-0.2-0.1-0.3-0.2C10.5,5.9,10.5,5.8,10.6,5.8z M6.7,12.6L6.7,12.6L6.7,12.6
|
||||||
|
c-0.1-0.1-0.2-0.3-0.3-0.5l0-0.1c0-0.1,0-0.1,0-0.2C6.6,11.9,6.8,12,7,12.2C6.9,12.3,6.8,12.4,6.7,12.6z M11.9,12.9
|
||||||
|
c-2.8-0.2-4.7-1.2-5.7-2.7l-0.1-0.1C6,9.8,5.9,9.6,5.8,9.4C7.7,9,8.7,7.9,9,6.6l0-0.1L8.2,6.3C8,7.4,7.2,8.3,5.5,8.6
|
||||||
|
C5.4,8,5.3,7.4,5.3,6.7l0-0.1l0.3,0.1c0,0,0.1,0,0.1,0c0.2,0,0.4-0.2,0.4-0.4v0l0-0.6l0,0c1.1-0.1,2.3,0.1,3.4,0.7l0.1,0.1
|
||||||
|
c1.7,1,2.7,2.8,2.9,5.8l0,0.2L12,12.9L11.9,12.9z M15,12.9c-0.3,0.1-0.7,0.2-0.9,0.4L14,13.3c-0.2,0.1-0.4,0.3-0.6,0.4
|
||||||
|
c-0.2,0.2-0.3,0.4-0.4,0.6c-0.1,0.3-0.3,0.6-0.4,0.9l0,0.1l0,0.1l0-0.1c-0.1-0.3-0.2-0.6-0.2-1l0-0.1c0-0.2,0.1-0.4,0.1-0.6
|
||||||
|
l0-0.1c0,0,0-0.1,0-0.1l0.7-0.7c0.3-0.1,0.5-0.2,0.8-0.2C14.4,12.6,14.7,12.7,15,12.9L15,12.9L15,12.9z"/>
|
||||||
|
<polygon class="st2" points="9,6.5 9,6.5 9,6.5 "/>
|
||||||
|
<path class="st2" d="M6.6,6.1c-0.2,0.2-0.2,0.5,0,0.7c0.2,0.2,0.5,0.2,0.7,0c0.2-0.2,0.2-0.5,0-0.7C7.1,5.9,6.8,5.9,6.6,6.1z
|
||||||
|
M7.2,6.7C7,6.8,6.9,6.8,6.7,6.7c-0.1-0.1-0.1-0.3,0-0.4c0.1-0.1,0.3-0.1,0.4,0C7.3,6.4,7.3,6.6,7.2,6.7z"/>
|
||||||
|
<path class="st2" d="M9.9,9c-0.2,0-0.4,0.1-0.4,0.4c0,0.4-0.2,0.5-0.4,0.5l-0.1,0c0,0,0,0,0,0l0,0c-0.2,0-0.4,0.1-0.5,0.4
|
||||||
|
c0,0.2,0.1,0.4,0.4,0.5c0.1,0,0.2,0,0.3,0c0.5-0.1,0.9-0.5,1-1.2C10.3,9.2,10.1,9,9.9,9z"/>
|
||||||
|
<path class="st2" d="M8.3,8.9C8.1,8.9,7.8,9,7.8,9.2c0,0,0,0,0,0C7.7,9.6,7.6,9.7,7.4,9.7c0,0-0.1,0-0.1,0l0,0
|
||||||
|
C7,9.6,6.8,9.8,6.8,10c-0.1,0.2,0.1,0.4,0.3,0.5c0.1,0,0.3,0,0.4,0c0.5-0.1,1-0.4,1.1-1.1C8.6,9.2,8.5,9,8.3,8.9z"/>
|
||||||
|
<path class="st2" d="M9,9c0.7-0.2,1-0.6,1.1-1.1c0-0.2,0-0.3,0-0.4l0,0c-0.1-0.2-0.3-0.4-0.5-0.3c-0.2,0-0.3,0.2-0.3,0.4l0,0
|
||||||
|
c0,0,0,0.1,0,0.1c0,0.2-0.1,0.3-0.5,0.4C8.6,8.2,8.5,8.4,8.6,8.7C8.6,8.9,8.8,9,9,9z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 4.1 KiB |
44
frontend/src/assets/legend/map-ylsb.svg
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 22.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg width="20" height="23" version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 20 23" style="enable-background:new 0 0 20 23;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:#0AC266;}
|
||||||
|
.st1{fill:#00A050;}
|
||||||
|
.st2{fill:#FFFFFF;}
|
||||||
|
</style>
|
||||||
|
<title>map-qixidi</title>
|
||||||
|
<g id="页面-1_8_">
|
||||||
|
<g id="map-qixidi_8_">
|
||||||
|
<path id="路径_18_" class="st0" d="M10,0.1c5.5,0,10,4.5,10,10c0,4.6-3.1,8.4-7.3,9.6c-0.6,0.6-1.2,1.3-1.7,2l-0.6,1
|
||||||
|
c-0.1,0.2-0.5,0.3-0.7,0.2c-0.1,0-0.1-0.1-0.2-0.2l-0.6-1c-0.5-0.8-1-1.4-1.7-2C3.1,18.5,0,14.7,0,10.1C0,4.5,4.5,0.1,10,0.1z"/>
|
||||||
|
<path id="路径_17_" class="st1" d="M10,1.1c-5,0-9,4-9,9c0,4,2.6,7.4,6.3,8.6l0.5,0.1L8,19c0.6,0.6,1.2,1.2,1.6,1.9l0.2,0.4
|
||||||
|
l0.2,0.3l0.2-0.3c0.4-0.7,1-1.4,1.6-2l0.3-0.3l0.2-0.2l0.2-0.1c3.8-1.1,6.5-4.6,6.5-8.7C19,5.1,15,1.1,10,1.1z"/>
|
||||||
|
<g>
|
||||||
|
<path class="st2" d="M15.1,11.1c0,0-0.2-0.2-0.2-0.6c0-0.2-0.1-0.3-0.1-0.5c0-0.1,0.1-0.3,0.1-0.5C15,9.2,15.1,9,15.1,9
|
||||||
|
c0.1-0.1,0.2-0.2,0.3-0.3c0.2-0.3,0.2-0.6,0.1-0.7c-0.1-0.2-0.3-0.5-0.7-0.5c-0.1,0-0.2,0-0.3,0c-0.3,0.1-0.7,0.2-0.9,0.3
|
||||||
|
c-0.3,0.1-0.6,0.3-0.7,0.5c0,0,0,0-0.1,0.1c-0.3-0.2-0.5-0.4-0.8-0.6c0.1-0.4,0.2-0.7,0.1-1.1c0,0,0-0.1,0-0.1
|
||||||
|
c0-0.1-0.1-0.3-0.2-0.4c-0.1-0.1-0.2-0.2-0.3-0.2c0,0,0,0-0.1,0c-0.2,0-0.3-0.1-0.5-0.1c-0.3,0-0.7,0.1-1.1,0.2
|
||||||
|
C9.6,6.5,9.3,6.6,9,6.8C8.9,6.9,8.8,7,8.6,7.1c-0.3,0-0.5,0.1-0.8,0.1C7.3,7.3,6.8,7.5,6.4,7.7C6,7.9,5.7,8.1,5.4,8.4
|
||||||
|
C5.1,8.7,4.8,9,4.7,9.4L4.6,9.8L4.8,10c0,0,0,0,0,0.1l-0.2,0.2l0.1,0.4c0.1,0.2,0.2,0.5,0.4,0.7c0.2,0.2,0.4,0.4,0.6,0.6
|
||||||
|
c0.4,0.3,1,0.6,1.7,0.8l0.3,0.1l0.1,0l0,0c0.2,0,0.5,0.1,0.8,0.1c0.1,0.1,0.2,0.1,0.3,0.2c0.3,0.2,0.6,0.4,0.9,0.5
|
||||||
|
c0.4,0.2,0.7,0.2,1.1,0.2c0.2,0,0.3,0,0.5-0.1l0,0c0.1,0,0.2-0.1,0.3-0.2c0.1-0.1,0.2-0.3,0.2-0.4c0,0,0,0,0,0l-0.1,0l0.1,0
|
||||||
|
c0.1-0.3,0-0.6-0.1-0.9c0.3-0.2,0.6-0.4,0.9-0.7c0,0,0,0,0.1,0.1c0.2,0.2,0.5,0.4,0.7,0.5c0.4,0.2,0.9,0.3,0.9,0.3
|
||||||
|
c0.1,0,0.2,0,0.3,0c0.4,0,0.6-0.2,0.7-0.5c0-0.1,0.1-0.4-0.1-0.7C15.3,11.3,15.2,11.2,15.1,11.1z M10.9,6.9c0.1,0,0.2,0,0.3,0
|
||||||
|
c0.1,0,0.1,0,0.1,0.1c0,0.2,0,0.3-0.1,0.5c-0.4-0.2-0.9-0.3-1.3-0.4C10.3,7,10.6,6.9,10.9,6.9z M7.5,12c-1-0.3-1.8-0.8-2.1-1.5
|
||||||
|
L5.9,10L5.4,9.6c0.3-0.6,1.1-1.2,2.1-1.5C8,8.6,8.2,9.3,8.2,10C8.2,10.7,7.9,11.4,7.5,12z M11.1,13.1c-0.1,0-0.2,0-0.3,0
|
||||||
|
c-0.2,0-0.5-0.1-0.8-0.2c0.4-0.1,0.8-0.2,1.2-0.4C11.2,12.7,11.2,12.9,11.1,13.1C11.2,13.1,11.2,13.1,11.1,13.1z M11.3,13.8
|
||||||
|
C11.3,13.8,11.3,13.8,11.3,13.8L11.3,13.8L11.3,13.8z M13.2,10.6C13.2,10.6,13.2,10.5,13.2,10.6c0-0.1,0-0.1,0-0.1l0-0.3
|
||||||
|
l-0.2,0.2c-0.3,0.3-0.9,0.8-1.5,1.2c-0.2,0.1-0.3,0.2-0.4,0.2c-0.6,0.3-1.1,0.4-1.7,0.4c-0.2,0-0.3,0-0.5,0c-0.2,0-0.3,0-0.5-0.1
|
||||||
|
c0.1-0.2,0.2-0.4,0.3-0.6c0.2-0.5,0.3-1,0.3-1.5c0-0.5-0.1-0.9-0.2-1.3c0-0.1,0-0.1-0.1-0.2C8.6,8.3,8.5,8.1,8.4,7.9
|
||||||
|
c0.2,0,0.3,0,0.5,0c0.1,0,0.3,0,0.4,0c0.5,0,1.1,0.1,1.6,0.4c0.2,0.1,0.4,0.2,0.6,0.3c0.5,0.3,1,0.7,1.5,1.2l0.2,0.2l0-0.3
|
||||||
|
c0,0,0-0.1,0-0.1c0-0.7,1.2-1.1,1.5-1.1c0,0,0,0,0,0C14.2,8.8,14.1,9.7,14,10l0,0l0,0.1c0,0.3,0.2,1.2,0.6,1.6c0,0,0,0,0,0
|
||||||
|
C14.3,11.7,13.2,11.3,13.2,10.6z"/>
|
||||||
|
<path class="st2" d="M6.9,9.3c-0.3,0-0.5,0.3-0.5,0.6c0,0.3,0.2,0.6,0.5,0.6s0.5-0.3,0.5-0.6C7.4,9.6,7.2,9.3,6.9,9.3z"/>
|
||||||
|
<path class="st2" d="M5.5,14.6h1.2v0.8H5.3c-0.4,0-0.7-0.3-0.7-0.7v-1.4h0.8v1.2C5.4,14.6,5.5,14.6,5.5,14.6z M5.4,5.5
|
||||||
|
c0-0.1,0.1-0.1,0.1-0.1h1.2V4.5H5.3c-0.4,0-0.7,0.3-0.7,0.7v1.4h0.8V5.5z M14.8,4.5h-1.4v0.8h1.2c0.1,0,0.1,0.1,0.1,0.1v1.2h0.8
|
||||||
|
V5.2C15.6,4.8,15.2,4.5,14.8,4.5z M14.7,14.5c0,0.1-0.1,0.1-0.1,0.1h-1.2v0.8h1.4c0.4,0,0.7-0.3,0.7-0.7v-1.4h-0.8V14.5z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 3.7 KiB |
31
frontend/src/assets/legend/map-znfj.svg
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 22.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg width="20" height="23" version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 20 23" style="enable-background:new 0 0 20 23;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:#0AC266;}
|
||||||
|
.st1{fill:#00A050;}
|
||||||
|
.st2{fill:#FFFFFF;}
|
||||||
|
</style>
|
||||||
|
<title>map-qixidi</title>
|
||||||
|
<g id="页面-1_6_">
|
||||||
|
<g id="map-qixidi_6_">
|
||||||
|
<path id="路径_14_" class="st0" d="M10,0c5.5,0,10,4.5,10,10c0,4.6-3.1,8.4-7.3,9.6c-0.6,0.6-1.2,1.3-1.7,2l-0.6,1
|
||||||
|
c-0.1,0.2-0.5,0.3-0.7,0.2c-0.1,0-0.1-0.1-0.2-0.2l-0.6-1c-0.5-0.8-1-1.4-1.7-2C3.1,18.5,0,14.6,0,10C0,4.5,4.5,0,10,0z"/>
|
||||||
|
<path id="路径_13_" class="st1" d="M10,1c-5,0-9,4-9,9c0,4,2.6,7.4,6.3,8.6l0.5,0.1L8,18.9c0.6,0.6,1.2,1.2,1.6,1.9l0.2,0.4
|
||||||
|
l0.2,0.3l0.2-0.3c0.4-0.7,1-1.4,1.6-2l0.3-0.3l0.2-0.2l0.2-0.1c3.8-1.1,6.5-4.6,6.5-8.7C19,5,15,1,10,1z"/>
|
||||||
|
<path class="st2" d="M11.3,11.8H8.2V8.4C8.2,8.2,8.4,8,8.7,8h3.4v3.5c0,0.2-0.2,0.4-0.4,0.4L11.3,11.8L11.3,11.8L11.3,11.8z"/>
|
||||||
|
<path class="st2" d="M9.3,14.4c0,0.1,0,0.2-0.1,0.3c-0.1,0.1-0.2,0.1-0.3,0.1c0,0,0,0,0,0H7.2c-1,0-1.9-0.8-1.9-1.9v-1.7
|
||||||
|
c0-0.2,0.2-0.4,0.4-0.4s0.4,0.2,0.4,0.4v1.7c0,0.6,0.5,1,1,1h1.7C9.1,13.9,9.3,14.1,9.3,14.4z M14.7,10.8L14.7,10.8
|
||||||
|
c-0.2,0-0.4,0.2-0.4,0.4v1.7c0,0.6-0.5,1-1,1h-1.7c-0.2,0-0.4,0.2-0.4,0.4s0.2,0.4,0.4,0.4h1.7c1,0,1.9-0.8,1.9-1.9v-1.7
|
||||||
|
c0-0.1,0-0.2-0.1-0.3C14.9,10.8,14.8,10.8,14.7,10.8z M13.2,5h-1.7c-0.2,0-0.4,0.2-0.4,0.4c0,0.2,0.2,0.4,0.4,0.4h1.7
|
||||||
|
c0.6,0,1,0.5,1,1v1.7c0,0.2,0.2,0.4,0.4,0.4s0.4-0.2,0.4-0.4V6.9C15.1,5.9,14.2,5,13.2,5z M8.8,5H7.2c-1,0-1.9,0.8-1.9,1.9v1.7
|
||||||
|
c0,0.2,0.2,0.4,0.4,0.4l0,0l0,0c0.2,0,0.4-0.2,0.4-0.4V6.9c0-0.6,0.5-1,1-1h1.7c0.2,0,0.4-0.2,0.4-0.4S9.1,5,8.8,5z"/>
|
||||||
|
<path class="st2" d="M14,9.5h0.8v0.8H14V9.5z M13.4,9.5h0.4v0.8h-0.4V9.5z M17,9.7l-0.9-0.8c-0.2-0.2-0.5,0-0.5,0.2v0.4h-0.6v0.8
|
||||||
|
h0.6v0.4c0,0.2,0.3,0.4,0.5,0.2l0.9-0.8C17.1,10,17.1,9.8,17,9.7L17,9.7z M5.3,9.5h0.8v0.8H5.3V9.5z M6.4,9.5h0.4v0.8H6.4V9.5z
|
||||||
|
M4.5,9.1c0-0.2-0.3-0.4-0.5-0.2L3.2,9.7c-0.1,0.1-0.1,0.3,0,0.4c0,0,0,0,0,0l0.9,0.8c0.2,0.2,0.5,0,0.5-0.2v-0.4h0.6V9.5H4.5
|
||||||
|
L4.5,9.1L4.5,9.1z M9.7,13.8h0.8v0.8H9.7V13.8z M9.7,13.1h0.8v0.4H9.7V13.1z M10.9,15.4h-0.4v-0.6H9.7v0.6H9.3
|
||||||
|
c-0.2,0-0.4,0.3-0.2,0.5l0.8,0.9c0.1,0.1,0.3,0.1,0.4,0c0,0,0,0,0,0l0.8-0.9C11.3,15.7,11.2,15.4,10.9,15.4L10.9,15.4z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.4 KiB |
@ -2741,8 +2741,8 @@ const StinfoAiVidoPointColumns: Array<any> = [
|
|||||||
url: ''
|
url: ''
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '监控内容类型',
|
name: '监控方式',
|
||||||
filed: 'sttpName',
|
filed: 'mwayName',
|
||||||
visible: true,
|
visible: true,
|
||||||
type: 'select',
|
type: 'select',
|
||||||
url: ''
|
url: ''
|
||||||
|
|||||||
@ -344,7 +344,15 @@ const columnsConfig = ref([
|
|||||||
{
|
{
|
||||||
type: 'MM',
|
type: 'MM',
|
||||||
columns: MMColumns
|
columns: MMColumns
|
||||||
}
|
},
|
||||||
|
{ type: 'AI_FISH', columns: StinfoAiVidoPointColumns },
|
||||||
|
{ type: 'AI_ANML', columns: StinfoAiVidoPointColumns },
|
||||||
|
{ type: 'AI_BIRD', columns: StinfoAiVidoPointColumns },
|
||||||
|
{ type: 'AI_RIV', columns: StinfoAiVidoPointColumns },
|
||||||
|
{ type: 'AI_FISHING', columns: StinfoAiVidoPointColumns },
|
||||||
|
{ type: 'AI_5001', columns: StinfoAiVidoPointColumns },
|
||||||
|
{ type: 'AI_5005', columns: StinfoAiVidoPointColumns },
|
||||||
|
{ type: 'AI_SORTER', columns: StinfoAiVidoPointColumns }
|
||||||
|
|
||||||
//DW_1
|
//DW_1
|
||||||
]);
|
]);
|
||||||
|
|||||||
217
frontend/src/components/MapModal/components/zhzbMonitorInfo.vue
Normal file
@ -0,0 +1,217 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div class="mb-2">
|
||||||
|
时间:
|
||||||
|
<a-range-picker
|
||||||
|
v-model:value="searchParams"
|
||||||
|
type="daterange"
|
||||||
|
:allow-clear="false"
|
||||||
|
value-format="YYYY-MM-DD HH:mm:ss"
|
||||||
|
:presets="DateSetting.RangeButton.year1"
|
||||||
|
/>
|
||||||
|
<a-button class="ml-2" type="primary" @click="initData">查询</a-button>
|
||||||
|
</div>
|
||||||
|
<BasicTable
|
||||||
|
ref="tableRef"
|
||||||
|
:scrollY="500"
|
||||||
|
:columns="columns"
|
||||||
|
:searchParams="{
|
||||||
|
sort: [{ field: 'tm', dir: 'desc' }]
|
||||||
|
}"
|
||||||
|
:list-url="currentApi"
|
||||||
|
:paginationConfig="{
|
||||||
|
showSizeChanger: false,
|
||||||
|
showQuickJumper: false
|
||||||
|
}"
|
||||||
|
/>
|
||||||
|
<!-- 附件/图片/视频 展示弹窗(fid 含多个时左侧有列表可切换展示) -->
|
||||||
|
<CommonAttachmentModal
|
||||||
|
v-model:open="attachmentOpen"
|
||||||
|
:fid="attachmentFid"
|
||||||
|
:title="attachmentTitle"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, watch, computed, h, nextTick } from 'vue';
|
||||||
|
import { Button } from 'ant-design-vue';
|
||||||
|
import BasicTable from '@/components/BasicTable/index.vue';
|
||||||
|
import CommonAttachmentModal from './CommonAttachmentModal.vue';
|
||||||
|
import { getAnimalList, getWarningList, getFishList } from '@/api/mapModal';
|
||||||
|
import { useModelStore } from '@/store/modules/model';
|
||||||
|
import { DateSetting } from '@/utils/enumeration';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
|
||||||
|
const modelStore = useModelStore();
|
||||||
|
const tableRef = ref();
|
||||||
|
const searchParams = ref([
|
||||||
|
dayjs().subtract(1, 'month').format('YYYY-MM-DD HH:mm:ss'),
|
||||||
|
dayjs().format('YYYY-MM-DD HH:mm:ss')
|
||||||
|
]);
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
isActive: { type: Boolean, default: false }
|
||||||
|
});
|
||||||
|
|
||||||
|
// ==================== 根据 sttpCode 选择接口 ====================
|
||||||
|
const sttpCode = computed(() => modelStore.params.sttpCode || '');
|
||||||
|
|
||||||
|
const currentApi = computed(() => {
|
||||||
|
const code = sttpCode.value;
|
||||||
|
if (code === 'AI_ANML' || code === 'AI_BIRD') return getAnimalList;
|
||||||
|
if (
|
||||||
|
code === 'AI_FISHING' ||
|
||||||
|
code === 'AI_RIV' ||
|
||||||
|
code === 'AI_5001' ||
|
||||||
|
code === 'AI_5005'
|
||||||
|
)
|
||||||
|
return getWarningList;
|
||||||
|
// 其余:AI_FISH / AI_SORTER / FPRD 等走鱼类接口
|
||||||
|
return getFishList;
|
||||||
|
});
|
||||||
|
|
||||||
|
const isAnimalType = () =>
|
||||||
|
sttpCode.value === 'AI_ANML' || sttpCode.value === 'AI_BIRD';
|
||||||
|
const isWarningType = () =>
|
||||||
|
['AI_FISHING', 'AI_RIV', 'AI_5001', 'AI_5005'].includes(sttpCode.value);
|
||||||
|
|
||||||
|
// ==================== 附件展示弹窗 ====================
|
||||||
|
const attachmentOpen = ref(false);
|
||||||
|
const attachmentFid = ref('');
|
||||||
|
const attachmentTitle = ref('查看附件');
|
||||||
|
const openAttachment = (fid: string, title: string) => {
|
||||||
|
const value = String(fid || '').trim();
|
||||||
|
if (!value || value === '-' || value === 'null' || value === 'undefined')
|
||||||
|
return;
|
||||||
|
attachmentFid.value = value;
|
||||||
|
attachmentTitle.value = title;
|
||||||
|
attachmentOpen.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 生成【媒体查看按钮】列
|
||||||
|
const renderMediaButton = (fidKey: string, label: string) => ({
|
||||||
|
title: label,
|
||||||
|
dataIndex: fidKey,
|
||||||
|
width: 110,
|
||||||
|
customRender: ({ text }: any) => {
|
||||||
|
const hasValidFid =
|
||||||
|
text &&
|
||||||
|
text !== '-' &&
|
||||||
|
String(text).trim() !== '' &&
|
||||||
|
text !== 'null' &&
|
||||||
|
text !== 'undefined';
|
||||||
|
return h(
|
||||||
|
Button,
|
||||||
|
{
|
||||||
|
type: 'link',
|
||||||
|
disabled: !hasValidFid,
|
||||||
|
size: 'small',
|
||||||
|
style: {
|
||||||
|
color: !hasValidFid ? '#ccc' : '#1890ff',
|
||||||
|
cursor: !hasValidFid ? 'not-allowed' : 'pointer'
|
||||||
|
},
|
||||||
|
onClick: () => {
|
||||||
|
if (hasValidFid) {
|
||||||
|
openAttachment(text, label);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
() => label
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const renderTimeColumn = () => ({
|
||||||
|
title: '时间',
|
||||||
|
dataIndex: 'tm',
|
||||||
|
width: 160,
|
||||||
|
sort: true,
|
||||||
|
customRender: ({ text }: any) =>
|
||||||
|
text && text !== '-' ? dayjs(text).format('YYYY-MM-DD HH:mm:ss') : '-'
|
||||||
|
});
|
||||||
|
|
||||||
|
// ==================== 三类表头(模拟,后期按实际字段补充) ====================
|
||||||
|
// 鱼类智能识别 / 智能分拣 / 鱼类调查(getFishList)
|
||||||
|
const fishColumns = [
|
||||||
|
renderTimeColumn(),
|
||||||
|
{ title: '鱼种类', dataIndex: 'ftp', width: 130 },
|
||||||
|
{ title: '游向', dataIndex: 'directionName', width: 130, sort: true },
|
||||||
|
{ title: '鱼长度', dataIndex: 'length', width: 100 },
|
||||||
|
{ title: '数量', dataIndex: 'fcnt', width: 100 },
|
||||||
|
renderMediaButton('firstimgurl', '查看图片'),
|
||||||
|
renderMediaButton('videourl', '查看视频')
|
||||||
|
];
|
||||||
|
|
||||||
|
// 动物 / 鸟类智能识别(getAnimalList)
|
||||||
|
const animalColumns = [
|
||||||
|
{ title: '记录时间', dataIndex: 'tm', width: 140, sort: true },
|
||||||
|
{ title: '拍摄时间', dataIndex: 'shootTime', width: 140, sort: true },
|
||||||
|
{ title: '识别时间', dataIndex: 'recognizeTime', width: 140, sort: true },
|
||||||
|
{ title: '动物名称', dataIndex: 'animalName', width: 140, sort: true },
|
||||||
|
{ title: '识别描述', dataIndex: 'behavior', width: 280 },
|
||||||
|
{ title: '备注', dataIndex: 'description', width: 200 },
|
||||||
|
renderMediaButton('imgPath', '查看图片'),
|
||||||
|
renderMediaButton('flpth', '查看视频')
|
||||||
|
];
|
||||||
|
|
||||||
|
// 钓鱼 / 违章监测 / 漂浮物 / 叠梁门(getWarningList):媒体信息统一在 fid
|
||||||
|
const warningColumns = [
|
||||||
|
renderTimeColumn(),
|
||||||
|
{ title: 'AI识别值', dataIndex: 'aiVal', width: 180 },
|
||||||
|
{ title: '备注', dataIndex: 'remark' },
|
||||||
|
renderMediaButton('fid', '操作')
|
||||||
|
];
|
||||||
|
|
||||||
|
// ==================== 动态列 ====================
|
||||||
|
const columns = computed(() => {
|
||||||
|
if (isAnimalType()) return animalColumns;
|
||||||
|
if (isWarningType()) return warningColumns;
|
||||||
|
return fishColumns;
|
||||||
|
});
|
||||||
|
|
||||||
|
const hasLoaded = ref(false);
|
||||||
|
const initData = async () => {
|
||||||
|
if (hasLoaded.value) return;
|
||||||
|
hasLoaded.value = true;
|
||||||
|
const filter = {
|
||||||
|
logic: 'and',
|
||||||
|
filters: [
|
||||||
|
{
|
||||||
|
field: 'tm',
|
||||||
|
operator: 'gte',
|
||||||
|
dataType: 'date',
|
||||||
|
value: searchParams.value[0]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'tm',
|
||||||
|
operator: 'lte',
|
||||||
|
dataType: 'date',
|
||||||
|
value: searchParams.value[1]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'stcd',
|
||||||
|
operator: 'eq',
|
||||||
|
dataType: 'string',
|
||||||
|
value: modelStore.params.stcd
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
// 等 BasicTable 挂载就绪后再查询(首次激活时 immediate 的 watch 可能先于子组件挂载)
|
||||||
|
await nextTick();
|
||||||
|
tableRef.value?.getList(filter);
|
||||||
|
};
|
||||||
|
|
||||||
|
// tab 切换激活时才查询(首次激活查询一次,不再一进入页面就查询)
|
||||||
|
watch(
|
||||||
|
() => props.isActive,
|
||||||
|
active => {
|
||||||
|
if (active) initData();
|
||||||
|
},
|
||||||
|
{ immediate: true, deep: true }
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
<style scoped>
|
||||||
|
.fish-facility-monitor-data {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -121,6 +121,12 @@
|
|||||||
:is-active="currentActiveKey === 'DZGJ'"
|
:is-active="currentActiveKey === 'DZGJ'"
|
||||||
:tabs-items="getTabChildren('DZGJ')"
|
:tabs-items="getTabChildren('DZGJ')"
|
||||||
/>
|
/>
|
||||||
|
<!-- 检测数据 - 智慧装备 -->
|
||||||
|
<ZhzbMonitorInfo
|
||||||
|
v-show="currentActiveKey === 'zhzbMonitorInfo'"
|
||||||
|
:is-active="currentActiveKey === 'zhzbMonitorInfo'"
|
||||||
|
/>
|
||||||
|
|
||||||
<!-- 生态流量泄放设施 - 监测数据 -->
|
<!-- 生态流量泄放设施 - 监测数据 -->
|
||||||
<FlowDischarge
|
<FlowDischarge
|
||||||
v-show="currentActiveKey === 'flowDischarge'"
|
v-show="currentActiveKey === 'flowDischarge'"
|
||||||
@ -284,6 +290,7 @@ import DZGJ from './components/DZGJ.vue'; // 水电站告警情况
|
|||||||
import FishZHFX from './components/FishZHFX.vue'; // 鱼类繁殖适宜性分析
|
import FishZHFX from './components/FishZHFX.vue'; // 鱼类繁殖适宜性分析
|
||||||
import EcologicalFlow from './components/EcologicalFlow.vue'; // 生态流量
|
import EcologicalFlow from './components/EcologicalFlow.vue'; // 生态流量
|
||||||
import Attachment from './components/Attachment.vue'; // 查看报告/批复文件
|
import Attachment from './components/Attachment.vue'; // 查看报告/批复文件
|
||||||
|
import ZhzbMonitorInfo from './components/zhzbMonitorInfo.vue'; // 智慧装备 - 监测数据
|
||||||
import WaterTemperatureRep from './components/WaterTemperatureRep.vue'; // 水温对比数据
|
import WaterTemperatureRep from './components/WaterTemperatureRep.vue'; // 水温对比数据
|
||||||
import { useModelStore } from '@/store/modules/model';
|
import { useModelStore } from '@/store/modules/model';
|
||||||
import { useUiStore } from '@/store/modules/ui';
|
import { useUiStore } from '@/store/modules/ui';
|
||||||
@ -888,7 +895,10 @@ const handleClose = () => {
|
|||||||
eqtp: '',
|
eqtp: '',
|
||||||
baseId: '',
|
baseId: '',
|
||||||
sttpCode: '',
|
sttpCode: '',
|
||||||
sttpMap: ''
|
sttpMap: '',
|
||||||
|
dtinType: '',
|
||||||
|
bldstt: '',
|
||||||
|
bldsttCcode: ''
|
||||||
};
|
};
|
||||||
// 清理状态,避免影响下次打开
|
// 清理状态,避免影响下次打开
|
||||||
modelStore.showStcdSelector = false;
|
modelStore.showStcdSelector = false;
|
||||||
@ -904,6 +914,7 @@ const handleClose = () => {
|
|||||||
modelStore.aiSites = [];
|
modelStore.aiSites = [];
|
||||||
modelStore.wtConfig = {};
|
modelStore.wtConfig = {};
|
||||||
modelStore.filter = {
|
modelStore.filter = {
|
||||||
|
year: '',
|
||||||
stllgzlx: '', // 生态流量 - 规则类型
|
stllgzlx: '', // 生态流量 - 规则类型
|
||||||
stllTmType: '', // 生态流量 - 时间类型
|
stllTmType: '', // 生态流量 - 时间类型
|
||||||
tm: '',
|
tm: '',
|
||||||
|
|||||||
@ -728,6 +728,17 @@ const DEVICETABS: Array<any> = [
|
|||||||
type: 'basic',
|
type: 'basic',
|
||||||
url: '/eng/base/msstbprpt/getStcdInfo',
|
url: '/eng/base/msstbprpt/getStcdInfo',
|
||||||
default: true // 默认显示
|
default: true // 默认显示
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '监测数据',
|
||||||
|
key: 'zhzbMonitorInfo',
|
||||||
|
type: 'zhzbMonitorInfo'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '实时视频',
|
||||||
|
key: 'videoInfo',
|
||||||
|
type: 'video',
|
||||||
|
url: '/video/dataStcdFrame/getVideoMonitorList'
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
// //电站告警
|
// //电站告警
|
||||||
@ -1232,6 +1243,16 @@ const handleTabs = (modaldata: any) => {
|
|||||||
// return WETabs
|
// return WETabs
|
||||||
case 'MM':
|
case 'MM':
|
||||||
return WeatherTabs;
|
return WeatherTabs;
|
||||||
|
case 'AI_FISH': // 智慧装备
|
||||||
|
case 'AI_ANML':
|
||||||
|
case 'AI_BIRD':
|
||||||
|
case 'AI_RIV':
|
||||||
|
case 'AI_FISHING':
|
||||||
|
case 'AI_5001':
|
||||||
|
case 'AI_5005':
|
||||||
|
case 'AI_SORTER':
|
||||||
|
return DEVICETABS;
|
||||||
|
|
||||||
// case 'WARN':
|
// case 'WARN':
|
||||||
// return WaterQualityMonitoring
|
// return WaterQualityMonitoring
|
||||||
// case 'AI':
|
// case 'AI':
|
||||||
|
|||||||
@ -2013,10 +2013,10 @@ export class MapOl implements MapInterface {
|
|||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 获取当前应应用基地裁切的底图图层集合
|
* 获取当前应应用基地裁切的底图图层集合
|
||||||
* @returns 当前可见底图图层列表
|
* @returns 当前可见底图图层列表(包括底图栅格和栖息地图层、自然保护区图层等矢量图层)
|
||||||
*/
|
*/
|
||||||
private getCurrentMaskTargetLayers(): TileLayer[] {
|
private getCurrentMaskTargetLayers(): (TileLayer | VectorLayer<any>)[] {
|
||||||
const layers: TileLayer[] = [];
|
const layers: (TileLayer | VectorLayer<any>)[] = [];
|
||||||
const baseLayer = this.layerRegistry.get(this.REGISTRY_KEY);
|
const baseLayer = this.layerRegistry.get(this.REGISTRY_KEY);
|
||||||
|
|
||||||
if (baseLayer instanceof TileLayer) {
|
if (baseLayer instanceof TileLayer) {
|
||||||
@ -2033,6 +2033,19 @@ export class MapOl implements MapInterface {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 遍历所有图层注册表,收集所有可见的 TileLayer 和 VectorLayer
|
||||||
|
// 这会自动包括栖息地图层、自然保护区图层等已勾选显示的基础图层
|
||||||
|
this.layerRegistry.forEach((layerInstance, layerKey) => {
|
||||||
|
if (
|
||||||
|
(layerInstance instanceof TileLayer ||
|
||||||
|
layerInstance instanceof VectorLayer) &&
|
||||||
|
layerInstance.getVisible() &&
|
||||||
|
!layers.includes(layerInstance)
|
||||||
|
) {
|
||||||
|
layers.push(layerInstance);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return layers;
|
return layers;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@ -2173,6 +2186,23 @@ export class MapOl implements MapInterface {
|
|||||||
if (this.isBatchPopupMode) {
|
if (this.isBatchPopupMode) {
|
||||||
this.requestUpdateBatchPopups(true);
|
this.requestUpdateBatchPopups(true);
|
||||||
}
|
}
|
||||||
|
// 如果当前处于基地裁切状态且图层显示,确保裁切事件已绑定
|
||||||
|
if (
|
||||||
|
this.currentClipGeoJson &&
|
||||||
|
checked &&
|
||||||
|
(layerInstance instanceof TileLayer ||
|
||||||
|
layerInstance instanceof VectorLayer)
|
||||||
|
) {
|
||||||
|
// 检查该图层是否已经绑定过裁切事件,如果没有则追加
|
||||||
|
const hasBinding =
|
||||||
|
this.regionMaskManager.hasLayerBinding(layerInstance);
|
||||||
|
if (!hasBinding) {
|
||||||
|
this.regionMaskManager.appendMaskToLayer(
|
||||||
|
layerInstance,
|
||||||
|
this.currentClipGeoJson
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
console.warn(
|
console.warn(
|
||||||
`未找到标识为 [${registryKey}] 的图层实例,当前注册表 keys:`,
|
`未找到标识为 [${registryKey}] 的图层实例,当前注册表 keys:`,
|
||||||
|
|||||||
@ -1,11 +1,18 @@
|
|||||||
import OlMap from 'ol/Map';
|
import OlMap from 'ol/Map';
|
||||||
import View from 'ol/View';
|
import View from 'ol/View';
|
||||||
import TileLayer from 'ol/layer/Tile';
|
import TileLayer from 'ol/layer/Tile';
|
||||||
|
import VectorLayer from 'ol/layer/Vector';
|
||||||
import GeoJSON from 'ol/format/GeoJSON';
|
import GeoJSON from 'ol/format/GeoJSON';
|
||||||
import VectorSource from 'ol/source/Vector';
|
import VectorSource from 'ol/source/Vector';
|
||||||
import { fromLonLat } from 'ol/proj';
|
import { fromLonLat } from 'ol/proj';
|
||||||
import { PointLayerManager } from './point-layer-manager';
|
import { PointLayerManager } from './point-layer-manager';
|
||||||
|
|
||||||
|
type MaskBinding = {
|
||||||
|
layer: TileLayer | VectorLayer<any>;
|
||||||
|
prerender: (event: any) => void;
|
||||||
|
postrender: (event: any) => void;
|
||||||
|
};
|
||||||
|
|
||||||
type RegionMaskManagerOptions = {
|
type RegionMaskManagerOptions = {
|
||||||
map: OlMap | null;
|
map: OlMap | null;
|
||||||
view: View | null;
|
view: View | null;
|
||||||
@ -20,11 +27,7 @@ export class RegionMaskManager {
|
|||||||
private pointLayerManager: PointLayerManager;
|
private pointLayerManager: PointLayerManager;
|
||||||
private defaultCenter: [number, number];
|
private defaultCenter: [number, number];
|
||||||
private defaultZoom: number;
|
private defaultZoom: number;
|
||||||
private maskBindings: Array<{
|
private maskBindings: Array<MaskBinding> = [];
|
||||||
layer: TileLayer;
|
|
||||||
prerender: (event: any) => void;
|
|
||||||
postrender: (event: any) => void;
|
|
||||||
}> = [];
|
|
||||||
|
|
||||||
constructor(options: RegionMaskManagerOptions) {
|
constructor(options: RegionMaskManagerOptions) {
|
||||||
this.map = options.map;
|
this.map = options.map;
|
||||||
@ -76,7 +79,10 @@ export class RegionMaskManager {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
feature.set('_regionVisible', this.isPointInPolygon(lon, lat, regionCoords));
|
feature.set(
|
||||||
|
'_regionVisible',
|
||||||
|
this.isPointInPolygon(lon, lat, regionCoords)
|
||||||
|
);
|
||||||
feature.changed();
|
feature.changed();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -114,12 +120,18 @@ export class RegionMaskManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 备注:把 GeoJSON 边界绑定到底图 prerender/postrender 事件,实现区域裁切遮罩。
|
// 备注:把 GeoJSON 边界绑定到底图 prerender/postrender 事件,实现区域裁切遮罩。
|
||||||
applyMapMask(rasterLayer: TileLayer, clipGeoJson: any): void {
|
applyMapMask(
|
||||||
|
rasterLayer: TileLayer | VectorLayer<any>,
|
||||||
|
clipGeoJson: any
|
||||||
|
): void {
|
||||||
this.applyMapMaskToLayers(rasterLayer ? [rasterLayer] : [], clipGeoJson);
|
this.applyMapMaskToLayers(rasterLayer ? [rasterLayer] : [], clipGeoJson);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 备注:把 GeoJSON 边界同时绑定到多个底图图层,保证多底图叠加场景下裁切边界保持一致。
|
// 备注:把 GeoJSON 边界同时绑定到多个底图图层和矢量图层,保证多图层叠加场景下裁切边界保持一致。
|
||||||
applyMapMaskToLayers(rasterLayers: TileLayer[] = [], clipGeoJson: any): void {
|
applyMapMaskToLayers(
|
||||||
|
rasterLayers: (TileLayer | VectorLayer<any>)[] = [],
|
||||||
|
clipGeoJson: any
|
||||||
|
): void {
|
||||||
if (!clipGeoJson) return;
|
if (!clipGeoJson) return;
|
||||||
|
|
||||||
const targetLayers = rasterLayers.filter(Boolean);
|
const targetLayers = rasterLayers.filter(Boolean);
|
||||||
@ -162,7 +174,9 @@ export class RegionMaskManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (geometry.getType() === 'MultiPolygon') {
|
} else if (geometry.getType() === 'MultiPolygon') {
|
||||||
const polygons = (geometry as any).getCoordinates() as number[][][][];
|
const polygons = (
|
||||||
|
geometry as any
|
||||||
|
).getCoordinates() as number[][][][];
|
||||||
for (const polygonRings of polygons) {
|
for (const polygonRings of polygons) {
|
||||||
for (const ring of polygonRings) {
|
for (const ring of polygonRings) {
|
||||||
if (this.drawRingToContext(context, ring, frameState)) {
|
if (this.drawRingToContext(context, ring, frameState)) {
|
||||||
@ -208,6 +222,93 @@ export class RegionMaskManager {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 备注:给单个图层追加裁切,不破坏已有裁切绑定。用于新图层动态加入时复用当前裁切边界。
|
||||||
|
appendMaskToLayer(
|
||||||
|
layer: TileLayer | VectorLayer<any>,
|
||||||
|
clipGeoJson: any
|
||||||
|
): void {
|
||||||
|
if (!clipGeoJson || !layer) return;
|
||||||
|
// 避免重复绑定
|
||||||
|
if (this.hasLayerBinding(layer)) return;
|
||||||
|
|
||||||
|
const features = new GeoJSON().readFeatures(clipGeoJson, {
|
||||||
|
dataProjection: 'EPSG:4326',
|
||||||
|
featureProjection: 'EPSG:3857'
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!features.length) return;
|
||||||
|
|
||||||
|
const maskPrerender = (event: any) => {
|
||||||
|
const context = event.context;
|
||||||
|
const frameState = event.frameState;
|
||||||
|
|
||||||
|
if (!context || !frameState || !this.map) return;
|
||||||
|
|
||||||
|
context.save();
|
||||||
|
context.setTransform(1, 0, 0, 1, 0, 0);
|
||||||
|
context.beginPath();
|
||||||
|
|
||||||
|
let hasValidPath = false;
|
||||||
|
|
||||||
|
for (const feature of features) {
|
||||||
|
const geometry = feature.getGeometry();
|
||||||
|
if (!geometry) continue;
|
||||||
|
|
||||||
|
if (geometry.getType() === 'Polygon') {
|
||||||
|
const rings = (geometry as any).getCoordinates() as number[][][];
|
||||||
|
for (const ring of rings) {
|
||||||
|
if (this.drawRingToContext(context, ring, frameState)) {
|
||||||
|
hasValidPath = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (geometry.getType() === 'MultiPolygon') {
|
||||||
|
const polygons = (geometry as any).getCoordinates() as number[][][][];
|
||||||
|
for (const polygonRings of polygons) {
|
||||||
|
for (const ring of polygonRings) {
|
||||||
|
if (this.drawRingToContext(context, ring, frameState)) {
|
||||||
|
hasValidPath = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasValidPath) return;
|
||||||
|
|
||||||
|
context.save();
|
||||||
|
context.lineWidth = 6;
|
||||||
|
context.strokeStyle = '#6D64DF';
|
||||||
|
context.stroke();
|
||||||
|
context.clip();
|
||||||
|
context.strokeStyle = '#CCC9F4';
|
||||||
|
context.lineWidth = 5;
|
||||||
|
context.stroke();
|
||||||
|
context.clip();
|
||||||
|
};
|
||||||
|
|
||||||
|
const maskPostrender = (event: any) => {
|
||||||
|
if (event.context) {
|
||||||
|
event.context.restore();
|
||||||
|
event.context.restore();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.maskBindings.push({
|
||||||
|
layer,
|
||||||
|
prerender: maskPrerender,
|
||||||
|
postrender: maskPostrender
|
||||||
|
});
|
||||||
|
|
||||||
|
layer.on('prerender', maskPrerender);
|
||||||
|
layer.on('postrender', maskPostrender);
|
||||||
|
layer.changed();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 备注:检查某个图层是否已经绑定了裁切事件,避免重复绑定。
|
||||||
|
hasLayerBinding(layer: TileLayer | VectorLayer<any>): boolean {
|
||||||
|
return this.maskBindings.some(binding => binding.layer === layer);
|
||||||
|
}
|
||||||
|
|
||||||
// 备注:清除当前底图遮罩并按需恢复默认视野,供切换基地和异常兜底复用。
|
// 备注:清除当前底图遮罩并按需恢复默认视野,供切换基地和异常兜底复用。
|
||||||
clearMapMask(resetView = true): void {
|
clearMapMask(resetView = true): void {
|
||||||
const maskedLayers = this.maskBindings.map(binding => binding.layer);
|
const maskedLayers = this.maskBindings.map(binding => binding.layer);
|
||||||
@ -308,7 +409,9 @@ export class RegionMaskManager {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const cssPixel = this.map?.getPixelFromCoordinate(coord as [number, number]);
|
const cssPixel = this.map?.getPixelFromCoordinate(
|
||||||
|
coord as [number, number]
|
||||||
|
);
|
||||||
if (!cssPixel) continue;
|
if (!cssPixel) continue;
|
||||||
|
|
||||||
const canvasX = cssPixel[0] * pixelRatio;
|
const canvasX = cssPixel[0] * pixelRatio;
|
||||||
|
|||||||
@ -1,8 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div
|
<div class="map-filter-container" v-show="!uiStore.isRoaming">
|
||||||
class="map-filter-container"
|
|
||||||
v-show="!uiStore.isRoaming && !uiStore.isSmartEquipment"
|
|
||||||
>
|
|
||||||
<div class="toolbar">
|
<div class="toolbar">
|
||||||
<a-form :model="formModel">
|
<a-form :model="formModel">
|
||||||
<a-row :gutter="10">
|
<a-row :gutter="10">
|
||||||
@ -91,6 +88,49 @@
|
|||||||
</a-select>
|
</a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
|
<a-col v-if="uiStore.isSmartEquipment">
|
||||||
|
<a-form-item label="" name="">
|
||||||
|
<a-select
|
||||||
|
v-model:value="power"
|
||||||
|
:loading="powerLoading"
|
||||||
|
show-search
|
||||||
|
:filter-option="filterOption"
|
||||||
|
style="width: 140px"
|
||||||
|
placeholder="请选择电站"
|
||||||
|
allow-clear
|
||||||
|
@change="getstcd"
|
||||||
|
>
|
||||||
|
<a-select-option
|
||||||
|
v-for="item in stationOptions"
|
||||||
|
:key="item.stcd"
|
||||||
|
:value="item.stcd"
|
||||||
|
:title="item.ennm"
|
||||||
|
>{{ item.ennm }}</a-select-option
|
||||||
|
>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col v-if="uiStore.isSmartEquipment">
|
||||||
|
<a-form-item label="" name="">
|
||||||
|
<a-select
|
||||||
|
v-model:value="equipmentTypeValue"
|
||||||
|
show-search
|
||||||
|
:filter-option="filterOption"
|
||||||
|
style="width: 160px"
|
||||||
|
placeholder="请选择装备类型"
|
||||||
|
allow-clear
|
||||||
|
@change="handleEquipmentTypeChange"
|
||||||
|
>
|
||||||
|
<a-select-option
|
||||||
|
v-for="item in equipmentTypeOptions"
|
||||||
|
:key="item.code"
|
||||||
|
:value="item.code"
|
||||||
|
:title="item.name"
|
||||||
|
>{{ item.name }}</a-select-option
|
||||||
|
>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
<a-col>
|
<a-col>
|
||||||
<a-form-item label="" name="anchorPointSelect">
|
<a-form-item label="" name="anchorPointSelect">
|
||||||
<a-select
|
<a-select
|
||||||
@ -139,6 +179,8 @@ import { useMapStore } from '@/store/modules/map';
|
|||||||
import { useModelStore } from '@/store/modules/model';
|
import { useModelStore } from '@/store/modules/model';
|
||||||
import { DateSetting } from '@/utils/enumeration';
|
import { DateSetting } from '@/utils/enumeration';
|
||||||
import { getFishList, getFishPointList } from '@/api/map';
|
import { getFishList, getFishPointList } from '@/api/map';
|
||||||
|
import { getEngInfoDropdown } from '@/api/select';
|
||||||
|
import { vmsstbprptGetKendoListWte } from '@/api/sz';
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const mapOrchestrator = useMapOrchestrator();
|
const mapOrchestrator = useMapOrchestrator();
|
||||||
@ -169,6 +211,19 @@ const DRAWER_STTP_CODES = [
|
|||||||
'DW',
|
'DW',
|
||||||
'WE',
|
'WE',
|
||||||
'WVA',
|
'WVA',
|
||||||
|
'FPRD',
|
||||||
|
''
|
||||||
|
];
|
||||||
|
// 智慧装备 - sttpCode
|
||||||
|
const SmartEquipmentCodes = [
|
||||||
|
'AI_FISH',
|
||||||
|
'AI_ANML',
|
||||||
|
'AI_BIRD',
|
||||||
|
'AI_RIV',
|
||||||
|
'AI_FISHING',
|
||||||
|
'AI_5001',
|
||||||
|
'AI_5005',
|
||||||
|
'AI_SORTER',
|
||||||
'FPRD'
|
'FPRD'
|
||||||
];
|
];
|
||||||
const siteRangePicker = [
|
const siteRangePicker = [
|
||||||
@ -203,6 +258,31 @@ const searchTimeRange = ref([
|
|||||||
dayjs(mapViewStore.searchTimeRange[1]).format('YYYY-MM-DD HH:mm:ss')
|
dayjs(mapViewStore.searchTimeRange[1]).format('YYYY-MM-DD HH:mm:ss')
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// 智慧装备 - 电站选择
|
||||||
|
const power = ref<string | undefined>(undefined);
|
||||||
|
const powerLoading = ref(false);
|
||||||
|
const stationOptions = ref<any[]>([]);
|
||||||
|
const equipmentOptions = ref<any[]>([]);
|
||||||
|
const equipmentLoading = ref(false);
|
||||||
|
const equipmentTypeValue = ref<string | undefined>(undefined);
|
||||||
|
const sttpCodeToName: Record<string, string> = {
|
||||||
|
FPRD: '鱼类调查装置',
|
||||||
|
AI_FISH: '鱼类智能识别装置',
|
||||||
|
AI_ANML: '动物智能识别装置',
|
||||||
|
AI_BIRD: '鸟类智能识别装置',
|
||||||
|
AI_RIV: '河道违章智能识别装置',
|
||||||
|
AI_SORTER: '智能分拣装置',
|
||||||
|
AI_FISHING: '钓鱼',
|
||||||
|
AI_5001: '漂浮物识别装置',
|
||||||
|
AI_5005: '叠梁门运行识别装置'
|
||||||
|
};
|
||||||
|
const equipmentTypeOptions = computed(() => {
|
||||||
|
return SmartEquipmentCodes.map(code => ({
|
||||||
|
code,
|
||||||
|
name: sttpCodeToName[code] || code
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
// 备注:筛选组件只负责根据当前路由决定展示哪些输入项。
|
// 备注:筛选组件只负责根据当前路由决定展示哪些输入项。
|
||||||
const isMenu = (menuPath: string) => {
|
const isMenu = (menuPath: string) => {
|
||||||
const path = route.path;
|
const path = route.path;
|
||||||
@ -217,7 +297,9 @@ const isFishSurveyMode = computed(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const anchorPointLoading = computed(() => {
|
const anchorPointLoading = computed(() => {
|
||||||
return isFishSurveyMode.value ? fishPointLoading.value : false;
|
if (isFishSurveyMode.value) return fishPointLoading.value;
|
||||||
|
if (uiStore.isSmartEquipment) return equipmentLoading.value;
|
||||||
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
const currentFishBaseId = computed(() => {
|
const currentFishBaseId = computed(() => {
|
||||||
@ -243,6 +325,7 @@ const anchorPointSelectValue = computed({
|
|||||||
watch(anchorPointSelectValue, value => {
|
watch(anchorPointSelectValue, value => {
|
||||||
if (!value) return;
|
if (!value) return;
|
||||||
const matched = anchorPointOptions.value.find(item => item.stcd === value);
|
const matched = anchorPointOptions.value.find(item => item.stcd === value);
|
||||||
|
console.log(matched);
|
||||||
if (matched) {
|
if (matched) {
|
||||||
modelStore.selectedAnchorPoint = matched;
|
modelStore.selectedAnchorPoint = matched;
|
||||||
}
|
}
|
||||||
@ -262,6 +345,7 @@ watch(
|
|||||||
anchorPointSelect: null,
|
anchorPointSelect: null,
|
||||||
fishSurveyZhuanZhi: false
|
fishSurveyZhuanZhi: false
|
||||||
};
|
};
|
||||||
|
equipmentTypeValue.value = undefined;
|
||||||
uiStore.setIsSearchActive(false);
|
uiStore.setIsSearchActive(false);
|
||||||
uiStore.setGlobalDrawerOpen(false);
|
uiStore.setGlobalDrawerOpen(false);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@ -364,9 +448,17 @@ const fetchFishSurveyOptions = async (
|
|||||||
|
|
||||||
fishPointOptions.value = nextFishPointOptions;
|
fishPointOptions.value = nextFishPointOptions;
|
||||||
fishSpeciesOptions.value = nextFishSpeciesOptions;
|
fishSpeciesOptions.value = nextFishSpeciesOptions;
|
||||||
// fishSurveyZhuanZhiParams.value.value = nextFishSpeciesOptions.map(
|
if (nextFishSpeciesOptions.length === 0) {
|
||||||
// item => item.value
|
fishSurveyZhuanZhiParams.value.value = [];
|
||||||
// );
|
fishSurveyZhuanZhiParams.value.anchorPointSelect = null;
|
||||||
|
modelStore.selectedFishSpecies = [];
|
||||||
|
modelStore.globalDrawerMode = 'basicInfo';
|
||||||
|
uiStore.setIsSearchActive(false);
|
||||||
|
uiStore.setGlobalDrawerOpen(false);
|
||||||
|
setTimeout(() => {
|
||||||
|
uiStore.setDrawerOpen(true);
|
||||||
|
}, 300);
|
||||||
|
}
|
||||||
syncFishAnchorPointSelection(nextFishPointOptions);
|
syncFishAnchorPointSelection(nextFishPointOptions);
|
||||||
} finally {
|
} finally {
|
||||||
fishPointLoading.value = false;
|
fishPointLoading.value = false;
|
||||||
@ -573,6 +665,16 @@ const anchorPointOptions = computed(() => {
|
|||||||
return filteredFishPointOptions.value;
|
return filteredFishPointOptions.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (uiStore.isSmartEquipment && equipmentOptions.value.length > 0) {
|
||||||
|
if (equipmentTypeValue.value) {
|
||||||
|
return equipmentOptions.value.filter(
|
||||||
|
(item: any) =>
|
||||||
|
String(item.sttpCode || item.sttp || '') === equipmentTypeValue.value
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return equipmentOptions.value;
|
||||||
|
}
|
||||||
|
|
||||||
const pointData = mapDataStore.pointData || [];
|
const pointData = mapDataStore.pointData || [];
|
||||||
const checkedLayerKeys = new Set<string>(
|
const checkedLayerKeys = new Set<string>(
|
||||||
mapViewStore.getCheckedLayerKeys() || []
|
mapViewStore.getCheckedLayerKeys() || []
|
||||||
@ -628,6 +730,82 @@ const filterAnchorPoint = (input: string, option: any) => {
|
|||||||
return stnm.includes(keyword) || baseName.includes(keyword);
|
return stnm.includes(keyword) || baseName.includes(keyword);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const filterOption = (inputValue: string, option: any) => {
|
||||||
|
const label = option.title || '';
|
||||||
|
const keyword = inputValue || '';
|
||||||
|
return label.indexOf(keyword) !== -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getDataList = async () => {
|
||||||
|
powerLoading.value = true;
|
||||||
|
power.value = undefined;
|
||||||
|
stationOptions.value = [];
|
||||||
|
const baseId =
|
||||||
|
jidiSelectEventStore.selectedItem?.wbsCode === 'all'
|
||||||
|
? ''
|
||||||
|
: jidiSelectEventStore.selectedItem?.wbsCode || '';
|
||||||
|
const res = await getEngInfoDropdown({
|
||||||
|
baseId
|
||||||
|
});
|
||||||
|
if (res.data) {
|
||||||
|
powerLoading.value = false;
|
||||||
|
stationOptions.value = res.data;
|
||||||
|
}
|
||||||
|
getstcd();
|
||||||
|
};
|
||||||
|
|
||||||
|
const getstcd = async () => {
|
||||||
|
equipmentLoading.value = true;
|
||||||
|
const baseId = jidiSelectEventStore.selectedItem?.wbsCode || '';
|
||||||
|
const params = {
|
||||||
|
filter: {
|
||||||
|
logic: 'and',
|
||||||
|
filters: [
|
||||||
|
baseId !== 'all'
|
||||||
|
? {
|
||||||
|
field: 'baseId',
|
||||||
|
operator: 'eq',
|
||||||
|
dataType: 'string',
|
||||||
|
value: baseId
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
power.value
|
||||||
|
? {
|
||||||
|
field: 'rstcd',
|
||||||
|
operator: 'eq',
|
||||||
|
dataType: 'string',
|
||||||
|
value: power.value
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
{
|
||||||
|
field: 'sttpCode',
|
||||||
|
operator: 'in',
|
||||||
|
dataType: 'string',
|
||||||
|
value: SmartEquipmentCodes
|
||||||
|
}
|
||||||
|
].filter(Boolean)
|
||||||
|
},
|
||||||
|
groupResultFlat: true
|
||||||
|
};
|
||||||
|
const res = await vmsstbprptGetKendoListWte(params);
|
||||||
|
if (res.data?.data?.length > 0) {
|
||||||
|
equipmentOptions.value = res.data.data;
|
||||||
|
} else {
|
||||||
|
equipmentOptions.value = [];
|
||||||
|
}
|
||||||
|
equipmentLoading.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleEquipmentTypeChange = (value: string | undefined) => {
|
||||||
|
// 清空锚点选择,因为选项列表会变化
|
||||||
|
formModel.value.anchorPointSelect = null;
|
||||||
|
uiStore.setIsSearchActive(false);
|
||||||
|
uiStore.setGlobalDrawerOpen(false);
|
||||||
|
setTimeout(() => {
|
||||||
|
uiStore.setDrawerOpen(true);
|
||||||
|
}, 300);
|
||||||
|
};
|
||||||
|
|
||||||
// 备注:基地切换后仅重置本地选中的搜索项,不在组件中直接控制地图。
|
// 备注:基地切换后仅重置本地选中的搜索项,不在组件中直接控制地图。
|
||||||
watch(
|
watch(
|
||||||
() => currentFishBaseId.value,
|
() => currentFishBaseId.value,
|
||||||
@ -646,11 +824,39 @@ watch(
|
|||||||
{ immediate: true }
|
{ immediate: true }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// 智慧装备:基地切换时重新加载电站列表
|
||||||
|
watch(
|
||||||
|
() => currentFishBaseId.value,
|
||||||
|
() => {
|
||||||
|
if (uiStore.isSmartEquipment) {
|
||||||
|
getDataList();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true, deep: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
// 智慧装备:切回页面时重新加载(基地可能已在其他页面切换过)
|
||||||
|
watch(
|
||||||
|
() => uiStore.isSmartEquipment,
|
||||||
|
newVal => {
|
||||||
|
if (newVal) {
|
||||||
|
getDataList();
|
||||||
|
} else {
|
||||||
|
equipmentTypeValue.value = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => formModel.value.fishSurveyZhuanZhi,
|
() => formModel.value.fishSurveyZhuanZhi,
|
||||||
async checked => {
|
async checked => {
|
||||||
if (!checked) {
|
if (!checked) {
|
||||||
resetFishSurveyState();
|
resetFishSurveyState();
|
||||||
|
uiStore.setIsSearchActive(false);
|
||||||
|
uiStore.setGlobalDrawerOpen(false);
|
||||||
|
setTimeout(() => {
|
||||||
|
uiStore.setDrawerOpen(true);
|
||||||
|
}, 300);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -739,7 +945,10 @@ const handleAnchorPointChange = (value: string) => {
|
|||||||
matched?.sttpCode || matched?.sttp || ''
|
matched?.sttpCode || matched?.sttp || ''
|
||||||
).toUpperCase();
|
).toUpperCase();
|
||||||
// 非抽屉图层:不弹抽屉,退出搜索状态,收起全局抽屉后恢复页面自带抽屉
|
// 非抽屉图层:不弹抽屉,退出搜索状态,收起全局抽屉后恢复页面自带抽屉
|
||||||
if (!DRAWER_STTP_CODES.includes(sttpCode)) {
|
if (
|
||||||
|
!DRAWER_STTP_CODES.includes(sttpCode) &&
|
||||||
|
!SmartEquipmentCodes.includes(sttpCode)
|
||||||
|
) {
|
||||||
uiStore.setIsSearchActive(false);
|
uiStore.setIsSearchActive(false);
|
||||||
uiStore.setGlobalDrawerOpen(false);
|
uiStore.setGlobalDrawerOpen(false);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
|||||||
@ -40,7 +40,6 @@ const isZhiNengPeiTu = computed(() => {
|
|||||||
<!-- 物种介绍模式:鱼种下拉选择时展示(动物/植物介绍 + 监测表格);否则展示基础信息 + 监测表格 -->
|
<!-- 物种介绍模式:鱼种下拉选择时展示(动物/植物介绍 + 监测表格);否则展示基础信息 + 监测表格 -->
|
||||||
<template v-if="modelStore.globalDrawerMode === 'speciesIntro'">
|
<template v-if="modelStore.globalDrawerMode === 'speciesIntro'">
|
||||||
<speciesIntroMod />
|
<speciesIntroMod />
|
||||||
<monitoringTableMod />
|
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<basicInfoMod />
|
<basicInfoMod />
|
||||||
|
|||||||
@ -1,77 +1,253 @@
|
|||||||
<!-- SidePanelItem.vue -->
|
<!-- SidePanelItem.vue -->
|
||||||
<template>
|
<template>
|
||||||
<SidePanelItem title="各基地设备统计">
|
<SidePanelItem title="各基地设备统计">
|
||||||
<div ref="chartRef" style="width: 100%; height: calc(100vh - 520px)"></div>
|
<a-spin :spinning="loading" wrapperClassName="chart-spin">
|
||||||
|
<div
|
||||||
|
ref="chartRef"
|
||||||
|
style="width: 100%; height: calc(100vh - 520px)"
|
||||||
|
></div>
|
||||||
|
</a-spin>
|
||||||
|
|
||||||
|
<!-- 弹框 -->
|
||||||
|
<a-modal
|
||||||
|
v-model:open="modalVisible"
|
||||||
|
:title="modalTitle"
|
||||||
|
:footer="null"
|
||||||
|
width="1536px"
|
||||||
|
@cancel="handleCloseModal"
|
||||||
|
>
|
||||||
|
<ZHZB v-if="currentType" :baseId="currentBaseId" :type="currentType" />
|
||||||
|
</a-modal>
|
||||||
</SidePanelItem>
|
</SidePanelItem>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import * as echarts from 'echarts';
|
import * as echarts from 'echarts';
|
||||||
import dayjs from 'dayjs';
|
import { ref, computed, onMounted, onUnmounted, watch } from 'vue';
|
||||||
import { ref, onMounted, onUnmounted, watch, nextTick } from 'vue';
|
import { imeBaseDeviceStat } from '@/api/sz';
|
||||||
|
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
||||||
import SidePanelItem from '@/components/SidePanelItem/index.vue';
|
import SidePanelItem from '@/components/SidePanelItem/index.vue';
|
||||||
|
import ZHZB from '@/modules/ZHZB/index.vue';
|
||||||
|
import { useDraggable } from '@/utils/drag';
|
||||||
|
|
||||||
|
const loading = ref(false);
|
||||||
|
const baseid = ref('all');
|
||||||
|
const jidiSelectEventStore = useJidiSelectEventStore();
|
||||||
|
// 弹框相关状态
|
||||||
|
const modalVisible = ref(false);
|
||||||
|
const currentType = ref<string | null>(null);
|
||||||
|
const currentBaseId = ref<string>('');
|
||||||
|
const currentBaseName = ref<string>('');
|
||||||
|
useDraggable(modalVisible, { boundary: true, resetOnOpen: true });
|
||||||
|
const modalTitle = computed(() => {
|
||||||
|
const typeName =
|
||||||
|
deviceList.find(d => d.code === currentType.value)?.name || '';
|
||||||
|
return `${currentBaseName.value}${typeName ? ' - ' + typeName : ''}`;
|
||||||
|
});
|
||||||
|
// 图表原始数据(用于点击时反查 baseId)
|
||||||
|
const chartData = ref<any[]>([]);
|
||||||
// 图表实例
|
// 图表实例
|
||||||
const chartRef = ref(null);
|
const chartRef = ref(null);
|
||||||
let chartInstance = null;
|
let chartInstance = null;
|
||||||
|
// 设备列表(与 EquipmentStatistics 中的 facilities 对应)
|
||||||
|
const deviceList = [
|
||||||
|
{ code: 'FPRD', name: '鱼类调查装置' },
|
||||||
|
{ code: 'AI_FISH', name: '鱼类智能识别装置' },
|
||||||
|
{ code: 'AI_ANML', name: '动物智能识别装置' },
|
||||||
|
{ code: 'AI_BIRD', name: '鸟类智能识别装置' },
|
||||||
|
{ code: 'AI_RIV', name: '河道违章智能识别装置' },
|
||||||
|
{ code: 'AI_SORTER', name: '智能分拣装置' },
|
||||||
|
{ code: 'AI_FISHING', name: '钓鱼' },
|
||||||
|
{ code: 'AI_5001', name: '漂浮物识别装置' },
|
||||||
|
{ code: 'AI_5005', name: '叠梁门运行识别装置' }
|
||||||
|
];
|
||||||
|
|
||||||
|
const chartColors = [
|
||||||
|
'#5B8FF9',
|
||||||
|
'#5AD8A6',
|
||||||
|
'#5D7092',
|
||||||
|
'#F6BD16',
|
||||||
|
'#E86452',
|
||||||
|
'#6DC8EC',
|
||||||
|
'#FF9845',
|
||||||
|
'#1E9493',
|
||||||
|
'#FF99C3'
|
||||||
|
];
|
||||||
|
|
||||||
// 初始化图表
|
// 初始化图表
|
||||||
const initChart = () => {
|
const initChart = () => {
|
||||||
chartInstance = echarts.init(chartRef.value);
|
chartInstance = echarts.init(chartRef.value);
|
||||||
const option = {
|
chartInstance.on('click', handleChartClick);
|
||||||
color: ['#5B8FF9', '#5AD8A6', '#5D7092'],
|
};
|
||||||
tooltip: { trigger: 'axis' },
|
|
||||||
legend: {
|
// 点击图表:弹出该基地该类型的设备明细弹框(柱状图与饼图共用)
|
||||||
data: [
|
const handleChartClick = (params: any) => {
|
||||||
{ name: '鱼类调查装置' },
|
if (!params || !params.seriesName) return;
|
||||||
{ name: '鱼类智能识别装置' },
|
// 忽略透明的“总数”占位系列
|
||||||
{ name: '动物智能识别装置' },
|
if (params.seriesName === 'total') return;
|
||||||
{ name: '鸟类智能识别装置' },
|
let typeCode: string | undefined;
|
||||||
{ name: '河道违章智能识别装置' },
|
let baseName: string;
|
||||||
{ name: '智能分拣装置' },
|
if (params.seriesType === 'pie') {
|
||||||
{ name: '钓鱼' },
|
// 饼图:name 是设备名,seriesName 是基地名
|
||||||
{ name: '漂浮物识别装置' },
|
typeCode = deviceList.find(d => d.name === params.name)?.code;
|
||||||
{ name: '叠梁门运行识别装置' }
|
baseName = params.seriesName;
|
||||||
]
|
} else {
|
||||||
},
|
// 柱状图:seriesName 是设备名,name 是基地名
|
||||||
grid: { left: 0, right: 30, top: 60, bottom: 40, containLabel: true },
|
typeCode = deviceList.find(d => d.name === params.seriesName)?.code;
|
||||||
xAxis: {
|
baseName = params.name;
|
||||||
type: 'value'
|
}
|
||||||
},
|
if (!typeCode) return;
|
||||||
yAxis: {
|
// 根据基地名反查该基地的 baseId
|
||||||
type: 'category',
|
const base = chartData.value.find(item => item.baseName === baseName);
|
||||||
// offset: -60,
|
currentType.value = typeCode;
|
||||||
data: [
|
currentBaseId.value = base?.baseId || '';
|
||||||
'金沙江干流',
|
currentBaseName.value = baseName || '';
|
||||||
'雅磨江干流',
|
modalVisible.value = true;
|
||||||
'大渡河干流',
|
};
|
||||||
'乌江干流',
|
|
||||||
'长江上游干流',
|
// 关闭弹框
|
||||||
'湘西',
|
const handleCloseModal = () => {
|
||||||
'黄河上游干流',
|
modalVisible.value = false;
|
||||||
'黄河中游干流',
|
currentType.value = null;
|
||||||
'南盘江-红水河',
|
currentBaseId.value = '';
|
||||||
'雅鲁藏布江干流'
|
currentBaseName.value = '';
|
||||||
]
|
};
|
||||||
},
|
|
||||||
series: [
|
// 构建多基地堆叠柱状图
|
||||||
|
const buildBarOption = (data: any[]) => {
|
||||||
|
const baseNames = data.map(item => item.baseName).reverse();
|
||||||
|
const series = deviceList.map(device => ({
|
||||||
|
name: device.name,
|
||||||
|
type: 'bar',
|
||||||
|
stack: 'total',
|
||||||
|
data: data.map(item => item.sttpCountMap[device.code] || 0).reverse()
|
||||||
|
}));
|
||||||
|
// 每个基地的堆叠总数,用于柱状图顶部的总数展示
|
||||||
|
const totals = data
|
||||||
|
.map(item =>
|
||||||
|
deviceList.reduce((sum, d) => sum + (item.sttpCountMap[d.code] || 0), 0)
|
||||||
|
)
|
||||||
|
.reverse();
|
||||||
|
return {
|
||||||
|
color: chartColors,
|
||||||
|
tooltip: { trigger: 'item', confine: true },
|
||||||
|
legend: { data: deviceList.map(d => ({ name: d.name })), type: 'scroll' },
|
||||||
|
grid: { left: 10, right: 30, top: 50, bottom: 20, containLabel: true },
|
||||||
|
xAxis: { type: 'value', minInterval: 1 },
|
||||||
|
yAxis: { type: 'category', data: baseNames },
|
||||||
|
dataZoom: [
|
||||||
{
|
{
|
||||||
name: '鱼类调查装置',
|
type: 'inside',
|
||||||
type: 'bar',
|
xAxisIndex: 0,
|
||||||
stack: 'total',
|
throttle: 50,
|
||||||
data: [12.3, 10, 8.8, 10, 7.2, 6, 15, 11, 16, 8.6, 18, 15, 20.2]
|
zoomOnMouseWheel: true,
|
||||||
},
|
moveOnMouseMove: true,
|
||||||
{
|
moveOnMouseWheel: false,
|
||||||
name: '鱼类智能识别装置',
|
start: 0,
|
||||||
type: 'bar',
|
end: 100
|
||||||
stack: 'total',
|
|
||||||
data: [12.3, 10, 8.8, 10, 7.2, 6, 15, 11, 16, 8.6, 18, 15, 20.2]
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
markLine: {
|
series: [
|
||||||
silent: true,
|
...series.map(s => ({
|
||||||
data: [{ xAxis: '05-14', lineStyle: { color: 'red', type: 'dashed' } }]
|
...s,
|
||||||
}
|
barMaxWidth: 30,
|
||||||
|
emphasis: {
|
||||||
|
itemStyle: { shadowBlur: 10, shadowColor: 'rgba(0,0,0,0.3)' }
|
||||||
|
}
|
||||||
|
})),
|
||||||
|
{
|
||||||
|
name: 'total',
|
||||||
|
type: 'bar',
|
||||||
|
stack: 'totalLabel',
|
||||||
|
barGap: '-100%',
|
||||||
|
data: totals,
|
||||||
|
barMaxWidth: 30,
|
||||||
|
itemStyle: { color: 'transparent' },
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
position: 'right',
|
||||||
|
color: '#333',
|
||||||
|
fontSize: 12,
|
||||||
|
formatter: (params: any) => {
|
||||||
|
if (params.value === 0) return '';
|
||||||
|
return params.value;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
silent: true,
|
||||||
|
tooltip: { show: false }
|
||||||
|
}
|
||||||
|
]
|
||||||
};
|
};
|
||||||
chartInstance.setOption(option);
|
};
|
||||||
|
|
||||||
|
// 构建单个基地的空心饼图(基地名称展示在下方)
|
||||||
|
const buildPieOption = (data: any[]) => {
|
||||||
|
const base = data[0];
|
||||||
|
const pieData = deviceList
|
||||||
|
.map(d => ({ name: d.name, value: base.sttpCountMap[d.code] || 0 }))
|
||||||
|
.filter(item => item.value > 0);
|
||||||
|
return {
|
||||||
|
color: chartColors,
|
||||||
|
tooltip: { trigger: 'item' },
|
||||||
|
legend: {
|
||||||
|
type: 'scroll',
|
||||||
|
orient: 'horizontal',
|
||||||
|
top: 0,
|
||||||
|
left: 'center'
|
||||||
|
},
|
||||||
|
graphic: [
|
||||||
|
{
|
||||||
|
type: 'text',
|
||||||
|
left: 'center',
|
||||||
|
bottom: 10,
|
||||||
|
style: { text: base.baseName, fill: '#333', fontSize: 14 }
|
||||||
|
}
|
||||||
|
],
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: base.baseName,
|
||||||
|
type: 'pie',
|
||||||
|
radius: ['36%', '54%'],
|
||||||
|
center: ['50%', '50%'],
|
||||||
|
avoidLabelOverlap: true,
|
||||||
|
itemStyle: {
|
||||||
|
borderRadius: 6,
|
||||||
|
borderColor: '#fff',
|
||||||
|
borderWidth: 2
|
||||||
|
},
|
||||||
|
label: { show: true, formatter: '{b}: {c}' },
|
||||||
|
emphasis: { label: { show: true, fontWeight: 'bold' } },
|
||||||
|
data: pieData
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// 更新图表数据
|
||||||
|
const updateChart = (data: any[]) => {
|
||||||
|
chartData.value = data || [];
|
||||||
|
if (!chartInstance) return;
|
||||||
|
if (!data.length) {
|
||||||
|
chartInstance.clear();
|
||||||
|
chartInstance.setOption({
|
||||||
|
graphic: {
|
||||||
|
type: 'text',
|
||||||
|
left: 'center',
|
||||||
|
top: 'center',
|
||||||
|
style: { text: '暂无数据', fill: '#999', fontSize: 14 }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 单个基地时展示空心饼图,否则展示多基地堆叠柱状图
|
||||||
|
const isSingleBase = baseid.value !== 'all' && data.length === 1;
|
||||||
|
const option = isSingleBase ? buildPieOption(data) : buildBarOption(data);
|
||||||
|
chartInstance.setOption(option, true);
|
||||||
|
// 菜单/抽屉展开动画期间容器宽度可能为 0,强制按动画进度多次 resize,避免图表延迟 ~1s 才出现
|
||||||
|
const doResize = () => chartInstance?.resize();
|
||||||
|
requestAnimationFrame(doResize);
|
||||||
|
setTimeout(doResize, 100);
|
||||||
|
setTimeout(doResize, 400);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 容器尺寸自适应(抽屉展开动画导致初始宽度为0时,ECharts 默认100px,展开完成后自动纠正)
|
// 容器尺寸自适应(抽屉展开动画导致初始宽度为0时,ECharts 默认100px,展开完成后自动纠正)
|
||||||
@ -79,6 +255,58 @@ let resizeObserver = null;
|
|||||||
const handleResize = () => {
|
const handleResize = () => {
|
||||||
chartInstance?.resize();
|
chartInstance?.resize();
|
||||||
};
|
};
|
||||||
|
const getDataList = async () => {
|
||||||
|
loading.value = true;
|
||||||
|
try {
|
||||||
|
const params = {
|
||||||
|
filter: {
|
||||||
|
logic: 'and',
|
||||||
|
filters: [
|
||||||
|
baseid.value !== 'all'
|
||||||
|
? {
|
||||||
|
field: 'baseId',
|
||||||
|
operator: 'eq',
|
||||||
|
dataType: 'string',
|
||||||
|
value: baseid.value
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
|
||||||
|
{
|
||||||
|
field: 'sttpCode',
|
||||||
|
operator: 'in',
|
||||||
|
dataType: 'string',
|
||||||
|
value: [
|
||||||
|
'AI_FISH',
|
||||||
|
'AI_ANML',
|
||||||
|
'AI_BIRD',
|
||||||
|
'AI_RIV',
|
||||||
|
'AI_FISHING',
|
||||||
|
'AI_5001',
|
||||||
|
'AI_5005',
|
||||||
|
'AI_SORTER',
|
||||||
|
'FPRD'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
].filter(Boolean)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const res = await imeBaseDeviceStat(params);
|
||||||
|
updateChart(res.data.data);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取设备统计数据失败:', error);
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => jidiSelectEventStore.selectedItem,
|
||||||
|
newVal => {
|
||||||
|
baseid.value = newVal.wbsCode;
|
||||||
|
getDataList();
|
||||||
|
},
|
||||||
|
{ deep: true }
|
||||||
|
);
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
initChart();
|
initChart();
|
||||||
@ -86,6 +314,9 @@ onMounted(() => {
|
|||||||
if (chartRef.value) {
|
if (chartRef.value) {
|
||||||
resizeObserver.observe(chartRef.value);
|
resizeObserver.observe(chartRef.value);
|
||||||
}
|
}
|
||||||
|
// 初始化时以当前已选基地为准,而不是默认 'all'
|
||||||
|
baseid.value = jidiSelectEventStore.selectedItem?.wbsCode || 'all';
|
||||||
|
getDataList();
|
||||||
});
|
});
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
v-for="facility in facilities"
|
v-for="facility in facilities"
|
||||||
:key="facility.name"
|
:key="facility.name"
|
||||||
class="facility-card"
|
class="facility-card"
|
||||||
|
@click="handleFacilityClick(facility)"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
style="
|
style="
|
||||||
@ -32,12 +33,31 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</a-spin>
|
</a-spin>
|
||||||
|
|
||||||
|
<!-- 弹框 -->
|
||||||
|
<a-modal
|
||||||
|
v-model:open="modalVisible"
|
||||||
|
title="设备统计"
|
||||||
|
:footer="null"
|
||||||
|
width="1536px"
|
||||||
|
@cancel="handleCloseModal"
|
||||||
|
>
|
||||||
|
<ZHZB
|
||||||
|
v-if="currentFacility"
|
||||||
|
:baseId="baseid"
|
||||||
|
:type="currentFacility.code"
|
||||||
|
/>
|
||||||
|
</a-modal>
|
||||||
</SidePanelItem>
|
</SidePanelItem>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref } from 'vue';
|
import { ref, onMounted, watch } from 'vue';
|
||||||
import SidePanelItem from '@/components/SidePanelItem/index.vue';
|
import SidePanelItem from '@/components/SidePanelItem/index.vue';
|
||||||
|
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
||||||
|
import { vmsstbprptGetKendoListWte } from '@/api/sz';
|
||||||
|
import ZHZB from '@/modules/ZHZB/index.vue';
|
||||||
|
import { useDraggable } from '@/utils/drag';
|
||||||
import equipment1 from '@/assets/svg/equipment1.svg';
|
import equipment1 from '@/assets/svg/equipment1.svg';
|
||||||
import equipment2 from '@/assets/svg/equipment2.svg';
|
import equipment2 from '@/assets/svg/equipment2.svg';
|
||||||
import equipment3 from '@/assets/svg/equipment3.svg';
|
import equipment3 from '@/assets/svg/equipment3.svg';
|
||||||
@ -48,12 +68,33 @@ import equipment7 from '@/assets/svg/equipment7.svg';
|
|||||||
import equipment8 from '@/assets/svg/equipment8.svg';
|
import equipment8 from '@/assets/svg/equipment8.svg';
|
||||||
import equipment9 from '@/assets/svg/equipment9.svg';
|
import equipment9 from '@/assets/svg/equipment9.svg';
|
||||||
|
|
||||||
|
const jidiSelectEventStore = useJidiSelectEventStore();
|
||||||
|
|
||||||
// Loading 状态
|
// Loading 状态
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
|
// 基地ID
|
||||||
|
const baseid = ref('');
|
||||||
|
// 弹框相关状态
|
||||||
|
const modalVisible = ref(false);
|
||||||
|
const currentFacility = ref<any>(null);
|
||||||
|
useDraggable(modalVisible, { boundary: true, resetOnOpen: true });
|
||||||
|
|
||||||
|
// 点击处理函数
|
||||||
|
const handleFacilityClick = (facility: any) => {
|
||||||
|
currentFacility.value = facility;
|
||||||
|
modalVisible.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 关闭弹框
|
||||||
|
const handleCloseModal = () => {
|
||||||
|
modalVisible.value = false;
|
||||||
|
currentFacility.value = null;
|
||||||
|
};
|
||||||
// 设施数据
|
// 设施数据
|
||||||
const facilities = ref([
|
const facilities = ref([
|
||||||
{
|
{
|
||||||
name: '鱼类调查装置',
|
name: '鱼类调查装置',
|
||||||
|
code: 'FPRD',
|
||||||
count: 0,
|
count: 0,
|
||||||
icon: equipment1,
|
icon: equipment1,
|
||||||
key: '26'
|
key: '26'
|
||||||
@ -61,52 +102,155 @@ const facilities = ref([
|
|||||||
{
|
{
|
||||||
name: '鱼类智能识别装置',
|
name: '鱼类智能识别装置',
|
||||||
count: 0,
|
count: 0,
|
||||||
|
code: 'AI_FISH',
|
||||||
icon: equipment2,
|
icon: equipment2,
|
||||||
key: '27'
|
key: '27'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '动物智能识别装置',
|
name: '动物智能识别装置',
|
||||||
count: 0,
|
count: 0,
|
||||||
|
code: 'AI_ANML',
|
||||||
icon: equipment3,
|
icon: equipment3,
|
||||||
key: '28'
|
key: '28'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '鸟类智能识别装置',
|
name: '鸟类智能识别装置',
|
||||||
count: 0,
|
count: 0,
|
||||||
|
code: 'AI_BIRD',
|
||||||
icon: equipment4,
|
icon: equipment4,
|
||||||
key: '29'
|
key: '29'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '河道违章智能识别装置',
|
name: '河道违章智能识别装置',
|
||||||
count: 0,
|
count: 0,
|
||||||
|
code: 'AI_RIV',
|
||||||
icon: equipment5,
|
icon: equipment5,
|
||||||
key: '29'
|
key: '29'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '智能分拣装置',
|
name: '智能分拣装置',
|
||||||
count: 0,
|
count: 0,
|
||||||
|
code: 'AI_SORTER',
|
||||||
icon: equipment6,
|
icon: equipment6,
|
||||||
key: '29'
|
key: '29'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '钓鱼',
|
name: '钓鱼',
|
||||||
count: 0,
|
count: 0,
|
||||||
|
code: 'AI_FISHING',
|
||||||
icon: equipment7,
|
icon: equipment7,
|
||||||
key: '30'
|
key: '30'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '漂浮物识别装置',
|
name: '漂浮物识别装置',
|
||||||
count: 0,
|
count: 0,
|
||||||
|
code: 'AI_5001',
|
||||||
icon: equipment8,
|
icon: equipment8,
|
||||||
key: '30'
|
key: '30'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '叠梁门运行识别装置',
|
name: '叠梁门运行识别装置',
|
||||||
count: 0,
|
count: 0,
|
||||||
|
code: 'AI_5005',
|
||||||
icon: equipment9,
|
icon: equipment9,
|
||||||
key: '31'
|
key: '31'
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// sttpCode 到设施名称的映射规则
|
||||||
|
const sttpCodeToNamePattern: Record<string, string> = {
|
||||||
|
AI_FISH: '鱼类',
|
||||||
|
AI_ANML: '动物',
|
||||||
|
AI_BIRD: '鸟类',
|
||||||
|
AI_RIV: '河道',
|
||||||
|
AI_FISHING: '钓鱼',
|
||||||
|
AI_5001: '漂浮物识别装置',
|
||||||
|
AI_5005: '叠梁门运行识别装置',
|
||||||
|
AI_SORTER: '智能分拣装置',
|
||||||
|
FPRD: '鱼类调查装置'
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取设备统计数据
|
||||||
|
const getDataList = async () => {
|
||||||
|
loading.value = true;
|
||||||
|
try {
|
||||||
|
const params = {
|
||||||
|
filter: {
|
||||||
|
logic: 'and',
|
||||||
|
filters: [
|
||||||
|
baseid.value !== 'all'
|
||||||
|
? {
|
||||||
|
field: 'baseId',
|
||||||
|
operator: 'eq',
|
||||||
|
dataType: 'string',
|
||||||
|
value: baseid.value
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
{
|
||||||
|
field: 'sttpCode',
|
||||||
|
operator: 'in',
|
||||||
|
dataType: 'string',
|
||||||
|
value: [
|
||||||
|
'AI_FISH',
|
||||||
|
'AI_ANML',
|
||||||
|
'AI_BIRD',
|
||||||
|
'AI_RIV',
|
||||||
|
'AI_FISHING',
|
||||||
|
'AI_5001',
|
||||||
|
'AI_5005',
|
||||||
|
'AI_SORTER',
|
||||||
|
'FPRD'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
].filter(Boolean)
|
||||||
|
},
|
||||||
|
group: [
|
||||||
|
{
|
||||||
|
dir: 'desc',
|
||||||
|
field: 'sttpCode'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
groupResultFlat: true
|
||||||
|
};
|
||||||
|
|
||||||
|
const res = await vmsstbprptGetKendoListWte(params);
|
||||||
|
if (res.data) {
|
||||||
|
const responseData = res?.data?.data || res?.data;
|
||||||
|
// 先重置所有 count 为 0
|
||||||
|
const finalData = facilities.value.map(item => ({ ...item, count: 0 }));
|
||||||
|
if (Array.isArray(responseData)) {
|
||||||
|
responseData.forEach((item: any) => {
|
||||||
|
const pattern = sttpCodeToNamePattern[item.sttpCode];
|
||||||
|
if (pattern) {
|
||||||
|
// 找到名称中包含该 pattern 的所有设施,均分 count
|
||||||
|
const matched = finalData.filter(f => f.code === item.sttpCode);
|
||||||
|
if (matched.length > 0) {
|
||||||
|
matched.forEach(f => {
|
||||||
|
f.count = item.count_sttpCode;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
facilities.value = finalData;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取设备统计数据失败:', error);
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => jidiSelectEventStore.selectedItem,
|
||||||
|
newVal => {
|
||||||
|
baseid.value = newVal.wbsCode;
|
||||||
|
getDataList();
|
||||||
|
},
|
||||||
|
{ deep: true, immediate: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
onMounted(() => {});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|||||||
430
frontend/src/modules/ZHZB/index.vue
Normal file
@ -0,0 +1,430 @@
|
|||||||
|
<template>
|
||||||
|
<div class="zhzb-container">
|
||||||
|
<!-- 搜索表单 -->
|
||||||
|
<div class="search-form">
|
||||||
|
<a-space size="middle">
|
||||||
|
<div>选择水电站:</div>
|
||||||
|
<a-select
|
||||||
|
v-model:value="searchData.stcd.dataDimensionData"
|
||||||
|
placeholder="请选择水电基地"
|
||||||
|
style="width: 200px"
|
||||||
|
show-search
|
||||||
|
:filter-option="filterOption"
|
||||||
|
:options="hydropowerStationOptions"
|
||||||
|
@change="handleHydropowerStationChange"
|
||||||
|
/>
|
||||||
|
<a-select
|
||||||
|
v-model:value="searchData.stnm"
|
||||||
|
placeholder="请选择电站"
|
||||||
|
style="width: 200px"
|
||||||
|
allow-clear
|
||||||
|
show-search
|
||||||
|
:filter-option="filterOption"
|
||||||
|
:options="stationOptions"
|
||||||
|
@change="handleStationChange"
|
||||||
|
/>
|
||||||
|
<a-select
|
||||||
|
v-model:value="searchData.type"
|
||||||
|
placeholder="请选择装备类型"
|
||||||
|
style="width: 160px"
|
||||||
|
allow-clear
|
||||||
|
:options="equipmentTypeOptions"
|
||||||
|
/>
|
||||||
|
<a-button type="primary" @click="handleSearch">查询</a-button>
|
||||||
|
<a-tooltip title="重置">
|
||||||
|
<a-button @click="handleReset">重置</a-button>
|
||||||
|
</a-tooltip>
|
||||||
|
</a-space>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 数据表格 -->
|
||||||
|
<a-table
|
||||||
|
:columns="columns"
|
||||||
|
:data-source="tableData"
|
||||||
|
:loading="loading"
|
||||||
|
:pagination="pagination"
|
||||||
|
:scroll="{ y: tableHeight }"
|
||||||
|
row-key="stcd"
|
||||||
|
@change="handleTableChange"
|
||||||
|
>
|
||||||
|
<template #bodyCell="{ column, record }">
|
||||||
|
<!-- 操作 -->
|
||||||
|
<template v-if="column.key === 'action'">
|
||||||
|
<a @click="handleViewDetail(record)" class="text_hocer">查看详情</a>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</a-table>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, computed, watch, onMounted } from 'vue';
|
||||||
|
import { wbsbGetKendoList, getVmsstbprpt } from '@/api/sw';
|
||||||
|
import { vmsstbprptGetKendoListWte } from '@/api/sz';
|
||||||
|
import { useModelStore } from '@/store/modules/model';
|
||||||
|
|
||||||
|
const modelStore = useModelStore();
|
||||||
|
|
||||||
|
// 智慧装备 - sttpCode
|
||||||
|
const SmartEquipmentCodes = [
|
||||||
|
'AI_FISH',
|
||||||
|
'AI_ANML',
|
||||||
|
'AI_BIRD',
|
||||||
|
'AI_RIV',
|
||||||
|
'AI_FISHING',
|
||||||
|
'AI_5001',
|
||||||
|
'AI_5005',
|
||||||
|
'AI_SORTER',
|
||||||
|
'FPRD'
|
||||||
|
];
|
||||||
|
const sttpCodeToName: Record<string, string> = {
|
||||||
|
FPRD: '鱼类调查装置',
|
||||||
|
AI_FISH: '鱼类智能识别装置',
|
||||||
|
AI_ANML: '动物智能识别装置',
|
||||||
|
AI_BIRD: '鸟类智能识别装置',
|
||||||
|
AI_RIV: '河道违章智能识别装置',
|
||||||
|
AI_SORTER: '智能分拣装置',
|
||||||
|
AI_FISHING: '钓鱼',
|
||||||
|
AI_5001: '漂浮物识别装置',
|
||||||
|
AI_5005: '叠梁门运行识别装置'
|
||||||
|
};
|
||||||
|
const equipmentTypeOptions = computed(() => {
|
||||||
|
return Object.keys(sttpCodeToName).map(code => ({
|
||||||
|
label: sttpCodeToName[code] || code,
|
||||||
|
value: code
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
// ==================== Props 定义 ====================
|
||||||
|
const props = defineProps<{
|
||||||
|
baseId?: string;
|
||||||
|
type?: string;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
// ==================== 状态管理 ====================
|
||||||
|
const loading = ref(false);
|
||||||
|
const tableData = ref<any[]>([]);
|
||||||
|
const pagination = ref({
|
||||||
|
current: 1,
|
||||||
|
pageSize: 20,
|
||||||
|
total: 0,
|
||||||
|
size: 'small',
|
||||||
|
showSizeChanger: true,
|
||||||
|
showQuickJumper: true,
|
||||||
|
showTotal: (total: number) => `共 ${total} 条`,
|
||||||
|
pageSizeOptions: ['10', '20', '50', '100']
|
||||||
|
});
|
||||||
|
const tableHeight = 'calc(48vh)';
|
||||||
|
|
||||||
|
// 水电站列表数据
|
||||||
|
const hydropowerStationList = ref<any[]>([]);
|
||||||
|
const stationDataList: any = ref([]);
|
||||||
|
|
||||||
|
// 转换为 a-select options 格式
|
||||||
|
const hydropowerStationOptions = computed(() => {
|
||||||
|
return hydropowerStationList.value.map(station => ({
|
||||||
|
label: station.wbsName,
|
||||||
|
value: station.wbsCode
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
const stationOptions = computed(() => {
|
||||||
|
return stationDataList.value.map(station => ({
|
||||||
|
label: station.stnm,
|
||||||
|
value: station.stcd
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
const searchData = ref<any>({
|
||||||
|
stcd: {
|
||||||
|
dataDimensionType: 'hyBase',
|
||||||
|
stcdId: '',
|
||||||
|
dataDimensionData: props.baseId || 'all'
|
||||||
|
},
|
||||||
|
stnm: null,
|
||||||
|
type: props.type || null
|
||||||
|
});
|
||||||
|
|
||||||
|
// ==================== 列配置 ====================
|
||||||
|
const columns = computed(() => {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
title: '监控点名称',
|
||||||
|
dataIndex: 'stnm',
|
||||||
|
key: 'stnm'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '基地名称',
|
||||||
|
dataIndex: 'baseName',
|
||||||
|
key: 'baseName'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '站址',
|
||||||
|
dataIndex: 'stlc',
|
||||||
|
key: 'stlc'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
key: 'action'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
});
|
||||||
|
|
||||||
|
// ==================== 过滤条件构建 ====================
|
||||||
|
const buildSearchFilter = () => {
|
||||||
|
const filters: any[] = [];
|
||||||
|
|
||||||
|
// 基地ID过滤
|
||||||
|
if (
|
||||||
|
searchData.value?.stcd?.dataDimensionData &&
|
||||||
|
searchData.value.stcd.dataDimensionData !== 'all'
|
||||||
|
) {
|
||||||
|
filters.push({
|
||||||
|
field: 'baseId',
|
||||||
|
operator: 'eq',
|
||||||
|
dataType: 'string',
|
||||||
|
value: searchData.value.stcd.dataDimensionData
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 电站过滤
|
||||||
|
if (searchData.value?.stnm) {
|
||||||
|
filters.push({
|
||||||
|
field: 'rstcd',
|
||||||
|
operator: 'eq',
|
||||||
|
dataType: 'string',
|
||||||
|
value: searchData.value.stnm
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 装备类型过滤
|
||||||
|
if (searchData.value?.type) {
|
||||||
|
filters.push({
|
||||||
|
field: 'sttpCode',
|
||||||
|
operator: 'eq',
|
||||||
|
dataType: 'string',
|
||||||
|
value: searchData.value.type
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
filters.push({
|
||||||
|
field: 'sttpCode',
|
||||||
|
operator: 'in',
|
||||||
|
dataType: 'string',
|
||||||
|
value: SmartEquipmentCodes
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
logic: 'and',
|
||||||
|
filters: filters.filter(
|
||||||
|
f => f.value !== undefined && f.value !== null && f.value !== ''
|
||||||
|
)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// ==================== API调用 ====================
|
||||||
|
const fetchData = async () => {
|
||||||
|
loading.value = true;
|
||||||
|
try {
|
||||||
|
const filter = buildSearchFilter();
|
||||||
|
const params = {
|
||||||
|
take: pagination.value.pageSize,
|
||||||
|
skip: pagination.value.current,
|
||||||
|
filter: filter,
|
||||||
|
groupResultFlat: true
|
||||||
|
};
|
||||||
|
|
||||||
|
const res = await vmsstbprptGetKendoListWte(params);
|
||||||
|
|
||||||
|
// 数据处理
|
||||||
|
const records = res?.data?.data || res?.data;
|
||||||
|
console.log(res);
|
||||||
|
const total = res?.data.total || 0;
|
||||||
|
|
||||||
|
tableData.value = records || [];
|
||||||
|
pagination.value.total = total;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取设备统计数据失败:', error);
|
||||||
|
tableData.value = [];
|
||||||
|
pagination.value.total = 0;
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getselect = async () => {
|
||||||
|
try {
|
||||||
|
const params = {
|
||||||
|
filter: {
|
||||||
|
logic: 'and',
|
||||||
|
filters: [
|
||||||
|
{
|
||||||
|
field: 'wbsType',
|
||||||
|
operator: 'eq',
|
||||||
|
dataType: 'string',
|
||||||
|
value: 'PSB'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'treeLevel',
|
||||||
|
operator: 'eq',
|
||||||
|
dataType: 'string',
|
||||||
|
value: '1'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
sort: [
|
||||||
|
{
|
||||||
|
field: 'orderIndex',
|
||||||
|
dir: 'asc'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
const res = await wbsbGetKendoList(params);
|
||||||
|
|
||||||
|
// 数据处理:提取水电站列表
|
||||||
|
if (res?.data?.data && Array.isArray(res.data.data)) {
|
||||||
|
hydropowerStationList.value = res.data.data;
|
||||||
|
getselectTwo(searchData.value.stcd.dataDimensionData);
|
||||||
|
} else {
|
||||||
|
hydropowerStationList.value = [];
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取水电基地列表失败:', error);
|
||||||
|
hydropowerStationList.value = [];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const getselectTwo = async (code: any) => {
|
||||||
|
const params = {
|
||||||
|
filter: {
|
||||||
|
logic: 'and',
|
||||||
|
filters: [
|
||||||
|
code != 'all'
|
||||||
|
? {
|
||||||
|
field: 'baseId',
|
||||||
|
operator: 'eq',
|
||||||
|
dataType: 'string',
|
||||||
|
value: code
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
{
|
||||||
|
field: 'sttpCode',
|
||||||
|
operator: 'eq',
|
||||||
|
dataType: 'string',
|
||||||
|
value: 'ENG'
|
||||||
|
}
|
||||||
|
].filter(Boolean)
|
||||||
|
},
|
||||||
|
select: ['stcd', 'stnm']
|
||||||
|
};
|
||||||
|
const res = await getVmsstbprpt(params);
|
||||||
|
stationDataList.value = res?.data?.data || res?.data;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ==================== 事件处理 ====================
|
||||||
|
const filterOption = (input: string, option: any) => {
|
||||||
|
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleHydropowerStationChange = (value: string) => {
|
||||||
|
// 清空测站选择
|
||||||
|
searchData.value.stnm = null;
|
||||||
|
searchData.value.stcd.stcdId = '';
|
||||||
|
// 获取该水电基地下的电站列表
|
||||||
|
getselectTwo(value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleStationChange = (value: string | undefined) => {
|
||||||
|
if (value) {
|
||||||
|
searchData.value.stcd.stcdId = value;
|
||||||
|
} else {
|
||||||
|
searchData.value.stcd.stcdId = '';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSearch = () => {
|
||||||
|
pagination.value.current = 1;
|
||||||
|
fetchData();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleReset = () => {
|
||||||
|
searchData.value = {
|
||||||
|
stcd: {
|
||||||
|
dataDimensionType: 'hyBase',
|
||||||
|
stcdId: '',
|
||||||
|
dataDimensionData: props.baseId || 'all'
|
||||||
|
},
|
||||||
|
stnm: null,
|
||||||
|
type: props.type || null
|
||||||
|
};
|
||||||
|
pagination.value.current = 1;
|
||||||
|
fetchData();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleTableChange = (pag: any) => {
|
||||||
|
pagination.value.current = pag.current;
|
||||||
|
pagination.value.pageSize = pag.pageSize;
|
||||||
|
fetchData();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleViewDetail = (record: any) => {
|
||||||
|
modelStore.modalVisible = true;
|
||||||
|
modelStore.params = record;
|
||||||
|
modelStore.title = record.stnm;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ==================== 监听 Props 变化 ====================
|
||||||
|
watch(
|
||||||
|
() => props.baseId,
|
||||||
|
newVal => {
|
||||||
|
if (newVal && newVal !== searchData.value.stcd.dataDimensionData) {
|
||||||
|
searchData.value.stcd.dataDimensionData = newVal;
|
||||||
|
getselectTwo(newVal);
|
||||||
|
fetchData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.type,
|
||||||
|
newVal => {
|
||||||
|
searchData.value.type = newVal || null;
|
||||||
|
fetchData();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// ==================== 生命周期 ====================
|
||||||
|
onMounted(() => {
|
||||||
|
fetchData();
|
||||||
|
getselect();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.zhzb-container {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
background-color: #ffffff;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
.search-form {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.ant-table-wrapper) {
|
||||||
|
flex: 1;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.text_hocer {
|
||||||
|
color: #2f6b98;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text_hocer:hover {
|
||||||
|
color: #40a9ff;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -423,18 +423,18 @@ const FPRDInfo = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '监控点类型',
|
label: '监控点类型',
|
||||||
value: 'stindx',
|
value: 'sttpName',
|
||||||
|
col: 24
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '监控方式',
|
||||||
|
value: 'mwayName',
|
||||||
col: 24
|
col: 24
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '监控点地址',
|
label: '监控点地址',
|
||||||
value: 'stlc',
|
value: 'stlc',
|
||||||
col: 24
|
col: 24
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '所属流域',
|
|
||||||
value: 'hbrvcdName',
|
|
||||||
col: 24
|
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
export {
|
export {
|
||||||
|
|||||||
@ -58,7 +58,7 @@ import { getStcdDetail } from '@/api/mapModal';
|
|||||||
|
|
||||||
const baseUrl = import.meta.env.VITE_APP_ATTACHMENT_URL;
|
const baseUrl = import.meta.env.VITE_APP_ATTACHMENT_URL;
|
||||||
const modelStore = useModelStore();
|
const modelStore = useModelStore();
|
||||||
const info = ref({});
|
const info: any = ref({});
|
||||||
const formDiv = ref(null);
|
const formDiv = ref(null);
|
||||||
const logo = ref('');
|
const logo = ref('');
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
@ -82,7 +82,15 @@ const moduleMap = {
|
|||||||
AIVDInfo: AIVDInfo,
|
AIVDInfo: AIVDInfo,
|
||||||
WEInfo: WEInfo,
|
WEInfo: WEInfo,
|
||||||
WVAInfo: WVAInfo,
|
WVAInfo: WVAInfo,
|
||||||
FPRDInfo: FPRDInfo
|
FPRDInfo: FPRDInfo,
|
||||||
|
AI_FISHInfo: FPRDInfo,
|
||||||
|
AI_ANMLInfo: FPRDInfo,
|
||||||
|
AI_BIRDInfo: FPRDInfo,
|
||||||
|
AI_RIVInfo: FPRDInfo,
|
||||||
|
AI_FISHINGInfo: FPRDInfo,
|
||||||
|
AI_5001Info: FPRDInfo,
|
||||||
|
AI_5005Info: FPRDInfo,
|
||||||
|
AI_SORTERInfo: FPRDInfo
|
||||||
} as const;
|
} as const;
|
||||||
watch(
|
watch(
|
||||||
() => modelStore.selectedAnchorPoint,
|
() => modelStore.selectedAnchorPoint,
|
||||||
@ -104,12 +112,16 @@ watch(
|
|||||||
if (data.sttpCode == 'ENG') {
|
if (data.sttpCode == 'ENG') {
|
||||||
data.sttp = data.sttpCode;
|
data.sttp = data.sttpCode;
|
||||||
}
|
}
|
||||||
if (data.sttp && data.sttp.includes('_')) {
|
if (
|
||||||
|
data.sttp &&
|
||||||
|
data.sttp.includes('_') &&
|
||||||
|
!data.sttp.startsWith('AI_')
|
||||||
|
) {
|
||||||
const code = data.sttp.split('_')[0];
|
const code = data.sttp.split('_')[0];
|
||||||
formDiv.value = moduleMap[code + 'Info'] || null;
|
formDiv.value = moduleMap[code + 'Info'] || null;
|
||||||
// debugger
|
// debugger
|
||||||
} else {
|
} else {
|
||||||
// 处理没有下划线的情况
|
// AI_开头和没有下划线的情况,直接用完整 sttp 匹配
|
||||||
formDiv.value = moduleMap[data.sttp + 'Info'];
|
formDiv.value = moduleMap[data.sttp + 'Info'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,509 @@
|
|||||||
|
<template>
|
||||||
|
<SidePanelItem title="监测数据" :shrink="false">
|
||||||
|
<template #title-right-content>
|
||||||
|
<a-range-picker
|
||||||
|
class="w-[220px]"
|
||||||
|
v-model:value="dateRange"
|
||||||
|
format="YYYY-MM-DD"
|
||||||
|
:show-time="showTimeConfig"
|
||||||
|
:allow-clear="false"
|
||||||
|
:presets="DateSetting.RangeButton.month1"
|
||||||
|
:disabled-date="disabledDate"
|
||||||
|
size="small"
|
||||||
|
@change="handleSearch"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<a-spin :spinning="loading" tip="加载中...">
|
||||||
|
<a-carousel
|
||||||
|
v-if="mediaList.length > 0"
|
||||||
|
ref="carouselRef"
|
||||||
|
arrows
|
||||||
|
class="media-carousel"
|
||||||
|
@beforeChange="onBeforeSlideChange"
|
||||||
|
@afterChange="onAfterSlideChange"
|
||||||
|
>
|
||||||
|
<template #prevArrow>
|
||||||
|
<div class="custom-slick-arrow" style="left: 10px; z-index: 1">
|
||||||
|
<left-circle-outlined />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #nextArrow>
|
||||||
|
<div class="custom-slick-arrow" style="right: 10px">
|
||||||
|
<right-circle-outlined />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div v-for="(item, index) in mediaList" :key="index" class="slide">
|
||||||
|
<div class="media-wrapper">
|
||||||
|
<a-image
|
||||||
|
v-if="item.imageUrl"
|
||||||
|
:src="item.imageUrl"
|
||||||
|
class="media-image"
|
||||||
|
:preview="{
|
||||||
|
visible: previewVisible === index,
|
||||||
|
onVisibleChange: (v: boolean) => {
|
||||||
|
previewVisible = v ? index : -1;
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
@click="previewVisible = index"
|
||||||
|
/>
|
||||||
|
<!-- 视频:仅挂载当前活跃项,其余显示占位,避免多个视频同时拉流/一起报错重试导致卡顿 -->
|
||||||
|
<LiveVideoBox
|
||||||
|
v-else-if="item.videoUrl && index === activeIndex"
|
||||||
|
:videoData="{ url: item.videoUrl }"
|
||||||
|
:showTitle="false"
|
||||||
|
height="100%"
|
||||||
|
/>
|
||||||
|
<div v-else-if="item.videoUrl" class="video-placeholder">
|
||||||
|
<i class="iconfont icon-jiankong"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="media-overlay">
|
||||||
|
<span class="overlay-time">{{ item.tm }}</span>
|
||||||
|
<a-button
|
||||||
|
type="primary"
|
||||||
|
class="overlay-btn"
|
||||||
|
size="small"
|
||||||
|
@click="handleDetail(item)"
|
||||||
|
>
|
||||||
|
详细信息
|
||||||
|
</a-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a-carousel>
|
||||||
|
<a-empty v-else description="暂无数据" />
|
||||||
|
</a-spin>
|
||||||
|
</SidePanelItem>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import dayjs, { Dayjs } from 'dayjs';
|
||||||
|
import { ref, watch, nextTick } from 'vue';
|
||||||
|
import { useModelStore } from '@/store/modules/model';
|
||||||
|
import SidePanelItem from '@/components/SidePanelItem/index.vue';
|
||||||
|
import { DateSetting } from '@/utils/enumeration';
|
||||||
|
import {
|
||||||
|
getAnimalList,
|
||||||
|
getWarningList,
|
||||||
|
getFishList,
|
||||||
|
getIdUrl
|
||||||
|
} from '@/api/mapModal';
|
||||||
|
import LiveVideoBox from '@/views/shiPinJianKong/components/LiveVideoBox.vue';
|
||||||
|
import { LeftCircleOutlined, RightCircleOutlined } from '@ant-design/icons-vue';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
sttpValue: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const modelStore = useModelStore();
|
||||||
|
const baseUrl = import.meta.env.VITE_APP_ATTACHMENT_URL;
|
||||||
|
|
||||||
|
const loading = ref(false);
|
||||||
|
const mediaList = ref<
|
||||||
|
{ tm: string; imageUrl: string; videoUrl: string; raw: any }[]
|
||||||
|
>([]);
|
||||||
|
const previewVisible = ref(-1);
|
||||||
|
// 轮播当前活跃项(用于视频懒挂载,仅当前项真正初始化播放器)
|
||||||
|
const activeIndex = ref(0);
|
||||||
|
|
||||||
|
// ==================== 自动轮播控制 ====================
|
||||||
|
const carouselRef = ref<any>(null);
|
||||||
|
let slideTimer: ReturnType<typeof setTimeout> | null = null;
|
||||||
|
const SLIDE_INTERVAL_IMAGE = 5000;
|
||||||
|
const SLIDE_TIMEOUT_VIDEO_ERROR = 15000;
|
||||||
|
|
||||||
|
const clearSlideTimer = () => {
|
||||||
|
if (slideTimer !== null) {
|
||||||
|
clearTimeout(slideTimer);
|
||||||
|
slideTimer = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const advanceToNext = () => {
|
||||||
|
carouselRef.value?.next();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleVideoPlay = () => {
|
||||||
|
// 视频重试成功开始播放,取消错误兜底定时器
|
||||||
|
clearSlideTimer();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleVideoError = () => {
|
||||||
|
// 视频出错,开始兜底超时等待重试
|
||||||
|
clearSlideTimer();
|
||||||
|
slideTimer = setTimeout(advanceToNext, SLIDE_TIMEOUT_VIDEO_ERROR);
|
||||||
|
};
|
||||||
|
|
||||||
|
const setupAutoAdvance = () => {
|
||||||
|
clearSlideTimer();
|
||||||
|
if (mediaList.value.length <= 1) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const el = carouselRef.value?.$el;
|
||||||
|
if (!el) return;
|
||||||
|
const activeSlide = el.querySelector('.slick-active');
|
||||||
|
if (!activeSlide) return;
|
||||||
|
|
||||||
|
const video = activeSlide.querySelector('video.video-js');
|
||||||
|
if (video) {
|
||||||
|
// 视频:等待 ended 事件,出错时兜底超时
|
||||||
|
video.addEventListener('ended', advanceToNext);
|
||||||
|
video.addEventListener('play', handleVideoPlay);
|
||||||
|
video.addEventListener('error', handleVideoError);
|
||||||
|
} else {
|
||||||
|
// 图片:固定延时后前进
|
||||||
|
slideTimer = setTimeout(advanceToNext, SLIDE_INTERVAL_IMAGE);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const cleanupAutoAdvance = () => {
|
||||||
|
clearSlideTimer();
|
||||||
|
try {
|
||||||
|
const el = carouselRef.value?.$el;
|
||||||
|
if (el) {
|
||||||
|
const activeSlide = el.querySelector('.slick-active');
|
||||||
|
if (activeSlide) {
|
||||||
|
const video = activeSlide.querySelector('video');
|
||||||
|
if (video) {
|
||||||
|
video.removeEventListener('ended', advanceToNext);
|
||||||
|
video.removeEventListener('play', handleVideoPlay);
|
||||||
|
video.removeEventListener('error', handleVideoError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onBeforeSlideChange = (current: number, next: number) => {
|
||||||
|
cleanupAutoAdvance();
|
||||||
|
// 预挂载即将进入的项,避免切换瞬间视频占位闪烁
|
||||||
|
if (typeof next === 'number') {
|
||||||
|
activeIndex.value = next;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onAfterSlideChange = (current: number) => {
|
||||||
|
if (typeof current === 'number') {
|
||||||
|
activeIndex.value = current;
|
||||||
|
}
|
||||||
|
nextTick(setupAutoAdvance);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 数据变化时(重新查询)初始化首张幻灯片的自动轮播
|
||||||
|
watch(mediaList, newVal => {
|
||||||
|
if (newVal.length > 0) {
|
||||||
|
activeIndex.value = 0;
|
||||||
|
nextTick(setupAutoAdvance);
|
||||||
|
} else {
|
||||||
|
cleanupAutoAdvance();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// ==================== 时间选择器 ====================
|
||||||
|
const showTimeConfig = {
|
||||||
|
format: 'HH:mm',
|
||||||
|
hourStep: 1,
|
||||||
|
minuteStep: 5,
|
||||||
|
secondStep: 60
|
||||||
|
};
|
||||||
|
const disabledDate = (current: Dayjs) =>
|
||||||
|
current && current.isAfter(dayjs(), 'day');
|
||||||
|
|
||||||
|
const initDateRange = (): [Dayjs, Dayjs] => {
|
||||||
|
return [dayjs().subtract(1, 'month'), dayjs()];
|
||||||
|
};
|
||||||
|
const dateRange = ref<[Dayjs, Dayjs] | undefined>(initDateRange());
|
||||||
|
|
||||||
|
// 根据 sttpValue 选择对应接口
|
||||||
|
const getApiBySttp = () => {
|
||||||
|
const sttp = props.sttpValue;
|
||||||
|
if (sttp === 'AI_ANML' || sttp === 'AI_BIRD') return getAnimalList;
|
||||||
|
if (
|
||||||
|
sttp === 'AI_FISHING' ||
|
||||||
|
sttp === 'AI_RIV' ||
|
||||||
|
sttp === 'AI_5001' ||
|
||||||
|
sttp === 'AI_5005'
|
||||||
|
)
|
||||||
|
return getWarningList;
|
||||||
|
return getFishList;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 判断是否为 getWarningList 系列
|
||||||
|
const isWarningType = () => {
|
||||||
|
const sttp = props.sttpValue;
|
||||||
|
return (
|
||||||
|
sttp === 'AI_FISHING' ||
|
||||||
|
sttp === 'AI_RIV' ||
|
||||||
|
sttp === 'AI_5001' ||
|
||||||
|
sttp === 'AI_5005'
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 判断是否为 getAnimalList 系列
|
||||||
|
const isAnimalType = () => {
|
||||||
|
const sttp = props.sttpValue;
|
||||||
|
return sttp === 'AI_ANML' || sttp === 'AI_BIRD';
|
||||||
|
};
|
||||||
|
|
||||||
|
// 将 raw 数据转成统一 mediaItem 格式
|
||||||
|
const toMediaItem = (raw: any, imageUrl?: string, videoUrl?: string) => ({
|
||||||
|
tm: raw.tm ? dayjs(raw.tm).format('YYYY-MM-DD HH:mm:ss') : '-',
|
||||||
|
imageUrl: imageUrl || '',
|
||||||
|
videoUrl: videoUrl || '',
|
||||||
|
raw
|
||||||
|
});
|
||||||
|
|
||||||
|
// 获取数据
|
||||||
|
const fetchData = async () => {
|
||||||
|
const stcd = modelStore.selectedAnchorPoint?.stcd;
|
||||||
|
if (!dateRange.value || !stcd) return;
|
||||||
|
|
||||||
|
loading.value = true;
|
||||||
|
mediaList.value = [];
|
||||||
|
previewVisible.value = -1;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const api = getApiBySttp();
|
||||||
|
const params = {
|
||||||
|
filter: {
|
||||||
|
logic: 'and',
|
||||||
|
filters: [
|
||||||
|
{ field: 'stcd', operator: 'eq', dataType: 'string', value: stcd },
|
||||||
|
{
|
||||||
|
field: 'tm',
|
||||||
|
operator: 'gte',
|
||||||
|
dataType: 'date',
|
||||||
|
value: dateRange.value[0].format('YYYY-MM-DD HH:mm:ss')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'tm',
|
||||||
|
operator: 'lte',
|
||||||
|
dataType: 'date',
|
||||||
|
value: dateRange.value[1].format('YYYY-MM-DD HH:mm:ss')
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
sort: [{ field: 'tm', dir: 'asc' }]
|
||||||
|
};
|
||||||
|
const res = await api(params);
|
||||||
|
const rawData = res?.data?.data || res?.data?.records || [];
|
||||||
|
|
||||||
|
if (isWarningType()) {
|
||||||
|
// getWarningList:fid 需要调用 getIdUrl 解析
|
||||||
|
const fids = rawData.map((item: any) => item.fid).filter(Boolean);
|
||||||
|
if (fids.length === 0) {
|
||||||
|
mediaList.value = rawData.map((item: any) => toMediaItem(item));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const idRes: any = await getIdUrl({ id: fids.join(',') });
|
||||||
|
const urlMap = idRes?.data || {};
|
||||||
|
|
||||||
|
mediaList.value = rawData.flatMap((item: any) => {
|
||||||
|
const fidStr = item.fid;
|
||||||
|
if (!fidStr) return [toMediaItem(item)];
|
||||||
|
|
||||||
|
// fid 可能包含多个逗号分隔的 ID,拆分为多个媒体项
|
||||||
|
const fidList = String(fidStr).split(',').filter(Boolean);
|
||||||
|
if (fidList.length === 0) return [toMediaItem(item)];
|
||||||
|
|
||||||
|
return fidList.map((fid: string) => {
|
||||||
|
const fidKey = fid.trim();
|
||||||
|
const fileInfo = urlMap[fidKey];
|
||||||
|
if (!fileInfo) return toMediaItem(item);
|
||||||
|
|
||||||
|
const ext = String(fileInfo.ext || '').toLowerCase();
|
||||||
|
const isImage = [
|
||||||
|
'.jpg',
|
||||||
|
'.jpeg',
|
||||||
|
'.png',
|
||||||
|
'.gif',
|
||||||
|
'.webp',
|
||||||
|
'.bmp'
|
||||||
|
].includes(ext);
|
||||||
|
const isVideo = ['.mp4', '.mov', '.avi', '.wmv', '.m3u8'].includes(
|
||||||
|
ext
|
||||||
|
);
|
||||||
|
const fullpath = fidKey ? `${baseUrl}/?${fidKey}` : '';
|
||||||
|
|
||||||
|
return toMediaItem(
|
||||||
|
item,
|
||||||
|
isImage ? fullpath : '',
|
||||||
|
isVideo ? fullpath : ''
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else if (isAnimalType()) {
|
||||||
|
// getAnimalList:imgPath(图片), flpth(视频)
|
||||||
|
mediaList.value = rawData.map((item: any) => {
|
||||||
|
const imgPath = item.imgPath || '';
|
||||||
|
const flpth = item.flpth || '';
|
||||||
|
const imageUrl = imgPath
|
||||||
|
? imgPath.startsWith('http')
|
||||||
|
? imgPath
|
||||||
|
: `${baseUrl}/?${imgPath}`
|
||||||
|
: '';
|
||||||
|
const videoUrl = flpth
|
||||||
|
? flpth.startsWith('http')
|
||||||
|
? flpth
|
||||||
|
: `${baseUrl}/?${flpth}`
|
||||||
|
: '';
|
||||||
|
return toMediaItem(item, imageUrl, videoUrl);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// getFishList:firstimgurl(图片), videourl(视频)
|
||||||
|
mediaList.value = rawData.map((item: any) => {
|
||||||
|
const firstimgurl = item.firstimgurl || '';
|
||||||
|
const videourl = item.videourl || '';
|
||||||
|
const imageUrl = firstimgurl
|
||||||
|
? firstimgurl.startsWith('http')
|
||||||
|
? firstimgurl
|
||||||
|
: `${baseUrl}/?${firstimgurl}`
|
||||||
|
: '';
|
||||||
|
const videoUrl = videourl
|
||||||
|
? videourl.startsWith('http')
|
||||||
|
? videourl
|
||||||
|
: `${baseUrl}/?${videourl}`
|
||||||
|
: '';
|
||||||
|
return toMediaItem(item, imageUrl, videoUrl);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取数据失败:', error);
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 详情按钮占位(先预留)
|
||||||
|
const handleDetail = (item: any) => {
|
||||||
|
console.log('详情', item);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 时间选择器 change 触发查询
|
||||||
|
const handleSearch = () => fetchData();
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => modelStore.selectedAnchorPoint?.stcd,
|
||||||
|
(newStcd, oldStcd) => {
|
||||||
|
if (!newStcd) return;
|
||||||
|
if (newStcd !== oldStcd) {
|
||||||
|
dateRange.value = initDateRange();
|
||||||
|
fetchData();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
// 全局时间范围变化时同步本地日期选择器
|
||||||
|
watch(
|
||||||
|
() => modelStore.filter.rangeTm,
|
||||||
|
newRange => {
|
||||||
|
if (Array.isArray(newRange) && newRange.length > 0) {
|
||||||
|
dateRange.value = [dayjs(newRange[0]), dayjs(newRange[1])];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ deep: true }
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.media-carousel {
|
||||||
|
width: 400px;
|
||||||
|
height: 250px;
|
||||||
|
|
||||||
|
:deep(.slick-slide) {
|
||||||
|
height: 250px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.slick-slide > div) {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.slick-arrow.custom-slick-arrow) {
|
||||||
|
width: 25px;
|
||||||
|
height: 25px;
|
||||||
|
font-size: 25px;
|
||||||
|
color: #fff;
|
||||||
|
transition: ease all 0.3s;
|
||||||
|
opacity: 0.5;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.slick-arrow.custom-slick-arrow:before) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.slick-arrow.custom-slick-arrow:hover) {
|
||||||
|
color: #fff;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide {
|
||||||
|
position: relative;
|
||||||
|
height: 250px;
|
||||||
|
background: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-placeholder {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background: #000;
|
||||||
|
color: #666;
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: 48px;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.media-wrapper {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
.media-image {
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 100%;
|
||||||
|
object-fit: contain;
|
||||||
|
cursor: zoom-in;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.media-overlay {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
height: 36px;
|
||||||
|
background: rgba(0, 0, 0, 0.5);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 0 12px;
|
||||||
|
z-index: 10;
|
||||||
|
|
||||||
|
.overlay-time {
|
||||||
|
color: #fff;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.overlay-btn {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -26,12 +26,19 @@
|
|||||||
<FlowDischarge v-if="sttpValue == 'EQ'" />
|
<FlowDischarge v-if="sttpValue == 'EQ'" />
|
||||||
<!-- 鱼类增殖站 -->
|
<!-- 鱼类增殖站 -->
|
||||||
<NormalOperationData v-if="sttpValue == 'FB'" />
|
<NormalOperationData v-if="sttpValue == 'FB'" />
|
||||||
|
<!-- 智慧装备 -->
|
||||||
|
<SmartEquipment
|
||||||
|
:sttpValue="sttpValue"
|
||||||
|
v-if="SmartEquipmentCodes.includes(sttpValue)"
|
||||||
|
/>
|
||||||
<!-- 实时视频 -->
|
<!-- 实时视频 -->
|
||||||
<VideoInfo
|
<VideoInfo
|
||||||
title="实时视频"
|
title="实时视频"
|
||||||
placeholder="请选择视频"
|
placeholder="请选择视频"
|
||||||
v-if="sttpValue == 'FB'"
|
v-if="sttpValue == 'FB' || SmartEquipmentCodes.includes(sttpValue)"
|
||||||
/>
|
/>
|
||||||
|
<!-- 监测数据 -->
|
||||||
|
<MonitorData v-if="sttpValue == 'WE'" />
|
||||||
|
|
||||||
<!-- 生态调查 -->
|
<!-- 生态调查 -->
|
||||||
<!-- <WaterTemperature v-if="sttpValue == 'WE'" /> -->
|
<!-- <WaterTemperature v-if="sttpValue == 'WE'" /> -->
|
||||||
@ -54,10 +61,24 @@ import Animal from '@/modules/rightSearchDrawer/monitoringTable/components/Anima
|
|||||||
import FlowDischarge from '@/modules/rightSearchDrawer/monitoringTable/components/FlowDischarge.vue';
|
import FlowDischarge from '@/modules/rightSearchDrawer/monitoringTable/components/FlowDischarge.vue';
|
||||||
import NormalOperationData from '@/modules/rightSearchDrawer/monitoringTable/components/NormalOperationData.vue';
|
import NormalOperationData from '@/modules/rightSearchDrawer/monitoringTable/components/NormalOperationData.vue';
|
||||||
import VideoInfo from '@/modules/rightSearchDrawer/monitoringTable/components/VideoInfo.vue';
|
import VideoInfo from '@/modules/rightSearchDrawer/monitoringTable/components/VideoInfo.vue';
|
||||||
|
import SmartEquipment from '@/modules/rightSearchDrawer/monitoringTable/components/SmartEquipment.vue';
|
||||||
|
import MonitorData from '@/modules/rightSearchDrawer/speciesIntro/monitorData.vue';
|
||||||
|
|
||||||
const modelStore = useModelStore();
|
const modelStore = useModelStore();
|
||||||
const sttpValue = ref('');
|
const sttpValue = ref('');
|
||||||
|
|
||||||
|
// 智慧装备 - sttpCode
|
||||||
|
const SmartEquipmentCodes = [
|
||||||
|
'AI_FISH',
|
||||||
|
'AI_ANML',
|
||||||
|
'AI_BIRD',
|
||||||
|
'AI_RIV',
|
||||||
|
'AI_FISHING',
|
||||||
|
'AI_5001',
|
||||||
|
'AI_5005',
|
||||||
|
'AI_SORTER',
|
||||||
|
'FPRD'
|
||||||
|
];
|
||||||
// 选中点位变化时刷新;初始已有点位时立即加载
|
// 选中点位变化时刷新;初始已有点位时立即加载
|
||||||
watch(
|
watch(
|
||||||
() => modelStore.selectedAnchorPoint,
|
() => modelStore.selectedAnchorPoint,
|
||||||
|
|||||||
257
frontend/src/modules/rightSearchDrawer/speciesIntro/fish.vue
Normal file
@ -0,0 +1,257 @@
|
|||||||
|
<template>
|
||||||
|
<SidePanelItem :title="panelTitle" :shrink="false">
|
||||||
|
<template #title-right-content>
|
||||||
|
<a-select
|
||||||
|
v-model:value="currentValue"
|
||||||
|
size="small"
|
||||||
|
style="width: 110px"
|
||||||
|
placeholder="请选择"
|
||||||
|
:options="speciesOptions"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<a-empty v-if="!currentValue" description="请先在上方选择物种" />
|
||||||
|
<a-spin v-else :spinning="loading" class="species-spin">
|
||||||
|
<div class="species-card">
|
||||||
|
<!-- 上方:图片轮播 -->
|
||||||
|
<div
|
||||||
|
class="species-image"
|
||||||
|
v-if="currentSpeciesData.imageList.length > 0"
|
||||||
|
>
|
||||||
|
<a-carousel
|
||||||
|
arrows
|
||||||
|
v-if="currentSpeciesData.imageList.length > 1"
|
||||||
|
class="species-carousel"
|
||||||
|
>
|
||||||
|
<template #prevArrow>
|
||||||
|
<div class="custom-slick-arrow" style="left: 10px; z-index: 1">
|
||||||
|
<left-circle-outlined />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #nextArrow>
|
||||||
|
<div class="custom-slick-arrow" style="right: 10px">
|
||||||
|
<right-circle-outlined />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div
|
||||||
|
v-for="(img, index) in currentSpeciesData.imageList"
|
||||||
|
:key="index"
|
||||||
|
>
|
||||||
|
<a-image :src="img" height="300px" class="species-image-img" />
|
||||||
|
</div>
|
||||||
|
</a-carousel>
|
||||||
|
</div>
|
||||||
|
<div v-else class="species-image species-image--empty">
|
||||||
|
<span>暂无图片</span>
|
||||||
|
</div>
|
||||||
|
<!-- 下方:文字描述 -->
|
||||||
|
<div class="species-info">
|
||||||
|
<div class="species-name">
|
||||||
|
{{ currentSpeciesData.name || currentLabel }}
|
||||||
|
</div>
|
||||||
|
<div class="species-desc">
|
||||||
|
{{ currentSpeciesData.shapedesc || '暂无描述' }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a-spin>
|
||||||
|
</SidePanelItem>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { computed, ref, watch } from 'vue';
|
||||||
|
import { useRoute } from 'vue-router';
|
||||||
|
import { useModelStore } from '@/store/modules/model';
|
||||||
|
import SidePanelItem from '@/components/SidePanelItem/index.vue';
|
||||||
|
import { getFishResourceZYList } from '@/api/DataQueryMenuModule';
|
||||||
|
import { LeftCircleOutlined, RightCircleOutlined } from '@ant-design/icons-vue';
|
||||||
|
|
||||||
|
const modelStore = useModelStore();
|
||||||
|
const route = useRoute();
|
||||||
|
const baseUrl = import.meta.env.VITE_APP_ATTACHMENT_URL;
|
||||||
|
|
||||||
|
// 面板标题:根据当前菜单展示对应介绍(水生→鱼类,陆生→动物)
|
||||||
|
const panelTitle = computed(() => {
|
||||||
|
if (route.path.includes('shengTaiDiaoCha/shuiShengShengTaiDiaoCha')) {
|
||||||
|
return '鱼类介绍';
|
||||||
|
}
|
||||||
|
if (route.path.includes('shengTaiDiaoCha/luShengShengTaiDiaoCha')) {
|
||||||
|
return '动物介绍';
|
||||||
|
}
|
||||||
|
return '物种介绍';
|
||||||
|
});
|
||||||
|
|
||||||
|
// 右上角下拉框选项 = 上方多选框已选中的物种
|
||||||
|
const speciesOptions = computed(() =>
|
||||||
|
(modelStore.selectedFishSpecies || []).map(item => ({
|
||||||
|
label: item.label,
|
||||||
|
value: item.value
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
|
||||||
|
const currentValue = ref<string | undefined>();
|
||||||
|
const loading = ref(false);
|
||||||
|
const currentSpeciesData = ref<{
|
||||||
|
name: string;
|
||||||
|
imageList: string[];
|
||||||
|
shapedesc: string;
|
||||||
|
}>({
|
||||||
|
name: '',
|
||||||
|
imageList: [],
|
||||||
|
shapedesc: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
// 当前选中的物种 label(下拉框未命中时兜底显示)
|
||||||
|
const currentLabel = computed(() => {
|
||||||
|
const matched = speciesOptions.value.find(
|
||||||
|
item => item.value === currentValue.value
|
||||||
|
);
|
||||||
|
return matched?.label || '';
|
||||||
|
});
|
||||||
|
|
||||||
|
// 请求物种详情数据
|
||||||
|
const fetchSpeciesData = async (ftp: string) => {
|
||||||
|
if (!ftp) return;
|
||||||
|
loading.value = true;
|
||||||
|
try {
|
||||||
|
const res = await getFishResourceZYList({
|
||||||
|
filter: {
|
||||||
|
logic: 'and',
|
||||||
|
filters: [
|
||||||
|
{ field: 'id', operator: 'eq', dataType: 'string', value: ftp }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const data = res?.data?.data?.[0];
|
||||||
|
if (data) {
|
||||||
|
let imageList: string[] = [];
|
||||||
|
if (data.inffile && data.inffile !== '-') {
|
||||||
|
imageList = data.inffile
|
||||||
|
.split(',')
|
||||||
|
.map((item: string) => item.trim())
|
||||||
|
.filter((item: string) => item && item !== '-' && item.length > 0)
|
||||||
|
.map((item: string) => `${baseUrl}/?${item}&view=jpg`);
|
||||||
|
}
|
||||||
|
currentSpeciesData.value = {
|
||||||
|
name: data.name || '',
|
||||||
|
imageList,
|
||||||
|
shapedesc: data.shapedesc || ''
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
currentSpeciesData.value = { name: '', imageList: [], shapedesc: '' };
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
currentSpeciesData.value = { name: '', imageList: [], shapedesc: '' };
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 已选物种列表变化时:保持当前选中不变,仅当不在列表中才切换到第一条
|
||||||
|
watch(
|
||||||
|
() => modelStore.selectedFishSpecies,
|
||||||
|
list => {
|
||||||
|
const items = list || [];
|
||||||
|
// 当前值仍在列表中,不做任何操作
|
||||||
|
if (
|
||||||
|
currentValue.value &&
|
||||||
|
items.some(item => item.value === currentValue.value)
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 当前值不在列表中,切换到第一条
|
||||||
|
const firstValue = items[0]?.value;
|
||||||
|
currentValue.value = firstValue;
|
||||||
|
if (firstValue) {
|
||||||
|
fetchSpeciesData(firstValue);
|
||||||
|
} else {
|
||||||
|
currentSpeciesData.value = { name: '', imageList: [], shapedesc: '' };
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true, deep: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
// 下拉框切换时重新请求数据
|
||||||
|
watch(currentValue, (newVal, oldVal) => {
|
||||||
|
if (newVal && newVal !== oldVal) {
|
||||||
|
fetchSpeciesData(newVal);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.species-spin {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.species-card {
|
||||||
|
border: 1px solid #e5edf3;
|
||||||
|
border-radius: 4px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.species-image {
|
||||||
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
background: #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.species-image--empty {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
color: #bfbfbf;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.species-carousel {
|
||||||
|
height: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.species-image-img {
|
||||||
|
width: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.species-info {
|
||||||
|
padding: 10px 12px 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.species-name {
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #2f6b98;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.species-desc {
|
||||||
|
font-size: 13px;
|
||||||
|
line-height: 22px;
|
||||||
|
color: #595959;
|
||||||
|
word-break: break-all;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.slick-slide) {
|
||||||
|
text-align: center;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.slick-arrow.custom-slick-arrow) {
|
||||||
|
width: 25px;
|
||||||
|
height: 25px;
|
||||||
|
font-size: 25px;
|
||||||
|
color: #fff;
|
||||||
|
transition: ease all 0.3s;
|
||||||
|
opacity: 0.5;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.slick-arrow.custom-slick-arrow:before) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.slick-arrow.custom-slick-arrow:hover) {
|
||||||
|
color: #fff;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -1,128 +1,13 @@
|
|||||||
<!--
|
|
||||||
物种介绍(动物/植物介绍)面板:
|
|
||||||
- 面板标题根据当前生态调查菜单动态展示(水生生态调查→鱼类介绍,陆生生态调查→动物介绍)
|
|
||||||
- 右上角下拉框(title-right-content 插槽)选项为上方鱼种/动物种多选框已选中的数据,默认展示第一条
|
|
||||||
- 主体区域只展示当前选中物种:上方图片、下方文字描述
|
|
||||||
- 数据来自 modelStore.selectedFishSpecies(预留 image / intro 字段,后续对接真实数据)
|
|
||||||
-->
|
|
||||||
<template>
|
<template>
|
||||||
<SidePanelItem :title="panelTitle" :shrink="false">
|
<div>
|
||||||
<template #title-right-content>
|
<Fish />
|
||||||
<a-select
|
<MonitorData />
|
||||||
v-model:value="currentValue"
|
</div>
|
||||||
size="small"
|
|
||||||
style="width: 110px"
|
|
||||||
placeholder="请选择"
|
|
||||||
:options="speciesOptions"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
<a-empty v-if="!currentSpecies" description="请先在上方选择物种" />
|
|
||||||
<div v-else class="species-card">
|
|
||||||
<!-- 上方:图片 -->
|
|
||||||
<a-image
|
|
||||||
v-if="currentSpecies.image"
|
|
||||||
class="species-image"
|
|
||||||
:src="currentSpecies.image"
|
|
||||||
:preview="false"
|
|
||||||
/>
|
|
||||||
<div v-else class="species-image species-image--empty">
|
|
||||||
<span>暂无图片</span>
|
|
||||||
</div>
|
|
||||||
<!-- 下方:文字描述 -->
|
|
||||||
<div class="species-info">
|
|
||||||
<div class="species-name">{{ currentSpecies.label }}</div>
|
|
||||||
<div class="species-desc">
|
|
||||||
{{ currentSpecies.intro || '暂无描述' }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</SidePanelItem>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, ref, watch } from 'vue';
|
import Fish from '@/modules/rightSearchDrawer/speciesIntro/fish.vue';
|
||||||
import { useRoute } from 'vue-router';
|
import MonitorData from '@/modules/rightSearchDrawer/speciesIntro/monitorData.vue';
|
||||||
import { useModelStore } from '@/store/modules/model';
|
|
||||||
import SidePanelItem from '@/components/SidePanelItem/index.vue';
|
|
||||||
|
|
||||||
const modelStore = useModelStore();
|
|
||||||
const route = useRoute();
|
|
||||||
|
|
||||||
// 面板标题:根据当前菜单展示对应介绍(水生→鱼类,陆生→动物)
|
|
||||||
const panelTitle = computed(() => {
|
|
||||||
if (route.path.includes('shengTaiDiaoCha/shuiShengShengTaiDiaoCha')) {
|
|
||||||
return '鱼类介绍';
|
|
||||||
}
|
|
||||||
if (route.path.includes('shengTaiDiaoCha/luShengShengTaiDiaoCha')) {
|
|
||||||
return '动物介绍';
|
|
||||||
}
|
|
||||||
return '物种介绍';
|
|
||||||
});
|
|
||||||
|
|
||||||
// 右上角下拉框选项 = 上方多选框已选中的物种
|
|
||||||
const speciesOptions = computed(() =>
|
|
||||||
(modelStore.selectedFishSpecies || []).map(item => ({
|
|
||||||
label: item.label,
|
|
||||||
value: item.value
|
|
||||||
}))
|
|
||||||
);
|
|
||||||
|
|
||||||
const currentValue = ref<string | undefined>();
|
|
||||||
|
|
||||||
// 当前展示的物种(默认第一条)
|
|
||||||
const currentSpecies = computed(() =>
|
|
||||||
speciesOptions.value.find(item => item.value === currentValue.value)
|
|
||||||
);
|
|
||||||
|
|
||||||
// 已选物种变化时,默认选中第一条
|
|
||||||
watch(
|
|
||||||
() => modelStore.selectedFishSpecies,
|
|
||||||
list => {
|
|
||||||
currentValue.value = (list || [])[0]?.value;
|
|
||||||
},
|
|
||||||
{ immediate: true, deep: true }
|
|
||||||
);
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped></style>
|
||||||
.species-card {
|
|
||||||
border: 1px solid #e5edf3;
|
|
||||||
border-radius: 4px;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.species-image {
|
|
||||||
display: block;
|
|
||||||
width: 100%;
|
|
||||||
height: 200px;
|
|
||||||
object-fit: cover;
|
|
||||||
background: #f5f5f5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.species-image--empty {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
color: #bfbfbf;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.species-info {
|
|
||||||
padding: 10px 12px 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.species-name {
|
|
||||||
font-size: 15px;
|
|
||||||
font-weight: 500;
|
|
||||||
color: #2f6b98;
|
|
||||||
margin-bottom: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.species-desc {
|
|
||||||
font-size: 13px;
|
|
||||||
line-height: 22px;
|
|
||||||
color: #595959;
|
|
||||||
word-break: break-all;
|
|
||||||
white-space: pre-wrap;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
@ -0,0 +1,236 @@
|
|||||||
|
<template>
|
||||||
|
<SidePanelItem title="监测数据" :shrink="false">
|
||||||
|
<template #title-right-content>
|
||||||
|
<a-select
|
||||||
|
v-model:value="currentValue"
|
||||||
|
size="small"
|
||||||
|
style="width: 80px"
|
||||||
|
placeholder="请选择"
|
||||||
|
:options="speciesOptions"
|
||||||
|
/>
|
||||||
|
<a-select
|
||||||
|
v-model:value="currentValue"
|
||||||
|
size="small"
|
||||||
|
style="width: 80px"
|
||||||
|
placeholder="请选择"
|
||||||
|
:options="speciesOptions"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<a-date-picker
|
||||||
|
class="w-[70px]"
|
||||||
|
v-model:value="dateRange"
|
||||||
|
picker="year"
|
||||||
|
format="YYYY"
|
||||||
|
value-format="YYYY"
|
||||||
|
:allowClear="false"
|
||||||
|
size="small"
|
||||||
|
@change="handleSearch"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<div class="w-full h-[300px] bg-[#00000050]"></div>
|
||||||
|
</SidePanelItem>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
import { computed, ref, watch } from 'vue';
|
||||||
|
import { useRoute } from 'vue-router';
|
||||||
|
import { useModelStore } from '@/store/modules/model';
|
||||||
|
import SidePanelItem from '@/components/SidePanelItem/index.vue';
|
||||||
|
import { getFishResourceZYList } from '@/api/DataQueryMenuModule';
|
||||||
|
import { LeftCircleOutlined, RightCircleOutlined } from '@ant-design/icons-vue';
|
||||||
|
|
||||||
|
const modelStore = useModelStore();
|
||||||
|
const route = useRoute();
|
||||||
|
const baseUrl = import.meta.env.VITE_APP_ATTACHMENT_URL;
|
||||||
|
|
||||||
|
const dateRange = ref('');
|
||||||
|
|
||||||
|
// 面板标题:根据当前菜单展示对应介绍(水生→鱼类,陆生→动物)
|
||||||
|
const panelTitle = computed(() => {
|
||||||
|
if (route.path.includes('shengTaiDiaoCha/shuiShengShengTaiDiaoCha')) {
|
||||||
|
return '鱼类介绍';
|
||||||
|
}
|
||||||
|
if (route.path.includes('shengTaiDiaoCha/luShengShengTaiDiaoCha')) {
|
||||||
|
return '动物介绍';
|
||||||
|
}
|
||||||
|
return '物种介绍';
|
||||||
|
});
|
||||||
|
|
||||||
|
// 右上角下拉框选项 = 上方多选框已选中的物种
|
||||||
|
const speciesOptions = computed(() =>
|
||||||
|
(modelStore.selectedFishSpecies || []).map(item => ({
|
||||||
|
label: item.label,
|
||||||
|
value: item.value
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
|
||||||
|
const currentValue = ref<string | undefined>();
|
||||||
|
const loading = ref(false);
|
||||||
|
const currentSpeciesData = ref<{
|
||||||
|
name: string;
|
||||||
|
imageList: string[];
|
||||||
|
shapedesc: string;
|
||||||
|
}>({
|
||||||
|
name: '',
|
||||||
|
imageList: [],
|
||||||
|
shapedesc: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
// 当前选中的物种 label(下拉框未命中时兜底显示)
|
||||||
|
const currentLabel = computed(() => {
|
||||||
|
const matched = speciesOptions.value.find(
|
||||||
|
item => item.value === currentValue.value
|
||||||
|
);
|
||||||
|
return matched?.label || '';
|
||||||
|
});
|
||||||
|
const handleSearch = () => {
|
||||||
|
console.log(dateRange.value);
|
||||||
|
};
|
||||||
|
// 请求物种详情数据
|
||||||
|
const fetchSpeciesData = async (ftp: string) => {
|
||||||
|
if (!ftp) return;
|
||||||
|
loading.value = true;
|
||||||
|
try {
|
||||||
|
const res = await getFishResourceZYList({
|
||||||
|
filter: {
|
||||||
|
logic: 'and',
|
||||||
|
filters: [
|
||||||
|
{ field: 'id', operator: 'eq', dataType: 'string', value: ftp }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const data = res?.data?.data?.[0];
|
||||||
|
if (data) {
|
||||||
|
let imageList: string[] = [];
|
||||||
|
if (data.inffile && data.inffile !== '-') {
|
||||||
|
imageList = data.inffile
|
||||||
|
.split(',')
|
||||||
|
.map((item: string) => item.trim())
|
||||||
|
.filter((item: string) => item && item !== '-' && item.length > 0)
|
||||||
|
.map((item: string) => `${baseUrl}/?${item}&view=jpg`);
|
||||||
|
}
|
||||||
|
currentSpeciesData.value = {
|
||||||
|
name: data.name || '',
|
||||||
|
imageList,
|
||||||
|
shapedesc: data.shapedesc || ''
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
currentSpeciesData.value = { name: '', imageList: [], shapedesc: '' };
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
currentSpeciesData.value = { name: '', imageList: [], shapedesc: '' };
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 已选物种列表变化时:保持当前选中不变,仅当不在列表中才切换到第一条
|
||||||
|
watch(
|
||||||
|
() => modelStore.selectedFishSpecies,
|
||||||
|
list => {
|
||||||
|
const items = list || [];
|
||||||
|
// 当前值仍在列表中,不做任何操作
|
||||||
|
if (
|
||||||
|
currentValue.value &&
|
||||||
|
items.some(item => item.value === currentValue.value)
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 当前值不在列表中,切换到第一条
|
||||||
|
const firstValue = items[0]?.value;
|
||||||
|
currentValue.value = firstValue;
|
||||||
|
if (firstValue) {
|
||||||
|
fetchSpeciesData(firstValue);
|
||||||
|
} else {
|
||||||
|
currentSpeciesData.value = { name: '', imageList: [], shapedesc: '' };
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true, deep: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
// 下拉框切换时重新请求数据
|
||||||
|
watch(currentValue, (newVal, oldVal) => {
|
||||||
|
if (newVal && newVal !== oldVal) {
|
||||||
|
fetchSpeciesData(newVal);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.species-spin {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.species-card {
|
||||||
|
border: 1px solid #e5edf3;
|
||||||
|
border-radius: 4px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.species-image {
|
||||||
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
background: #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.species-image--empty {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
color: #bfbfbf;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.species-carousel {
|
||||||
|
height: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.species-image-img {
|
||||||
|
width: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.species-info {
|
||||||
|
padding: 10px 12px 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.species-name {
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #2f6b98;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.species-desc {
|
||||||
|
font-size: 13px;
|
||||||
|
line-height: 22px;
|
||||||
|
color: #595959;
|
||||||
|
word-break: break-all;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.slick-slide) {
|
||||||
|
text-align: center;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.slick-arrow.custom-slick-arrow) {
|
||||||
|
width: 25px;
|
||||||
|
height: 25px;
|
||||||
|
font-size: 25px;
|
||||||
|
color: #fff;
|
||||||
|
transition: ease all 0.3s;
|
||||||
|
opacity: 0.5;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.slick-arrow.custom-slick-arrow:before) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.slick-arrow.custom-slick-arrow:hover) {
|
||||||
|
color: #fff;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -469,12 +469,7 @@ const getselectTwo = async (code: any) => {
|
|||||||
dir: 'asc'
|
dir: 'asc'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
: [
|
: [],
|
||||||
{
|
|
||||||
field: 'ttpwr',
|
|
||||||
dir: 'desc'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
select: ['stcd', 'stnm']
|
select: ['stcd', 'stnm']
|
||||||
};
|
};
|
||||||
const res = await getVmsstbprpt(params);
|
const res = await getVmsstbprpt(params);
|
||||||
|
|||||||
@ -1,328 +1,356 @@
|
|||||||
<!-- SidePanelItem.vue -->
|
<!-- SidePanelItem.vue -->
|
||||||
<template>
|
<template>
|
||||||
<SidePanelItem title="水质监测工作开展情况">
|
<SidePanelItem title="水质监测工作开展情况">
|
||||||
<a-spin :spinning="loading" tip="加载中...">
|
<a-spin :spinning="loading" tip="加载中...">
|
||||||
<div class="facility-grid">
|
<div class="facility-grid">
|
||||||
<div v-for="facility in facilities" :key="facility.name" class="facility-card"
|
<div
|
||||||
@click="handleFacilityClick(facility)">
|
v-for="facility in facilities"
|
||||||
<div style="width: 60px;height: 62px;display: flex;align-items: center;justify-content: center;">
|
:key="facility.name"
|
||||||
<div class="facility-icon">
|
class="facility-card"
|
||||||
<i style="color: #fff;" :class="facility.icon" type="icon-shengtailiuliang2"></i>
|
@click="handleFacilityClick(facility)"
|
||||||
</div>
|
>
|
||||||
</div>
|
<div
|
||||||
|
style="
|
||||||
<div class="facility-info">
|
width: 60px;
|
||||||
<div class="facility-name">{{ facility.name }}</div>
|
height: 62px;
|
||||||
<div style="font-size: 16px;"> <span class="facility-count">{{ facility.count
|
display: flex;
|
||||||
}}</span><span>个</span></div>
|
align-items: center;
|
||||||
</div>
|
justify-content: center;
|
||||||
</div>
|
"
|
||||||
|
>
|
||||||
|
<div class="facility-icon">
|
||||||
|
<i
|
||||||
|
style="color: #fff"
|
||||||
|
:class="facility.icon"
|
||||||
|
type="icon-shengtailiuliang2"
|
||||||
|
></i>
|
||||||
</div>
|
</div>
|
||||||
</a-spin>
|
</div>
|
||||||
</SidePanelItem>
|
|
||||||
<!-- 弹框 -->
|
<div class="facility-info">
|
||||||
<a-modal v-model:open="modalVisible" :title="'水质监测工作开展情况'" :footer="null" width="1536px" @cancel="handleCloseModal">
|
<div class="facility-name">{{ facility.name }}</div>
|
||||||
<ShuiwenjiancegongzuoEJ v-if="currentFacility" :activeKey="currentFacility.key" :tabs="facilities"
|
<div style="font-size: 16px">
|
||||||
:baseId="baseid" />
|
<span class="facility-count">{{ facility.count }}</span
|
||||||
</a-modal>
|
><span>个</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a-spin>
|
||||||
|
</SidePanelItem>
|
||||||
|
<!-- 弹框 -->
|
||||||
|
<a-modal
|
||||||
|
v-model:open="modalVisible"
|
||||||
|
:title="'水质监测工作开展情况'"
|
||||||
|
:footer="null"
|
||||||
|
width="1536px"
|
||||||
|
@cancel="handleCloseModal"
|
||||||
|
>
|
||||||
|
<ShuiwenjiancegongzuoEJ
|
||||||
|
v-if="currentFacility"
|
||||||
|
:activeKey="currentFacility.key"
|
||||||
|
:tabs="facilities"
|
||||||
|
:baseId="baseid"
|
||||||
|
/>
|
||||||
|
</a-modal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, onMounted, watch } from 'vue';
|
import { ref, onMounted, watch } from 'vue';
|
||||||
import SidePanelItem from '@/components/SidePanelItem/index.vue';
|
import SidePanelItem from '@/components/SidePanelItem/index.vue';
|
||||||
import { useJidiSelectEventStore } from "@/store/modules/jidiSelectEvent";
|
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
||||||
import { msstbprptGetKendoList } from '@/api/sz'
|
import { msstbprptGetKendoList } from '@/api/sz';
|
||||||
import ShuiwenjiancegongzuoEJ from "./shuiwenjiancegongzuoEJ.vue"
|
import ShuiwenjiancegongzuoEJ from './shuiwenjiancegongzuoEJ.vue';
|
||||||
import { useDraggable } from '@/utils/drag';
|
import { useDraggable } from '@/utils/drag';
|
||||||
|
|
||||||
// 定义组件名(便于调试和递归)
|
// 定义组件名(便于调试和递归)
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'shuizhijiancegongzuoQK'
|
name: 'shuizhijiancegongzuoQK'
|
||||||
});
|
});
|
||||||
const JidiSelectEventStore = useJidiSelectEventStore();
|
const JidiSelectEventStore = useJidiSelectEventStore();
|
||||||
// loading状态
|
// loading状态
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
// 设施数据
|
// 设施数据
|
||||||
const facilities = ref([
|
const facilities = ref([
|
||||||
{
|
{
|
||||||
name: '河道水质站',
|
name: '河道水质站',
|
||||||
count: 0,
|
count: 0,
|
||||||
icon: 'icon iconfont icon-qixidi',
|
icon: 'icon iconfont icon-qixidi',
|
||||||
key: '0'
|
key: '0'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'icon iconfont icon-yuleizengzhizhan',
|
icon: 'icon iconfont icon-yuleizengzhizhan',
|
||||||
name: '增殖站水质站',
|
name: '增殖站水质站',
|
||||||
count: '0',
|
count: '0',
|
||||||
key: '3'
|
key: '3'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '国家水质站',
|
name: '国家水质站',
|
||||||
count: 0,
|
count: 0,
|
||||||
icon: 'icon iconfont icon-diwenshuijianhuan',
|
icon: 'icon iconfont icon-diwenshuijianhuan',
|
||||||
key: '1'
|
key: '1'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '人工水质监测断面',
|
name: '人工水质监测断面',
|
||||||
count: 0,
|
count: 0,
|
||||||
icon: 'icon iconfont icon-shuiwen-line',
|
icon: 'icon iconfont icon-shuiwen-line',
|
||||||
key: '2'
|
key: '2'
|
||||||
},
|
}
|
||||||
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// 弹框相关状态
|
// 弹框相关状态
|
||||||
const modalVisible = ref(false);
|
const modalVisible = ref(false);
|
||||||
const currentFacility = ref<any>(null);
|
const currentFacility = ref<any>(null);
|
||||||
const baseid = ref("")
|
const baseid = ref('');
|
||||||
|
|
||||||
useDraggable(modalVisible, { boundary: true, resetOnOpen: true });
|
useDraggable(modalVisible, { boundary: true, resetOnOpen: true });
|
||||||
//获取水质监测工作开展情况数据
|
//获取水质监测工作开展情况数据
|
||||||
const getDataList = async () => {
|
const getDataList = async () => {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
try {
|
try {
|
||||||
let data1 = {
|
let data1 = {
|
||||||
"filter": {
|
filter: {
|
||||||
"logic": "and",
|
logic: 'and',
|
||||||
"filters": [
|
filters: [
|
||||||
baseid.value != "all" ? {
|
baseid.value != 'all'
|
||||||
"field": "baseId",
|
? {
|
||||||
"operator": "eq",
|
field: 'baseId',
|
||||||
"dataType": "string",
|
operator: 'eq',
|
||||||
"value": baseid.value
|
dataType: 'string',
|
||||||
} : null,
|
value: baseid.value
|
||||||
{
|
}
|
||||||
"field": "isDeleted",
|
: null,
|
||||||
"operator": "eq",
|
{
|
||||||
"value": 0
|
field: 'isDeleted',
|
||||||
},
|
operator: 'eq',
|
||||||
{
|
value: 0
|
||||||
"field": "sttpCode",
|
},
|
||||||
"operator": "eq",
|
{
|
||||||
"value": "WQ"
|
field: 'sttpCode',
|
||||||
},
|
operator: 'eq',
|
||||||
{
|
value: 'WQ'
|
||||||
"logic": "or",
|
},
|
||||||
"filters": [
|
{
|
||||||
{
|
logic: 'or',
|
||||||
"logic": "and",
|
filters: [
|
||||||
"filters": [
|
{
|
||||||
{
|
logic: 'and',
|
||||||
"field": "mway",
|
filters: [
|
||||||
"operator": "eq",
|
{
|
||||||
"value": 2
|
field: 'mway',
|
||||||
},
|
operator: 'eq',
|
||||||
{
|
value: 2
|
||||||
"field": "dtinType",
|
},
|
||||||
"operator": "eq",
|
{
|
||||||
"value": 0
|
field: 'dtinType',
|
||||||
}
|
operator: 'eq',
|
||||||
]
|
value: 0
|
||||||
},
|
}
|
||||||
{
|
]
|
||||||
"logic": "and",
|
},
|
||||||
"filters": [
|
{
|
||||||
{
|
logic: 'and',
|
||||||
"field": "mway",
|
filters: [
|
||||||
"operator": "eq",
|
{
|
||||||
"value": 1
|
field: 'mway',
|
||||||
},
|
operator: 'eq',
|
||||||
{
|
value: 1
|
||||||
"field": "dtinType",
|
},
|
||||||
"operator": "eq",
|
{
|
||||||
"value": 2
|
field: 'dtinType',
|
||||||
}
|
operator: 'eq',
|
||||||
]
|
value: 2
|
||||||
},
|
}
|
||||||
{
|
]
|
||||||
"logic": "and",
|
},
|
||||||
"filters": [
|
{
|
||||||
{
|
logic: 'and',
|
||||||
"field": "mway",
|
filters: [
|
||||||
"operator": "eq",
|
{
|
||||||
"value": 2
|
field: 'mway',
|
||||||
},
|
operator: 'eq',
|
||||||
{
|
value: 2
|
||||||
"field": "dtinType",
|
},
|
||||||
"operator": "eq",
|
{
|
||||||
"value": 1
|
field: 'dtinType',
|
||||||
}
|
operator: 'eq',
|
||||||
]
|
value: 1
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
].filter(Boolean)
|
|
||||||
},
|
|
||||||
"group": [
|
|
||||||
{
|
|
||||||
"dir": "asc",
|
|
||||||
"field": "dtinType"
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
|
}
|
||||||
|
].filter(Boolean)
|
||||||
|
},
|
||||||
|
group: [
|
||||||
|
{
|
||||||
|
dir: 'asc',
|
||||||
|
field: 'dtinType'
|
||||||
}
|
}
|
||||||
let data2 = {
|
]
|
||||||
"filter": {
|
};
|
||||||
"logic": "and",
|
let data2 = {
|
||||||
"filters": [
|
filter: {
|
||||||
baseid.value != "all" ? {
|
logic: 'and',
|
||||||
"field": "baseId",
|
filters: [
|
||||||
"operator": "eq",
|
baseid.value != 'all'
|
||||||
"dataType": "string",
|
? {
|
||||||
"value": baseid.value
|
field: 'baseId',
|
||||||
} : null,
|
operator: 'eq',
|
||||||
{
|
dataType: 'string',
|
||||||
"field": "isDeleted",
|
value: baseid.value
|
||||||
"operator": "eq",
|
}
|
||||||
"value": 0
|
: null,
|
||||||
},
|
{
|
||||||
{
|
field: 'isDeleted',
|
||||||
"field": "sttpCode",
|
operator: 'eq',
|
||||||
"operator": "eq",
|
value: 0
|
||||||
"value": "WQFB"
|
},
|
||||||
},
|
{
|
||||||
{
|
field: 'sttpCode',
|
||||||
"filters": [
|
operator: 'eq',
|
||||||
{
|
value: 'WQFB'
|
||||||
"logic": "and",
|
},
|
||||||
"filters": [
|
{
|
||||||
{
|
filters: [
|
||||||
"field": "mway",
|
{
|
||||||
"operator": "eq",
|
logic: 'and',
|
||||||
"value": 2
|
filters: [
|
||||||
},
|
{
|
||||||
{
|
field: 'mway',
|
||||||
"field": "dtinType",
|
operator: 'eq',
|
||||||
"operator": "eq",
|
value: 2
|
||||||
"value": 0
|
},
|
||||||
}
|
{
|
||||||
]
|
field: 'dtinType',
|
||||||
}
|
operator: 'eq',
|
||||||
]
|
value: 0
|
||||||
}
|
}
|
||||||
].filter(Boolean)
|
]
|
||||||
},
|
}
|
||||||
"group": [
|
|
||||||
{
|
|
||||||
"dir": "asc",
|
|
||||||
"field": "dtinType"
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
|
}
|
||||||
|
].filter(Boolean)
|
||||||
|
},
|
||||||
|
group: [
|
||||||
|
{
|
||||||
|
dir: 'asc',
|
||||||
|
field: 'dtinType'
|
||||||
}
|
}
|
||||||
// const params = [data1, data2]
|
]
|
||||||
const res1 = await msstbprptGetKendoList(data1);
|
};
|
||||||
//
|
// const params = [data1, data2]
|
||||||
let finalData = facilities.value.map((item) => ({ ...item, count: 0 }))
|
const res1 = await msstbprptGetKendoList(data1);
|
||||||
if (res1.data) {
|
//
|
||||||
const { data } = res1
|
let finalData = facilities.value.map(item => ({ ...item, count: 0 }));
|
||||||
data.data.forEach((item: any, index: number) => {
|
if (res1.data) {
|
||||||
const target = finalData.find((n) => n.key == item.key)
|
const { data } = res1;
|
||||||
if (target) {
|
data.data.forEach((item: any, index: number) => {
|
||||||
target.count = item.count || 0
|
const target = finalData.find(n => n.key == item.key);
|
||||||
}
|
if (target) {
|
||||||
})
|
target.count = item.count || 0;
|
||||||
}
|
}
|
||||||
console.log(finalData)
|
});
|
||||||
// /
|
|
||||||
const res2 = await msstbprptGetKendoList(data2);
|
|
||||||
if (res2.data) {
|
|
||||||
const responseData = res2?.data?.data
|
|
||||||
const target1 = finalData.find((n) => n.key == '3')
|
|
||||||
if (target1) {
|
|
||||||
target1.count = responseData[0]?.count || 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
facilities.value = finalData
|
|
||||||
console.log(finalData)
|
|
||||||
//
|
|
||||||
} catch (error) {
|
|
||||||
console.error('获取数据失败:', error);
|
|
||||||
} finally {
|
|
||||||
loading.value = false;
|
|
||||||
}
|
}
|
||||||
}
|
console.log(finalData);
|
||||||
|
// /
|
||||||
|
const res2 = await msstbprptGetKendoList(data2);
|
||||||
|
if (res2.data) {
|
||||||
|
const responseData = res2?.data?.data;
|
||||||
|
const target1 = finalData.find(n => n.key == '3');
|
||||||
|
if (target1) {
|
||||||
|
target1.count = responseData[0]?.count || 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
facilities.value = finalData;
|
||||||
|
console.log(finalData);
|
||||||
|
//
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取数据失败:', error);
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
watch(
|
watch(
|
||||||
() => JidiSelectEventStore.selectedItem,
|
() => JidiSelectEventStore.selectedItem,
|
||||||
(newVal) => {
|
newVal => {
|
||||||
baseid.value = newVal.wbsCode;
|
baseid.value = newVal.wbsCode;
|
||||||
getDataList()
|
getDataList();
|
||||||
},
|
},
|
||||||
{ deep: true, immediate: true }
|
{ deep: true, immediate: true }
|
||||||
);
|
);
|
||||||
// 点击处理函数
|
// 点击处理函数
|
||||||
const handleFacilityClick = (facility: any) => {
|
const handleFacilityClick = (facility: any) => {
|
||||||
// console.log(facility);
|
// console.log(facility);
|
||||||
currentFacility.value = facility;
|
currentFacility.value = facility;
|
||||||
modalVisible.value = true;
|
modalVisible.value = true;
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
// 关闭弹框
|
// 关闭弹框
|
||||||
const handleCloseModal = () => {
|
const handleCloseModal = () => {
|
||||||
modalVisible.value = false;
|
modalVisible.value = false;
|
||||||
currentFacility.value = null;
|
currentFacility.value = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// 页面加载时执行的逻辑
|
// 页面加载时执行的逻辑
|
||||||
onMounted(() => {
|
onMounted(() => {});
|
||||||
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.facility-grid {
|
.facility-grid {
|
||||||
width: 406px;
|
width: 406px;
|
||||||
flex-flow: wrap;
|
flex-flow: wrap;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, Noto Sans, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;
|
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto,
|
||||||
|
Helvetica Neue, Arial, Noto Sans, sans-serif, Apple Color Emoji,
|
||||||
|
Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;
|
||||||
}
|
}
|
||||||
|
|
||||||
.facility-card {
|
.facility-card {
|
||||||
width: 200px;
|
width: 200px;
|
||||||
height: 70px;
|
height: 70px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
margin: 4px 0px;
|
margin: 4px 0px;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
border: 1px solid #e8e8e8;
|
border: 1px solid #e8e8e8;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
transition: all 0.3s;
|
transition: all 0.3s;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
.facility-icon {
|
.facility-icon {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
width: 40px;
|
width: 40px;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
// margin-right: 8px;
|
// margin-right: 8px;
|
||||||
background: #5389b5;
|
background: #2f6b98;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
|
|
||||||
.anticon {
|
.anticon {
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.facility-info {
|
.facility-info {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.facility-name {
|
.facility-name {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
color: #333;
|
color: #333;
|
||||||
// margin-bottom: 4px;
|
// margin-bottom: 4px;
|
||||||
// font-weight: 500;
|
// font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
.facility-count {
|
.facility-count {
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
color: #2f6b98;
|
color: #2f6b98;
|
||||||
// font-weight: 600;
|
// font-weight: 600;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@ -1,20 +1,18 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { onMounted, onUnmounted, ref } from 'vue';
|
import { onMounted, onUnmounted, ref, watch } from 'vue';
|
||||||
import { useUiStore } from '@/store/modules/ui';
|
import { useUiStore } from '@/store/modules/ui';
|
||||||
import JidiSelectorMod from '@/modules/jidiSelectorMod.vue';
|
import JidiSelectorMod from '@/modules/jidiSelectorMod.vue';
|
||||||
import RightDrawer from '@/components/RightDrawer/index.vue';
|
import RightDrawer from '@/components/RightDrawer/index.vue';
|
||||||
import EquipmentStatistics from '@/modules/EquipmentStatistics/index.vue'; //设备统计
|
import EquipmentStatistics from '@/modules/EquipmentStatistics/index.vue'; //设备统计
|
||||||
import BaseStatistics from '@/modules/BaseStatistics/index.vue'; //基础统计
|
import BaseStatistics from '@/modules/BaseStatistics/index.vue'; //基础统计
|
||||||
const uiStore = useUiStore();
|
const uiStore = useUiStore();
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
uiStore.isSmartEquipment = true;
|
uiStore.isSmartEquipment = true;
|
||||||
});
|
});
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
uiStore.isSmartEquipment = false;
|
uiStore.isSmartEquipment = false;
|
||||||
});
|
});
|
||||||
const filter2 = ref('jinshajiang');
|
|
||||||
const filter3 = ref('lianghekou');
|
|
||||||
const filter4 = ref('station');
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -22,19 +20,6 @@ const filter4 = ref('station');
|
|||||||
<div class="leftContent">
|
<div class="leftContent">
|
||||||
<JidiSelectorMod />
|
<JidiSelectorMod />
|
||||||
</div>
|
</div>
|
||||||
<div class="selector">
|
|
||||||
<div style="display: flex; gap: 12px; align-items: center">
|
|
||||||
<a-select v-model:value="filter2" style="width: 160px">
|
|
||||||
<a-select-option value="jinshajiang">金沙江干流</a-select-option>
|
|
||||||
</a-select>
|
|
||||||
<a-select v-model:value="filter3" style="width: 140px">
|
|
||||||
<a-select-option value="lianghekou">两河口</a-select-option>
|
|
||||||
</a-select>
|
|
||||||
<a-select v-model:value="filter4" style="width: 200px">
|
|
||||||
<a-select-option value="station">两河口库尾水温站</a-select-option>
|
|
||||||
</a-select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="rightContent">
|
<div class="rightContent">
|
||||||
<RightDrawer>
|
<RightDrawer>
|
||||||
<EquipmentStatistics />
|
<EquipmentStatistics />
|
||||||
|
|||||||