refactor: 重构工艺参数面板组件结构 style: 更新界面样式和布局 docs: 添加i18n多语言支持 chore: 新增API接口和工具组件 fix: 修复部分组件显示问题 perf: 优化数据加载和渲染性能 test: 更新测试用例 build: 添加依赖配置
710 lines
20 KiB
Vue
710 lines
20 KiB
Vue
<template>
|
||
<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="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" 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="280px"
|
||
/>
|
||
</el-card>
|
||
</el-col>
|
||
<el-col :span="12">
|
||
<el-card>
|
||
<div slot="header" class="card-header">
|
||
<span>换辊信息</span>
|
||
</div>
|
||
<MiniTable
|
||
v-loading="rollHistoryLoading"
|
||
:columns="rollHistoryColumns"
|
||
:data="rollHistoryData"
|
||
tableHeight="280px"
|
||
/>
|
||
</el-card>
|
||
</el-col>
|
||
</el-row>
|
||
|
||
<el-row :gutter="20" class="table-section">
|
||
<el-col :span="24">
|
||
<el-card>
|
||
<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="280px"
|
||
/>
|
||
</el-card>
|
||
</el-col>
|
||
</el-row>
|
||
|
||
<!-- 过程跟踪区域 -->
|
||
<el-row :gutter="20" class="table-section">
|
||
<el-col :span="24">
|
||
<el-card>
|
||
<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="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>
|
||
|
||
<script>
|
||
import CurrentTime from "./components/CurrentTime.vue";
|
||
import HomeMain from "./components/HomeMain.vue";
|
||
import MiniTable from "./components/MiniTable.vue";
|
||
// 引入日志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, // 加载状态
|
||
rollHistoryData: [], // 轧辊历史数据
|
||
rollHistoryLoading: false, // 轧辊历史数据加载状态
|
||
planData: [], // 生产计划数据
|
||
planLoading: false, // 生产计划数据加载状态
|
||
measureData: [], // 过程跟踪数据
|
||
measureLoading: false, // 过程跟踪加载状态
|
||
measureColumns: [] // 过程跟踪列配置
|
||
};
|
||
},
|
||
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 || []; // 赋值表格数据
|
||
})
|
||
.catch((error) => {
|
||
this.tableLoading = false;
|
||
console.error("获取日志数据失败:", error);
|
||
this.$message.error("获取日志数据失败,请稍后重试");
|
||
});
|
||
},
|
||
// 获取轧辊历史列表
|
||
getRollHistorytList() {
|
||
this.rollHistoryLoading = true;
|
||
getRollHistorytList(this.queryForm)
|
||
.then((response) => {
|
||
this.rollHistoryLoading = false;
|
||
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 => {
|
||
return {
|
||
...item,
|
||
onlineDate: item.onlineDate?.replace('T', ' '),
|
||
startDate: item.startDate?.replace('T', ' '),
|
||
endDate: item.endDate?.replace('T', ' '),
|
||
furInDate: item.furInDate?.replace('T', ' '),
|
||
furOutDate: item.furOutDate?.replace('T', ' '),
|
||
}
|
||
}); // 赋值表格数据
|
||
})
|
||
.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);
|
||
$theme-bg1: #454c51;
|
||
$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> |