首页、系统界面颜色

This commit is contained in:
1378012178@qq.com 2025-08-29 11:01:15 +08:00
parent 566e89ea0a
commit f270321079
9 changed files with 770 additions and 198 deletions

4
.env
View File

@ -2,10 +2,10 @@
VITE_PORT = 3100
# 网站标题
VITE_GLOB_APP_TITLE = 磐石市智慧供热监管平台
VITE_GLOB_APP_TITLE = 磐石市供热信息化平台
# 简称,此变量只能是字符/下划线
VITE_GLOB_APP_SHORT_NAME = 供热监管平台
VITE_GLOB_APP_SHORT_NAME = 供热信息化平台
# 单点登录服务端地址
VITE_GLOB_APP_CAS_BASE_URL=http://cas.test.com:8443/cas

View File

@ -1,11 +1,9 @@
import { defHttp } from '/@/utils/http/axios';
import { message } from 'ant-design-vue';
import { useGlobSetting } from '/@/hooks/setting';
const globSetting = useGlobSetting();
const baseUploadUrl = globSetting.uploadUrl;
enum Api {
slcx = '/exportapi/homeApi/slcx',
cqglfgswd = '/exportapi/homeApi/cqglfgswd',
glfzb = '/exportapi/homeApi/glfzb',
}
/**
@ -14,7 +12,7 @@ enum Api {
*/
export const slcx = () => {
return defHttp.post({ url: Api.slcx });
}
};
/**
*
@ -22,4 +20,12 @@ export const slcx = () => {
*/
export const cqglfgswd = () => {
return defHttp.post({ url: Api.cqglfgswd });
}
};
/**
*
* @param params
*/
export const glfzb = () => {
return defHttp.post({ url: Api.glfzb });
};

View File

