feat(hfnf): 总览页全屏/加载态 + 瓮福明细列合并与自动查询
- hfnf_index: 全屏按钮(浏览器全屏+CSS覆盖菜单,退出恢复菜单),loading 蒙层; 标题改"工业生产数据采集总览",系统名称改"水泥生产数据采集"; 瓮福烧结矿卡片跳转 /wengfu_mplogx - wengfu_mplogx: 监测值/布尔值合并为单列"监测值"(开关测点显示 开/关); 测点与时间选择器 @change 自动查询 - hfnf api: 新增 stats 接口, mplogx 指向 10.0.11.52:5800 - router: BASE_INFO 缺失时回登录页(防空指针) - vue.config: 新增 /hfnf_stats 代理 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
74da00c70e
commit
65c26f7d15
|
|
@ -66,8 +66,13 @@ router.beforeEach(async (to, from, next) => {
|
|||
}
|
||||
//加载动态/静态路由
|
||||
if (!isGetRouter) {
|
||||
let baseInfo = tool.data.get('BASE_INFO');
|
||||
if (!baseInfo) {
|
||||
next({ path: '/login' });
|
||||
return false;
|
||||
}
|
||||
let userMenu = [];
|
||||
if(tool.data.get('BASE_INFO').base.base_menucate=='dynamic'){
|
||||
if(baseInfo.base.base_menucate=='dynamic'){
|
||||
userMenu = tool.data.get("MENU") || [];
|
||||
}else{
|
||||
let permissions = tool.data.get("PERMISSIONS") || [];//账号页面权限
|
||||
|
|
@ -114,7 +119,9 @@ router.onError((error) => {
|
|||
|
||||
//入侵追加自定义方法、对象
|
||||
router.sc_getMenu = () => {
|
||||
if(tool.data.get('BASE_INFO').base.base_menucate=='dynamic'){
|
||||
let baseInfo = tool.data.get('BASE_INFO');
|
||||
if(!baseInfo) return [];
|
||||
if(baseInfo.base.base_menucate=='dynamic'){
|
||||
return tool.data.get("MENU") || []
|
||||
}
|
||||
else{
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div class="hfnf-dashboard">
|
||||
<div class="hfnf-dashboard" :class="{ 'is-fullscreen': isFullscreen }" v-loading="loading" element-loading-text="数据加载中..." element-loading-background="rgba(245, 247, 250, 0.85)">
|
||||
<!-- 顶部总览横幅 -->
|
||||
<div class="summary-banner">
|
||||
<div class="banner-left">
|
||||
|
|
@ -7,7 +7,7 @@
|
|||
<img src="/media/logo2.png" class="banner-logo" />
|
||||
</div>
|
||||
<div class="banner-info">
|
||||
<h2>水泥生产数据采集总览</h2>
|
||||
<h2>工业生产数据采集总览</h2>
|
||||
<p>覆盖 {{ factories.length }} 家工厂 · 实时数据监控</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -17,13 +17,17 @@
|
|||
<span class="total-value">{{ formatNumber(totalCount) }}</span>
|
||||
<span class="total-unit">条</span>
|
||||
</div>
|
||||
<el-button type="primary" plain class="back-btn" @click="toggleFullscreen">
|
||||
<el-icon><FullScreen /></el-icon>
|
||||
{{ isFullscreen ? '退出全屏' : '进入全屏' }}
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 工厂数据卡片 -->
|
||||
<el-row :gutter="16" class="factory-row">
|
||||
<el-col :xs="24" :sm="12" :md="6" v-for="(item, index) in factories" :key="item.name">
|
||||
<div class="factory-card" :style="{ borderTopColor: item.color }">
|
||||
<div class="factory-card" :style="{ borderTopColor: item.color }" @click="goDetail(item)">
|
||||
<div class="card-header">
|
||||
<div class="card-icon" :style="{ backgroundColor: item.bgColor }">
|
||||
<el-icon :size="24" :color="item.color"><OfficeBuilding /></el-icon>
|
||||
|
|
@ -114,7 +118,7 @@
|
|||
</div>
|
||||
<div class="sys-info-content">
|
||||
<span class="sys-info-label">系统名称</span>
|
||||
<span class="sys-info-value">水泥生产数据人工智能采集融合系统</span>
|
||||
<span class="sys-info-value">水泥生产数据采集</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sys-info-item">
|
||||
|
|
@ -190,8 +194,8 @@ const pieChartRef = ref(null)
|
|||
let barChart = null
|
||||
let pieChart = null
|
||||
|
||||
const colors = ['#409eff', '#67c23a', '#e6a23c', '#f56c6c']
|
||||
const bgColors = ['#ecf5ff', '#f0f9eb', '#fdf6ec', '#fef0f0']
|
||||
const colors = ['#409eff', '#67c23a', '#e6a23c', '#f56c6c', '#9b59b6']
|
||||
const bgColors = ['#ecf5ff', '#f0f9eb', '#fdf6ec', '#fef0f0', '#f5eef8']
|
||||
|
||||
// 各工厂与数据表的映射关系
|
||||
const factoryDefs = [
|
||||
|
|
@ -199,10 +203,13 @@ const factoryDefs = [
|
|||
{ name: '中联万吨', match: (t) => t === 'mplogx_xzzl' }, // 中联万吨
|
||||
{ name: '铜梁水泥', match: (t) => t === 'mplogx_tlxn' }, // 铜梁水泥
|
||||
{ name: '槐坎南方水泥', match: (t) => t.startsWith('mplogx_hknf') }, // 槁坎南方水泥
|
||||
{ name: '瓮福烧结矿', match: (t) => t === 'mplogx_wengfu' }, // 瓮福烧结矿
|
||||
]
|
||||
|
||||
const totalCount = ref(0)
|
||||
const tables = ref([])
|
||||
const loading = ref(true)
|
||||
const isFullscreen = ref(false)
|
||||
|
||||
const factories = computed(() => {
|
||||
const total = totalCount.value
|
||||
|
|
@ -227,11 +234,31 @@ const maxFactory = computed(() => {
|
|||
})
|
||||
|
||||
const formatNumber = (num) => {
|
||||
return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',')
|
||||
return (num || 0).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',')
|
||||
}
|
||||
|
||||
const goDetail = () => {
|
||||
router.push('/hfnf_mplogx')
|
||||
const toggleFullscreen = () => {
|
||||
// 浏览器沉浸式全屏;菜单的显隐由 isFullscreen 驱动的 CSS class 控制(见样式)
|
||||
if (document.fullscreenElement) {
|
||||
document.exitFullscreen()
|
||||
} else {
|
||||
document.documentElement.requestFullscreen()
|
||||
}
|
||||
}
|
||||
|
||||
const handleFullscreenChange = () => {
|
||||
isFullscreen.value = !!document.fullscreenElement
|
||||
// 切换全屏后图表需要重绘以适配新尺寸
|
||||
nextTick(() => handleResize())
|
||||
}
|
||||
|
||||
const goDetail = (item) => {
|
||||
// 瓮福烧结矿 跳转独立明细页,其余跳默认明细页
|
||||
if (item && item.name === '瓮福烧结矿') {
|
||||
router.push('/wengfu_mplogx')
|
||||
} else {
|
||||
router.push('/hfnf_mplogx')
|
||||
}
|
||||
}
|
||||
|
||||
const goStandard = () => {
|
||||
|
|
@ -351,8 +378,11 @@ onMounted(() => {
|
|||
initBarChart()
|
||||
initPieChart()
|
||||
})
|
||||
}).finally(() => {
|
||||
loading.value = false
|
||||
})
|
||||
window.addEventListener('resize', handleResize)
|
||||
document.addEventListener('fullscreenchange', handleFullscreenChange)
|
||||
// 多压一条相同的历史记录,使浏览器后退可被 popstate 拦截
|
||||
history.pushState(null, '', location.href)
|
||||
window.addEventListener('popstate', handlePopState)
|
||||
|
|
@ -360,6 +390,7 @@ onMounted(() => {
|
|||
|
||||
onBeforeUnmount(() => {
|
||||
window.removeEventListener('resize', handleResize)
|
||||
document.removeEventListener('fullscreenchange', handleFullscreenChange)
|
||||
window.removeEventListener('popstate', handlePopState)
|
||||
barChart?.dispose()
|
||||
pieChart?.dispose()
|
||||
|
|
@ -373,6 +404,21 @@ onBeforeUnmount(() => {
|
|||
min-height: calc(100vh - 60px);
|
||||
}
|
||||
|
||||
/* 全屏态:dashboard 固定铺满屏幕、遮住左侧菜单与顶栏;退出移除 class 即恢复 */
|
||||
.hfnf-dashboard.is-fullscreen {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
min-height: 100%;
|
||||
z-index: 9999;
|
||||
overflow-y: auto;
|
||||
background: #f5f7fa;
|
||||
}
|
||||
|
||||
/* 顶部横幅 */
|
||||
.summary-banner {
|
||||
display: flex;
|
||||
|
|
@ -422,6 +468,22 @@ onBeforeUnmount(() => {
|
|||
|
||||
.banner-right {
|
||||
text-align: right;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.back-btn {
|
||||
background: rgba(255, 255, 255, 0.15);
|
||||
border-color: rgba(255, 255, 255, 0.4);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.back-btn:hover {
|
||||
background: rgba(255, 255, 255, 0.3);
|
||||
border-color: rgba(255, 255, 255, 0.6);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.total-block {
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
collapse-tags-tooltip
|
||||
:max-collapse-tags="3"
|
||||
@visible-change="onSelectVisible"
|
||||
@change="handleQuery"
|
||||
popper-class="mpoint-select-popper"
|
||||
>
|
||||
<el-option
|
||||
|
|
@ -44,6 +45,7 @@
|
|||
end-placeholder="结束时间"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
style="width:380px;"
|
||||
@change="handleQuery"
|
||||
/>
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleQuery">查询</el-button>
|
||||
<el-button type="success" icon="el-icon-download" @click="handleExport" :loading="exporting">导出Excel</el-button>
|
||||
|
|
@ -64,14 +66,9 @@
|
|||
<el-table-column label="测点名称" prop="mpoint_name" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="测点ID" prop="mpoint_id" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="监测时间" prop="timex" align="center"></el-table-column>
|
||||
<el-table-column label="监测值" prop="val" align="right">
|
||||
<el-table-column label="监测值" align="center">
|
||||
<template #default="{ row }">
|
||||
{{ row.val != null ? Number(row.val).toFixed(4) : '' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="布尔值" prop="val_bool" align="center">
|
||||
<template #default="{ row }">
|
||||
{{ row.val_bool != null ? (row.val_bool ? '是' : '否') : '' }}
|
||||
{{ formatVal(row) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
</scTable>
|
||||
|
|
@ -90,6 +87,17 @@ const apiObj = ref(API.enm.wengfu_mplogx.list)
|
|||
const query = ref({})
|
||||
const table = ref(null)
|
||||
|
||||
// 监测值:数值类用 val,布尔类(开关测点)用 val_bool(开/关),都统一到这一列
|
||||
const formatVal = (row) => {
|
||||
if (row.val != null && row.val !== '') {
|
||||
return Number(row.val).toFixed(4)
|
||||
}
|
||||
if (row.val_bool != null) {
|
||||
return row.val_bool ? '开' : '关'
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
const selectedMpoints = ref([])
|
||||
const timeRange = ref([])
|
||||
const mpointOptions = ref([])
|
||||
|
|
@ -265,16 +273,12 @@ const handleExport = async () => {
|
|||
}
|
||||
|
||||
const exportToExcel = (data) => {
|
||||
const hasBool = data.some(item => item.val_bool != null)
|
||||
const rows = data.map(item => {
|
||||
const row = {
|
||||
'测点名称': item.mpoint_name || '',
|
||||
'测点ID': item.mpoint_id,
|
||||
'监测时间': item.timex,
|
||||
'监测值': item.val,
|
||||
}
|
||||
if (hasBool) {
|
||||
row['布尔值'] = item.val_bool != null ? (item.val_bool ? '是' : '否') : ''
|
||||
'监测值': formatVal(item),
|
||||
}
|
||||
return row
|
||||
})
|
||||
|
|
|
|||
|
|
@ -28,6 +28,13 @@ module.exports = defineConfig({
|
|||
pathRewrite: {
|
||||
'^/api': '/'
|
||||
}
|
||||
},
|
||||
'/hfnf_stats': {
|
||||
target: 'http://10.0.11.52:5900',
|
||||
changeOrigin: true,
|
||||
pathRewrite: {
|
||||
'^/hfnf_stats': ''
|
||||
}
|
||||
}
|
||||
},
|
||||
client: {
|
||||
|
|
|
|||
Loading…
Reference in New Issue