添加统计图

This commit is contained in:
yangjun 2025-09-02 20:48:33 +08:00
parent f7722ea708
commit bc48ba4734
16 changed files with 2060 additions and 0 deletions

View File

@ -3,6 +3,7 @@ import { defHttp } from '/@/utils/http/axios';
enum Api {
slcx = '/exportapi/homeApi/slcx',
cqglfgswd = '/exportapi/homeApi/cqglfgswd',
getStaticList = '/exportapi/homeApi/getStaticList',
glfzb = '/exportapi/homeApi/glfzb',
}
@ -21,6 +22,9 @@ export const slcx = () => {
export const cqglfgswd = () => {
return defHttp.post({ url: Api.cqglfgswd });
};
export const getStaticList = (params) => {
return defHttp.post({ url: Api.getStaticList,params });
};
/**
*

View File

@ -0,0 +1,184 @@
<template>
<div ref="cityChartRef" ></div>
</template>
<script lang="ts" setup>
import { ref, onMounted, nextTick, onUnmounted } from 'vue';
import * as echarts from 'echarts';
import { slcx, cqglfgswd } from '/@/api/dashboard/api';
/* ---- dom refs ---- */
const cityChartRef = ref<HTMLElement | null>(null);
const countyFlowChartRef = ref<HTMLElement | null>(null);
/* ---- echarts instances & options ---- */
let cityChart: echarts.ECharts | null = null;
let countyChart: echarts.ECharts | null = null;
let countyPowerChart: echarts.ECharts | null = null;
let countyFlowChart: echarts.ECharts | null = null;
let cityOption: any = null;
let countyOption: any = null;
let countyPowerOption: any = null;
let countyFlowOption: any = null;
/* ---- helpers ---- */
function safeNum(v: any) {
if (v === null || v === undefined || v === '') return null;
const n = Number(v);
return Number.isNaN(n) ? null : n;
}
function sortByTime(arr: any[]) {
return [...arr].sort((a, b) => {
const ta = new Date(a.datatime || a.view032 || '').getTime();
const tb = new Date(b.datatime || b.view032 || '').getTime();
return (isNaN(ta) ? 0 : ta) - (isNaN(tb) ? 0 : tb);
});
}
function splitByRegion(data: any[]) {
const city = data.filter(d => String(d.regionType).includes('城区'));
const county = data.filter(d => String(d.regionType).includes('郊县'));
return { city: sortByTime(city), county: sortByTime(county) };
}
function buildXAxis(records: any[], key = 'view028') {
return records.map((r: any) => {
return ((r[key] ?? '').toString().replace(/锅炉房/g, '')).trim();
});
}
/* ---- build options折线改为直线 smooth: false ---- */
function prepareOptions(records: any[]) {
const { city, county } = splitByRegion(records);
const cityX = buildXAxis(city, 'view028');
const citySW = city.map((r: any) => safeNum(r.view005));
const cityHW = city.map((r: any) => safeNum(r.view006));
cityOption = {
title: { text: '城区供/回水温度【实时】', left: 'center', top: 10 },
tooltip: { trigger: 'axis' },
legend: { top: 36, left: 'center' },
grid: { left: '6%', right: '4%', bottom: 70, top: 70, containLabel: true },
xAxis: { type: 'category', data: cityX, axisLabel: { rotate: 20 } },
yAxis: { type: 'value', name: '℃' },
series: [
{ name: '供水温度', type: 'line', data: citySW, smooth: false, showSymbol: false, lineStyle: { type: 'solid' } },
{ name: '回水温度', type: 'line', data: cityHW, smooth: false, showSymbol: false, lineStyle: { type: 'solid' } }
],
color: ['#176AB3', '#2F9E8A'] // 线
};
const countyX = buildXAxis(county, 'view028');
const countySW = county.map((r: any) => safeNum(r.view035));
const countyHW = county.map((r: any) => safeNum(r.view036));
countyOption = {
title: { text: '郊县供/回水温度【实时】', left: 'center', top: 10 },
tooltip: { trigger: 'axis' },
legend: { top: 36, left: 'center' },
grid: { left: '6%', right: '4%', bottom: 70, top: 70, containLabel: true },
xAxis: { type: 'category', data: countyX, axisLabel: { rotate: 20 } },
yAxis: { type: 'value', name: '℃' },
series: [
{ name: '供水温度', type: 'line', data: countySW, smooth: false, showSymbol: false, lineStyle: { type: 'solid' } },
{ name: '回水温度', type: 'line', data: countyHW, smooth: false, showSymbol: false, lineStyle: { type: 'solid' } }
],
color: ['#D64545', '#12A0A6']
};
const powerY = county.map((r: any) => safeNum(r.view041));
countyPowerOption = {
title: { text: '', left: 'center', top: 8 },
tooltip: { trigger: 'axis' },
grid: { left: '6%', right: '6%', bottom: 60, top: 50, containLabel: true },
xAxis: { type: 'category', data: countyX, axisLabel: { rotate: 20 } },
yAxis: { type: 'value', name: '瞬时热量' },
series: [{ name: '瞬时热量', type: 'line', data: powerY, smooth: false, areaStyle: {}, showSymbol: false, lineStyle: { type: 'solid' } }],
color: ['#E89B3B']
};
const flowY = county.map((r: any) => safeNum(r.view037));
countyFlowOption = {
title: { text: '', left: 'center', top: 8 },
tooltip: { trigger: 'axis' },
grid: { left: '6%', right: '6%', bottom: 60, top: 50, containLabel: true },
xAxis: { type: 'category', data: countyX, axisLabel: { rotate: 20 } },
yAxis: { type: 'value', name: '瞬时流量' },
series: [{ name: '瞬时流量', type: 'line', data: flowY, smooth: false, showSymbol: false, lineStyle: { type: 'solid' } }],
color: ['#7C55FF']
};
}
/* ---- lazy init & resize ---- */
let resizeAdded = false;
function ensureResize() {
if (resizeAdded) return;
const onResize = () => {
cityChart?.resize();
countyChart?.resize();
countyPowerChart?.resize();
countyFlowChart?.resize();
};
window.addEventListener('resize', onResize);
onUnmounted(() => window.removeEventListener('resize', onResize));
resizeAdded = true;
}
function initCityIfNeed() {
if (!cityChart && cityChartRef.value && cityOption) {
cityChart = echarts.init(cityChartRef.value);
cityChart.setOption(cityOption);
} else {
cityChart?.resize();
}
}
function onTabChange(key: string) {
nextTick(() => {
if (key === 'city') {
if (!cityChart && cityChartRef.value) {
cityChart = echarts.init(cityChartRef.value);
}
cityChart?.setOption(cityOption, true);
cityChart?.resize();
} else if (key === 'county') {
countyChart?.setOption(countyOption, true);
countyChart?.resize();
}
});
}
let timer: number | null = null;
/* ---- load data ---- */
async function loadData() {
try {
// 2.
const r = await cqglfgswd();
const records = r?.data ?? [];
prepareOptions(records);
// 3. DOM
await nextTick();
// 4.
if (!cityChart && cityChartRef.value) {
cityChart = echarts.init(cityChartRef.value);
}
cityChart?.setOption(cityOption, true);
// 5.
ensureResize();
} catch (err) {
console.error('load error', err);
}
}
onMounted(() => {
loadData();
});
</script>
<style scoped>
</style>

View File

@ -0,0 +1,113 @@
<template>
<div class="container2">
<div ref="cityChartRef" style="width: 100%; height: 600px;"></div>
</div>
</template>
<script lang="ts" setup>
import { ref, onMounted, nextTick, onUnmounted } from 'vue';
import * as echarts from 'echarts';
import { cqglfgswd,getStaticList } from '/@/api/dashboard/api';
/* ---- dom refs ---- */
const cityChartRef = ref<HTMLElement | null>(null);
/* ---- echarts instances & options ---- */
let cityChart: echarts.ECharts | null = null;
let cityOption: any = null;
/* ---- helpers ---- */
function safeNum(v: any) {
if (v === null || v === undefined || v === '') return null;
const n = Number(v);
return Number.isNaN(n) ? null : n;
}
function sortByTime(arr: any[]) {
return [...arr].sort((a, b) => {
const ta = new Date(a.datatime || a.view032 || '').getTime();
const tb = new Date(b.datatime || b.view032 || '').getTime();
return (isNaN(ta) ? 0 : ta) - (isNaN(tb) ? 0 : tb);
});
}
function splitByRegion(data: any[]) {
const city = data.filter(d => String(d.regionType).includes('城区'));
return { city: sortByTime(city) };
}
function buildXAxis(records: any[], key = 'view028') {
return records.map((r: any) => {
return ((r[key] ?? '').toString().replace(/锅炉房/g, '')).trim();
});
}
/* ---- build options折线改为直线 smooth: false ---- */
function prepareOptions(records: any[]) {
console.log("🚀 ~ prepareOptions ~ records:", records)
const { city } = splitByRegion(records);
console.log("🚀 ~ prepareOptions ~ city:", city)
const cityX = buildXAxis(city, 'view028');
console.log("🚀 ~ prepareOptions ~ cityX:", cityX)
const citySW = city.map((r: any) => safeNum(r.view005));
const cityHW = city.map((r: any) => safeNum(r.view006));
cityOption = {
title: { text: '城区锅炉房供/回水温度', left: 'center', top: 10 },
tooltip: { trigger: 'axis' },
legend: { top: 36, left: 'center' },
grid: { left: '6%', right: '4%', bottom: 70, top: 70, containLabel: true },
xAxis: { type: 'category', data: cityX, axisLabel: { rotate: 20 } },
yAxis: { type: 'value', name: '℃' },
series: [
{ name: '供水温度', type: 'line', data: citySW, smooth: false, showSymbol: false, lineStyle: { type: 'solid' } },
{ name: '回水温度', type: 'line', data: cityHW, smooth: false, showSymbol: false, lineStyle: { type: 'solid' } }
],
color: ['#176AB3', '#2F9E8A'] // 线
};
}
/* ---- lazy init & resize ---- */
let resizeAdded = false;
function ensureResize() {
if (resizeAdded) return;
const onResize = () => {
cityChart?.resize();
};
window.addEventListener('resize', onResize);
onUnmounted(() => window.removeEventListener('resize', onResize));
resizeAdded = true;
}
/* ---- load data ---- */
async function loadData() {
try {
// 1.
// 2.
const r = await cqglfgswd();
const records = r?.data ?? [];
prepareOptions(records);
// 3. DOM
await nextTick();
cityChart = echarts.init(cityChartRef.value);
cityChart?.setOption(cityOption, true);
// 5.
ensureResize();
} catch (err) {
console.error('load error', err);
}
}
onMounted(() => {
loadData();
});
</script>
<style scoped lang="less">
.container2 {
display: flex;
align-items: center; /* 垂直居中 */
justify-content: center; /* 水平居中 */
height: calc(100vh - 120px); /* 需要设置容器高度 */
background: white;
}
</style>

View File

@ -0,0 +1,145 @@
<template>
<div style="background-color: #fff;padding:14px;height: 100%;">
<a-row :span="24" style="margin-top:10px;">
<a-col :span="4" style="padding-left: 30px;">
<a-select ref="select"
placeholder="选择锅炉房"
v-model:value="queryParam.sourceId"
style="width: 155px;"
@focus="focus"
@change="handleChange">
<a-select-option :value="item.sourceId" v-for="item in heatsource" :key="item.id">{{item.sourceName}}</a-select-option>
</a-select>
</a-col>
<a-col :span="4">
<a-date-picker v-model:value="queryParam.startDate" value-format="YYYY-MM" picker="month" placeholder="请选择时间" @change="handleChange" />
</a-col>
<a-col :span="24" >
<div ref="cityChartRef" style="width: 100%; height: 600px;"></div>
</a-col>
</a-row>
</div>
</template>
<script lang="ts" setup>
import { ref, onMounted, nextTick, onUnmounted } from 'vue';
import * as echarts from 'echarts';
import { cqglfgswd,getStaticList } from '/@/api/dashboard/api';
import { heatsourcelist } from "@/views/base/simconfig/Simconfig.api";
import dayjs from 'dayjs';
/* ---- dom refs ---- */
const cityChartRef = ref<HTMLElement | null>(null);
/* ---- echarts instances & options ---- */
let cityChart: echarts.ECharts | null = null;
let cityOption: any = null;
const queryParam = ref<any>({});
/* ---- helpers ---- */
function safeNum(v: any) {
if (v === null || v === undefined || v === '') return null;
const n = Number(v);
return Number.isNaN(n) ? null : n;
}
function sortByTime(arr: any[]) {
return [...arr].sort((a, b) => {
const ta = new Date(a.datatime || a.view032 || '').getTime();
const tb = new Date(b.datatime || b.view032 || '').getTime();
return (isNaN(ta) ? 0 : ta) - (isNaN(tb) ? 0 : tb);
});
}
const heatsource = ref();
async function getHeatsource(){
heatsource.value = await heatsourcelist({regionType: '城区'});
}
async function handleChange(){
loadData();
}
function splitByRegion(data: any[]) {
const city = data.filter(d => String(d.regionType).includes('城区'));
return { city: sortByTime(city) };
}
function buildXAxis(records: any[], key = 'view028') {
return records.map((r: any) => {
return ((r[key] ?? '').toString().replace(/锅炉房/g, '')).trim();
});
}
/* ---- build options折线改为直线 smooth: false ---- */
function prepareOptions(records: any[]) {
const { city } = splitByRegion(records);
const cityX = buildXAxis(city, 'datatime');
const citySW = city.map((r: any) => safeNum(r.view005));
const cityHW = city.map((r: any) => safeNum(r.view006));
cityOption = {
title: { text: '城区锅炉房历史供/回水温度', left: 'center', top: 10 },
tooltip: { trigger: 'axis' },
legend: { top: 36, left: 'center' },
grid: { left: '6%', right: '4%', bottom: 70, top: 70, containLabel: true },
xAxis: { type: 'category', data: cityX, axisLabel: { rotate: 20 } },
yAxis: { type: 'value', name: '℃' },
series: [
{ name: '供水温度', type: 'line', data: citySW, smooth: false, showSymbol: false, lineStyle: { type: 'solid' } },
{ name: '回水温度', type: 'line', data: cityHW, smooth: false, showSymbol: false, lineStyle: { type: 'solid' } }
],
color: ['#176AB3', '#2F9E8A'] // 线
};
}
/* ---- lazy init & resize ---- */
let resizeAdded = false;
function ensureResize() {
if (resizeAdded) return;
const onResize = () => {
cityChart?.resize();
};
window.addEventListener('resize', onResize);
onUnmounted(() => window.removeEventListener('resize', onResize));
resizeAdded = true;
}
/* ---- load data ---- */
async function loadData() {
console.log("🚀 ~ loadData ~ queryParam.value:", queryParam.value)
queryParam.value.startTime = dayjs(queryParam.value.startDate).format('YYMM');
try {
// 1.
// 2.
const r = await getStaticList(queryParam.value);
const records = r?.data ?? [];
prepareOptions(records);
// 3. DOM
await nextTick();
cityChart = echarts.init(cityChartRef.value);
cityChart?.setOption(cityOption, true);
// 5.
ensureResize();
} catch (err) {
console.error('load error', err);
}
}
onMounted( async () => {
await getHeatsource()
var list = heatsource.value
queryParam.value.sourceId = list[0].sourceId
queryParam.value.startDate = dayjs().format('YYYY-MM');
loadData();
});
</script>
<style scoped lang="less">
.bjclass {
display: flex;
align-items: center; /* 垂直居中 */
justify-content: center; /* 水平居中 */
height: calc(100vh - 120px); /* 需要设置容器高度 */
background: white;
}
</style>

View File

@ -0,0 +1,113 @@
<template>
<div class="container2">
<div ref="cityChartRef" style="width: 100%; height: 600px;"></div>
</div>
</template>
<script lang="ts" setup>
import { ref, onMounted, nextTick, onUnmounted } from 'vue';
import * as echarts from 'echarts';
import { cqglfgswd,getStaticList } from '/@/api/dashboard/api';
/* ---- dom refs ---- */
const cityChartRef = ref<HTMLElement | null>(null);
/* ---- echarts instances & options ---- */
let cityChart: echarts.ECharts | null = null;
let cityOption: any = null;
/* ---- helpers ---- */
function safeNum(v: any) {
if (v === null || v === undefined || v === '') return null;
const n = Number(v);
return Number.isNaN(n) ? null : n;
}
function sortByTime(arr: any[]) {
return [...arr].sort((a, b) => {
const ta = new Date(a.datatime || a.view032 || '').getTime();
const tb = new Date(b.datatime || b.view032 || '').getTime();
return (isNaN(ta) ? 0 : ta) - (isNaN(tb) ? 0 : tb);
});
}
function splitByRegion(data: any[]) {
const city = data.filter(d => String(d.regionType).includes('郊县'));
return { city: sortByTime(city) };
}
function buildXAxis(records: any[], key = 'view028') {
return records.map((r: any) => {
return ((r[key] ?? '').toString().replace(/锅炉房/g, '')).trim();
});
}
/* ---- build options折线改为直线 smooth: false ---- */
function prepareOptions(records: any[]) {
console.log("🚀 ~ prepareOptions ~ records:", records)
const { city } = splitByRegion(records);
console.log("🚀 ~ prepareOptions ~ city:", city)
const cityX = buildXAxis(city, 'view028');
console.log("🚀 ~ prepareOptions ~ cityX:", cityX)
const citySW = city.map((r: any) => safeNum(r.view005));
const cityHW = city.map((r: any) => safeNum(r.view006));
cityOption = {
title: { text: '郊县锅炉房供/回水温度', left: 'center', top: 10 },
tooltip: { trigger: 'axis' },
legend: { top: 36, left: 'center' },
grid: { left: '6%', right: '4%', bottom: 70, top: 70, containLabel: true },
xAxis: { type: 'category', data: cityX, axisLabel: { rotate: 20 } },
yAxis: { type: 'value', name: '℃' },
series: [
{ name: '供水温度', type: 'line', data: citySW, smooth: false, showSymbol: false, lineStyle: { type: 'solid' } },
{ name: '回水温度', type: 'line', data: cityHW, smooth: false, showSymbol: false, lineStyle: { type: 'solid' } }
],
color: ['#176AB3', '#2F9E8A'] // 线
};
}
/* ---- lazy init & resize ---- */
let resizeAdded = false;
function ensureResize() {
if (resizeAdded) return;
const onResize = () => {
cityChart?.resize();
};
window.addEventListener('resize', onResize);
onUnmounted(() => window.removeEventListener('resize', onResize));
resizeAdded = true;
}
/* ---- load data ---- */
async function loadData() {
try {
// 1.
// 2.
const r = await cqglfgswd();
const records = r?.data ?? [];
prepareOptions(records);
// 3. DOM
await nextTick();
cityChart = echarts.init(cityChartRef.value);
cityChart?.setOption(cityOption, true);
// 5.
ensureResize();
} catch (err) {
console.error('load error', err);
}
}
onMounted(() => {
loadData();
});
</script>
<style scoped lang="less">
.container2 {
display: flex;
align-items: center; /* 垂直居中 */
justify-content: center; /* 水平居中 */
height: calc(100vh - 120px); /* 需要设置容器高度 */
background: white;
}
</style>

View File

@ -0,0 +1,145 @@
<template>
<div style="background-color: #fff;padding:14px;height: 100%;">
<a-row :span="24" style="margin-top:10px;">
<a-col :span="4" style="padding-left: 30px;">
<a-select ref="select"
placeholder="选择锅炉房"
v-model:value="queryParam.sourceId"
style="width: 155px;"
@focus="focus"
@change="handleChange">
<a-select-option :value="item.sourceId" v-for="item in heatsource" :key="item.id">{{item.sourceName}}</a-select-option>
</a-select>
</a-col>
<a-col :span="4">
<a-date-picker v-model:value="queryParam.startDate" value-format="YYYY-MM" picker="month" placeholder="请选择时间" @change="handleChange" />
</a-col>
<a-col :span="24" >
<div ref="cityChartRef" style="width: 100%; height: 600px;"></div>
</a-col>
</a-row>
</div>
</template>
<script lang="ts" setup>
import { ref, onMounted, nextTick, onUnmounted } from 'vue';
import * as echarts from 'echarts';
import { cqglfgswd,getStaticList } from '/@/api/dashboard/api';
import { heatsourcelist } from "@/views/base/simconfig/Simconfig.api";
import dayjs from 'dayjs';
/* ---- dom refs ---- */
const cityChartRef = ref<HTMLElement | null>(null);
/* ---- echarts instances & options ---- */
let cityChart: echarts.ECharts | null = null;
let cityOption: any = null;
const queryParam = ref<any>({});
/* ---- helpers ---- */
function safeNum(v: any) {
if (v === null || v === undefined || v === '') return null;
const n = Number(v);
return Number.isNaN(n) ? null : n;
}
function sortByTime(arr: any[]) {
return [...arr].sort((a, b) => {
const ta = new Date(a.datatime || a.view032 || '').getTime();
const tb = new Date(b.datatime || b.view032 || '').getTime();
return (isNaN(ta) ? 0 : ta) - (isNaN(tb) ? 0 : tb);
});
}
const heatsource = ref();
async function getHeatsource(){
heatsource.value = await heatsourcelist({regionType: '郊县'});
}
async function handleChange(){
loadData();
}
function splitByRegion(data: any[]) {
const city = data.filter(d => String(d.regionType).includes('郊县'));
return { city: sortByTime(city) };
}
function buildXAxis(records: any[], key = 'view028') {
return records.map((r: any) => {
return ((r[key] ?? '').toString().replace(/锅炉房/g, '')).trim();
});
}
/* ---- build options折线改为直线 smooth: false ---- */
function prepareOptions(records: any[]) {
const { city } = splitByRegion(records);
const cityX = buildXAxis(city, 'datatime');
const citySW = city.map((r: any) => safeNum(r.view005));
const cityHW = city.map((r: any) => safeNum(r.view006));
cityOption = {
title: { text: '郊县锅炉房历史供/回水温度', left: 'center', top: 10 },
tooltip: { trigger: 'axis' },
legend: { top: 36, left: 'center' },
grid: { left: '6%', right: '4%', bottom: 70, top: 70, containLabel: true },
xAxis: { type: 'category', data: cityX, axisLabel: { rotate: 20 } },
yAxis: { type: 'value', name: '℃' },
series: [
{ name: '供水温度', type: 'line', data: citySW, smooth: false, showSymbol: false, lineStyle: { type: 'solid' } },
{ name: '回水温度', type: 'line', data: cityHW, smooth: false, showSymbol: false, lineStyle: { type: 'solid' } }
],
color: ['#176AB3', '#2F9E8A'] // 线
};
}
/* ---- lazy init & resize ---- */
let resizeAdded = false;
function ensureResize() {
if (resizeAdded) return;
const onResize = () => {
cityChart?.resize();
};
window.addEventListener('resize', onResize);
onUnmounted(() => window.removeEventListener('resize', onResize));
resizeAdded = true;
}
/* ---- load data ---- */
async function loadData() {
console.log("🚀 ~ loadData ~ queryParam.value:", queryParam.value)
queryParam.value.startTime = dayjs(queryParam.value.startDate).format('YYMM');
try {
// 1.
// 2.
const r = await getStaticList(queryParam.value);
const records = r?.data ?? [];
prepareOptions(records);
// 3. DOM
await nextTick();
cityChart = echarts.init(cityChartRef.value);
cityChart?.setOption(cityOption, true);
// 5.
ensureResize();
} catch (err) {
console.error('load error', err);
}
}
onMounted( async () => {
await getHeatsource()
var list = heatsource.value
queryParam.value.sourceId = list[0].sourceId
queryParam.value.startDate = dayjs().format('YYYY-MM');
loadData();
});
</script>
<style scoped lang="less">
.bjclass {
display: flex;
align-items: center; /* 垂直居中 */
justify-content: center; /* 水平居中 */
height: calc(100vh - 120px); /* 需要设置容器高度 */
background: white;
}
</style>

View File

@ -0,0 +1,111 @@
<template>
<div class="container2">
<div ref="cityChartRef" style="width: 100%; height: 600px;"></div>
</div>
</template>
<script lang="ts" setup>
import { ref, onMounted, nextTick, onUnmounted } from 'vue';
import * as echarts from 'echarts';
import { cqglfgswd,getStaticList } from '/@/api/dashboard/api';
/* ---- dom refs ---- */
const cityChartRef = ref<HTMLElement | null>(null);
/* ---- echarts instances & options ---- */
let cityChart: echarts.ECharts | null = null;
let cityOption: any = null;
/* ---- helpers ---- */
function safeNum(v: any) {
if (v === null || v === undefined || v === '') return null;
const n = Number(v);
return Number.isNaN(n) ? null : n;
}
function sortByTime(arr: any[]) {
return [...arr].sort((a, b) => {
const ta = new Date(a.datatime || a.view032 || '').getTime();
const tb = new Date(b.datatime || b.view032 || '').getTime();
return (isNaN(ta) ? 0 : ta) - (isNaN(tb) ? 0 : tb);
});
}
function splitByRegion(data: any[]) {
const city = data.filter(d => String(d.regionType).includes('郊县'));
return { city: sortByTime(city) };
}
function buildXAxis(records: any[], key = 'view028') {
return records.map((r: any) => {
return ((r[key] ?? '').toString().replace(/锅炉房/g, '')).trim();
});
}
/* ---- build options折线改为直线 smooth: false ---- */
function prepareOptions(records: any[]) {
console.log("🚀 ~ prepareOptions ~ records:", records)
const { city } = splitByRegion(records);
console.log("🚀 ~ prepareOptions ~ city:", city)
const cityX = buildXAxis(city, 'view028');
console.log("🚀 ~ prepareOptions ~ cityX:", cityX)
const citySW = city.map((r: any) => safeNum(r.view037));
cityOption = {
title: { text: '郊县锅炉房热流量', left: 'center', top: 10 },
tooltip: { trigger: 'axis' },
legend: { top: 36, left: 'center' },
grid: { left: '6%', right: '4%', bottom: 70, top: 70, containLabel: true },
xAxis: { type: 'category', data: cityX, axisLabel: { rotate: 20 } },
yAxis: { type: 'value', name: 'Kj' },
series: [
{ name: '热流量', type: 'line', data: citySW, smooth: false, showSymbol: false, lineStyle: { type: 'solid' } },
],
color: ['#176AB3', '#2F9E8A'] // 线
};
}
/* ---- lazy init & resize ---- */
let resizeAdded = false;
function ensureResize() {
if (resizeAdded) return;
const onResize = () => {
cityChart?.resize();
};
window.addEventListener('resize', onResize);
onUnmounted(() => window.removeEventListener('resize', onResize));
resizeAdded = true;
}
/* ---- load data ---- */
async function loadData() {
try {
// 1.
// 2.
const r = await cqglfgswd();
const records = r?.data ?? [];
prepareOptions(records);
// 3. DOM
await nextTick();
cityChart = echarts.init(cityChartRef.value);
cityChart?.setOption(cityOption, true);
// 5.
ensureResize();
} catch (err) {
console.error('load error', err);
}
}
onMounted(() => {
loadData();
});
</script>
<style scoped lang="less">
.container2 {
display: flex;
align-items: center; /* 垂直居中 */
justify-content: center; /* 水平居中 */
height: calc(100vh - 120px); /* 需要设置容器高度 */
background: white;
}
</style>

View File

@ -0,0 +1,143 @@
<template>
<div style="background-color: #fff;padding:14px;height: 100%;">
<a-row :span="24" style="margin-top:10px;">
<a-col :span="4" style="padding-left: 30px;">
<a-select ref="select"
placeholder="选择锅炉房"
v-model:value="queryParam.sourceId"
style="width: 155px;"
@focus="focus"
@change="handleChange">
<a-select-option :value="item.sourceId" v-for="item in heatsource" :key="item.id">{{item.sourceName}}</a-select-option>
</a-select>
</a-col>
<a-col :span="4">
<a-date-picker v-model:value="queryParam.startDate" value-format="YYYY-MM" picker="month" placeholder="请选择时间" @change="handleChange" />
</a-col>
<a-col :span="24" >
<div ref="cityChartRef" style="width: 100%; height: 600px;"></div>
</a-col>
</a-row>
</div>
</template>
<script lang="ts" setup>
import { ref, onMounted, nextTick, onUnmounted } from 'vue';
import * as echarts from 'echarts';
import { cqglfgswd,getStaticList } from '/@/api/dashboard/api';
import { heatsourcelist } from "@/views/base/simconfig/Simconfig.api";
import dayjs from 'dayjs';
/* ---- dom refs ---- */
const cityChartRef = ref<HTMLElement | null>(null);
/* ---- echarts instances & options ---- */
let cityChart: echarts.ECharts | null = null;
let cityOption: any = null;
const queryParam = ref<any>({});
/* ---- helpers ---- */
function safeNum(v: any) {
if (v === null || v === undefined || v === '') return null;
const n = Number(v);
return Number.isNaN(n) ? null : n;
}
function sortByTime(arr: any[]) {
return [...arr].sort((a, b) => {
const ta = new Date(a.datatime || a.view032 || '').getTime();
const tb = new Date(b.datatime || b.view032 || '').getTime();
return (isNaN(ta) ? 0 : ta) - (isNaN(tb) ? 0 : tb);
});
}
const heatsource = ref();
async function getHeatsource(){
heatsource.value = await heatsourcelist({regionType: '郊县'});
}
async function handleChange(){
loadData();
}
function splitByRegion(data: any[]) {
const city = data.filter(d => String(d.regionType).includes('郊县'));
return { city: sortByTime(city) };
}
function buildXAxis(records: any[], key = 'view028') {
return records.map((r: any) => {
return ((r[key] ?? '').toString().replace(/锅炉房/g, '')).trim();
});
}
/* ---- build options折线改为直线 smooth: false ---- */
function prepareOptions(records: any[]) {
const { city } = splitByRegion(records);
const cityX = buildXAxis(city, 'datatime');
const citySW = city.map((r: any) => safeNum(r.view037));
cityOption = {
title: { text: '郊县锅炉房历史热流量', left: 'center', top: 10 },
tooltip: { trigger: 'axis' },
legend: { top: 36, left: 'center' },
grid: { left: '6%', right: '4%', bottom: 70, top: 70, containLabel: true },
xAxis: { type: 'category', data: cityX, axisLabel: { rotate: 20 } },
yAxis: { type: 'value', name: 'Kj' },
series: [
{ name: '热流量', type: 'line', data: citySW, smooth: false, showSymbol: false, lineStyle: { type: 'solid' } },
],
color: ['#176AB3', '#2F9E8A'] // 线
};
}
/* ---- lazy init & resize ---- */
let resizeAdded = false;
function ensureResize() {
if (resizeAdded) return;
const onResize = () => {
cityChart?.resize();
};
window.addEventListener('resize', onResize);
onUnmounted(() => window.removeEventListener('resize', onResize));
resizeAdded = true;
}
/* ---- load data ---- */
async function loadData() {
console.log("🚀 ~ loadData ~ queryParam.value:", queryParam.value)
queryParam.value.startTime = dayjs(queryParam.value.startDate).format('YYMM');
try {
// 1.
// 2.
const r = await getStaticList(queryParam.value);
const records = r?.data ?? [];
prepareOptions(records);
// 3. DOM
await nextTick();
cityChart = echarts.init(cityChartRef.value);
cityChart?.setOption(cityOption, true);
// 5.
ensureResize();
} catch (err) {
console.error('load error', err);
}
}
onMounted( async () => {
await getHeatsource()
var list = heatsource.value
queryParam.value.sourceId = list[0].sourceId
queryParam.value.startDate = dayjs().format('YYYY-MM');
loadData();
});
</script>
<style scoped lang="less">
.bjclass {
display: flex;
align-items: center; /* 垂直居中 */
justify-content: center; /* 水平居中 */
height: calc(100vh - 120px); /* 需要设置容器高度 */
background: white;
}
</style>

View File

@ -0,0 +1,111 @@
<template>
<div class="container2">
<div ref="cityChartRef" style="width: 100%; height: 600px;"></div>
</div>
</template>
<script lang="ts" setup>
import { ref, onMounted, nextTick, onUnmounted } from 'vue';
import * as echarts from 'echarts';
import { cqglfgswd,getStaticList } from '/@/api/dashboard/api';
/* ---- dom refs ---- */
const cityChartRef = ref<HTMLElement | null>(null);
/* ---- echarts instances & options ---- */
let cityChart: echarts.ECharts | null = null;
let cityOption: any = null;
/* ---- helpers ---- */
function safeNum(v: any) {
if (v === null || v === undefined || v === '') return null;
const n = Number(v);
return Number.isNaN(n) ? null : n;
}
function sortByTime(arr: any[]) {
return [...arr].sort((a, b) => {
const ta = new Date(a.datatime || a.view032 || '').getTime();
const tb = new Date(b.datatime || b.view032 || '').getTime();
return (isNaN(ta) ? 0 : ta) - (isNaN(tb) ? 0 : tb);
});
}
function splitByRegion(data: any[]) {
const city = data.filter(d => String(d.regionType).includes('郊县'));
return { city: sortByTime(city) };
}
function buildXAxis(records: any[], key = 'view028') {
return records.map((r: any) => {
return ((r[key] ?? '').toString().replace(/锅炉房/g, '')).trim();
});
}
/* ---- build options折线改为直线 smooth: false ---- */
function prepareOptions(records: any[]) {
console.log("🚀 ~ prepareOptions ~ records:", records)
const { city } = splitByRegion(records);
console.log("🚀 ~ prepareOptions ~ city:", city)
const cityX = buildXAxis(city, 'view028');
console.log("🚀 ~ prepareOptions ~ cityX:", cityX)
const citySW = city.map((r: any) => safeNum(r.view041));
cityOption = {
title: { text: '郊县锅炉房水流量', left: 'center', top: 10 },
tooltip: { trigger: 'axis' },
legend: { top: 36, left: 'center' },
grid: { left: '6%', right: '4%', bottom: 70, top: 70, containLabel: true },
xAxis: { type: 'category', data: cityX, axisLabel: { rotate: 20 } },
yAxis: { type: 'value', name: 'm³/s' },
series: [
{ name: '水流量', type: 'line', data: citySW, smooth: false, showSymbol: false, lineStyle: { type: 'solid' } },
],
color: ['#176AB3', '#2F9E8A'] // 线
};
}
/* ---- lazy init & resize ---- */
let resizeAdded = false;
function ensureResize() {
if (resizeAdded) return;
const onResize = () => {
cityChart?.resize();
};
window.addEventListener('resize', onResize);
onUnmounted(() => window.removeEventListener('resize', onResize));
resizeAdded = true;
}
/* ---- load data ---- */
async function loadData() {
try {
// 1.
// 2.
const r = await cqglfgswd();
const records = r?.data ?? [];
prepareOptions(records);
// 3. DOM
await nextTick();
cityChart = echarts.init(cityChartRef.value);
cityChart?.setOption(cityOption, true);
// 5.
ensureResize();
} catch (err) {
console.error('load error', err);
}
}
onMounted(() => {
loadData();
});
</script>
<style scoped lang="less">
.container2 {
display: flex;
align-items: center; /* 垂直居中 */
justify-content: center; /* 水平居中 */
height: calc(100vh - 120px); /* 需要设置容器高度 */
background: white;
}
</style>

View File

@ -0,0 +1,143 @@
<template>
<div style="background-color: #fff;padding:14px;height: 100%;">
<a-row :span="24" style="margin-top:10px;">
<a-col :span="4" style="padding-left: 30px;">
<a-select ref="select"
placeholder="选择锅炉房"
v-model:value="queryParam.sourceId"
style="width: 155px;"
@focus="focus"
@change="handleChange">
<a-select-option :value="item.sourceId" v-for="item in heatsource" :key="item.id">{{item.sourceName}}</a-select-option>
</a-select>
</a-col>
<a-col :span="4">
<a-date-picker v-model:value="queryParam.startDate" value-format="YYYY-MM" picker="month" placeholder="请选择时间" @change="handleChange" />
</a-col>
<a-col :span="24" >
<div ref="cityChartRef" style="width: 100%; height: 600px;"></div>
</a-col>
</a-row>
</div>
</template>
<script lang="ts" setup>
import { ref, onMounted, nextTick, onUnmounted } from 'vue';
import * as echarts from 'echarts';
import { cqglfgswd,getStaticList } from '/@/api/dashboard/api';
import { heatsourcelist } from "@/views/base/simconfig/Simconfig.api";
import dayjs from 'dayjs';
/* ---- dom refs ---- */
const cityChartRef = ref<HTMLElement | null>(null);
/* ---- echarts instances & options ---- */
let cityChart: echarts.ECharts | null = null;
let cityOption: any = null;
const queryParam = ref<any>({});
/* ---- helpers ---- */
function safeNum(v: any) {
if (v === null || v === undefined || v === '') return null;
const n = Number(v);
return Number.isNaN(n) ? null : n;
}
function sortByTime(arr: any[]) {
return [...arr].sort((a, b) => {
const ta = new Date(a.datatime || a.view032 || '').getTime();
const tb = new Date(b.datatime || b.view032 || '').getTime();
return (isNaN(ta) ? 0 : ta) - (isNaN(tb) ? 0 : tb);
});
}
const heatsource = ref();
async function getHeatsource(){
heatsource.value = await heatsourcelist({regionType: '郊县'});
}
async function handleChange(){
loadData();
}
function splitByRegion(data: any[]) {
const city = data.filter(d => String(d.regionType).includes('郊县'));
return { city: sortByTime(city) };
}
function buildXAxis(records: any[], key = 'view028') {
return records.map((r: any) => {
return ((r[key] ?? '').toString().replace(/锅炉房/g, '')).trim();
});
}
/* ---- build options折线改为直线 smooth: false ---- */
function prepareOptions(records: any[]) {
const { city } = splitByRegion(records);
const cityX = buildXAxis(city, 'datatime');
const citySW = city.map((r: any) => safeNum(r.view037));
cityOption = {
title: { text: '郊县锅炉房历史水流量', left: 'center', top: 10 },
tooltip: { trigger: 'axis' },
legend: { top: 36, left: 'center' },
grid: { left: '6%', right: '4%', bottom: 70, top: 70, containLabel: true },
xAxis: { type: 'category', data: cityX, axisLabel: { rotate: 20 } },
yAxis: { type: 'value', name: 'm³/s' },
series: [
{ name: '水流量', type: 'line', data: citySW, smooth: false, showSymbol: false, lineStyle: { type: 'solid' } },
],
color: ['#176AB3', '#2F9E8A'] // 线
};
}
/* ---- lazy init & resize ---- */
let resizeAdded = false;
function ensureResize() {
if (resizeAdded) return;
const onResize = () => {
cityChart?.resize();
};
window.addEventListener('resize', onResize);
onUnmounted(() => window.removeEventListener('resize', onResize));
resizeAdded = true;
}
/* ---- load data ---- */
async function loadData() {
console.log("🚀 ~ loadData ~ queryParam.value:", queryParam.value)
queryParam.value.startTime = dayjs(queryParam.value.startDate).format('YYMM');
try {
// 1.
// 2.
const r = await getStaticList(queryParam.value);
const records = r?.data ?? [];
prepareOptions(records);
// 3. DOM
await nextTick();
cityChart = echarts.init(cityChartRef.value);
cityChart?.setOption(cityOption, true);
// 5.
ensureResize();
} catch (err) {
console.error('load error', err);
}
}
onMounted( async () => {
await getHeatsource()
var list = heatsource.value
queryParam.value.sourceId = list[0].sourceId
queryParam.value.startDate = dayjs().format('YYYY-MM');
loadData();
});
</script>
<style scoped lang="less">
.bjclass {
display: flex;
align-items: center; /* 垂直居中 */
justify-content: center; /* 水平居中 */
height: calc(100vh - 120px); /* 需要设置容器高度 */
background: white;
}
</style>

View File

@ -0,0 +1,113 @@
<template>
<div class="container2">
<div ref="cityChartRef" style="width: 100%; height: 600px;"></div>
</div>
</template>
<script lang="ts" setup>
import { ref, onMounted, nextTick, onUnmounted } from 'vue';
import * as echarts from 'echarts';
import { cqglfgswd,getStaticList } from '/@/api/dashboard/api';
/* ---- dom refs ---- */
const cityChartRef = ref<HTMLElement | null>(null);
/* ---- echarts instances & options ---- */
let cityChart: echarts.ECharts | null = null;
let cityOption: any = null;
/* ---- helpers ---- */
function safeNum(v: any) {
if (v === null || v === undefined || v === '') return null;
const n = Number(v);
return Number.isNaN(n) ? null : n;
}
function sortByTime(arr: any[]) {
return [...arr].sort((a, b) => {
const ta = new Date(a.datatime || a.view032 || '').getTime();
const tb = new Date(b.datatime || b.view032 || '').getTime();
return (isNaN(ta) ? 0 : ta) - (isNaN(tb) ? 0 : tb);
});
}
function splitByRegion(data: any[]) {
const city = data.filter(d => String(d.regionType).includes('城区'));
return { city: sortByTime(city) };
}
function buildXAxis(records: any[], key = 'view028') {
return records.map((r: any) => {
return ((r[key] ?? '').toString().replace(/锅炉房/g, '')).trim();
});
}
/* ---- build options折线改为直线 smooth: false ---- */
function prepareOptions(records: any[]) {
console.log("🚀 ~ prepareOptions ~ records:", records)
const { city } = splitByRegion(records);
console.log("🚀 ~ prepareOptions ~ city:", city)
const cityX = buildXAxis(city, 'view028');
console.log("🚀 ~ prepareOptions ~ cityX:", cityX)
const citySW = city.map((r: any) => safeNum(r.view007));
const cityHW = city.map((r: any) => safeNum(r.view008));
cityOption = {
title: { text: '城区锅炉房供/回水压力', left: 'center', top: 10 },
tooltip: { trigger: 'axis' },
legend: { top: 36, left: 'center' },
grid: { left: '6%', right: '4%', bottom: 70, top: 70, containLabel: true },
xAxis: { type: 'category', data: cityX, axisLabel: { rotate: 20 } },
yAxis: { type: 'value', name: 'Pa' },
series: [
{ name: '供水压力', type: 'line', data: citySW, smooth: false, showSymbol: false, lineStyle: { type: 'solid' } },
{ name: '回水压力', type: 'line', data: cityHW, smooth: false, showSymbol: false, lineStyle: { type: 'solid' } }
],
color: ['#176AB3', '#2F9E8A'] // 线
};
}
/* ---- lazy init & resize ---- */
let resizeAdded = false;
function ensureResize() {
if (resizeAdded) return;
const onResize = () => {
cityChart?.resize();
};
window.addEventListener('resize', onResize);
onUnmounted(() => window.removeEventListener('resize', onResize));
resizeAdded = true;
}
/* ---- load data ---- */
async function loadData() {
try {
// 1.
// 2.
const r = await cqglfgswd();
const records = r?.data ?? [];
prepareOptions(records);
// 3. DOM
await nextTick();
cityChart = echarts.init(cityChartRef.value);
cityChart?.setOption(cityOption, true);
// 5.
ensureResize();
} catch (err) {
console.error('load error', err);
}
}
onMounted(() => {
loadData();
});
</script>
<style scoped lang="less">
.container2 {
display: flex;
align-items: center; /* 垂直居中 */
justify-content: center; /* 水平居中 */
height: calc(100vh - 120px); /* 需要设置容器高度 */
background: white;
}
</style>

View File

@ -0,0 +1,145 @@
<template>
<div style="background-color: #fff;padding:14px;height: 100%;">
<a-row :span="24" style="margin-top:10px;">
<a-col :span="4" style="padding-left: 30px;">
<a-select ref="select"
placeholder="选择锅炉房"
v-model:value="queryParam.sourceId"
style="width: 155px;"
@focus="focus"
@change="handleChange">
<a-select-option :value="item.sourceId" v-for="item in heatsource" :key="item.id">{{item.sourceName}}</a-select-option>
</a-select>
</a-col>
<a-col :span="4">
<a-date-picker v-model:value="queryParam.startDate" value-format="YYYY-MM" picker="month" placeholder="请选择时间" @change="handleChange" />
</a-col>
<a-col :span="24" >
<div ref="cityChartRef" style="width: 100%; height: 600px;"></div>
</a-col>
</a-row>
</div>
</template>
<script lang="ts" setup>
import { ref, onMounted, nextTick, onUnmounted } from 'vue';
import * as echarts from 'echarts';
import { cqglfgswd,getStaticList } from '/@/api/dashboard/api';
import { heatsourcelist } from "@/views/base/simconfig/Simconfig.api";
import dayjs from 'dayjs';
/* ---- dom refs ---- */
const cityChartRef = ref<HTMLElement | null>(null);
/* ---- echarts instances & options ---- */
let cityChart: echarts.ECharts | null = null;
let cityOption: any = null;
const queryParam = ref<any>({});
/* ---- helpers ---- */
function safeNum(v: any) {
if (v === null || v === undefined || v === '') return null;
const n = Number(v);
return Number.isNaN(n) ? null : n;
}
function sortByTime(arr: any[]) {
return [...arr].sort((a, b) => {
const ta = new Date(a.datatime || a.view032 || '').getTime();
const tb = new Date(b.datatime || b.view032 || '').getTime();
return (isNaN(ta) ? 0 : ta) - (isNaN(tb) ? 0 : tb);
});
}
const heatsource = ref();
async function getHeatsource(){
heatsource.value = await heatsourcelist({regionType: '城区'});
}
async function handleChange(){
loadData();
}
function splitByRegion(data: any[]) {
const city = data.filter(d => String(d.regionType).includes('城区'));
return { city: sortByTime(city) };
}
function buildXAxis(records: any[], key = 'view028') {
return records.map((r: any) => {
return ((r[key] ?? '').toString().replace(/锅炉房/g, '')).trim();
});
}
/* ---- build options折线改为直线 smooth: false ---- */
function prepareOptions(records: any[]) {
const { city } = splitByRegion(records);
const cityX = buildXAxis(city, 'datatime');
const citySW = city.map((r: any) => safeNum(r.view007));
const cityHW = city.map((r: any) => safeNum(r.view008));
cityOption = {
title: { text: '城区锅炉房历史供/回水压力', left: 'center', top: 10 },
tooltip: { trigger: 'axis' },
legend: { top: 36, left: 'center' },
grid: { left: '6%', right: '4%', bottom: 70, top: 70, containLabel: true },
xAxis: { type: 'category', data: cityX, axisLabel: { rotate: 20 } },
yAxis: { type: 'value', name: 'Pa' },
series: [
{ name: '供水压力', type: 'line', data: citySW, smooth: false, showSymbol: false, lineStyle: { type: 'solid' } },
{ name: '回水压力', type: 'line', data: cityHW, smooth: false, showSymbol: false, lineStyle: { type: 'solid' } }
],
color: ['#176AB3', '#2F9E8A'] // 线
};
}
/* ---- lazy init & resize ---- */
let resizeAdded = false;
function ensureResize() {
if (resizeAdded) return;
const onResize = () => {
cityChart?.resize();
};
window.addEventListener('resize', onResize);
onUnmounted(() => window.removeEventListener('resize', onResize));
resizeAdded = true;
}
/* ---- load data ---- */
async function loadData() {
console.log("🚀 ~ loadData ~ queryParam.value:", queryParam.value)
queryParam.value.startTime = dayjs(queryParam.value.startDate).format('YYMM');
try {
// 1.
// 2.
const r = await getStaticList(queryParam.value);
const records = r?.data ?? [];
prepareOptions(records);
// 3. DOM
await nextTick();
cityChart = echarts.init(cityChartRef.value);
cityChart?.setOption(cityOption, true);
// 5.
ensureResize();
} catch (err) {
console.error('load error', err);
}
}
onMounted( async () => {
await getHeatsource()
var list = heatsource.value
queryParam.value.sourceId = list[0].sourceId
queryParam.value.startDate = dayjs().format('YYYY-MM');
loadData();
});
</script>
<style scoped lang="less">
.bjclass {
display: flex;
align-items: center; /* 垂直居中 */
justify-content: center; /* 水平居中 */
height: calc(100vh - 120px); /* 需要设置容器高度 */
background: white;
}
</style>

View File

@ -0,0 +1,113 @@
<template>
<div class="container2">
<div ref="cityChartRef" style="width: 100%; height: 600px;"></div>
</div>
</template>
<script lang="ts" setup>
import { ref, onMounted, nextTick, onUnmounted } from 'vue';
import * as echarts from 'echarts';
import { cqglfgswd,getStaticList } from '/@/api/dashboard/api';
/* ---- dom refs ---- */
const cityChartRef = ref<HTMLElement | null>(null);
/* ---- echarts instances & options ---- */
let cityChart: echarts.ECharts | null = null;
let cityOption: any = null;
/* ---- helpers ---- */
function safeNum(v: any) {
if (v === null || v === undefined || v === '') return null;
const n = Number(v);
return Number.isNaN(n) ? null : n;
}
function sortByTime(arr: any[]) {
return [...arr].sort((a, b) => {
const ta = new Date(a.datatime || a.view032 || '').getTime();
const tb = new Date(b.datatime || b.view032 || '').getTime();
return (isNaN(ta) ? 0 : ta) - (isNaN(tb) ? 0 : tb);
});
}
function splitByRegion(data: any[]) {
const city = data.filter(d => String(d.regionType).includes('郊县'));
return { city: sortByTime(city) };
}
function buildXAxis(records: any[], key = 'view028') {
return records.map((r: any) => {
return ((r[key] ?? '').toString().replace(/锅炉房/g, '')).trim();
});
}
/* ---- build options折线改为直线 smooth: false ---- */
function prepareOptions(records: any[]) {
console.log("🚀 ~ prepareOptions ~ records:", records)
const { city } = splitByRegion(records);
console.log("🚀 ~ prepareOptions ~ city:", city)
const cityX = buildXAxis(city, 'view028');
console.log("🚀 ~ prepareOptions ~ cityX:", cityX)
const citySW = city.map((r: any) => safeNum(r.view007));
const cityHW = city.map((r: any) => safeNum(r.view008));
cityOption = {
title: { text: '郊县锅炉房供/回水压力', left: 'center', top: 10 },
tooltip: { trigger: 'axis' },
legend: { top: 36, left: 'center' },
grid: { left: '6%', right: '4%', bottom: 70, top: 70, containLabel: true },
xAxis: { type: 'category', data: cityX, axisLabel: { rotate: 20 } },
yAxis: { type: 'value', name: 'Pa' },
series: [
{ name: '供水压力', type: 'line', data: citySW, smooth: false, showSymbol: false, lineStyle: { type: 'solid' } },
{ name: '回水压力', type: 'line', data: cityHW, smooth: false, showSymbol: false, lineStyle: { type: 'solid' } }
],
color: ['#176AB3', '#2F9E8A'] // 线
};
}
/* ---- lazy init & resize ---- */
let resizeAdded = false;
function ensureResize() {
if (resizeAdded) return;
const onResize = () => {
cityChart?.resize();
};
window.addEventListener('resize', onResize);
onUnmounted(() => window.removeEventListener('resize', onResize));
resizeAdded = true;
}
/* ---- load data ---- */
async function loadData() {
try {
// 1.
// 2.
const r = await cqglfgswd();
const records = r?.data ?? [];
prepareOptions(records);
// 3. DOM
await nextTick();
cityChart = echarts.init(cityChartRef.value);
cityChart?.setOption(cityOption, true);
// 5.
ensureResize();
} catch (err) {
console.error('load error', err);
}
}
onMounted(() => {
loadData();
});
</script>
<style scoped lang="less">
.container2 {
display: flex;
align-items: center; /* 垂直居中 */
justify-content: center; /* 水平居中 */
height: calc(100vh - 120px); /* 需要设置容器高度 */
background: white;
}
</style>

View File

@ -0,0 +1,145 @@
<template>
<div style="background-color: #fff;padding:14px;height: 100%;">
<a-row :span="24" style="margin-top:10px;">
<a-col :span="4" style="padding-left: 30px;">
<a-select ref="select"
placeholder="选择锅炉房"
v-model:value="queryParam.sourceId"
style="width: 155px;"
@focus="focus"
@change="handleChange">
<a-select-option :value="item.sourceId" v-for="item in heatsource" :key="item.id">{{item.sourceName}}</a-select-option>
</a-select>
</a-col>
<a-col :span="4">
<a-date-picker v-model:value="queryParam.startDate" value-format="YYYY-MM" picker="month" placeholder="请选择时间" @change="handleChange" />
</a-col>
<a-col :span="24" >
<div ref="cityChartRef" style="width: 100%; height: 600px;"></div>
</a-col>
</a-row>
</div>
</template>
<script lang="ts" setup>
import { ref, onMounted, nextTick, onUnmounted } from 'vue';
import * as echarts from 'echarts';
import { cqglfgswd,getStaticList } from '/@/api/dashboard/api';
import { heatsourcelist } from "@/views/base/simconfig/Simconfig.api";
import dayjs from 'dayjs';
/* ---- dom refs ---- */
const cityChartRef = ref<HTMLElement | null>(null);
/* ---- echarts instances & options ---- */
let cityChart: echarts.ECharts | null = null;
let cityOption: any = null;
const queryParam = ref<any>({});
/* ---- helpers ---- */
function safeNum(v: any) {
if (v === null || v === undefined || v === '') return null;
const n = Number(v);
return Number.isNaN(n) ? null : n;
}
function sortByTime(arr: any[]) {
return [...arr].sort((a, b) => {
const ta = new Date(a.datatime || a.view032 || '').getTime();
const tb = new Date(b.datatime || b.view032 || '').getTime();
return (isNaN(ta) ? 0 : ta) - (isNaN(tb) ? 0 : tb);
});
}
const heatsource = ref();
async function getHeatsource(){
heatsource.value = await heatsourcelist({regionType: '郊县'});
}
async function handleChange(){
loadData();
}
function splitByRegion(data: any[]) {
const city = data.filter(d => String(d.regionType).includes('郊县'));
return { city: sortByTime(city) };
}
function buildXAxis(records: any[], key = 'view028') {
return records.map((r: any) => {
return ((r[key] ?? '').toString().replace(/锅炉房/g, '')).trim();
});
}
/* ---- build options折线改为直线 smooth: false ---- */
function prepareOptions(records: any[]) {
const { city } = splitByRegion(records);
const cityX = buildXAxis(city, 'datatime');
const citySW = city.map((r: any) => safeNum(r.view007));
const cityHW = city.map((r: any) => safeNum(r.view008));
cityOption = {
title: { text: '郊县锅炉房历史供/回水压力', left: 'center', top: 10 },
tooltip: { trigger: 'axis' },
legend: { top: 36, left: 'center' },
grid: { left: '6%', right: '4%', bottom: 70, top: 70, containLabel: true },
xAxis: { type: 'category', data: cityX, axisLabel: { rotate: 20 } },
yAxis: { type: 'value', name: 'Pa' },
series: [
{ name: '供水压力', type: 'line', data: citySW, smooth: false, showSymbol: false, lineStyle: { type: 'solid' } },
{ name: '回水压力', type: 'line', data: cityHW, smooth: false, showSymbol: false, lineStyle: { type: 'solid' } }
],
color: ['#176AB3', '#2F9E8A'] // 线
};
}
/* ---- lazy init & resize ---- */
let resizeAdded = false;
function ensureResize() {
if (resizeAdded) return;
const onResize = () => {
cityChart?.resize();
};
window.addEventListener('resize', onResize);
onUnmounted(() => window.removeEventListener('resize', onResize));
resizeAdded = true;
}
/* ---- load data ---- */
async function loadData() {
console.log("🚀 ~ loadData ~ queryParam.value:", queryParam.value)
queryParam.value.startTime = dayjs(queryParam.value.startDate).format('YYMM');
try {
// 1.
// 2.
const r = await getStaticList(queryParam.value);
const records = r?.data ?? [];
prepareOptions(records);
// 3. DOM
await nextTick();
cityChart = echarts.init(cityChartRef.value);
cityChart?.setOption(cityOption, true);
// 5.
ensureResize();
} catch (err) {
console.error('load error', err);
}
}
onMounted( async () => {
await getHeatsource()
var list = heatsource.value
queryParam.value.sourceId = list[0].sourceId
queryParam.value.startDate = dayjs().format('YYYY-MM');
loadData();
});
</script>
<style scoped lang="less">
.bjclass {
display: flex;
align-items: center; /* 垂直居中 */
justify-content: center; /* 水平居中 */
height: calc(100vh - 120px); /* 需要设置容器高度 */
background: white;
}
</style>

View File

@ -0,0 +1,219 @@
export interface GrowCardItem {
icon: string;
title: string;
value?: number;
total: number;
color?: string;
action?: string;
footer?: string;
}
export const growCardList: GrowCardItem[] = [
{
title: '访问数',
icon: 'visit-count|svg',
value: 2000,
total: 120000,
color: 'green',
action: '月',
},
{
title: '成交额',
icon: 'total-sales|svg',
value: 20000,
total: 500000,
color: 'blue',
action: '月',
},
{
title: '下载数',
icon: 'download-count|svg',
value: 8000,
total: 120000,
color: 'orange',
action: '周',
},
{
title: '成交数',
icon: 'transaction|svg',
value: 5000,
total: 50000,
color: 'purple',
action: '年',
},
];
export const chartCardList: GrowCardItem[] = [
{
title: '总销售额',
icon: 'visit-count|svg',
total: 126560,
value: 234.56,
footer: '日均销售额',
},
{
title: '订单量',
icon: 'total-sales|svg',
value: 1234,
total: 8846,
color: 'blue',
footer: '日订单量',
},
{
title: '支付笔数',
icon: 'download-count|svg',
value: 60,
total: 6560,
color: 'orange',
footer: '转化率',
},
{
title: '运营活动效果',
icon: 'transaction|svg',
total: 78,
},
];
export const bdcCardList: GrowCardItem[] = [
{
title: '受理量',
icon: 'ant-design:info-circle-outlined',
total: 100,
value: 60,
footer: '今日受理量',
},
{
title: '办结量',
icon: 'ant-design:info-circle-outlined',
value: 54,
total: 87,
color: 'blue',
footer: '今日办结量',
},
{
title: '用户受理量',
icon: 'ant-design:info-circle-outlined',
value: 13,
total: 15,
color: 'orange',
footer: '用户今日受理量',
},
{
title: '用户办结量',
icon: 'ant-design:info-circle-outlined',
total: 9,
value: 7,
footer: '用户今日办结量',
},
];
export const table = {
dataSource: [
{ reBizCode: '1', type: '转移登记', acceptBy: '张三', acceptDate: '2019-01-22', curNode: '任务分派', flowRate: 60 },
{ reBizCode: '2', type: '抵押登记', acceptBy: '李四', acceptDate: '2019-01-23', curNode: '领导审核', flowRate: 30 },
{ reBizCode: '3', type: '转移登记', acceptBy: '王武', acceptDate: '2019-01-25', curNode: '任务处理', flowRate: 20 },
{ reBizCode: '4', type: '转移登记', acceptBy: '赵楼', acceptDate: '2019-11-22', curNode: '部门审核', flowRate: 80 },
{ reBizCode: '5', type: '转移登记', acceptBy: '钱就', acceptDate: '2019-12-12', curNode: '任务分派', flowRate: 90 },
{ reBizCode: '6', type: '转移登记', acceptBy: '孙吧', acceptDate: '2019-03-06', curNode: '任务处理', flowRate: 10 },
{ reBizCode: '7', type: '抵押登记', acceptBy: '周大', acceptDate: '2019-04-13', curNode: '任务分派', flowRate: 100 },
{ reBizCode: '8', type: '抵押登记', acceptBy: '吴二', acceptDate: '2019-05-09', curNode: '任务上报', flowRate: 50 },
{ reBizCode: '9', type: '抵押登记', acceptBy: '郑爽', acceptDate: '2019-07-12', curNode: '任务处理', flowRate: 63 },
{ reBizCode: '20', type: '抵押登记', acceptBy: '林有', acceptDate: '2019-12-12', curNode: '任务打回', flowRate: 59 },
{ reBizCode: '11', type: '转移登记', acceptBy: '码云', acceptDate: '2019-09-10', curNode: '任务签收', flowRate: 87 },
],
columns: [
{
title: '业务号',
align: 'center',
dataIndex: 'reBizCode',
},
{
title: '业务类型',
align: 'center',
dataIndex: 'type',
},
{
title: '受理人',
align: 'center',
dataIndex: 'acceptBy',
},
{
title: '受理时间',
align: 'center',
dataIndex: 'acceptDate',
},
{
title: '当前节点',
align: 'center',
dataIndex: 'curNode',
},
{
title: '办理时长',
align: 'center',
dataIndex: 'flowRate',
},
],
ipagination: {
current: 1,
pageSize: 5,
pageSizeOptions: ['10', '20', '30'],
showTotal: (total, range) => {
return range[0] + '-' + range[1] + ' 共' + total + '条';
},
showQuickJumper: true,
showSizeChanger: true,
total: 0,
},
};
export const table1 = {
dataSource: [
{ reBizCode: 'A001', type: '转移登记', acceptBy: '张四', acceptDate: '2019-01-22', curNode: '任务分派', flowRate: 12 },
{ reBizCode: 'A002', type: '抵押登记', acceptBy: '李吧', acceptDate: '2019-01-23', curNode: '任务签收', flowRate: 3 },
{ reBizCode: 'A003', type: '转移登记', acceptBy: '王三', acceptDate: '2019-01-25', curNode: '任务处理', flowRate: 24 },
{ reBizCode: 'A004', type: '转移登记', acceptBy: '赵二', acceptDate: '2019-11-22', curNode: '部门审核', flowRate: 10 },
{ reBizCode: 'A005', type: '转移登记', acceptBy: '钱大', acceptDate: '2019-12-12', curNode: '任务签收', flowRate: 8 },
{ reBizCode: 'A006', type: '转移登记', acceptBy: '孙就', acceptDate: '2019-03-06', curNode: '任务处理', flowRate: 10 },
{ reBizCode: 'A007', type: '抵押登记', acceptBy: '周晕', acceptDate: '2019-04-13', curNode: '部门审核', flowRate: 24 },
{ reBizCode: 'A008', type: '抵押登记', acceptBy: '吴有', acceptDate: '2019-05-09', curNode: '部门审核', flowRate: 30 },
{ reBizCode: 'A009', type: '抵押登记', acceptBy: '郑武', acceptDate: '2019-07-12', curNode: '任务分派', flowRate: 1 },
{ reBizCode: 'A0010', type: '抵押登记', acceptBy: '林爽', acceptDate: '2019-12-12', curNode: '部门审核', flowRate: 16 },
{ reBizCode: 'A0011', type: '转移登记', acceptBy: '码楼', acceptDate: '2019-09-10', curNode: '部门审核', flowRate: 7 },
],
columns: [
{
title: '业务号',
align: 'center',
dataIndex: 'reBizCode',
},
{
title: '受理人',
align: 'center',
dataIndex: 'acceptBy',
},
{
title: '发起时间',
align: 'center',
dataIndex: 'acceptDate',
},
{
title: '当前节点',
align: 'center',
dataIndex: 'curNode',
},
{
title: '超时时间',
align: 'center',
dataIndex: 'flowRate',
},
],
ipagination: {
current: 1,
pageSize: 5,
pageSizeOptions: ['10', '20', '30'],
showTotal: (total, range) => {
return range[0] + '-' + range[1] + ' 共' + total + '条';
},
showQuickJumper: true,
showSizeChanger: true,
total: 0,
},
};

View File

@ -0,0 +1,113 @@
<template>
<div class="container">
<div ref="cityChartRef" style="width: 100%; height: 600px;"></div>
</div>
</template>
<script lang="ts" setup>
import { ref, onMounted, nextTick, onUnmounted } from 'vue';
import * as echarts from 'echarts';
import { cqglfgswd,getStaticList } from '/@/api/dashboard/api';
/* ---- dom refs ---- */
const cityChartRef = ref<HTMLElement | null>(null);
/* ---- echarts instances & options ---- */
let cityChart: echarts.ECharts | null = null;
let cityOption: any = null;
/* ---- helpers ---- */
function safeNum(v: any) {
if (v === null || v === undefined || v === '') return null;
const n = Number(v);
return Number.isNaN(n) ? null : n;
}
function sortByTime(arr: any[]) {
return [...arr].sort((a, b) => {
const ta = new Date(a.datatime || a.view032 || '').getTime();
const tb = new Date(b.datatime || b.view032 || '').getTime();
return (isNaN(ta) ? 0 : ta) - (isNaN(tb) ? 0 : tb);
});
}
function splitByRegion(data: any[]) {
const city = data.filter(d => String(d.regionType).includes('城区'));
return { city: sortByTime(city) };
}
function buildXAxis(records: any[], key = 'view028') {
return records.map((r: any) => {
return ((r[key] ?? '').toString().replace(/锅炉房/g, '')).trim();
});
}
/* ---- build options折线改为直线 smooth: false ---- */
function prepareOptions(records: any[]) {
console.log("🚀 ~ prepareOptions ~ records:", records)
const { city } = splitByRegion(records);
console.log("🚀 ~ prepareOptions ~ city:", city)
const cityX = buildXAxis(city, 'view028');
console.log("🚀 ~ prepareOptions ~ cityX:", cityX)
const citySW = city.map((r: any) => safeNum(r.view005));
const cityHW = city.map((r: any) => safeNum(r.view006));
cityOption = {
title: { text: '锅炉房供/回水温度', left: 'center', top: 10 },
tooltip: { trigger: 'axis' },
legend: { top: 36, left: 'center' },
grid: { left: '6%', right: '4%', bottom: 70, top: 70, containLabel: true },
xAxis: { type: 'category', data: cityX, axisLabel: { rotate: 20 } },
yAxis: { type: 'value', name: '℃' },
series: [
{ name: '供水温度', type: 'line', data: citySW, smooth: false, showSymbol: false, lineStyle: { type: 'solid' } },
{ name: '回水温度', type: 'line', data: cityHW, smooth: false, showSymbol: false, lineStyle: { type: 'solid' } }
],
color: ['#176AB3', '#2F9E8A'] // 线
};
}
/* ---- lazy init & resize ---- */
let resizeAdded = false;
function ensureResize() {
if (resizeAdded) return;
const onResize = () => {
cityChart?.resize();
};
window.addEventListener('resize', onResize);
onUnmounted(() => window.removeEventListener('resize', onResize));
resizeAdded = true;
}
/* ---- load data ---- */
async function loadData() {
try {
// 1.
// 2.
const r = await cqglfgswd();
const records = r?.data ?? [];
prepareOptions(records);
// 3. DOM
await nextTick();
cityChart = echarts.init(cityChartRef.value);
cityChart?.setOption(cityOption, true);
// 5.
ensureResize();
} catch (err) {
console.error('load error', err);
}
}
onMounted(() => {
loadData();
});
</script>
<style scoped lang="less">
.container {
display: flex;
align-items: center; /* 垂直居中 */
justify-content: center; /* 水平居中 */
height: calc(100vh - 120px); /* 需要设置容器高度 */
background: white;
}
</style>