@ -0,0 +1,204 @@
import type { ProjectConfig } from '/#/config';
import { MenuTypeEnum, MenuModeEnum, TriggerEnum, MixSidebarTriggerEnum } from '/@/enums/menuEnum';
import { CacheTypeEnum } from '/@/enums/cacheEnum';
import {
ContentEnum,
PermissionModeEnum,
ThemeEnum,
RouterTransitionEnum,
SettingButtonPositionEnum,
SessionTimeoutProcessingEnum,
TabsThemeEnum,
} from '/@/enums/appEnum';
import { SIDE_BAR_BG_COLOR_LIST, HEADER_PRESET_BG_COLOR_LIST } from './designSetting';
import { primaryColor } from '../../build/config/themeConfig';
import { darkMode } from '/@/settings/designSetting';
// ! 改动后需要清空浏览器缓存
const setting: ProjectConfig = {
// 是否显示SettingButton
showSettingButton: true,
// 是否显示主题切换按钮
showDarkModeToggle: true,
// 设置按钮位置 可选项
// SettingButtonPositionEnum.AUTO: 自动选择
// SettingButtonPositionEnum.HEADER: 位于头部
// SettingButtonPositionEnum.FIXED: 固定在右侧
settingButtonPosition: SettingButtonPositionEnum.AUTO,
// 权限模式,默认前端角色权限模式
// ROUTE_MAPPING: 前端模式(菜单由路由生成,默认)
// ROLE前端模式菜单路由分开
// BACK后台模式
permissionMode: PermissionModeEnum.BACK,
// 权限缓存存放位置。默认存放于localStorage
permissionCacheType: CacheTypeEnum.LOCAL,
// 会话超时处理方案
// SessionTimeoutProcessingEnum.ROUTE_JUMP: 路由跳转到登录页
// SessionTimeoutProcessingEnum.PAGE_COVERAGE: 生成登录弹窗,覆盖当前页面
sessionTimeoutProcessing: SessionTimeoutProcessingEnum.ROUTE_JUMP,
// 项目主题色
themeColor: primaryColor,
// update-begin--author:liaozhiyang---date:20250414--for【QQYUN-11956】修复projectSetting中配置主题模式不生效
// 项目主题模式
themeMode: darkMode,
// update-end--author:liaozhiyang---date:20250414--for【QQYUN-11956】修复projectSetting中配置主题模式不生效
// 网站灰色模式,用于可能悼念的日期开启
grayMode: false,
// 色弱模式
colorWeak: false,
// 是否取消菜单,顶部,多标签页显示, 用于可能内嵌在别的系统内
fullContent: false,
// 主题内容宽度
contentMode: ContentEnum.FULL,
// 是否显示logo
showLogo: true,
// 是否显示底部信息 copyright
showFooter: false,
// ai图标显示
aiIconShow: false,
// 头部配置
headerSetting: {
// 背景色
bgColor: HEADER_PRESET_BG_COLOR_LIST[4],
// 固定头部
fixed: true,
// 是否显示顶部
show: true,
// 主题
theme: ThemeEnum.LIGHT,
// 开启锁屏功能
useLockPage: false,
// 显示全屏按钮
showFullScreen: false,
// 显示官网按钮
showDoc: false,
// 显示消息中心按钮
showNotice: true,
// 显示菜单搜索按钮
showSearch: true,
},
// 菜单配置
menuSetting: {
// 背景色
bgColor: SIDE_BAR_BG_COLOR_LIST[0],
// 是否固定住左侧菜单
fixed: true,
// 菜单折叠
collapsed: false,
// 折叠菜单时候是否显示菜单名
collapsedShowTitle: false,
// 是否可拖拽
// Only limited to the opening of the left menu, the mouse has a drag bar on the right side of the menu
canDrag: false,
// Whether to show no dom
show: true,
// Whether to show dom
hidden: false,
// 菜单宽度
menuWidth: 210,
// 菜单模式
mode: MenuModeEnum.INLINE,
// 菜单类型
type: MenuTypeEnum.SIDEBAR,
// 菜单主题
theme: ThemeEnum.DARK,
// update-begin--author:liaozhiyang---date:20241203---for【issues/7522】解决menuSetting ts警告
// 左侧导航栏文字颜色调整区分彩色和暗黑 (不对应配置)
isThemeBright: false,
// update-end--author:liaozhiyang---date:20241203---for【issues/7522】解决menuSetting ts警告
// 分割菜单
split: false,
// 顶部菜单布局
topMenuAlign: 'center',
// 折叠触发器的位置
trigger: TriggerEnum.HEADER,
// 手风琴模式,只展示一个菜单
accordion: true,
// 在路由切换的时候关闭左侧混合菜单展开菜单
closeMixSidebarOnChange: false,
// 左侧混合菜单模块切换触发方式 click |'hover'
mixSideTrigger: MixSidebarTriggerEnum.CLICK,
// 是否固定左侧混合菜单
mixSideFixed: false,
},
// 多标签
multiTabsSetting: {
// 刷新后是否保留已经打开的标签页
cache: false,
// 开启
show: true,
// 是否可以拖拽
canDrag: true,
// 开启快速操作
showQuick: true,
// 是否显示刷新按钮
showRedo: true,
// 是否显示折叠按钮
showFold: true,
// 标签页样式
theme: TabsThemeEnum.CARD,
},
// 动画配置
transitionSetting: {
// 是否开启切换动画
// The disabled state will also disable pageLoading
enable: true,
// 动画名 Route basic switching animation
basicTransition: RouterTransitionEnum.FADE_SIDE,
// 是否打开页面切换loading
// Only open when enable=true
openPageLoading: true,
//是否打开页面切换顶部进度条
openNProgress: true,
},
// 是否开启KeepAlive缓存 开发时候最好关闭,不然每次都需要清除缓存
openKeepAlive: true,
// 自动锁屏时间为0不锁屏。 单位分钟 默认1个小时
lockTime: 0,
// 显示面包屑
showBreadCrumb: false,
// 显示面包屑图标
showBreadCrumbIcon: true,
// 是否使用全局错误捕获
useErrorHandle: false,
// 是否开启回到顶部
useOpenBackTop: true,
// 是否可以嵌入iframe页面
canEmbedIFramePage: true,
// 切换界面的时候是否删除未关闭的message及notify
closeMessageOnSwitch: true,
// 切换界面的时候是否取消已经发送但是未响应的http请求。
// 如果开启,想对单独接口覆盖。可以在单独接口设置
removeAllHttpPending: false,
};
export default setting;

View File

