首页、系统界面颜色
This commit is contained in:
parent
566e89ea0a
commit
f270321079
4
.env
4
.env
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1,25 +1,31 @@
|
|||
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',
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param params
|
||||
*/
|
||||
export const slcx = () => {
|
||||
return defHttp.post({url: Api.slcx});
|
||||
}
|
||||
return defHttp.post({ url: Api.slcx });
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param params
|
||||
*/
|
||||
export const cqglfgswd = () => {
|
||||
return defHttp.post({url: Api.cqglfgswd});
|
||||
}
|
||||
return defHttp.post({ url: Api.cqglfgswd });
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param params
|
||||
*/
|
||||
export const glfzb = () => {
|
||||
return defHttp.post({ url: Api.glfzb });
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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">
|
||||
|
|
|
|||
|
|
@ -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">
|
||||
|
|
|
|||
Loading…
Reference in New Issue