init
This commit is contained in:
2025-06-27 17:42:38 +08:00
commit bd6402478b
5317 changed files with 785994 additions and 0 deletions
@@ -0,0 +1,604 @@
<template>
<div class="outer-d">
<div class="top-title"> 长庆油田环境监测设备 </div>
<div class="map-d">
<template v-if="!loading">
<service-map
ref="serviceMap"
:map-list="mapList"
:marker-content="null"
:label-content="labelContent"
@get-marker-info="getMarkerInfo"
@get-detail="getDetail"
id="meterId"
/>
<div class="search-d">
所属单位
<ApiSelect
:value="orgCode"
:api="allSecondaryDepartsNew"
@change="
(v) => {
orgCode = v;
}
"
resultField="result"
labelField="departName"
valueField="orgCode"
:after-fetch="
(data) => {
data.unshift({
orgCode: '1',
departName: '全部单位',
});
return data;
}
"
:allowClear="true"
:show-default-value="false"
:immediate="true"
:showSearch="true"
:filterOption="
(input: string, option: any): boolean => {
const str: string = input.toLowerCase();
return option.label.toLowerCase().indexOf(str) >= 0;
}"
style="width: 260px"
/>
<a-button type="primary" @click="searchB">查询</a-button>
<a-button style="background-color: #a4adb3; color: #ffffff" @click="resetB">重置</a-button>
</div>
<div class="z" v-if="radioValue !== '3'">
<div class="inner" v-if="radioValue === '0'"></div>
<div class="outer" v-if="radioValue === '1'"></div>
<div class="water" v-if="radioValue === '3'"></div>
<div class="pollen" v-if="radioValue === '2'"></div>
<div class="z-d">
<div v-for="(item, index) in describe[radioValue]" :key="`describe${index}`">
{{ item }}
</div>
</div>
</div>
<div class="z" style="height: 100px; flex-direction: column; justify-content: space-around" v-else>
<div style="display: flex; color: #ffffff; font-weight: bold">
<div style="background-color: #00ff1a; width: 20px; height: 20px; border-radius: 6px; margin-right: 10px"></div>
<div>达标</div>
</div>
<div style="display: flex; color: #ffffff; font-weight: bold">
<div style="background-color: #ec0808; width: 20px; height: 20px; border-radius: 6px; margin-right: 10px"></div>
<div>不达标</div>
</div>
</div>
<a-radio-group v-model:value="radioValue" button-style="solid" class="radio-group-d" @change="initList">
<a-radio-button value="0">室内环境</a-radio-button>
<a-radio-button value="1">室外环境</a-radio-button>
<a-radio-button value="3">水质监测</a-radio-button>
<a-radio-button value="2">过敏源监测</a-radio-button>
</a-radio-group>
<div class="bottom-d">
<div
class="bottom-d-item"
v-for="(item, index) in deviceInfo"
:key="`bottom-d-item-${index}`"
:style="{ margin: index === 1 ? '0 25px 0 50px' : index === 2 ? '0 50px 0 25px' : 0 }"
>
<div>
<span>运行正常:{{ item.working }}台</span>
<span
style="color: red; cursor: pointer"
@click="
() => {
openModalA(true, {
type: item?.value,
title: item?.name,
orgCode: orgCode === '1' ? '' : orgCode,
});
}
"
>异常列表</span
>
</div>
<div style="font-size: 30px; font-weight: bold; display: flex; justify-content: center">
<div style="position: relative">
{{ item.sum }}
<span style="font-size: 16px; margin-left: -7px">台</span>
</div>
</div>
<div style="display: flex; justify-content: center; align-items: center">
<div style="position: relative">
<div style="display: flex; align-items: center; position: absolute; top: 0; height: 100%; left: -30px">
<img :src="imgInfos[index]" alt="" style="width: 25px; height: 23px" />
</div>
{{ item?.name }}
</div>
</div>
</div>
</div>
</template>
<template v-else>
<div style="width: 100%; height: 100%; display: flex; align-items: center; justify-content: center">
<a-spin size="large" />
</div>
</template>
</div>
</div>
<environment-modal
@register="registerModal"
@close-modal="
() => {
count++;
}
"
/>
<environment-abnormal-modal @register="registerModalA" />
</template>
<script setup lang="ts">
import ServiceMap from '/@/views/archivesManage/institution/timeService/components/serviceMap.vue';
import { nextTick, onMounted, ref, onBeforeUnmount } from 'vue';
import { listApi, statisticsApi } from '/@/views/archivesManage/institution/timeService/environment/environment.api';
import { getName } from '/@/views/interveneNew/compoents/utils';
import ApiSelect from '/@/components/Form/src/components/ApiSelect.vue';
import { allSecondaryDepartsNew } from '/@/utils/orgSearchInfo';
import EnvironmentModal from '/@/views/archivesManage/institution/timeService/components/environmentModal.vue';
import { useModal } from '/@/components/Modal';
import innerPng from '/@/assets/images/enviroment/institution/inner.png';
import outerPng from '/@/assets/images/enviroment/institution/outer.png';
import waterPng from '/@/assets/images/enviroment/institution/water.png';
import pollenPng from '/@/assets/images/enviroment/institution/pollen.png';
import innerPngS from '/@/assets/images/enviroment/institution/inner-s.png';
import outerPngS from '/@/assets/images/enviroment/institution/outer-s.png';
import waterPngS from '/@/assets/images/enviroment/institution/water-s.png';
import pollenPngS from '/@/assets/images/enviroment/institution/pollen-s.png';
import EnvironmentAbnormalModal from '/@/views/archivesManage/institution/timeService/environment/components/environmentAbnormalModal.vue';
const [registerModal, { openModal }] = useModal();
const [registerModalA, { openModal: openModalA }] = useModal();
const imgInfo = ref({
'0': innerPng,
'1': outerPng,
'3': waterPng,
'2': pollenPng,
});
const imgInfos = ref({
0: innerPngS,
1: outerPngS,
2: waterPngS,
3: pollenPngS,
});
const describe = ref({
'0': ['清洁', '未污染', '轻污染', '中污染', '重污染'],
'1': ['优', '良', '轻度污染', '中度污染', '重度污染', '严重污染'],
'3': ['达标', '不达标'],
'2': ['很低', '低', '中等', '高', '很高'],
});
const colorInfo = ref({
'0': [
{ value: 1, label: '#66c706' },
{ value: 2, label: '#f5cc27' },
{ value: 3, label: '#fe8700' },
{ value: 4, label: '#e60707' },
{ value: 5, label: '#940654' },
],
'1': [
{ value: 1, label: '#66c706' },
{ value: 2, label: '#f5cc27' },
{ value: 3, label: '#fe8700' },
{ value: 4, label: '#e60707' },
{ value: 5, label: '#65001c' },
{ value: 6, label: '#65001c' },
],
'3': [
{ value: 0, label: '#ec0808' },
{ value: 1, label: '#66c706' },
],
'2': [
{ value: 1, label: '#66c706' },
{ value: 2, label: '#f5cc27' },
{ value: 3, label: '#fe8700' },
{ value: 4, label: '#e60707' },
{ value: 5, label: '#65001c' },
],
});
const level = ref({
'0': [
{ value: 1, label: 'I级' },
{ value: 2, label: 'II级' },
{ value: 3, label: 'III级' },
{ value: 4, label: 'IV级' },
{ value: 5, label: 'V级' },
],
'1': [
{ value: 1, label: '一级' },
{ value: 2, label: '二级' },
{ value: 3, label: '三级' },
{ value: 4, label: '四级' },
{ value: 5, label: '五级' },
{ value: 5, label: '六级' },
],
'3': [
{ value: 0, label: '不合格' },
{ value: 1, label: '合格' },
],
});
const loading = ref(true);
const radioValue = ref('0');
const serviceMap = ref();
const mapList = ref<any[]>([]);
const labelContent = ref('');
const deviceInfo = ref({});
const orgCode = ref('1');
const count = ref(0);
function getMarkerInfo(e) {
let color = e.newData ? getName(e.newData.score, colorInfo.value[radioValue.value]) : 'red';
switch (radioValue.value) {
case '0':
labelContent.value = innerDoor(e, color);
break;
case '1':
labelContent.value = outerDoor(e, color);
break;
case '3':
labelContent.value = water(e, color);
break;
case '2':
labelContent.value = pollen(e, color);
break;
}
serviceMap.value.setLabel(labelContent.value);
}
function innerDoor(e, color) {
return `
<div style="background-color: #ffffff; padding: 10px; border-radius: 10px;z-index: 999">
<div style="display: flex; align-items: center">
<div>
<div style="font-size: 18px; font-weight: bold">${e.meterName}</div>
<div style="margin-top: 10px">单位名称:${e.orgName || '-'}</div>
<div style="margin-top: 10px">综合指数:${e.newData ? Math.round(e.newData.compositeIndex * 100) / 100 : '-'}</div>
<div style="margin-top: 10px;">空气质量级别:${e.newData ? getName(e.newData.score, level.value[radioValue.value]) : '-'}</div>
<div style="margin-top: 10px;">更新时间:${e.lastMonitorDate || '-'}</div>
</div>
<div style="margin-left: 10px">
<div style="padding: 30px; border-radius: 50%; border: 5px solid ${color}">
<div style="text-align: center; font-size: 12px">空气质量</div>
<div style="text-align: center; font-size: 19px; font-weight: bold; color: green;margin-top: 10px">
${e.newData?.score_dictText || '-'}
</div>
</div>
</div>
</div>
<div style="padding: 5px 0 0;
border-top: 1px dashed #cecece;
margin: 5px 0 0;">
设备地址:${e?.meterAddress || '-'}
</div>
<div style="text-align: center;height: 30px;line-height: 30px;" onclick="getDetail('${e.meterCode}')">
<span style="cursor: pointer;color: #2189ff">查看监测数据></span>
</div>
</div>
`;
}
function outerDoor(e, color) {
return `
<div style="background-color: #ffffff; padding: 10px; border-radius: 10px;z-index: 999">
<div style="display: flex; align-items: center">
<div>
<div style="font-size: 18px; font-weight: bold">${e.meterName}</div>
<div style="margin-top: 10px">单位名称:${e.orgName || '-'}</div>
<div style="margin-top: 10px">空气质量指数(AQI)${e?.newData?.compositeIndex || '-'}</div>
<div style="margin-top: 10px;">空气质量级别:${e.newData ? getName(e.newData.score, level.value[radioValue.value]) : '-'}</div>
<div style="margin-top: 10px;">更新时间:${e.lastMonitorDate || '-'}</div>
</div>
<div style="margin-left: 10px">
<div style="padding: 30px; border-radius: 50%; border: 5px solid ${color}">
<div style="text-align: center; font-size: 12px">空气质量评价</div>
<div style="text-align: center; font-size: 19px; font-weight: bold; color: green;margin-top: 10px">
${e.newData?.score_dictText || '-'}
</div>
</div>
</div>
</div>
<div style="padding: 5px 0 0;
border-top: 1px dashed #cecece;
margin: 5px 0 0;">
设备地址:${e?.meterAddress || '-'}
</div>
<div style="text-align: center;height: 30px;line-height: 30px;" onclick="getDetail('${e.meterCode}')">
<span style="cursor: pointer;color: #2189ff">查看监测数据></span>
</div>
</div>
`;
}
function water(e, color) {
return `
<div style="background-color: #ffffff; padding: 10px; border-radius: 10px;z-index: 999">
<div style="display: flex; align-items: center">
<div>
<div style="font-size: 18px; font-weight: bold">${e.meterName}</div>
<div style="margin-top: 10px">单位名称:${e.orgName || '-'}</div>
<div style="margin-top: 10px">TDS${e.newData?.tds || '-'}</div>
<div style="margin-top: 10px;">PH${e.newData?.ph || '-'}</div>
<div style="margin-top: 10px;">电导率:${e.newData?.conductivity || '-'}</div>
<div style="margin-top: 10px;">更新时间:${e.lastMonitorDate || '-'}</div>
</div>
<div style="margin-left: 10px">
<div style="padding: 30px; border-radius: 50%; border: 5px solid ${color}">
<div style="text-align: center; font-size: 12px">空气质量评价</div>
<div style="text-align: center; font-size: 19px; font-weight: bold; color: green;margin-top: 10px">
${e.newData?.score_dictText || '-'}
</div>
</div>
</div>
</div>
<div style="padding: 5px 0 0;
border-top: 1px dashed #cecece;
margin: 5px 0 0;">
设备地址:${e?.meterAddress || '-'}
</div>
<div style="text-align: center;height: 30px;line-height: 30px;" onclick="getDetail('${e.meterCode}')">
<span style="cursor: pointer;color: #2189ff">查看监测数据></span>
</div>
</div>
`;
}
function pollen(e, color) {
return `
<div style="background-color: #ffffff; padding: 10px; border-radius: 10px;z-index: 999">
<div style="display: flex; align-items: center">
<div>
<div style="font-size: 18px; font-weight: bold">${e.meterName}</div>
<div style="margin-top: 10px">单位名称:${e.orgName || '-'}</div>
<div style="margin-top: 10px">花粉浓度:${e.newData?.totalPollen || '-'}</div>
<div style="margin-top: 10px;">主要过敏源:${e.newData?.majorAllergens || '-'}</div>
<div style="margin-top: 10px;">更新时间:${e.lastMonitorDate || '-'}</div>
</div>
<div style="margin-left: 10px">
<div style="padding: 30px; border-radius: 50%; border: 5px solid ${color}">
<div style="text-align: center; font-size: 12px">空气质量评价</div>
<div style="text-align: center; font-size: 19px; font-weight: bold; color: green;margin-top: 10px">
${e.newData?.score_dictText || '-'}
</div>
</div>
</div>
</div>
<div style="padding: 5px 0 0;
border-top: 1px dashed #cecece;
margin: 5px 0 0;">
设备地址:${e?.meterAddress || '-'}
</div>
<div style="text-align: center;height: 30px;line-height: 30px;" onclick="getDetail('${e.meterCode}')">
<span style="cursor: pointer;color: #2189ff">查看监测数据></span>
</div>
</div>
`;
}
function getDetail(e) {
openModal(true, {
typeId: radioValue.value,
meterCode: e.meterCode,
});
}
onMounted(async () => {
await initList();
loading.value = false;
await nextTick(() => {
serviceMap.value.initMap(mapList.value);
});
await getStatistics();
});
onBeforeUnmount(() => {
serviceMap.value.destroyMap();
});
async function getStatistics() {
try {
const res = await statisticsApi({ orgCode: orgCode.value === '1' ? '' : orgCode.value });
deviceInfo.value = [
{
sum: res?.indoorMeterSum || 0,
working: res?.indoorMeterWorking || 0,
name: '室内环境',
value: '0',
},
{
sum: res?.outdoorMeterSum || 0,
working: res?.outdoorMeterWorking || 0,
name: '室外环境',
value: '1',
},
{
sum: res?.waterQualityMeterSum || 0,
working: res?.waterQualityMeterWorking || 0,
name: '水质监测设备',
value: '3',
},
{
sum: res?.pollenMeterSum || 0,
working: res?.pollenMeterWorking || 0,
name: '过敏源监测设备',
value: '2',
},
];
} catch (e) {
console.log(e);
}
}
async function initList() {
try {
mapList.value = (await listApi({ type: radioValue.value, orgCode: orgCode.value === '1' ? '' : orgCode.value })).map((item) => {
let color = item.newData ? getName(item.newData.score, colorInfo.value[radioValue.value]) : 'red';
item['img'] = imgInfo.value[radioValue.value];
item[
'markerContent'
] = `<div style="white-space: nowrap;display: flex;background-color: ${color};padding: 5px 10px;border-radius: 10px">
<img src="${imgInfo.value[radioValue.value]}" alt="" style="width: 20px;height: 20px; margin-right: 5px"/>
<span style="color: #ffffff">${
item.newData
? item.newData.score_dictText +
(radioValue.value !== '3' ? '(' + item.newData[radioValue.value !== '2' ? 'compositeIndex' : 'totalPollen'] + ')' : '')
: '暂无数据'
}</span>
</div>`;
return item;
});
} catch (e) {
mapList.value = [];
console.log(e);
}
}
async function searchB() {
await initList();
await getStatistics();
}
async function resetB() {
orgCode.value = '1';
await searchB();
}
</script>
<style scoped lang="less">
.outer-d {
position: relative;
width: 100%;
height: 100%;
}
.top-title {
padding: 10px;
text-align: center;
font-size: 20px;
}
.search-d {
box-shadow: 2px 2px 0 0 rgba(0, 0, 0, 0.35);
border-radius: 5px;
background-color: #ffffff;
padding: 10px 20px;
position: absolute;
top: 10px;
left: 10px;
z-index: 99;
> :nth-child(n + 1) {
margin-left: 10px;
}
}
.radio-group-d {
position: absolute;
top: 20px;
right: 10px;
z-index: 99;
}
.bottom-d {
border-radius: 5px;
width: 100%;
position: absolute;
bottom: 8%;
left: 0;
z-index: 99;
display: flex;
align-items: center;
justify-content: center;
.bottom-d-item {
width: 200px;
border-radius: 5px;
box-shadow: 2px 2px 4px 1px rgba(0, 0, 0, 0.35);
background-color: #ffffff;
> div {
width: 100%;
text-align: center;
&:nth-child(1) {
color: green;
text-align: left;
padding: 5px 15px 0;
display: flex;
justify-content: space-between;
}
&:nth-child(2) {
font-size: 18px;
font-weight: bold;
padding: 3px 0 3px 0;
}
&:nth-child(3) {
font-size: 18px;
font-weight: bold;
padding: 0 0 10px 0;
}
}
}
}
.map-d {
position: absolute;
width: calc(100% - 20px);
height: calc(100% - 70px);
top: 50px;
left: 10px;
}
.z {
position: absolute;
top: 100px;
right: 50px;
background-color: rgba(#8c8c8c, 0.5);
border-radius: 10px;
padding: 10px 30px 10px 10px;
display: flex;
height: 300px;
.inner {
width: 15px;
height: 100%;
border-radius: 7px;
background: linear-gradient(#02fb1b 0, #2ab539 25%, #f7e303 50%, #fe8a02 75%, #ed1507 100%);
}
.outer {
width: 15px;
height: 100%;
border-radius: 7px;
background: linear-gradient(#0efe19 0, #fed302 20%, #fe8702 40%, #ef1b07 60%, #962e91 80%, #3d095f 100%);
}
.pollen {
width: 15px;
height: 100%;
border-radius: 7px;
background: linear-gradient(#01fbe2 0, #36ce20 25%, #f3df04 50%, #fe8902 75%, #ed1008 100%);
}
.z-d {
height: 100%;
display: flex;
flex-direction: column;
justify-content: space-between;
padding-left: 8px;
color: #ffffff;
font-weight: bold;
}
}
:deep(.ant-radio-button-wrapper) {
color: #1684fc !important;
border-color: #1684fc !important;
&:before {
background-color: #1684fc !important;
}
}
:deep(.ant-radio-button-wrapper-checked) {
color: #ffffff !important;
}
</style>