4 changed files with 475 additions and 0 deletions
@ -0,0 +1,91 @@ |
|||
<template> |
|||
<div class="tabBox"> |
|||
<Card title="氨氮曲线图" :loading="loading"> |
|||
<div ref="chartRef1" :style="{ width, height }"></div> |
|||
</Card> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup lang="ts"> |
|||
import { watch, ref, Ref, watchEffect } from 'vue'; |
|||
import { useECharts } from '@/hooks/web/useECharts'; |
|||
import { Card } from 'ant-design-vue'; |
|||
|
|||
const subTab = ref<String>('a'); |
|||
const props = defineProps({ |
|||
loading: Boolean, |
|||
width: { |
|||
type: String as PropType<string>, |
|||
default: '100%', |
|||
}, |
|||
height: { |
|||
type: String as PropType<string>, |
|||
default: '300px', |
|||
}, |
|||
}); |
|||
|
|||
const chartRef1 = ref<HTMLDivElement | null>(null); |
|||
const setOptions1 = useECharts(chartRef1 as Ref<HTMLDivElement>).setOptions; |
|||
watch( |
|||
() => subTab.value, |
|||
() => { |
|||
setOptions1({ |
|||
tooltip: { |
|||
trigger: 'axis', |
|||
}, |
|||
grid: { |
|||
left: '3%', |
|||
right: '4%', |
|||
bottom: '3%', |
|||
containLabel: true, |
|||
}, |
|||
legend: { |
|||
data: ['cod', 'tn×10', 'tp×100'], |
|||
}, |
|||
xAxis: { |
|||
type: 'category', |
|||
boundaryGap: true, |
|||
data: [ |
|||
'2025-5-12', |
|||
'2025-5-13', |
|||
'2025-5-14', |
|||
'2025-5-15', |
|||
'2025-5-16', |
|||
'2025-5-17', |
|||
'2025-5-18', |
|||
'2025-5-19', |
|||
'2025-5-20', |
|||
'2025-5-12', |
|||
'2025-5-21', |
|||
'2025-5-22', |
|||
], |
|||
}, |
|||
yAxis: { |
|||
type: 'value', |
|||
name: '氨氮曲线图', // 单位说明文本 |
|||
nameLocation: 'end', // 文本位置(start/center/end) |
|||
nameTextStyle: { |
|||
color: '#666', |
|||
fontSize: 12, |
|||
align: 'left', // 文本对齐方向 |
|||
padding: [0, 0, 0, -30], // 调整位置 [上,右,下,左] |
|||
}, |
|||
}, |
|||
series: [ |
|||
{ |
|||
name: '氨氮', |
|||
data: [90, 200, 150, 80, 70, 78, 123, 29, 45, 99], |
|||
type: 'line', |
|||
itemStyle: {}, |
|||
}, |
|||
], |
|||
}); |
|||
}, |
|||
{ immediate: true }, |
|||
); |
|||
</script> |
|||
<style lang="less"> |
|||
.tabBox { |
|||
margin: 20px; |
|||
} |
|||
</style> |
@ -0,0 +1,127 @@ |
|||
<template> |
|||
<PageWrapper dense> |
|||
<div style="margin: 20px; border-radius: 10px; background: #fff"> |
|||
<div class="tabBox"> |
|||
<a-tabs v-model:activeKey="activeKey" size="large"> |
|||
<a-tab-pane key="总览" tab="总览"> |
|||
<div style="margin: 1%; padding: 1%; border-radius: 10px; background: #fff"> |
|||
<span>监测因子:</span> |
|||
<a-select |
|||
v-model:value="searchInfo.monitorType" |
|||
style="width: 180px" |
|||
:options="monitorTypeOptions" |
|||
placeholder="请选择" |
|||
allowClear |
|||
/> |
|||
<span style="margin-left: 20px">时间:</span> |
|||
<a-select |
|||
v-model:value="searchInfo.timeType" |
|||
style="width: 180px" |
|||
:options="timeTypeOptions" |
|||
placeholder="请选择" |
|||
allowClear |
|||
/> |
|||
<a-button type="primary" @click="search" style="margin-left: 20px">查询</a-button> |
|||
<div id="amapContainer" style="height: 80vh; margin-top: 10px"> </div> |
|||
</div> |
|||
</a-tab-pane> |
|||
<a-tab-pane key="实时数据" tab="实时数据"> |
|||
<info></info> |
|||
</a-tab-pane> |
|||
<a-tab-pane key="曲线分析" tab="曲线分析"> |
|||
<analysis></analysis> |
|||
</a-tab-pane> |
|||
</a-tabs> |
|||
</div> |
|||
</div> |
|||
</PageWrapper> |
|||
</template> |
|||
|
|||
<script setup lang="ts"> |
|||
import { ref, reactive, onMounted } from 'vue'; |
|||
import { PageWrapper } from '@/components/Page'; |
|||
import AMapLoader from '@amap/amap-jsapi-loader'; |
|||
import info from './info.vue' |
|||
import analysis from './analysis.vue'; |
|||
const activeKey = ref('总览'); |
|||
const searchInfo = reactive({ |
|||
monitorType: null, |
|||
timeType: null, |
|||
}); |
|||
const monitorTypeOptions = [ |
|||
{ |
|||
value: 'PH', |
|||
}, |
|||
{ |
|||
value: 'DO', |
|||
}, |
|||
{ |
|||
value: 'COD', |
|||
}, |
|||
{ |
|||
value: 'TP', |
|||
}, |
|||
{ |
|||
value: 'NH3-N', |
|||
}, |
|||
]; |
|||
const timeTypeOptions = [ |
|||
{ |
|||
value: '实时数据', |
|||
}, |
|||
{ |
|||
value: '日均值', |
|||
}, |
|||
{ |
|||
value: '月均值', |
|||
}, |
|||
]; |
|||
const search = async () => {}; |
|||
const points = ref<any>([ |
|||
{ |
|||
longitude: 119.21, |
|||
latitude: 29.7, |
|||
}, |
|||
]); |
|||
onMounted(() => { |
|||
AMapLoader.load({ |
|||
key: '786a2e7cc6d4be5ba1d6174a0aa10f2b', |
|||
version: '2.0', |
|||
plugins: [], // 如果需要插件,请在这里添加 |
|||
}) |
|||
.then((AMap) => { |
|||
const map = new AMap.Map('amapContainer', { |
|||
zoom: 10, // 初始化地图层级 |
|||
center: [119.0426, 29.6], // 初始化地图中心点坐标 |
|||
}); |
|||
|
|||
// 添加标记点 |
|||
points.value.forEach((point) => { |
|||
const marker = new AMap.Marker({ |
|||
position: new AMap.LngLat(point.longitude, point.latitude), |
|||
title: point.station, |
|||
}); |
|||
|
|||
marker.on('click', () => { |
|||
console.log('1'); |
|||
}); |
|||
|
|||
map.add(marker); |
|||
}); |
|||
}) |
|||
.catch((e) => { |
|||
console.error(e); // 错误处理 |
|||
}); |
|||
}); |
|||
</script> |
|||
<style lang="less"> |
|||
.tabBox { |
|||
margin: 10px; |
|||
} |
|||
|
|||
.title { |
|||
margin: 10px 0; |
|||
font-size: 20px; |
|||
font-weight: 550; |
|||
} |
|||
</style> |
@ -0,0 +1,256 @@ |
|||
<template> |
|||
<div class="tabBox"> |
|||
<div class="md:flex enter-y"> |
|||
<div class="md:w-1/3 w-full"> |
|||
<Card title="污染源统计" :loading="loading"> |
|||
<div ref="chartRef1" :style="{ width, height }"></div> |
|||
</Card> |
|||
</div> |
|||
<div class="md:w-1/3 w-full"> |
|||
<Card title="水源统计" :loading="loading"> |
|||
<div class="md:flex enter-y"> |
|||
<div class="md:w-1/2 w-full" ref="chartRef2" :style="{ width, height }"> </div> |
|||
<div class="md:w-1/2 w-full"> |
|||
<div> |
|||
<span style="font-weight: 600">全区水质前三:</span> |
|||
<div v-for="(item, index) in topThree" :key="index"> |
|||
{{ index }}- {{ item.name }}:{{ item.percent }} |
|||
</div> |
|||
</div> |
|||
<div style="top: 50%; position: absolute"> |
|||
<span style="font-weight: 600">全区水质后三:</span> |
|||
<div v-for="(item, index) in lastThree" :key="index"> |
|||
{{ index }}- {{ item.name }}:{{ item.percent }} |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</Card> |
|||
</div> |
|||
<div class="md:w-1/3 w-full"> |
|||
<Card title="河道统计" :loading="loading"> |
|||
<div ref="chartRef3" :style="{ width, height }"></div> |
|||
</Card> |
|||
</div> |
|||
</div> |
|||
|
|||
<div> |
|||
<Card :loading="loading"> |
|||
<div> |
|||
<a-table :dataSource="dataSource" :columns="columns" :pagination="false" bordered /> |
|||
</div> |
|||
</Card> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup lang="ts"> |
|||
import { watch, ref, Ref, watchEffect } from 'vue'; |
|||
import { useECharts } from '@/hooks/web/useECharts'; |
|||
import { Card } from 'ant-design-vue'; |
|||
|
|||
const subTab = ref<String>('a'); |
|||
const props = defineProps({ |
|||
loading: Boolean, |
|||
width: { |
|||
type: String as PropType<string>, |
|||
default: '100%', |
|||
}, |
|||
height: { |
|||
type: String as PropType<string>, |
|||
default: '300px', |
|||
}, |
|||
}); |
|||
const topThree = [ |
|||
{ |
|||
name: 'xx', |
|||
percent: '100%', |
|||
}, |
|||
{ |
|||
name: 'xx', |
|||
percent: '98%', |
|||
}, |
|||
{ |
|||
name: 'xx', |
|||
percent: '95%', |
|||
}, |
|||
]; |
|||
const lastThree = [ |
|||
{ |
|||
name: 'xx', |
|||
percent: '60%', |
|||
}, |
|||
{ |
|||
name: 'xx', |
|||
percent: '55%', |
|||
}, |
|||
{ |
|||
name: 'xx', |
|||
percent: '39%', |
|||
}, |
|||
]; |
|||
const chartRef1 = ref<HTMLDivElement | null>(null); |
|||
const setOptions1 = useECharts(chartRef1 as Ref<HTMLDivElement>).setOptions; |
|||
const chartRef2 = ref<HTMLDivElement | null>(null); |
|||
const setOptions2 = useECharts(chartRef2 as Ref<HTMLDivElement>).setOptions; |
|||
const chartRef3 = ref<HTMLDivElement | null>(null); |
|||
const setOptions3 = useECharts(chartRef3 as Ref<HTMLDivElement>).setOptions; |
|||
const dataSource = ref([]) |
|||
const columns = [ |
|||
{ |
|||
dataIndex: 'index', |
|||
key: 'index', |
|||
title: '序号', |
|||
customCell: (_, index:any) => { |
|||
return index |
|||
}, |
|||
}, |
|||
{ |
|||
dataIndex: 'monitorTime', |
|||
key: 'monitorTime', |
|||
title: '监测时间', |
|||
}, |
|||
{ |
|||
dataIndex: 'ph', |
|||
key: 'ph', |
|||
title: 'PH值(6-9)', |
|||
}, |
|||
{ |
|||
dataIndex: 'oxygenDemand', |
|||
key: 'oxygenDemand', |
|||
title: '化学需氧量(250mg/L)', |
|||
}, |
|||
{ |
|||
dataIndex: 'ammoniaOxygen', |
|||
key: 'ammoniaOxygen', |
|||
title: '氨氧(mg/L)', |
|||
}, |
|||
{ |
|||
dataIndex: 'flowRate', |
|||
key: 'flowRate', |
|||
title: '废水瞬时流量(升/秒)', |
|||
}, |
|||
{ |
|||
dataIndex: 'restChlorine', |
|||
key: 'restChlorine', |
|||
title: '总余氯(8mg/L)', |
|||
}, |
|||
]; |
|||
watch( |
|||
() => subTab.value, |
|||
() => { |
|||
setOptions1({ |
|||
tooltip: { |
|||
trigger: 'item', |
|||
formatter: '{a} <br/>{b}: {c} ({d}%)', // {d}% 表示百分比 |
|||
}, |
|||
legend: { |
|||
top: '5%', |
|||
left: 'center', |
|||
}, |
|||
series: [ |
|||
{ |
|||
name: '污染源统计', |
|||
type: 'pie', |
|||
radius: ['40%', '70%'], |
|||
avoidLabelOverlap: false, |
|||
label: { |
|||
show: false, |
|||
position: 'center', |
|||
}, |
|||
labelLine: { |
|||
show: false, |
|||
}, |
|||
data: [ |
|||
{ value: 1048, name: '污水处理厂' }, |
|||
{ value: 735, name: '工业污染源' }, |
|||
{ value: 580, name: '畜禽养殖场' }, |
|||
], |
|||
}, |
|||
], |
|||
}); |
|||
setOptions2({ |
|||
tooltip: { |
|||
trigger: 'item', |
|||
formatter: '{a} <br/>{b}:({d}%)', // {d}% 表示百分比 |
|||
}, |
|||
legend: { |
|||
top: '5%', |
|||
left: 'center', |
|||
}, |
|||
series: [ |
|||
{ |
|||
name: '全区水质达标率', |
|||
type: 'pie', |
|||
radius: ['40%', '70%'], |
|||
avoidLabelOverlap: false, |
|||
label: { |
|||
show: false, |
|||
position: 'center', |
|||
}, |
|||
labelLine: { |
|||
show: false, |
|||
}, |
|||
data: [ |
|||
{ value: 800, name: '达标数' }, |
|||
{ value: 200, name: '未达标' }, |
|||
], |
|||
}, |
|||
], |
|||
graphic: { |
|||
elements: [ |
|||
{ |
|||
type: 'text', |
|||
left: 'center', // 水平居中 |
|||
bottom: '5%', // 调整位置,在饼图和图例之间 |
|||
style: { |
|||
text: '良好', |
|||
fontSize: 20, |
|||
fontWeight: 'bold', |
|||
fill: '#00a854', |
|||
align: 'center', |
|||
}, |
|||
}, |
|||
], |
|||
}, |
|||
}); |
|||
setOptions3({ |
|||
tooltip: { |
|||
trigger: 'item', |
|||
formatter: '{a} <br/>{b}: {c} ({d}%)', // {d}% 表示百分比 |
|||
}, |
|||
legend: { |
|||
top: '5%', |
|||
left: 'center', |
|||
}, |
|||
series: [ |
|||
{ |
|||
name: '河道统计', |
|||
type: 'pie', |
|||
radius: ['40%', '70%'], |
|||
avoidLabelOverlap: false, |
|||
label: { |
|||
show: false, |
|||
position: 'center', |
|||
}, |
|||
labelLine: { |
|||
show: false, |
|||
}, |
|||
data: [ |
|||
{ value: 42, name: '河长' }, |
|||
{ value: 20, name: '工作人员' }, |
|||
{ value: 10, name: '公示牌' }, |
|||
{ value: 3, name: '排污口数量' }, |
|||
], |
|||
}, |
|||
], |
|||
}); |
|||
}, |
|||
{ immediate: true }, |
|||
); |
|||
</script> |
|||
<style lang="less"> |
|||
.tabBox { |
|||
margin: 20px; |
|||
} |
|||
</style> |
Loading…
Reference in new issue