2025-10-14 14:17:44 +08:00
|
|
|
|
<template>
|
2025-10-31 16:15:28 +08:00
|
|
|
|
<div class="statistics">
|
2025-10-14 14:17:44 +08:00
|
|
|
|
<div class="banner">
|
2026-04-03 02:05:29 +08:00
|
|
|
|
<div class="banner-title-picker">
|
|
|
|
|
|
<el-dropdown
|
|
|
|
|
|
class="banner-type-dropdown"
|
|
|
|
|
|
trigger="click"
|
|
|
|
|
|
@command="handleCommand"
|
|
|
|
|
|
>
|
|
|
|
|
|
<span class="banner-select-trigger">
|
|
|
|
|
|
<span class="banner-select-text">{{ currentTitle }}</span>
|
|
|
|
|
|
<svg
|
|
|
|
|
|
class="banner-select-chevron"
|
|
|
|
|
|
viewBox="0 0 24 24"
|
|
|
|
|
|
width="40"
|
|
|
|
|
|
height="40"
|
|
|
|
|
|
aria-hidden="true"
|
|
|
|
|
|
focusable="false"
|
|
|
|
|
|
>
|
|
|
|
|
|
<path fill="#ffffff" d="M7 10l5 5 5-5H7z" />
|
|
|
|
|
|
</svg>
|
|
|
|
|
|
</span>
|
|
|
|
|
|
<el-dropdown-menu slot="dropdown" class="banner-type-dropdown-popper">
|
|
|
|
|
|
<el-dropdown-item command="全部科考船">全部科考船</el-dropdown-item>
|
|
|
|
|
|
<el-dropdown-item
|
|
|
|
|
|
v-for="item in titles"
|
|
|
|
|
|
:key="item.tsy_id"
|
|
|
|
|
|
:command="item.report_name"
|
|
|
|
|
|
>
|
|
|
|
|
|
{{ item.report_name }}
|
|
|
|
|
|
</el-dropdown-item>
|
|
|
|
|
|
</el-dropdown-menu>
|
|
|
|
|
|
</el-dropdown>
|
|
|
|
|
|
<p class="banner-title-picker__hint">点击选择</p>
|
|
|
|
|
|
</div>
|
2025-10-31 16:15:28 +08:00
|
|
|
|
<div class="numbers">
|
|
|
|
|
|
<div v-for="(item, index) in numbers" :key="index" class="item">
|
|
|
|
|
|
<div class="value">{{ item.value }}<span class="unit">{{ item.unit }}</span></div>
|
|
|
|
|
|
<div class="label">{{ item.label }}</div>
|
2025-10-14 14:17:44 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2025-10-31 16:15:28 +08:00
|
|
|
|
<!-- 地图板块-->
|
|
|
|
|
|
<div class="map-module">
|
|
|
|
|
|
<div class="bezel">
|
|
|
|
|
|
<div class="map-title">参航单位</div>
|
2025-11-18 15:33:41 +08:00
|
|
|
|
<div id="baiduCesiumContainer" ref="baiduCesiumContainer" style="height: 100%;width:100%;" />
|
2025-10-14 14:17:44 +08:00
|
|
|
|
</div>
|
2025-10-31 16:15:28 +08:00
|
|
|
|
<div class="bezel">
|
|
|
|
|
|
<div class="map-title">航次地图</div>
|
2026-04-03 02:05:29 +08:00
|
|
|
|
<div class="map-year-panel">
|
|
|
|
|
|
<span class="map-year-label">年份</span>
|
|
|
|
|
|
<el-date-picker
|
|
|
|
|
|
v-model="voyageYear"
|
|
|
|
|
|
type="year"
|
|
|
|
|
|
size="small"
|
|
|
|
|
|
placeholder="全部"
|
|
|
|
|
|
class="map-year"
|
|
|
|
|
|
clearable
|
|
|
|
|
|
format="yyyy"
|
|
|
|
|
|
@change="selectVoyageYear"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</div>
|
2025-10-31 16:15:28 +08:00
|
|
|
|
<div id="cesiumContainer" ref="cesiumContainer" style="height: 100%;width:100%;" />
|
2025-10-14 14:17:44 +08:00
|
|
|
|
</div>
|
2025-10-31 16:15:28 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
<!-- echarts板块-->
|
|
|
|
|
|
<div class="echarts-module">
|
|
|
|
|
|
<div class="bezel">
|
|
|
|
|
|
<BarChart
|
|
|
|
|
|
:title="barData1.title"
|
|
|
|
|
|
:chart-data="barData1.salesData"
|
|
|
|
|
|
:categories="barData1.productCategories"
|
|
|
|
|
|
chart-type="single"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</div>
|
2026-04-03 02:05:29 +08:00
|
|
|
|
<div class="bezel">
|
|
|
|
|
|
<BarChart
|
|
|
|
|
|
:title="barDataDays.title"
|
|
|
|
|
|
:chart-data="barDataDays.salesData"
|
|
|
|
|
|
:categories="barDataDays.productCategories"
|
|
|
|
|
|
chart-type="single"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</div>
|
2025-10-31 16:15:28 +08:00
|
|
|
|
<div class="bezel">
|
|
|
|
|
|
<BarChart
|
|
|
|
|
|
:title="barData2.title"
|
|
|
|
|
|
:chart-data="barData2.salesData"
|
|
|
|
|
|
:categories="barData2.productCategories"
|
|
|
|
|
|
chart-type="stacked"
|
|
|
|
|
|
stack-name="新增单位数"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="bezel">
|
|
|
|
|
|
<BarChart
|
|
|
|
|
|
:title="barData3.title"
|
|
|
|
|
|
:chart-data="barData3.salesData"
|
|
|
|
|
|
:categories="barData3.productCategories"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="bezel">
|
|
|
|
|
|
<BarChart
|
|
|
|
|
|
:title="barData4.title"
|
|
|
|
|
|
:chart-data="barData4.salesData"
|
|
|
|
|
|
:categories="barData4.productCategories"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="bezel">
|
|
|
|
|
|
<PieChart
|
|
|
|
|
|
:chart-data="pieData"
|
|
|
|
|
|
title="参航单位类型"
|
|
|
|
|
|
chart-type="ring"
|
|
|
|
|
|
/>
|
2025-10-14 14:17:44 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script>
|
2025-10-31 16:15:28 +08:00
|
|
|
|
import BarChart from './components/BarChart.vue'
|
|
|
|
|
|
import PieChart from './components/PieChart.vue'
|
|
|
|
|
|
import { setImageryViewModels } from '../../utils/common'
|
|
|
|
|
|
import { reportList, shipTotal, shipUnit, shipUnitYear, shipVoyage } from '../../api/statistics'
|
|
|
|
|
|
import { getYearRange, filterDictItems } from '../../utils/index'
|
|
|
|
|
|
const Cesium = window.Cesium
|
2025-10-14 14:17:44 +08:00
|
|
|
|
|
|
|
|
|
|
export default {
|
|
|
|
|
|
components: {
|
2025-10-31 16:15:28 +08:00
|
|
|
|
BarChart,
|
|
|
|
|
|
PieChart
|
2025-10-14 14:17:44 +08:00
|
|
|
|
},
|
|
|
|
|
|
data() {
|
|
|
|
|
|
return {
|
2025-10-31 16:15:28 +08:00
|
|
|
|
currentTitle: '全部科考船',
|
|
|
|
|
|
titles: [],
|
|
|
|
|
|
numbers: [
|
2025-10-14 14:17:44 +08:00
|
|
|
|
{
|
2025-10-31 16:15:28 +08:00
|
|
|
|
label: '航次',
|
|
|
|
|
|
value: '',
|
|
|
|
|
|
unit: '次'
|
2025-10-14 14:17:44 +08:00
|
|
|
|
},
|
|
|
|
|
|
{
|
2025-10-31 16:15:28 +08:00
|
|
|
|
label: '航次天数',
|
|
|
|
|
|
value: '',
|
|
|
|
|
|
unit: '天'
|
2025-10-14 14:17:44 +08:00
|
|
|
|
},
|
|
|
|
|
|
{
|
2025-10-31 16:15:28 +08:00
|
|
|
|
label: '参航单位',
|
|
|
|
|
|
value: '',
|
|
|
|
|
|
unit: '家'
|
2025-10-14 14:17:44 +08:00
|
|
|
|
},
|
|
|
|
|
|
{
|
2025-10-31 16:15:28 +08:00
|
|
|
|
label: '数据样品个数',
|
|
|
|
|
|
value: '',
|
|
|
|
|
|
unit: '个'
|
2025-10-14 14:17:44 +08:00
|
|
|
|
},
|
|
|
|
|
|
{
|
2025-10-31 16:15:28 +08:00
|
|
|
|
label: '累计里程',
|
|
|
|
|
|
value: '',
|
2026-04-03 02:05:29 +08:00
|
|
|
|
unit: 'km'
|
2025-10-14 14:17:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
],
|
2025-11-18 15:33:41 +08:00
|
|
|
|
// Cesium相关 - 参航单位地图
|
|
|
|
|
|
baiduCesiumViewer: null,
|
|
|
|
|
|
baiduCesiumEntities: [], // 存储参航单位标记实体
|
2025-10-31 16:15:28 +08:00
|
|
|
|
viewer: null,
|
|
|
|
|
|
// 地图图层基础地址
|
|
|
|
|
|
CesiumHostAddr: `${window.location.protocol}//${window.location.hostname}:${window.location.port}/`,
|
|
|
|
|
|
trackLineLayers: [],
|
|
|
|
|
|
voyageYear: '',
|
|
|
|
|
|
barData1: {},
|
2026-04-03 02:05:29 +08:00
|
|
|
|
/** 年度航次天数(与 barData1 同源接口按年) */
|
|
|
|
|
|
barDataDays: {},
|
2025-10-31 16:15:28 +08:00
|
|
|
|
barData2: {},
|
|
|
|
|
|
barData3: {},
|
|
|
|
|
|
barData4: {},
|
|
|
|
|
|
pieData: []
|
2025-10-14 14:17:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
},
|
2025-10-31 16:15:28 +08:00
|
|
|
|
created() {
|
|
|
|
|
|
this.getTypeList()
|
|
|
|
|
|
this.getShipList()
|
|
|
|
|
|
this.getShipUnit()
|
|
|
|
|
|
this.gitShipVoyage()
|
|
|
|
|
|
this.gitShipUnitYear()
|
|
|
|
|
|
this.getChartBar({ year: '2025' })
|
|
|
|
|
|
},
|
2025-10-14 14:17:44 +08:00
|
|
|
|
mounted() {
|
2025-10-31 16:15:28 +08:00
|
|
|
|
this.imageryViewModels = setImageryViewModels(this.CesiumHostAddr)
|
2025-11-18 15:33:41 +08:00
|
|
|
|
this.initCesium() // 初始化航次地图
|
|
|
|
|
|
this.initBaiduCesium() // 初始化参航单位地图
|
|
|
|
|
|
},
|
|
|
|
|
|
beforeDestroy() {
|
|
|
|
|
|
// 清理Cesium资源
|
|
|
|
|
|
if (this.baiduCesiumViewer) {
|
|
|
|
|
|
this.baiduCesiumViewer.destroy()
|
|
|
|
|
|
}
|
|
|
|
|
|
if (this.viewer) {
|
|
|
|
|
|
this.viewer.destroy()
|
|
|
|
|
|
}
|
2025-10-14 14:17:44 +08:00
|
|
|
|
},
|
|
|
|
|
|
methods: {
|
2025-10-31 16:15:28 +08:00
|
|
|
|
// 科考船数据
|
|
|
|
|
|
getTypeList() {
|
|
|
|
|
|
reportList().then(res => {
|
|
|
|
|
|
this.titles = filterDictItems(res.array, '科考船')
|
|
|
|
|
|
})
|
|
|
|
|
|
},
|
|
|
|
|
|
// 选择科考船
|
|
|
|
|
|
handleCommand(command) {
|
|
|
|
|
|
this.currentTitle = command
|
|
|
|
|
|
this.removeSingleLineImg()
|
|
|
|
|
|
if (command === '全部科考船') {
|
|
|
|
|
|
this.getShipList()
|
|
|
|
|
|
this.gitShipVoyage()
|
|
|
|
|
|
this.gitShipUnitYear()
|
|
|
|
|
|
this.getChartBar({ year: '2025' })
|
|
|
|
|
|
} else {
|
|
|
|
|
|
this.getShipList({ ship_name: command })
|
|
|
|
|
|
this.gitShipVoyage({ ship_name: command })
|
|
|
|
|
|
this.gitShipUnitYear({ ship_name: command })
|
|
|
|
|
|
this.getChartBar({ year: '2025', ship_name: command })
|
2025-10-14 14:17:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
},
|
2025-10-31 16:15:28 +08:00
|
|
|
|
// 汇总统计数据
|
|
|
|
|
|
getShipList(params = {}) {
|
|
|
|
|
|
shipTotal(params).then(res => {
|
|
|
|
|
|
const obj = res.array[0]
|
|
|
|
|
|
this.numbers[0].value = obj.member_total
|
|
|
|
|
|
this.numbers[1].value = obj.days_total
|
|
|
|
|
|
this.numbers[2].value = obj.unit_total
|
|
|
|
|
|
this.numbers[3].value = obj.dataset_total
|
|
|
|
|
|
this.numbers[4].value = obj.mileage_total
|
|
|
|
|
|
})
|
|
|
|
|
|
},
|
|
|
|
|
|
// 参航单位统计
|
|
|
|
|
|
getShipUnit() {
|
|
|
|
|
|
shipUnit().then(res => {
|
2025-11-18 15:33:41 +08:00
|
|
|
|
// 清除之前的标记
|
|
|
|
|
|
this.clearBaiduCesiumMarkers()
|
|
|
|
|
|
|
|
|
|
|
|
// 创建参航单位标记
|
|
|
|
|
|
this.createBaiduCesiumMarkers(res.array)
|
|
|
|
|
|
|
2025-10-31 16:15:28 +08:00
|
|
|
|
const typeCount = res.array.reduce((acc, unit) => {
|
|
|
|
|
|
const type = unit.unit_type
|
|
|
|
|
|
acc[type] = (acc[type] || 0) + 1 // 如果类型已存在则计数+1,否则初始化为1
|
|
|
|
|
|
return acc
|
|
|
|
|
|
}, {})
|
|
|
|
|
|
this.pieData = Object.entries(typeCount).map(([type, count]) => ({
|
|
|
|
|
|
name: type,
|
|
|
|
|
|
value: count
|
|
|
|
|
|
}))
|
|
|
|
|
|
})
|
2025-10-14 14:17:44 +08:00
|
|
|
|
},
|
2025-11-18 15:33:41 +08:00
|
|
|
|
// 创建参航单位Cesium标记点
|
|
|
|
|
|
createBaiduCesiumMarkers(units) {
|
|
|
|
|
|
if (!this.baiduCesiumViewer) return
|
|
|
|
|
|
|
|
|
|
|
|
const entities = []
|
|
|
|
|
|
|
|
|
|
|
|
units.forEach((item, index) => {
|
|
|
|
|
|
// 创建标记实体
|
|
|
|
|
|
const entity = this.baiduCesiumViewer.entities.add({
|
|
|
|
|
|
position: Cesium.Cartesian3.fromDegrees(item.unit_lon, item.unit_lat),
|
|
|
|
|
|
billboard: {
|
|
|
|
|
|
image: '../../../static/img/01.png', // 正常状态的图标
|
|
|
|
|
|
width: 32,
|
|
|
|
|
|
height: 32,
|
|
|
|
|
|
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
|
|
|
|
|
horizontalOrigin: Cesium.HorizontalOrigin.CENTER
|
|
|
|
|
|
},
|
|
|
|
|
|
label: {
|
|
|
|
|
|
text: item.unit_name,
|
|
|
|
|
|
font: '14pt monospace',
|
|
|
|
|
|
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
|
|
|
|
|
|
outlineWidth: 2,
|
|
|
|
|
|
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
|
|
|
|
|
pixelOffset: new Cesium.Cartesian2(0, -40), // 标签在标记下方
|
|
|
|
|
|
fillColor: Cesium.Color.WHITE,
|
|
|
|
|
|
outlineColor: Cesium.Color.BLACK
|
|
|
|
|
|
},
|
|
|
|
|
|
unitData: item, // 存储原始数据
|
|
|
|
|
|
index: index // 存储索引
|
|
|
|
|
|
})
|
|
|
|
|
|
entities.push(entity)
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
this.baiduCesiumEntities = entities
|
|
|
|
|
|
|
|
|
|
|
|
// 调整视角以显示所有标记
|
|
|
|
|
|
if (entities.length > 0) {
|
|
|
|
|
|
this.baiduCesiumViewer.zoomTo(entities)
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
// 清除参航单位标记
|
|
|
|
|
|
clearBaiduCesiumMarkers() {
|
|
|
|
|
|
if (this.baiduCesiumViewer && this.baiduCesiumEntities.length > 0) {
|
|
|
|
|
|
this.baiduCesiumEntities.forEach(entity => {
|
|
|
|
|
|
this.baiduCesiumViewer.entities.remove(entity)
|
|
|
|
|
|
})
|
|
|
|
|
|
this.baiduCesiumEntities = []
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
2025-10-31 16:15:28 +08:00
|
|
|
|
// 航次统计
|
|
|
|
|
|
gitShipVoyage(params = {}) {
|
|
|
|
|
|
shipVoyage(params).then(res => {
|
|
|
|
|
|
// 添加轨迹图层
|
|
|
|
|
|
res.array.forEach(item => {
|
|
|
|
|
|
this.addSingleLineImg(item)
|
|
|
|
|
|
})
|
|
|
|
|
|
})
|
|
|
|
|
|
},
|
2025-11-18 15:33:41 +08:00
|
|
|
|
// 初始化Cesium - 参航单位地图
|
|
|
|
|
|
initBaiduCesium() {
|
|
|
|
|
|
this.baiduCesiumViewer = new Cesium.Viewer(this.$refs.baiduCesiumContainer, {
|
|
|
|
|
|
sceneMode: Cesium.SceneMode.SCENE2D,
|
|
|
|
|
|
shadows: false,
|
|
|
|
|
|
timeline: false,
|
|
|
|
|
|
baseLayerPicker: false,
|
|
|
|
|
|
imageryProviderViewModels: this.imageryViewModels,
|
|
|
|
|
|
terrainProviderViewModels: [],
|
|
|
|
|
|
fullscreenButton: false,
|
|
|
|
|
|
selectionIndicator: false,
|
|
|
|
|
|
homeButton: false,
|
|
|
|
|
|
sceneModePicker: false,
|
|
|
|
|
|
animation: false,
|
|
|
|
|
|
infoBox: false,
|
|
|
|
|
|
geocoder: false,
|
|
|
|
|
|
navigationHelpButton: false
|
|
|
|
|
|
})
|
|
|
|
|
|
this.baiduCesiumViewer._cesiumWidget._creditContainer.style.display = 'none'
|
|
|
|
|
|
this.baiduCesiumViewer.scene.sun.show = false
|
|
|
|
|
|
this.baiduCesiumViewer.scene.moon.show = false
|
|
|
|
|
|
this.baiduCesiumViewer.scene.fog.enabled = false
|
|
|
|
|
|
this.baiduCesiumViewer.scene.skyAtmosphere.show = false
|
|
|
|
|
|
this.baiduCesiumViewer.scene.sun.show = false
|
|
|
|
|
|
this.baiduCesiumViewer.scene.skyBox.show = false
|
|
|
|
|
|
this.baiduCesiumViewer.scene.globe.enableLighting = false
|
|
|
|
|
|
this.baiduCesiumViewer.shadowMap.darkness = 0.8
|
|
|
|
|
|
this.baiduCesiumViewer.scene._sunBloom = false
|
|
|
|
|
|
this.baiduCesiumViewer.scene.globe.showGroundAtmosphere = false
|
|
|
|
|
|
this.baiduCesiumViewer.scene.postProcessStages.fxaa.enabled = true
|
|
|
|
|
|
|
|
|
|
|
|
this.baiduCesiumViewer.camera.setView({
|
|
|
|
|
|
destination: Cesium.Cartesian3.fromDegrees(114.4040, 30.5196, 4000000)
|
2025-10-31 16:15:28 +08:00
|
|
|
|
})
|
2025-10-14 14:17:44 +08:00
|
|
|
|
},
|
2025-10-31 16:15:28 +08:00
|
|
|
|
// 初始化cesium
|
|
|
|
|
|
initCesium() {
|
|
|
|
|
|
Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJkY2Y5NWY2Ni1mODQ1LTQ3YTUtYjc4Zi1jYzhjMGI2YzcxMWYiLCJpZCI6MTI5ODMwLCJpYXQiOjE2Nzk0Njk5NTd9.DTH54ioOH-HLqeNIetBe9hFyrPOX2Vp1AQmZzw8TIZ4'
|
|
|
|
|
|
this.viewer = new Cesium.Viewer('cesiumContainer', {
|
|
|
|
|
|
sceneMode: Cesium.SceneMode.SCENE2D,
|
|
|
|
|
|
shadows: false,
|
|
|
|
|
|
timeline: false,
|
|
|
|
|
|
baseLayerPicker: false,
|
|
|
|
|
|
// 设置自定义底图
|
|
|
|
|
|
imageryProviderViewModels: this.imageryViewModels,
|
|
|
|
|
|
// 关闭默认的地形底图
|
|
|
|
|
|
terrainProviderViewModels: [],
|
|
|
|
|
|
fullscreenButton: false,
|
|
|
|
|
|
selectionIndicator: false,
|
|
|
|
|
|
homeButton: false,
|
|
|
|
|
|
sceneModePicker: false,
|
|
|
|
|
|
animation: false,
|
|
|
|
|
|
infoBox: false,
|
|
|
|
|
|
geocoder: false,
|
|
|
|
|
|
navigationHelpButton: false
|
|
|
|
|
|
})
|
|
|
|
|
|
this.viewer._cesiumWidget._creditContainer.style.display = 'none'
|
|
|
|
|
|
this.viewer.scene.sun.show = false
|
|
|
|
|
|
this.viewer.scene.moon.show = false
|
|
|
|
|
|
this.viewer.scene.fog.enabled = false
|
|
|
|
|
|
this.viewer.scene.skyAtmosphere.show = false
|
|
|
|
|
|
this.viewer.scene.sun.show = false
|
|
|
|
|
|
this.viewer.scene.skyBox.show = false
|
|
|
|
|
|
this.viewer.scene.globe.enableLighting = false
|
|
|
|
|
|
this.viewer.shadowMap.darkness = 0.8
|
|
|
|
|
|
this.viewer.scene._sunBloom = false
|
|
|
|
|
|
this.viewer.scene.globe.showGroundAtmosphere = false
|
|
|
|
|
|
this.viewer.scene.postProcessStages.fxaa.enabled = true
|
|
|
|
|
|
|
|
|
|
|
|
this.viewer.camera.setView({
|
|
|
|
|
|
// 指定相机初始位置
|
|
|
|
|
|
destination: Cesium.Cartesian3.fromDegrees(112, 18, 4000000)
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2025-10-14 14:17:44 +08:00
|
|
|
|
},
|
2025-10-31 16:15:28 +08:00
|
|
|
|
// 添加轨迹图层
|
|
|
|
|
|
addSingleLineImg(item) {
|
|
|
|
|
|
const trackLine = new Cesium.WebMapTileServiceImageryProvider(
|
|
|
|
|
|
{
|
|
|
|
|
|
url: `${this.CesiumHostAddr}geoserver/gwc/service/wmts/rest/dsds:${item.voyage_name}/{TileMatrixSet}/{TileMatrixSet}:{TileMatrix}/{TileRow}/{TileCol}?format=image/png`,
|
|
|
|
|
|
layer: `dsds:${item.voyage_name}`,
|
|
|
|
|
|
style: 'default',
|
|
|
|
|
|
format: 'image/png',
|
|
|
|
|
|
tileMatrixSetID: 'EPSG:4326',
|
|
|
|
|
|
tilingScheme: new Cesium.GeographicTilingScheme()
|
2025-10-14 14:17:44 +08:00
|
|
|
|
}
|
2025-10-31 16:15:28 +08:00
|
|
|
|
)
|
|
|
|
|
|
const trackLineLayer = this.viewer.imageryLayers.addImageryProvider(trackLine)
|
|
|
|
|
|
this.trackLineLayers.push(trackLineLayer)
|
|
|
|
|
|
},
|
|
|
|
|
|
// 移除轨迹图层
|
|
|
|
|
|
removeSingleLineImg() {
|
|
|
|
|
|
if (this.trackLineLayers.length) {
|
|
|
|
|
|
this.trackLineLayers.forEach(line => {
|
|
|
|
|
|
this.viewer.imageryLayers.remove(line)
|
|
|
|
|
|
})
|
2025-10-14 14:17:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
},
|
2025-10-31 16:15:28 +08:00
|
|
|
|
// 选择航次地图年份
|
|
|
|
|
|
selectVoyageYear(val) {
|
|
|
|
|
|
const shipName = this.currentTitle === '全部科考船' ? '' : this.currentTitle
|
|
|
|
|
|
if (val) {
|
|
|
|
|
|
this.removeSingleLineImg()
|
|
|
|
|
|
const params = getYearRange(val)
|
|
|
|
|
|
this.gitShipVoyage({ ...params, ship_name: shipName })
|
|
|
|
|
|
} else {
|
|
|
|
|
|
this.gitShipVoyage({ ship_name: shipName })
|
2025-10-14 14:17:44 +08:00
|
|
|
|
}
|
2025-10-31 16:15:28 +08:00
|
|
|
|
},
|
|
|
|
|
|
// 参航单位年度
|
|
|
|
|
|
gitShipUnitYear(params = {}) {
|
|
|
|
|
|
shipUnitYear(params).then(res => {
|
|
|
|
|
|
const originalData = res.array
|
|
|
|
|
|
const sortedData = originalData.sort((a, b) => a.voyage_year - b.voyage_year)
|
|
|
|
|
|
this.barData2 = {
|
|
|
|
|
|
title: '年度参航单位',
|
|
|
|
|
|
salesData: [
|
|
|
|
|
|
{
|
|
|
|
|
|
name: '参航单位',
|
|
|
|
|
|
data: sortedData.map(item => item.unit_total),
|
|
|
|
|
|
stack: '新增单位数'
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: '新增单位',
|
|
|
|
|
|
data: sortedData.map(item => item.year_unit_total),
|
|
|
|
|
|
stack: '新增单位数'
|
|
|
|
|
|
}
|
|
|
|
|
|
],
|
|
|
|
|
|
productCategories: sortedData.map(item => item.voyage_year.toString())
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
},
|
|
|
|
|
|
// 柱状图数据
|
|
|
|
|
|
getChartBar(params) {
|
|
|
|
|
|
shipTotal(params).then(res => {
|
|
|
|
|
|
const originalData = res.array
|
|
|
|
|
|
const sortedData = originalData.sort((a, b) => a.year - b.year)
|
|
|
|
|
|
this.barData1 = {
|
|
|
|
|
|
title: '年度航次数',
|
|
|
|
|
|
salesData: sortedData.map(item => item.member_total),
|
|
|
|
|
|
productCategories: sortedData.map(item => item.year.toString())
|
|
|
|
|
|
}
|
2026-04-03 02:05:29 +08:00
|
|
|
|
this.barDataDays = {
|
|
|
|
|
|
title: '年度航次天数',
|
|
|
|
|
|
salesData: sortedData.map(item => item.days_total),
|
|
|
|
|
|
productCategories: sortedData.map(item => item.year.toString())
|
|
|
|
|
|
}
|
2025-10-31 16:15:28 +08:00
|
|
|
|
this.barData3 = {
|
|
|
|
|
|
title: '样品集个数',
|
|
|
|
|
|
salesData: sortedData.map(item => item.dataset_total),
|
|
|
|
|
|
productCategories: sortedData.map(item => item.year.toString())
|
|
|
|
|
|
}
|
|
|
|
|
|
this.barData4 = {
|
|
|
|
|
|
title: '里程数',
|
|
|
|
|
|
salesData: sortedData.map(item => item.mileage_total),
|
|
|
|
|
|
productCategories: sortedData.map(item => item.year.toString())
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
2025-10-14 14:17:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style scoped lang="scss">
|
2025-10-31 16:15:28 +08:00
|
|
|
|
.statistics {
|
|
|
|
|
|
background-color: #ebf1f7;
|
|
|
|
|
|
|
2025-10-14 14:17:44 +08:00
|
|
|
|
.banner {
|
2025-10-31 16:15:28 +08:00
|
|
|
|
background-image: url(../../../static/images/bannerny1.jpg);
|
2026-04-03 02:05:29 +08:00
|
|
|
|
background-repeat: no-repeat;
|
|
|
|
|
|
background-position: center;
|
|
|
|
|
|
background-size: 100% 100%;
|
2025-10-14 14:17:44 +08:00
|
|
|
|
width: 100%;
|
2025-10-31 16:15:28 +08:00
|
|
|
|
height: 480px;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
color: #fff;
|
|
|
|
|
|
|
2026-04-03 02:05:29 +08:00
|
|
|
|
.banner-title-picker {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
align-items: center;
|
2025-10-31 16:15:28 +08:00
|
|
|
|
margin-bottom: 40px;
|
2026-04-03 02:05:29 +08:00
|
|
|
|
padding: 12px 16px 0;
|
|
|
|
|
|
max-width: 100%;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.banner-type-dropdown {
|
|
|
|
|
|
display: inline-block;
|
|
|
|
|
|
width: auto;
|
|
|
|
|
|
max-width: 100%;
|
|
|
|
|
|
vertical-align: top;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.banner-select-trigger {
|
|
|
|
|
|
display: inline-flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
gap: 12px;
|
|
|
|
|
|
padding: 2px 0;
|
|
|
|
|
|
border: none;
|
|
|
|
|
|
border-radius: 0;
|
|
|
|
|
|
background: transparent;
|
|
|
|
|
|
box-shadow: none;
|
2025-10-31 16:15:28 +08:00
|
|
|
|
cursor: pointer;
|
2026-04-03 02:05:29 +08:00
|
|
|
|
user-select: none;
|
|
|
|
|
|
outline: none;
|
|
|
|
|
|
|
|
|
|
|
|
&:hover .banner-select-text {
|
|
|
|
|
|
opacity: 0.92;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
&:focus-visible {
|
|
|
|
|
|
outline: 2px solid rgba(255, 255, 255, 0.65);
|
|
|
|
|
|
outline-offset: 6px;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.banner-select-text {
|
|
|
|
|
|
font-size: 52px;
|
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
|
color: #fff;
|
|
|
|
|
|
line-height: 1.15;
|
|
|
|
|
|
max-width: #{"min(90vw, 920px)"};
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
text-overflow: ellipsis;
|
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.banner-select-chevron {
|
|
|
|
|
|
flex-shrink: 0;
|
|
|
|
|
|
color: #ffffff;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.banner-title-picker__hint {
|
|
|
|
|
|
margin: 14px 0 0;
|
|
|
|
|
|
padding: 0;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
font-weight: 400;
|
|
|
|
|
|
letter-spacing: 0.12em;
|
|
|
|
|
|
color: rgba(255, 255, 255, 0.78);
|
|
|
|
|
|
line-height: 1.4;
|
2025-10-14 14:17:44 +08:00
|
|
|
|
}
|
2025-10-31 16:15:28 +08:00
|
|
|
|
|
|
|
|
|
|
.numbers {
|
2025-10-14 14:17:44 +08:00
|
|
|
|
display: flex;
|
2025-10-31 16:15:28 +08:00
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
gap: 80px;
|
|
|
|
|
|
|
|
|
|
|
|
.item {
|
2025-10-14 14:17:44 +08:00
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
justify-content: center;
|
2025-10-31 16:15:28 +08:00
|
|
|
|
align-items: center;
|
|
|
|
|
|
.value {
|
2025-10-14 14:17:44 +08:00
|
|
|
|
font-size: 56px;
|
|
|
|
|
|
font-weight: bold;
|
2025-10-31 16:15:28 +08:00
|
|
|
|
.unit {
|
|
|
|
|
|
font-size: 26px;
|
2025-10-14 14:17:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-10-31 16:15:28 +08:00
|
|
|
|
.label {
|
|
|
|
|
|
font-size: 18px;
|
|
|
|
|
|
}
|
2025-10-14 14:17:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-10-31 16:15:28 +08:00
|
|
|
|
.map-module {
|
|
|
|
|
|
padding: 50px 50px;
|
2025-10-14 14:17:44 +08:00
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: space-between;
|
2025-10-31 16:15:28 +08:00
|
|
|
|
gap: 50px;
|
|
|
|
|
|
.bezel {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
width: 100%;
|
2025-10-14 14:17:44 +08:00
|
|
|
|
height: 520px;
|
|
|
|
|
|
border-radius: 10px;
|
|
|
|
|
|
overflow: hidden;
|
2025-10-31 16:15:28 +08:00
|
|
|
|
border: 1px solid #ccc;
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
|
|
|
|
|
|
.map-title {
|
2025-10-14 14:17:44 +08:00
|
|
|
|
position: absolute;
|
|
|
|
|
|
top: 20px;
|
|
|
|
|
|
left: 20px;
|
2025-10-31 16:15:28 +08:00
|
|
|
|
color: white;
|
2025-10-14 14:17:44 +08:00
|
|
|
|
z-index: 8888;
|
|
|
|
|
|
font-size: 22px;
|
|
|
|
|
|
}
|
2026-04-03 02:05:29 +08:00
|
|
|
|
|
|
|
|
|
|
.map-year-panel {
|
2025-10-31 16:15:28 +08:00
|
|
|
|
position: absolute;
|
2026-04-03 02:05:29 +08:00
|
|
|
|
top: 16px;
|
|
|
|
|
|
right: 16px;
|
2025-10-31 16:15:28 +08:00
|
|
|
|
z-index: 8888;
|
2026-04-03 02:05:29 +08:00
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
gap: 10px;
|
|
|
|
|
|
padding: 6px 10px 6px 12px;
|
|
|
|
|
|
border-radius: 10px;
|
|
|
|
|
|
background: rgba(255, 255, 255, 0.68);
|
|
|
|
|
|
border: 1px solid rgba(255, 255, 255, 0.55);
|
|
|
|
|
|
box-shadow: 0 4px 18px rgba(0, 0, 0, 0.14);
|
|
|
|
|
|
backdrop-filter: blur(12px);
|
|
|
|
|
|
-webkit-backdrop-filter: blur(12px);
|
|
|
|
|
|
transition:
|
|
|
|
|
|
background 0.25s ease,
|
|
|
|
|
|
border-color 0.25s ease,
|
|
|
|
|
|
box-shadow 0.25s ease,
|
|
|
|
|
|
transform 0.25s ease;
|
|
|
|
|
|
|
|
|
|
|
|
&:hover {
|
|
|
|
|
|
background: rgba(255, 255, 255, 0.82);
|
|
|
|
|
|
border-color: rgba(255, 255, 255, 0.92);
|
|
|
|
|
|
transform: translateY(-2px);
|
|
|
|
|
|
box-shadow: 0 10px 28px rgba(0, 0, 0, 0.2);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.map-year-label {
|
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
color: rgba(28, 42, 58, 0.78);
|
|
|
|
|
|
letter-spacing: 0.04em;
|
|
|
|
|
|
user-select: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.map-year {
|
|
|
|
|
|
width: 120px;
|
|
|
|
|
|
|
|
|
|
|
|
::v-deep .el-input__inner {
|
|
|
|
|
|
height: 34px;
|
|
|
|
|
|
line-height: 34px;
|
|
|
|
|
|
padding-left: 30px;
|
|
|
|
|
|
padding-right: 28px;
|
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
border: 1px solid rgba(0, 50, 90, 0.12);
|
|
|
|
|
|
background: rgba(255, 255, 255, 0.55);
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
color: #1c2d3f;
|
|
|
|
|
|
transition:
|
|
|
|
|
|
background 0.2s ease,
|
|
|
|
|
|
border-color 0.2s ease,
|
|
|
|
|
|
box-shadow 0.2s ease;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
::v-deep .el-input__inner:hover,
|
|
|
|
|
|
::v-deep .el-input__inner:focus {
|
|
|
|
|
|
border-color: rgba(0, 90, 150, 0.42);
|
|
|
|
|
|
background: rgba(255, 255, 255, 0.78);
|
|
|
|
|
|
box-shadow: 0 2px 8px rgba(0, 50, 100, 0.1);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
::v-deep .el-input__prefix {
|
|
|
|
|
|
left: 8px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
::v-deep .el-input__suffix {
|
|
|
|
|
|
right: 6px;
|
|
|
|
|
|
}
|
2025-10-31 16:15:28 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
.echarts-module {
|
|
|
|
|
|
padding: 0 50px 50px;
|
|
|
|
|
|
display: grid;
|
|
|
|
|
|
grid-template-columns: repeat(3, 1fr);
|
|
|
|
|
|
gap: 50px;
|
|
|
|
|
|
grid-auto-rows: 300px;
|
|
|
|
|
|
|
|
|
|
|
|
.bezel {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
height: 100%;
|
|
|
|
|
|
border-radius: 10px;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
border: 1px solid #ccc;
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
|
|
|
|
|
|
.map-title {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
top: 20px;
|
|
|
|
|
|
left: 20px;
|
|
|
|
|
|
color: white;
|
|
|
|
|
|
z-index: 8888;
|
|
|
|
|
|
font-size: 22px;
|
2025-10-14 14:17:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-04-03 02:05:29 +08:00
|
|
|
|
</style>
|
|
|
|
|
|
|
|
|
|
|
|
<style lang="scss">
|
|
|
|
|
|
.banner-type-dropdown-popper.el-dropdown-menu {
|
|
|
|
|
|
min-width: 240px;
|
|
|
|
|
|
max-height: #{"min(60vh, 420px)"};
|
|
|
|
|
|
overflow-y: auto;
|
|
|
|
|
|
padding: 6px 0;
|
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.35);
|
|
|
|
|
|
}
|
2025-10-31 16:15:28 +08:00
|
|
|
|
|
2026-04-03 02:05:29 +08:00
|
|
|
|
.banner-type-dropdown-popper.el-dropdown-menu .el-dropdown-menu__item {
|
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
|
line-height: 22px;
|
|
|
|
|
|
padding: 14px 22px;
|
2025-10-14 14:17:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
</style>
|