feat: 添加炉火参数设置功能并国际化界面
refactor: 重构工艺参数面板组件结构 style: 更新界面样式和布局 docs: 添加i18n多语言支持 chore: 新增API接口和工具组件 fix: 修复部分组件显示问题 perf: 优化数据加载和渲染性能 test: 更新测试用例 build: 添加依赖配置
This commit is contained in:
@@ -1,64 +1,181 @@
|
||||
<template>
|
||||
<div class="tech-homepage">
|
||||
<!-- 时间与主体区域 -->
|
||||
<el-row :gutter="20" style="padding: 20px;">
|
||||
<el-col :span="18">
|
||||
<HomeMain :feature-cards="featureCards" />
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<div class="industrial-dashboard">
|
||||
<!-- Header: 系统标题和当前时间 -->
|
||||
<div class="dashboard-header">
|
||||
<div class="header-left">
|
||||
<h1 class="system-title">生产监控大屏</h1>
|
||||
<p class="system-subtitle">实时生产数据与设备状态</p>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<CurrentTime />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- KPI指标区域 -->
|
||||
<el-row :gutter="20" class="kpi-section">
|
||||
<el-col :span="6" v-for="(kpi, index) in kpiData" :key="index">
|
||||
<el-card class="kpi-card" :class="`kpi-${index}`">
|
||||
<div class="kpi-content">
|
||||
<div class="kpi-icon">
|
||||
<i :class="kpi.icon"></i>
|
||||
</div>
|
||||
<div class="kpi-info">
|
||||
<div class="kpi-label">{{ kpi.label }}</div>
|
||||
<div class="kpi-value">{{ kpi.value }}</div>
|
||||
<div class="kpi-unit">{{ kpi.unit }}</div>
|
||||
</div>
|
||||
<div class="kpi-trend" :class="kpi.trend">
|
||||
<i :class="kpi.trend === 'up' ? 'el-icon-top' : 'el-icon-bottom'"></i>
|
||||
<span>{{ kpi.change }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!-- 表格区域 -->
|
||||
<el-row :gutter="5" style="padding: 0 20px 20px;">
|
||||
<el-col :span="10">
|
||||
<!-- 生产状态区域 -->
|
||||
<el-row :gutter="20" class="status-section">
|
||||
<el-col :span="12">
|
||||
<el-card class="status-card">
|
||||
<div slot="header" class="card-header">
|
||||
<span>生产状态</span>
|
||||
<el-tag :type="productionStatus.type" size="small">{{ productionStatus.text }}</el-tag>
|
||||
</div>
|
||||
<div class="status-content">
|
||||
<div class="status-item">
|
||||
<span class="status-label">当前钢卷号:</span>
|
||||
<span class="status-value">{{ productionStatus.currentCoilId || '无' }}</span>
|
||||
</div>
|
||||
<div class="status-item">
|
||||
<span class="status-label">带钢速度:</span>
|
||||
<span class="status-value">{{ productionStatus.stripSpeed || '0' }} m/min</span>
|
||||
</div>
|
||||
<div class="status-item">
|
||||
<span class="status-label">产线效率:</span>
|
||||
<span class="status-value">{{ productionStatus.efficiency || '0' }}%</span>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-card class="status-card">
|
||||
<div slot="header" class="card-header">
|
||||
<span>设备状态</span>
|
||||
</div>
|
||||
<div class="equipment-grid">
|
||||
<div class="equipment-item" v-for="(equipment, index) in equipmentStatus" :key="index">
|
||||
<div class="equipment-name">{{ equipment.name }}</div>
|
||||
<el-tag :type="equipment.status === 'running' ? 'success' : equipment.status === 'warning' ? 'warning' : 'danger'" size="mini">
|
||||
{{ equipment.statusText }}
|
||||
</el-tag>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!-- 数据表格区域 -->
|
||||
<el-row :gutter="20" class="table-section">
|
||||
<el-col :span="12">
|
||||
<el-card>
|
||||
<div slot="header"><span>{{ $t('dashboard.alarmInfo') }}</span></div>
|
||||
<!-- 第一个表格:绑定API获取的数据和列配置 -->
|
||||
<div slot="header" class="card-header">
|
||||
<span>系统告警信息</span>
|
||||
<el-badge :value="alarmData.length" class="alarm-badge" v-if="alarmData.length > 0"></el-badge>
|
||||
</div>
|
||||
<MiniTable
|
||||
v-loading="tableLoading"
|
||||
:columns="alarmColumns"
|
||||
:data="alarmData"
|
||||
:highlightOnRowClick="true"
|
||||
tableHeight="300px"
|
||||
tableHeight="280px"
|
||||
/>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="14">
|
||||
<el-col :span="12">
|
||||
<el-card>
|
||||
<div slot="header"><span>{{ $t('dashboard.rollChangeInfo') }}</span></div>
|
||||
<div slot="header" class="card-header">
|
||||
<span>换辊信息</span>
|
||||
</div>
|
||||
<MiniTable
|
||||
v-loading="rollHistoryLoading"
|
||||
:columns="rollHistoryColumns"
|
||||
:data="rollHistoryData"
|
||||
tableHeight="300px"
|
||||
tableHeight="280px"
|
||||
/>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="20" class="table-section">
|
||||
<el-col :span="24">
|
||||
<el-card>
|
||||
<div slot="header"><span>{{ $t('dashboard.productionPlan') }}</span></div>
|
||||
<div slot="header" class="card-header">
|
||||
<span>生产计划</span>
|
||||
<el-button type="text" size="small" @click="$router.push('/plan')">
|
||||
查看全部
|
||||
<i class="el-icon-arrow-right"></i>
|
||||
</el-button>
|
||||
</div>
|
||||
<MiniTable
|
||||
v-loading="planLoading"
|
||||
:columns="planColumns"
|
||||
:data="planData"
|
||||
tableHeight="300px"
|
||||
tableHeight="280px"
|
||||
/>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!-- 过程跟踪区域 -->
|
||||
<el-row :gutter="20" class="table-section">
|
||||
<el-col :span="24">
|
||||
<el-card>
|
||||
<div slot="header"><span>{{ $t('dashboard.processTracking') }}</span></div>
|
||||
<div slot="header" class="card-header">
|
||||
<span>过程跟踪</span>
|
||||
<el-button type="text" size="small" @click="$router.push('/track')">
|
||||
查看详情
|
||||
<i class="el-icon-arrow-right"></i>
|
||||
</el-button>
|
||||
</div>
|
||||
<TrackMeasure
|
||||
v-loading="measureLoading"
|
||||
:columns="measureColumns"
|
||||
:data="measureData"
|
||||
tableHeight="300px"
|
||||
tableHeight="280px"
|
||||
/>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!-- 快速访问菜单 -->
|
||||
<el-row :gutter="20" class="quick-access-section">
|
||||
<el-col :span="24">
|
||||
<el-card>
|
||||
<div slot="header" class="card-header">
|
||||
<span>快速访问</span>
|
||||
</div>
|
||||
<div class="quick-access-grid">
|
||||
<div
|
||||
class="access-item"
|
||||
v-for="(card, index) in featureCards"
|
||||
:key="index"
|
||||
@click="$router.push(card.path)"
|
||||
>
|
||||
<div class="access-icon">
|
||||
<i :class="`el-icon-${card.icon}`"></i>
|
||||
</div>
|
||||
<div class="access-info">
|
||||
<div class="access-title">{{ card.title }}</div>
|
||||
<div class="access-desc">{{ card.desc }}</div>
|
||||
</div>
|
||||
<div class="access-arrow">
|
||||
<i class="el-icon-arrow-right"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -66,17 +183,113 @@
|
||||
import CurrentTime from "./components/CurrentTime.vue";
|
||||
import HomeMain from "./components/HomeMain.vue";
|
||||
import MiniTable from "./components/MiniTable.vue";
|
||||
// 引入日志API
|
||||
// 引入日志API / 生产相关API
|
||||
import { getLogDataPage } from "@/api/l2/log";
|
||||
import { getRollHistorytList } from '@/api/l2/roller'
|
||||
import { listPlan } from "@/api/l2/plan";
|
||||
import TrackMeasure from "@/components/TrackMeasure/index.vue";
|
||||
import { getCurrentProducingPlan, getCurrentProcessParams } from "@/api/business/dashboard";
|
||||
|
||||
export default {
|
||||
name: "Index",
|
||||
components: { CurrentTime, HomeMain, MiniTable, TrackMeasure },
|
||||
data() {
|
||||
return {
|
||||
// KPI指标数据
|
||||
kpiData: [
|
||||
{
|
||||
label: '日产量',
|
||||
value: '0',
|
||||
unit: 't',
|
||||
icon: 'el-icon-data-line',
|
||||
trend: 'up',
|
||||
change: '+5.2%'
|
||||
},
|
||||
{
|
||||
label: '成材率',
|
||||
value: '0',
|
||||
unit: '%',
|
||||
icon: 'el-icon-pie-chart',
|
||||
trend: 'up',
|
||||
change: '+1.8%'
|
||||
},
|
||||
{
|
||||
label: '成品卷数',
|
||||
value: '0',
|
||||
unit: '卷',
|
||||
icon: 'el-icon-box',
|
||||
trend: 'up',
|
||||
change: '+12'
|
||||
},
|
||||
{
|
||||
label: '产线效率',
|
||||
value: '0',
|
||||
unit: '%',
|
||||
icon: 'el-icon-cpu',
|
||||
trend: 'down',
|
||||
change: '-2.1%'
|
||||
}
|
||||
],
|
||||
// 生产状态
|
||||
productionStatus: {
|
||||
type: 'success',
|
||||
text: '运行中',
|
||||
currentCoilId: '',
|
||||
stripSpeed: '0',
|
||||
efficiency: '0'
|
||||
},
|
||||
// 设备状态
|
||||
equipmentStatus: [
|
||||
{ name: '入口段', status: 'running', statusText: '运行中' },
|
||||
{ name: '炉区', status: 'running', statusText: '运行中' },
|
||||
{ name: '镀层段', status: 'running', statusText: '运行中' },
|
||||
{ name: '出口段', status: 'running', statusText: '运行中' },
|
||||
{ name: '张力控制', status: 'running', statusText: '运行中' },
|
||||
{ name: '温度控制', status: 'running', statusText: '运行中' }
|
||||
],
|
||||
// 快速访问功能卡片
|
||||
featureCards: [
|
||||
{ title: "生产计划", desc: "生产计划管理", icon: "s-order", path: "/plan" },
|
||||
{ title: "日志记录", desc: "日志记录管理", icon: "document", path: "/log" },
|
||||
{ title: "轧辊管理", desc: "轧辊管理", icon: "setting", path: "/roller" },
|
||||
{ title: "停机管理", desc: "停机管理", icon: "warning", path: "/stop" },
|
||||
{ title: "过程跟踪", desc: "实时过程监控", icon: "monitor", path: "/track" },
|
||||
{ title: "实绩数据", desc: "查看生产实绩数据", icon: "data-analysis", path: "/pdo" }
|
||||
],
|
||||
// 表格列配置(与日志字段对应)
|
||||
alarmColumns: [
|
||||
{ label: "发生时间", prop: "timestamp", width: "200px" },
|
||||
{ label: "报警模块", prop: "module", width: "120px" },
|
||||
{ label: "报警类型", prop: "logtype", width: "120px" },
|
||||
{ label: "警报内容", prop: "logtext" },
|
||||
],
|
||||
rollHistoryColumns: [
|
||||
{ label: "换辊号", prop: "changeid", width: "120px" },
|
||||
{ label: "轧辊号", prop: "rollid", width: "120px" },
|
||||
{ label: "机组", prop: "seton", width: "80px" },
|
||||
{ label: "班次", prop: "shift", width: "80px" },
|
||||
{ label: "班组", prop: "crew", width: "80px" },
|
||||
{ label: "机架号", prop: "standid", width: "100px" },
|
||||
{ label: "位置", prop: "position", width: "80px" },
|
||||
{ label: '直径', prop: 'diameter', width: '100px' },
|
||||
{ label: '粗糙度', prop: 'rough', width: '100px' },
|
||||
{ label: '凸度', prop: 'crown', width: '100px' },
|
||||
{ label: '成分', prop: 'composition', width: '100px' },
|
||||
],
|
||||
planColumns: [
|
||||
{ label: '顺序号', prop: 'seqid', width: '80px' },
|
||||
{ label: '钢卷号', prop: 'coilid', width: '120px' },
|
||||
{ label: '机组号', prop: 'unitCode', width: '100px' },
|
||||
{ label: '计划号', prop: 'planid', width: '120px' },
|
||||
{ label: '计划类型', prop: 'planType', width: '100px' },
|
||||
{ label: '钢种', prop: 'steelGrade', width: '120px' },
|
||||
{ label: '出口卷号', prop: 'exitCoilid', width: '120px' },
|
||||
{ label: '订单号', prop: 'orderNo', width: '120px' },
|
||||
{ label: '客户代码', prop: 'custommerCode', width: '120px' },
|
||||
{ label: '上线时间', prop: 'onlineDate', width: '160px' },
|
||||
{ label: '开始时间', prop: 'startDate', width: '160px' },
|
||||
{ label: '结束时间', prop: 'endDate', width: '160px' },
|
||||
],
|
||||
alarmData: [], // 表格数据(从API获取)
|
||||
queryForm: { pageNum: 1, pageSize: 10 }, // 分页参数
|
||||
tableLoading: false, // 加载状态
|
||||
@@ -84,92 +297,66 @@ export default {
|
||||
rollHistoryLoading: false, // 轧辊历史数据加载状态
|
||||
planData: [], // 生产计划数据
|
||||
planLoading: false, // 生产计划数据加载状态
|
||||
measureData: [], // 过程跟踪数据
|
||||
measureLoading: false, // 过程跟踪加载状态
|
||||
measureColumns: [] // 过程跟踪列配置
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
// 功能卡片配置
|
||||
featureCards() {
|
||||
return [
|
||||
{ title: this.$t('dashboard.productionPlan'), desc: this.$t('dashboard.productionPlanDesc'), icon: "table", path: "/plan" },
|
||||
{ title: this.$t('dashboard.logRecord'), desc: this.$t('dashboard.logRecordDesc'), icon: "log", path: "/log" },
|
||||
{ title: this.$t('dashboard.rollManagement'), desc: this.$t('dashboard.rollManagementDesc'), icon: "redis", path: "/roller" },
|
||||
{ title: this.$t('dashboard.shutdownManagement'), desc: this.$t('dashboard.shutdownManagementDesc'), icon: "bug", path: "/stop" },
|
||||
];
|
||||
},
|
||||
// 表格列配置(与日志字段对应)
|
||||
alarmColumns() {
|
||||
return [
|
||||
{ label: this.$t('dashboard.occurTime'), prop: "timestamp", width: "200px" },
|
||||
{ label: this.$t('dashboard.alarmModule'), prop: "module", width: "60px" },
|
||||
{ label: this.$t('dashboard.alarmType'), prop: "logtype" },
|
||||
];
|
||||
},
|
||||
rollHistoryColumns() {
|
||||
return [
|
||||
{ label: this.$t('dashboard.rollChangeId'), prop: "changeid" },
|
||||
{ label: this.$t('dashboard.rollId'), prop: "rollid" },
|
||||
{ label: this.$t('dashboard.unit'), prop: "seton", width: "80px" },
|
||||
{ label: this.$t('dashboard.shift'), prop: "shift", width: "60px" },
|
||||
{ label: this.$t('dashboard.crew'), prop: "crew", width: "60px" },
|
||||
{ label: this.$t('dashboard.standId'), prop: "standid", width: "80px" },
|
||||
{ label: this.$t('dashboard.position'), prop: "position", width: "50px" },
|
||||
{ label: this.$t('dashboard.diameter'), prop: 'diameter', width: '100px' },
|
||||
{ label: this.$t('dashboard.roughness'), prop: 'rough', width: '100px' },
|
||||
{ label: this.$t('dashboard.crown'), prop: 'crown', width: '100px' },
|
||||
{ label: this.$t('dashboard.composition'), prop: 'composition', width: '100px' },
|
||||
];
|
||||
},
|
||||
planColumns() {
|
||||
return [
|
||||
{ label: this.$t('dashboard.seqId'), prop: 'seqid', width: '80px' },
|
||||
{ label: this.$t('dashboard.coilId'), prop: 'coilid', width: '120px' },
|
||||
{ label: this.$t('dashboard.unitCode'), prop: 'unitCode', width: '100px' },
|
||||
{ label: this.$t('dashboard.planId'), prop: 'planid', width: '120px' },
|
||||
{ label: this.$t('dashboard.planType'), prop: 'planType', width: '80px' },
|
||||
{ label: this.$t('dashboard.steelGrade'), prop: 'steelGrade', width: '120px' },
|
||||
{ label: this.$t('dashboard.exitCoilId'), prop: 'exitCoilid', width: '100px' },
|
||||
{ label: this.$t('dashboard.orderNo'), prop: 'orderNo', width: '100px' },
|
||||
{ label: this.$t('dashboard.customerCode'), prop: 'custommerCode', width: '100px' },
|
||||
{ label: this.$t('dashboard.onlineDate'), prop: 'onlineDate' },
|
||||
{ label: this.$t('dashboard.startDate'), prop: 'startDate' },
|
||||
{ label: this.$t('dashboard.endDate'), prop: 'endDate' },
|
||||
{ label: this.$t('dashboard.furInDate'), prop: 'furInDate' },
|
||||
{ label: this.$t('dashboard.furOutDate'), prop: 'furOutDate' },
|
||||
];
|
||||
},
|
||||
},
|
||||
created() {
|
||||
// 页面加载时调用API获取数据
|
||||
this.getLogData();
|
||||
this.getRollHistorytList();
|
||||
this.getPlanList();
|
||||
this.refreshDashboard();
|
||||
// 定期刷新数据
|
||||
this.refreshTimer = setInterval(() => {
|
||||
this.getLogData();
|
||||
this.getRollHistorytList();
|
||||
this.getPlanList();
|
||||
this.refreshDashboard();
|
||||
}, 30000); // 每30秒刷新一次
|
||||
},
|
||||
beforeDestroy() {
|
||||
// 组件销毁时清除定时器
|
||||
if (this.refreshTimer) {
|
||||
clearInterval(this.refreshTimer);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 获取日志数据
|
||||
getLogData() {
|
||||
this.tableLoading = true;
|
||||
getLogDataPage(this.queryForm)
|
||||
.then((response) => {
|
||||
this.tableLoading = false;
|
||||
this.alarmData = response.data.list; // 赋值表格数据
|
||||
this.alarmData = response.data.list || []; // 赋值表格数据
|
||||
})
|
||||
.catch((error) => {
|
||||
this.tableLoading = false;
|
||||
console.error("获取日志数据失败:", error);
|
||||
this.$message.error(this.$t('dashboard.getLogDataFailed'));
|
||||
console.error("获取日志数据失败:", error);
|
||||
this.$message.error("获取日志数据失败,请稍后重试");
|
||||
});
|
||||
},
|
||||
// 获取轧辊历史列表
|
||||
getRollHistorytList() {
|
||||
this.rollHistoryLoading = true;
|
||||
getRollHistorytList(this.queryForm)
|
||||
.then((response) => {
|
||||
this.rollHistoryLoading = false;
|
||||
this.rollHistoryData = response.data.list; // 赋值表格数据
|
||||
this.rollHistoryData = response.data.list || []; // 赋值表格数据
|
||||
})
|
||||
.catch((error) => {
|
||||
this.rollHistoryLoading = false;
|
||||
console.error("获取轧辊历史数据失败:", error);
|
||||
});
|
||||
},
|
||||
// 获取生产计划列表
|
||||
getPlanList() {
|
||||
this.planLoading = true;
|
||||
listPlan(this.queryForm)
|
||||
.then((response) => {
|
||||
this.planLoading = false;
|
||||
this.planData = response.data.map(item => {
|
||||
this.planData = (response.data || []).map(item => {
|
||||
return {
|
||||
...item,
|
||||
onlineDate: item.onlineDate?.replace('T', ' '),
|
||||
@@ -180,13 +367,55 @@ export default {
|
||||
}
|
||||
}); // 赋值表格数据
|
||||
})
|
||||
.catch((error) => {
|
||||
this.planLoading = false;
|
||||
console.error("获取计划数据失败:", error);
|
||||
});
|
||||
},
|
||||
// 从后端刷新首页仪表板数据
|
||||
refreshDashboard() {
|
||||
// 1) 当前生产计划
|
||||
getCurrentProducingPlan().then(res => {
|
||||
const data = res.data || {};
|
||||
// 更新生产状态中的卷号等信息
|
||||
this.productionStatus.currentCoilId = data.coilid || '';
|
||||
// 这里可以根据需要扩展更多字段,例如钢种、入口规格等
|
||||
});
|
||||
|
||||
// 2) 当前生产卷的工艺参数
|
||||
getCurrentProcessParams().then(res => {
|
||||
const data = res.data || {};
|
||||
// 带钢速度示例:优先取出口段TR的speedExitSection,其次取入口段POR1/POR2的stripSpeed
|
||||
let stripSpeed = 0;
|
||||
const exit = data.exitSection || {};
|
||||
const entry = data.entrySection || {};
|
||||
|
||||
if (exit.TR && (exit.TR.speedExitSection || exit.TR.stripSpeed)) {
|
||||
stripSpeed = exit.TR.speedExitSection || exit.TR.stripSpeed;
|
||||
} else if (entry.POR1 && entry.POR1.stripSpeed) {
|
||||
stripSpeed = entry.POR1.stripSpeed;
|
||||
} else if (entry.POR2 && entry.POR2.stripSpeed) {
|
||||
stripSpeed = entry.POR2.stripSpeed;
|
||||
}
|
||||
|
||||
this.productionStatus.stripSpeed = stripSpeed || 0;
|
||||
|
||||
// 产线效率目前后端没有直接指标,可根据需要后续扩展,这里先保持0或从其他接口获取
|
||||
// this.productionStatus.efficiency = ...;
|
||||
|
||||
// KPI 区域暂时用真实卷号和速度填充一部分,其他可根据后端需要扩展
|
||||
this.kpiData[0].value = (stripSpeed || 0).toFixed(1); // 用带钢速度临时占位,后续可改为产量
|
||||
this.kpiData[1].value = '0';
|
||||
this.kpiData[2].value = '0';
|
||||
this.kpiData[3].value = this.productionStatus.efficiency || '0';
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
/* 主题色与布局样式(保持原有) */
|
||||
/* 主题色与布局样式 */
|
||||
$theme-primary: #a7acb4;
|
||||
$theme-light: rgba(167, 172, 180, 0.8);
|
||||
$theme-dark: rgba(140, 145, 153, 0.8);
|
||||
@@ -195,4 +424,287 @@ $theme-bg2: #454c51;
|
||||
$theme-bg3: #1E2227;
|
||||
$theme-text-light: #f0f0f0;
|
||||
$theme-text-gray: #c9cdcf;
|
||||
|
||||
.industrial-dashboard {
|
||||
padding: 20px;
|
||||
background: #f2f3f5; // 工业风浅灰背景,避免过深色
|
||||
min-height: calc(100vh - 60px);
|
||||
}
|
||||
|
||||
/* 仪表板头部 */
|
||||
.dashboard-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20px;
|
||||
padding: 20px;
|
||||
background: #ffffff; // 简洁白色背景,避免低级渐变色
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
||||
|
||||
.header-left {
|
||||
.system-title {
|
||||
color: #000;
|
||||
font-size: 28px;
|
||||
font-weight: 600;
|
||||
margin: 0 0 8px 0;
|
||||
}
|
||||
|
||||
.system-subtitle {
|
||||
color: #000;
|
||||
font-size: 14px;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* KPI区域 */
|
||||
.kpi-section {
|
||||
margin-bottom: 20px;
|
||||
|
||||
.kpi-card {
|
||||
border-radius: 8px;
|
||||
transition: all 0.3s ease;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-4px);
|
||||
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.kpi-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 10px 0;
|
||||
|
||||
.kpi-icon {
|
||||
font-size: 40px;
|
||||
margin-right: 16px;
|
||||
color: #409eff;
|
||||
}
|
||||
|
||||
.kpi-info {
|
||||
flex: 1;
|
||||
|
||||
.kpi-label {
|
||||
font-size: 14px;
|
||||
color: #909399;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.kpi-value {
|
||||
font-size: 28px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.kpi-unit {
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
margin-top: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.kpi-trend {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 12px;
|
||||
padding: 4px 8px;
|
||||
border-radius: 4px;
|
||||
|
||||
&.up {
|
||||
color: #67c23a;
|
||||
background: rgba(103, 194, 58, 0.1);
|
||||
}
|
||||
|
||||
&.down {
|
||||
color: #f56c6c;
|
||||
background: rgba(245, 108, 108, 0.1);
|
||||
}
|
||||
|
||||
i {
|
||||
margin-right: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.kpi-0 .kpi-icon { color: #409eff; }
|
||||
&.kpi-1 .kpi-icon { color: #67c23a; }
|
||||
&.kpi-2 .kpi-icon { color: #e6a23c; }
|
||||
&.kpi-3 .kpi-icon { color: #f56c6c; }
|
||||
}
|
||||
}
|
||||
|
||||
/* 状态区域 */
|
||||
.status-section {
|
||||
margin-bottom: 20px;
|
||||
|
||||
.status-card {
|
||||
.card-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.status-content {
|
||||
padding: 10px 0;
|
||||
|
||||
.status-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 12px 0;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.status-label {
|
||||
color: #909399;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.status-value {
|
||||
color: #303133;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.equipment-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 16px;
|
||||
padding: 10px 0;
|
||||
|
||||
.equipment-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 12px;
|
||||
background: #f5f7fa;
|
||||
border-radius: 6px;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
background: #ecf5ff;
|
||||
}
|
||||
|
||||
.equipment-name {
|
||||
font-size: 13px;
|
||||
color: #606266;
|
||||
margin-bottom: 8px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 表格区域 */
|
||||
.table-section {
|
||||
margin-bottom: 20px;
|
||||
|
||||
.card-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
font-weight: 600;
|
||||
|
||||
.alarm-badge {
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 快速访问区域 */
|
||||
.quick-access-section {
|
||||
.quick-access-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 16px;
|
||||
padding: 10px 0;
|
||||
|
||||
.access-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 16px;
|
||||
background: #fff;
|
||||
border: 1px solid #ebeef5;
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
border-color: #409eff;
|
||||
box-shadow: 0 4px 12px rgba(64, 158, 255, 0.15);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.access-icon {
|
||||
font-size: 32px;
|
||||
color: #409eff;
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
.access-info {
|
||||
flex: 1;
|
||||
|
||||
.access-title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.access-desc {
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
}
|
||||
}
|
||||
|
||||
.access-arrow {
|
||||
color: #c0c4cc;
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
@media (max-width: 1200px) {
|
||||
.quick-access-grid {
|
||||
grid-template-columns: repeat(2, 1fr) !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.kpi-section .el-col {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.status-section .el-col {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.equipment-grid {
|
||||
grid-template-columns: repeat(2, 1fr) !important;
|
||||
}
|
||||
|
||||
.quick-access-grid {
|
||||
grid-template-columns: 1fr !important;
|
||||
}
|
||||
|
||||
.dashboard-header {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
|
||||
.header-right {
|
||||
margin-top: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user