@ -16,189 +16,77 @@ import { darkMode } from '/@/settings/designSetting';
// ! 改动后需要清空浏览器缓存
const setting: ProjectConfig = {
// 是否显示SettingButton
showSettingButton: true,
// 是否显示主题切换按钮
showDarkModeToggle: true,
// 设置按钮位置 可选项
// SettingButtonPositionEnum.AUTO: 自动选择
// SettingButtonPositionEnum.HEADER: 位于头部
// SettingButtonPositionEnum.FIXED: 固定在右侧
settingButtonPosition: SettingButtonPositionEnum.AUTO,
// 权限模式,默认前端角色权限模式
// ROUTE_MAPPING: 前端模式(菜单由路由生成,默认)
// ROLE前端模式菜单路由分开
// BACK后台模式
permissionMode: PermissionModeEnum.BACK,
// 权限缓存存放位置。默认存放于localStorage
permissionCacheType: CacheTypeEnum.LOCAL,
// 会话超时处理方案
// SessionTimeoutProcessingEnum.ROUTE_JUMP: 路由跳转到登录页
// SessionTimeoutProcessingEnum.PAGE_COVERAGE: 生成登录弹窗,覆盖当前页面
sessionTimeoutProcessing: SessionTimeoutProcessingEnum.ROUTE_JUMP,
// 项目主题色
themeColor: primaryColor,
// update-begin--author:liaozhiyang---date:20250414--for【QQYUN-11956】修复projectSetting中配置主题模式不生效
// 项目主题模式
themeMode: darkMode,
// update-end--author:liaozhiyang---date:20250414--for【QQYUN-11956】修复projectSetting中配置主题模式不生效
// 网站灰色模式,用于可能悼念的日期开启
grayMode: false,
// 色弱模式
colorWeak: false,
// 是否取消菜单,顶部,多标签页显示, 用于可能内嵌在别的系统内
fullContent: false,
// 主题内容宽度
contentMode: ContentEnum.FULL,
// 是否显示logo
showLogo: true,
// 是否显示底部信息 copyright
showFooter: false,
// ai图标显示
aiIconShow: false,
// 头部配置
headerSetting: {
// 背景色
bgColor: HEADER_PRESET_BG_COLOR_LIST[4],
// 固定头部
fixed: true,
// 是否显示顶部
show: true,
// 主题
theme: ThemeEnum.LIGHT,
// 开启锁屏功能
useLockPage: false,
// 显示全屏按钮
showFullScreen: false,
// 显示官网按钮
showDoc: false,
// 显示消息中心按钮
showNotice: true,
// 显示菜单搜索按钮
showSearch: true,
"showSettingButton": true,
"showDarkModeToggle": true,
"settingButtonPosition": "auto",
"permissionMode": "BACK",
"permissionCacheType": 1,
"sessionTimeoutProcessing": 0,
"themeColor": "#1890ff",
"themeMode": "light",
"grayMode": false,
"colorWeak": false,
"fullContent": false,
"contentMode": "full",
"showLogo": true,
"showFooter": false,
"aiIconShow": false,
"headerSetting": {
"bgColor": "#ffffff",
"fixed": true,
"show": true,
"theme": "light",
"useLockPage": false,
"showFullScreen": false,
"showDoc": false,
"showNotice": true,
"showSearch": true
},
// 菜单配置
menuSetting: {
// 背景色
bgColor: SIDE_BAR_BG_COLOR_LIST[0],
// 是否固定住左侧菜单
fixed: true,
// 菜单折叠
collapsed: false,
// 折叠菜单时候是否显示菜单名
collapsedShowTitle: false,
// 是否可拖拽
// Only limited to the opening of the left menu, the mouse has a drag bar on the right side of the menu
canDrag: false,
// Whether to show no dom
show: true,
// Whether to show dom
hidden: false,
// 菜单宽度
menuWidth: 210,
// 菜单模式
mode: MenuModeEnum.INLINE,
// 菜单类型
type: MenuTypeEnum.SIDEBAR,
// 菜单主题
theme: ThemeEnum.DARK,
// update-begin--author:liaozhiyang---date:20241203---for【issues/7522】解决menuSetting ts警告
// 左侧导航栏文字颜色调整区分彩色和暗黑 (不对应配置)
isThemeBright: false,
// update-end--author:liaozhiyang---date:20241203---for【issues/7522】解决menuSetting ts警告
// 分割菜单
split: false,
// 顶部菜单布局
topMenuAlign: 'center',
// 折叠触发器的位置
trigger: TriggerEnum.HEADER,
// 手风琴模式,只展示一个菜单
accordion: true,
// 在路由切换的时候关闭左侧混合菜单展开菜单
closeMixSidebarOnChange: false,
// 左侧混合菜单模块切换触发方式 click |'hover'
mixSideTrigger: MixSidebarTriggerEnum.CLICK,
// 是否固定左侧混合菜单
mixSideFixed: false,
"menuSetting": {
"bgColor": "#ffffff",
"fixed": true,
"collapsed": false,
"collapsedShowTitle": false,
"canDrag": false,
"show": true,
"hidden": false,
"menuWidth": 210,
"mode": "inline",
"type": "sidebar",
"theme": "light",
"isThemeBright": false,
"split": false,
"topMenuAlign": "center",
"trigger": "HEADER",
"accordion": true,
"closeMixSidebarOnChange": false,
"mixSideTrigger": "click",
"mixSideFixed": false
},
// 多标签
multiTabsSetting: {
// 刷新后是否保留已经打开的标签页
cache: false,
// 开启
show: true,
// 是否可以拖拽
canDrag: true,
// 开启快速操作
showQuick: true,
// 是否显示刷新按钮
showRedo: true,
// 是否显示折叠按钮
showFold: true,
// 标签页样式
theme: TabsThemeEnum.CARD,
"multiTabsSetting": {
"cache": false,
"show": true,
"canDrag": true,
"showQuick": true,
"showRedo": true,
"showFold": true,
"theme": "card"
},
// 动画配置
transitionSetting: {
// 是否开启切换动画
// The disabled state will also disable pageLoading
enable: true,
// 动画名 Route basic switching animation
basicTransition: RouterTransitionEnum.FADE_SIDE,
// 是否打开页面切换loading
// Only open when enable=true
openPageLoading: true,
//是否打开页面切换顶部进度条
openNProgress: true,
"transitionSetting": {
"enable": true,
"basicTransition": "fade-slide",
"openPageLoading": true,
"openNProgress": true
},
// 是否开启KeepAlive缓存 开发时候最好关闭,不然每次都需要清除缓存
openKeepAlive: true,
// 自动锁屏时间为0不锁屏。 单位分钟 默认1个小时
lockTime: 0,
// 显示面包屑
showBreadCrumb: false,
// 显示面包屑图标
showBreadCrumbIcon: true,
// 是否使用全局错误捕获
useErrorHandle: false,
// 是否开启回到顶部
useOpenBackTop: true,
// 是否可以嵌入iframe页面
canEmbedIFramePage: true,
// 切换界面的时候是否删除未关闭的message及notify
closeMessageOnSwitch: true,
// 切换界面的时候是否取消已经发送但是未响应的http请求。
// 如果开启,想对单独接口覆盖。可以在单独接口设置
removeAllHttpPending: false,
};
"openKeepAlive": true,
"lockTime": 0,
"showBreadCrumb": false,
"showBreadCrumbIcon": true,
"useErrorHandle": false,
"useOpenBackTop": true,
"canEmbedIFramePage": true,
"closeMessageOnSwitch": true,
"removeAllHttpPending": false
}
export default setting;

View File

@ -1,10 +1,484 @@
<template>
<div style="width: 100%; padding: 14px;">
1
<div class="page-shell">
<div class="container">
<!-- 第一排4 卡片宽度占满 -->
<a-row :gutter="[20, 20]" class="card-row">
<a-col :xs="24" :sm="12" :md="6" v-for="(c, i) in cards" :key="i">
<a-card class="dash-card" :hoverable="true">
<div class="card-accent" :style="{ background: c.color }"></div>
<div class="card-body">
<div class="card-left">
<div class="card-label">{{ c.label }}</div>
<div class="card-note">{{ c.note }}</div>
</div>
<div class="card-value">{{ c.value }}</div>
</div>
</a-card>
</a-col>
</a-row>
<!-- 第二排Tabs 温度图整行宽度占满 -->
<a-card class="charts-card">
<a-tabs v-model:activeKey="activeTab" centered @change="onTabChange">
<a-tab-pane key="city" tab="城区供回水温度">
<div ref="cityChartRef" class="chart-large"></div>
</a-tab-pane>
<a-tab-pane key="county" tab="郊县供回水温度">
<div ref="countyChartRef" class="chart-large"></div>
</a-tab-pane>
</a-tabs>
</a-card>
<!-- 第三排左右两个图各占一半总体占满 -->
<a-row :gutter="20" class="third-row">
<a-col :xs="24" :md="12">
<a-card bordered class="mini-card">
<div class="mini-title">郊县瞬时热量实时</div>
<div ref="countyPowerChartRef" class="chart-medium"></div>
</a-card>
</a-col>
<a-col :xs="24" :md="12">
<a-card bordered class="mini-card" style="margin-left: 8px;">
<div class="mini-title">郊县瞬时流量实时</div>
<div ref="countyFlowChartRef" class="chart-medium"></div>
</a-card>
</a-col>
</a-row>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { ref, onMounted, nextTick, onUnmounted } from 'vue';
import * as echarts from 'echarts';
import { slcx, cqglfgswd } from '/@/api/dashboard/api';
/* ---- state ---- */
const activeTab = ref('city');
const cards = ref([
{ label: '城区锅炉房数量', value: 0, note: '实时统计', color: 'linear-gradient(90deg,#5B8FF9,#2FC25B)' },
{ label: '城区换热站数量', value: 0, note: '实时统计', color: 'linear-gradient(90deg,#2FC25B,#FACC14)' },
{ label: '郊县数量', value: 0, note: '实时统计', color: 'linear-gradient(90deg,#F04864,#9254DE)' },
{ label: '郊县锅炉房数量', value: 0, note: '实时统计', color: 'linear-gradient(90deg,#9254DE,#5B8FF9)' }
]);
/* ---- dom refs ---- */
const cityChartRef = ref<HTMLElement | null>(null);
const countyChartRef = ref<HTMLElement | null>(null);
const countyPowerChartRef = 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 initCountyIfNeed() {
if (!countyChart && countyChartRef.value && countyOption) {
countyChart = echarts.init(countyChartRef.value);
countyChart.setOption(countyOption);
} else {
countyChart?.resize();
}
}
function initPowerIfNeed() {
if (!countyPowerChart && countyPowerChartRef.value && countyPowerOption) {
countyPowerChart = echarts.init(countyPowerChartRef.value);
countyPowerChart.setOption(countyPowerOption);
} else {
countyPowerChart?.resize();
}
}
function initFlowIfNeed() {
if (!countyFlowChart && countyFlowChartRef.value && countyFlowOption) {
countyFlowChart = echarts.init(countyFlowChartRef.value);
countyFlowChart.setOption(countyFlowOption);
} else {
countyFlowChart?.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') {
if (!countyChart && countyChartRef.value) {
countyChart = echarts.init(countyChartRef.value);
}
countyChart?.setOption(countyOption, true);
countyChart?.resize();
}
});
}
let timer: number | null = null;
/* ---- load data ---- */
async function loadData() {
try {
// 1.
const s = await slcx();
cards.value = [
{ label: '城区锅炉房数量', value: s?.cqglfsl ?? 0, note: '实时统计', color: 'linear-gradient(90deg,#5B8FF9,#2FC25B)' },
{ label: '城区换热站数量', value: s?.cqhrzsl ?? 0, note: '实时统计', color: 'linear-gradient(90deg,#2FC25B,#FACC14)' },
{ label: '郊县数量', value: s?.jxsl ?? 0, note: '实时统计', color: 'linear-gradient(90deg,#F04864,#9254DE)' },
{ label: '郊县锅炉房数量', value: s?.jxglfsl ?? 0, note: '实时统计', color: 'linear-gradient(90deg,#9254DE,#5B8FF9)' }
];
// 2.
const r = await cqglfgswd();
const records = r?.data ?? [];
prepareOptions(records);
// 3. DOM
await nextTick();
// 4.
if (activeTab.value === 'city') {
if (!cityChart && cityChartRef.value) {
cityChart = echarts.init(cityChartRef.value);
}
cityChart?.setOption(cityOption, true);
} else {
if (!countyChart && countyChartRef.value) {
countyChart = echarts.init(countyChartRef.value);
}
countyChart?.setOption(countyOption, true);
}
//
if (!countyPowerChart && countyPowerChartRef.value) {
countyPowerChart = echarts.init(countyPowerChartRef.value);
}
countyPowerChart?.setOption(countyPowerOption, true);
if (!countyFlowChart && countyFlowChartRef.value) {
countyFlowChart = echarts.init(countyFlowChartRef.value);
}
countyFlowChart?.setOption(countyFlowOption, true);
// 5.
ensureResize();
} catch (err) {
console.error('load error', err);
}
}
/* ---- lifecycle ---- */
onMounted(() => {
loadData();
timer = window.setInterval(() => {
console.log('刷新数据…', new Date().toLocaleTimeString());
loadData();
}, 5 * 60 * 1000);
// }, 5 * 1000);
});
onUnmounted(() => {
if (cityChart) { cityChart.dispose(); cityChart = null; }
if (countyChart) { countyChart.dispose(); countyChart = null; }
if (countyPowerChart) { countyPowerChart.dispose(); countyPowerChart = null; }
if (countyFlowChart) { countyFlowChart.dispose(); countyFlowChart = null; }
if (timer) {
clearInterval(timer);
timer = null;
}
});
</script>
<style scoped>
/* 外层背景与容器:真正铺满视口宽度 */
.page-shell {
background: #f4f6fa;
min-height: 100vh;
box-sizing: border-box;
}
.container {
width: 100vw;
max-width: 100%;
padding: 14px;
margin: 0;
box-sizing: border-box;
}
/* header */
.header {
display: flex;
flex-direction: column;
align-items: flex-start;
margin-bottom: 18px;
padding: 0 16px;
}
.title {
font-size: 20px;
font-weight: 700;
color: #0b3b66;
}
/* 不纯黑:深蓝 */
.subtitle {
font-size: 12px;
color: #6f7f8f;
margin-top: 6px;
}
/* 卡片行:卡片横向填满列宽,文字左/右分布,垂直居中 */
.card-row {
margin-bottom: 18px;
width: 101%;
}
.dash-card {
position: relative;
overflow: hidden;
border-radius: 6px;
padding: 0;
box-shadow: 0 6px 20px rgba(31, 45, 61, 0.06);
transition: transform .12s;
height: 110px;
width: 100%;
box-sizing: border-box;
}
.dash-card:hover {
transform: translateY(-6px);
}
.card-accent {
height: 6px;
width: 100%;
position: absolute;
top: 0;
left: 0;
}
.card-body {
padding: 14px 18px;
background: #fff;
height: 100%;
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
}
.card-left {
display: flex;
flex-direction: column;
justify-content: center;
}
.card-label {
color: #6f7f8f;
font-size: 13px;
margin-bottom: 6px;
}
.card-note {
font-size: 12px;
color: #9aa7b7;
}
/* 大数字不再纯黑,右对齐,垂直居中 */
.card-value {
font-size: 32px;
font-weight: 800;
color: #0b63a7;
/* 品牌蓝,不纯黑 */
text-align: right;
line-height: 1;
}
/* 大图容器:宽度占满父容器 */
.charts-card {
border-radius: 8px;
box-shadow: 0 6px 18px rgba(31, 45, 61, 0.04);
margin-bottom: 18px;
padding: 12px 0;
}
.chart-large {
width: 100%;
height: 420px;
border-radius: 6px;
background: #ffffff;
padding: 8px;
box-sizing: border-box;
}
/* 第三排小卡:各占半宽,总体占满 */
.third-row {
margin-top: 6px;
width: 100%;
}
.mini-card {
border-radius: 8px;
background: #fff;
box-shadow: 0 4px 12px rgba(31, 45, 61, 0.04);
padding: 12px;
box-sizing: border-box;
width: 101.5%;
}
.mini-title {
font-weight: 600;
color: #223344;
margin-bottom: 8px;
}
.chart-medium {
width: 100%;
height: 320px;
background: #fff;
border-radius: 6px;
padding: 8px;
box-sizing: border-box;
}
/* 响应:移动端仍保留内边距 */
@media (max-width: 900px) {
.header {
padding: 0 12px;
}
.chart-large {
height: 320px;
}
.chart-medium {
height: 260px;
}
.card-body {
padding: 12px;
}
.card-value {
font-size: 28px;
}
}
</style>

View File

@ -1,7 +1,7 @@
<template>
<div class="index-body2">
<div class="index_header">
<span class="index_header-word">磐石市智慧供热监管平台</span>
<span class="index_header-word">磐石市供热信息化平台</span>
</div>
<div class="index-central">
<div style="width: 20px;height: 20px;position: absolute;cursor: pointer;" @click="showList"></div>

View File

@ -1,7 +1,7 @@
<template>
<div class="index-body2">
<div class="index_header">
<span class="index_header-word">磐石市智慧供热监管平台</span>
<span class="index_header-word">磐石市供热信息化平台</span>
</div>
<div class="index-central">
<a-row class="row">

View File

@ -2,7 +2,7 @@
<div :class="prefixCls" class="login-background-img">
<div class="index-body">
<div class="index_header">
<span class="index_header-word">磐石市智慧供热监管平台</span>
<span class="index_header-word">磐石市供热信息化平台</span>
</div>
<div class="index-centre">
<div class="index-padd">