| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198 |
- <!-- 首页工作台:轻量化蓝白科技风 B端数据中台 - Element Plus -->
- <template>
- <div class="workspace-container">
- <!-- 顶部标题栏 -->
- <header class="oa-header">
- <div class="header-left">
- <h1 class="system-title">乌拉海沟水库综合应用管理系统</h1>
- <el-tag type="primary" effect="dark" round size="small">工作台</el-tag>
- </div>
- <div class="header-right">
- <el-tooltip content="返回大屏" placement="bottom">
- <div class="back-bigscreen-btn" @click="$emit('backToDashboard')">
- <svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
- <path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path>
- <polyline points="9 22 9 12 15 12 15 22"></polyline>
- </svg>
- </div>
- </el-tooltip>
- <el-input v-model="searchText" placeholder="搜索功能、工单、设备..." clearable class="header-search">
- <template #prefix>
- <el-icon><Search /></el-icon>
- </template>
- </el-input>
- <span class="header-date">{{ currentDate }}</span>
- <span class="header-time">{{ currentTime }}</span>
- </div>
- </header>
- <!-- 主体区域 -->
- <div class="oa-body">
- <!-- 左侧树状菜单 -->
- <aside class="sidebar">
- <el-menu :default-active="activeMenu" class="sidebar-menu" @select="handleMenuSelect">
- <template v-for="(group, index) in menuTree" :key="index">
- <el-menu-item v-if="!group.children || group.children.length === 0" :index="group.name">
- <span class="menu-top-item">{{ group.name }}</span>
- </el-menu-item>
- <el-sub-menu v-else :index="group.name">
- <template #title>
- <span>{{ group.name }}</span>
- </template>
- <el-menu-item v-for="(item, idx) in group.children" :key="idx" :index="item.id">
- <span>{{ item.name }}</span>
- </el-menu-item>
- </el-sub-menu>
- </template>
- </el-menu>
- </aside>
- <!-- 右侧内容区 -->
- <main class="oa-main">
- <!-- 设备运维页面 -->
- <DeviceMaintainView v-if="activeMenu === '设备运维'" />
- <!-- 闸门控制页面 -->
- <GateControlAdminView v-if="activeMenu === '闸门控制'" />
- <!-- 巡检计划页面 -->
- <PatrolPlanView v-if="activeMenu === 'patrol-plan'" />
- <!-- 巡检记录页面 -->
- <PatrolRecordView v-if="activeMenu === 'patrol-record'" />
- <!-- 隐患台账页面 -->
- <PatrolHiddenView v-if="activeMenu === 'patrol-hidden'" />
- <!-- 水雨情监测页面 -->
- <WaterRainView v-if="activeMenu === 'hydro-realtime'" />
- <HydroHistoryView v-if="activeMenu === 'hydro-history'" />
- <!-- 水资源调度模块 -->
- <WaterResourceAllocationView v-if="isWaterActive" ref="waterView" :default-tab="waterTabMap[activeMenu]" :key="activeMenu" />
- <!-- 工程效益 -->
- <BenefitSummaryView v-if="isBenefitActive" :key="activeMenu" />
- <!-- 资料档案模块 -->
- <ArchiveFilesView v-if="activeMenu === 'archive-files'" />
- <ArchiveOrdersView v-if="activeMenu === 'archive-orders'" />
- <ArchiveLifecycleView v-if="activeMenu === 'archive-lifecycle'" />
- <!-- 系统权限模块 -->
- <SysRoleView v-if="activeMenu === 'sys-role'" />
- <SysUserView v-if="activeMenu === 'sys-user'" />
- <SysLogView v-if="activeMenu === 'sys-log'" />
- <!-- 首页内容 -->
- <template v-if="isHomePage">
- <!-- 核心水情数据卡片 -->
- <section class="glass-card stats-section">
- <div class="card-header">
- <span class="card-title">实时水情</span>
- <div class="card-actions">
- <el-tag :type="waterLevelStatus.type" effect="dark" size="small">
- {{ waterLevelStatus.text }}
- </el-tag>
- </div>
- </div>
- <div class="stats-grid">
- <div class="stat-card" v-for="(card, index) in waterDataCards" :key="index">
- <div class="stat-card-left">
- <div class="stat-icon-wrap" :style="{ background: card.iconBg }">
- <span class="stat-icon">{{ card.icon }}</span>
- </div>
- <span class="stat-label">{{ card.title }}</span>
- </div>
- <div class="stat-card-right">
- <div class="stat-card-value">
- <span class="stat-value">{{ card.value }}</span>
- <span class="stat-unit">{{ card.unit }}</span>
- </div>
- <span class="stat-time">{{ card.updateTime }}</span>
- </div>
- </div>
- </div>
- </section>
- <!-- 中间区域:预警 + 工单 + 设备状态 -->
- <section class="middle-section">
- <!-- 左侧:预警信息 + 待办工单 -->
- <div class="middle-left">
- <!-- 预警信息 -->
- <div class="glass-card warning-panel">
- <div class="card-header">
- <span class="card-title">预警信息</span>
- <el-badge :value="warningList.length" :max="99" class="warning-badge">
- <el-button type="danger" size="small" plain>查看全部</el-button>
- </el-badge>
- </div>
- <div class="card-body">
- <div class="warning-list">
- <div v-for="(item, index) in warningList" :key="index"
- :class="['warning-item', `warning-${item.level}`]">
- <div class="warning-icon">
- <el-icon><Warning /></el-icon>
- </div>
- <div class="warning-content">
- <div class="warning-title">{{ item.title }}</div>
- <div class="warning-meta">
- <span>{{ item.location }}</span>
- <span>{{ item.time }}</span>
- </div>
- </div>
- <el-tag :type="getWarningType(item.level)" size="small" effect="dark">
- {{ item.levelText }}
- </el-tag>
- </div>
- </div>
- </div>
- </div>
- <!-- 月度指标统计 -->
- <div class="glass-card stats-table-panel">
- <div class="card-header">
- <span class="card-title">月度指标统计</span>
- <div class="card-actions">
- <el-button type="primary" size="small" plain>导出Excel</el-button>
- <el-button type="primary" size="small" plain>导出PDF</el-button>
- </div>
- </div>
- <div class="card-body">
- <el-table :data="monthlyStats" stripe style="width: 100%" size="small">
- <el-table-column prop="name" label="统计项" width="120" />
- <el-table-column label="本月数值">
- <template #default="{ row }">
- <span class="value-highlight">{{ row.value }}</span>
- </template>
- </el-table-column>
- <el-table-column prop="unit" label="单位" width="80" />
- <el-table-column label="环比变化" width="100">
- <template #default="{ row }">
- <span :class="['trend', row.trend > 0 ? 'trend-up' : 'trend-down']">
- {{ row.trend > 0 ? '+' : '' }}{{ row.trend }}%
- </span>
- </template>
- </el-table-column>
- <el-table-column label="趋势" width="80">
- <template #default="{ row }">
- <div class="mini-chart">
- <div class="chart-bar" :style="{ height: Math.abs(row.trend) + '%', background: row.trend > 0 ? '#52c41a' : '#ff4d4f' }"></div>
- </div>
- </template>
- </el-table-column>
- </el-table>
- </div>
- </div>
- <!-- 待办工单 -->
- <div class="glass-card todo-panel">
- <div class="card-header">
- <span class="card-title">待办工单</span>
- <el-button type="primary" size="small" plain>查看全部</el-button>
- </div>
- <div class="card-body">
- <el-table :data="todoList" stripe style="width: 100%" size="small" header-row-class-name="table-header" height="150">
- <el-table-column prop="type" label="工单类型" width="100" />
- <el-table-column prop="location" label="关联点位" />
- <el-table-column prop="reportTime" label="上报时间" width="140" />
- <el-table-column prop="responsible" label="责任人" width="80" />
- <el-table-column label="状态" width="80">
- <template #default="{ row }">
- <el-tag :type="getStatusType(row.status)" size="small" effect="light" round>
- {{ row.status }}
- </el-tag>
- </template>
- </el-table-column>
- <el-table-column label="操作" width="70">
- <template #default>
- <el-button type="primary" link size="small">处理</el-button>
- </template>
- </el-table-column>
- </el-table>
- </div>
- </div>
- </div>
- <!-- 右侧:设备状态 + 今日调度 + 月度统计 -->
- <div class="middle-right">
- <!-- 设备运行状态 -->
- <div class="glass-card device-panel">
- <div class="card-header">
- <span class="card-title">设备状态</span>
- <el-button type="primary" size="small" link>设备管理</el-button>
- </div>
- <div class="device-stats">
- <div class="device-stat-item" v-for="(item, index) in deviceStats" :key="index">
- <div class="device-stat-icon" :style="{ background: item.color }">
- <span>{{ item.icon }}</span>
- </div>
- <div class="device-stat-info">
- <span class="device-stat-value">{{ item.value }}</span>
- <span class="device-stat-label">{{ item.label }}</span>
- </div>
- </div>
- </div>
- <div class="device-list">
- <div v-for="(device, index) in deviceList" :key="index" class="device-item">
- <div class="device-info">
- <span class="device-name">{{ device.name }}</span>
- <span class="device-location">{{ device.location }}</span>
- </div>
- <el-tag :type="getDeviceStatusType(device.status)" size="small" effect="light">
- {{ device.statusText }}
- </el-tag>
- </div>
- </div>
- </div>
- <!-- 今日调度计划 -->
- <div class="glass-card schedule-panel">
- <div class="card-header">
- <span class="card-title">今日调度</span>
- <el-button type="primary" size="small" plain>调度管理</el-button>
- </div>
- <div class="card-body">
- <div class="schedule-list">
- <div v-for="(item, index) in todaySchedule" :key="index" class="schedule-item">
- <div class="schedule-time">{{ item.time }}</div>
- <div class="schedule-content">
- <div class="schedule-title">{{ item.title }}</div>
- <div class="schedule-desc">{{ item.description }}</div>
- </div>
- <el-tag :type="getScheduleType(item.status)" size="small" effect="light">
- {{ item.statusText }}
- </el-tag>
- </div>
- </div>
- </div>
- </div>
- </div>
- </section>
- <!-- 底部:快捷功能 + 气象信息 -->
- <section class="bottom-section">
- <!-- 快捷功能 -->
- <div class="glass-card quick-panel">
- <div class="card-header">
- <span class="card-title">快捷功能</span>
- </div>
- <div class="quick-grid">
- <div class="quick-item" v-for="(item, index) in quickAccess" :key="index" @click="handleQuickAccess(item.name)">
- <div class="quick-icon" :style="{ background: item.gradient }">
- <span>{{ item.icon }}</span>
- </div>
- <span class="quick-label">{{ item.name }}</span>
- </div>
- </div>
- </div>
- <!-- 气象信息 -->
- <div class="glass-card weather-panel">
- <div class="card-header">
- <span class="card-title">气象信息</span>
- <span class="weather-update">更新于 {{ weatherData.updateTime }}</span>
- </div>
- <div class="weather-content">
- <div class="weather-main">
- <div class="weather-icon">{{ weatherData.icon }}</div>
- <div class="weather-info">
- <span class="weather-temp">{{ weatherData.temperature }}°C</span>
- <span class="weather-desc">{{ weatherData.description }}</span>
- </div>
- </div>
- <div class="weather-details">
- <div class="weather-detail-item">
- <span class="detail-label">湿度</span>
- <span class="detail-value">{{ weatherData.humidity }}%</span>
- </div>
- <div class="weather-detail-item">
- <span class="detail-label">风速</span>
- <span class="detail-value">{{ weatherData.windSpeed }}m/s</span>
- </div>
- <div class="weather-detail-item">
- <span class="detail-label">降雨概率</span>
- <span class="detail-value">{{ weatherData.rainProbability }}%</span>
- </div>
- </div>
- <div class="weather-forecast">
- <div v-for="(day, index) in weatherForecast" :key="index" class="forecast-item">
- <span class="forecast-day">{{ day.day }}</span>
- <span class="forecast-icon">{{ day.icon }}</span>
- <span class="forecast-temp">{{ day.high }}°/{{ day.low }}°</span>
- </div>
- </div>
- </div>
- </div>
- </section>
- </template>
- </main>
- </div>
- </div>
- </template>
- <script>
- import { Search, Warning } from '@element-plus/icons-vue'
- import DeviceMaintainView from '../admin/DeviceMaintainView.vue'
- import PatrolPlanView from '../admin/PatrolPlanView.vue'
- import PatrolRecordView from '../admin/PatrolRecordView.vue'
- import PatrolHiddenView from '../admin/PatrolHiddenView.vue'
- import WaterRainView from '../admin/WaterRainView.vue'
- import HydroHistoryView from '../admin/HydroHistoryView.vue'
- import WaterResourceAllocationView from '../admin/WaterResourceAllocationView.vue'
- import GateControlAdminView from '../admin/GateControlAdminView.vue'
- import BenefitSummaryView from '../admin/BenefitSummaryView.vue'
- import ArchiveFilesView from '../admin/ArchiveFilesView.vue'
- import ArchiveOrdersView from '../admin/ArchiveOrdersView.vue'
- import ArchiveLifecycleView from '../admin/ArchiveLifecycleView.vue'
- import SysRoleView from '../admin/SysRoleView.vue'
- import SysUserView from '../admin/SysUserView.vue'
- import SysLogView from '../admin/SysLogView.vue'
- export default {
- name: 'WorkspaceView',
- components: { Search, Warning, DeviceMaintainView, PatrolPlanView, PatrolRecordView, PatrolHiddenView, WaterRainView, HydroHistoryView, WaterResourceAllocationView, GateControlAdminView, BenefitSummaryView, ArchiveFilesView, ArchiveOrdersView, ArchiveLifecycleView, SysRoleView, SysUserView, SysLogView },
- data() {
- return {
- currentDate: '',
- currentTime: '',
- searchText: '',
- timer: null,
- activeMenu: 'dashboard',
- waterTabMap: {
- 'water-supply': 'supply',
- 'water-eco': 'eco'
- },
- menuTree: [
- { name: '首页', children: [] },
- { name: '日常巡检', children: [{ id: 'patrol-plan', name: '巡检计划' }, { id: 'patrol-record', name: '巡检记录' }, { id: 'patrol-hidden', name: '隐患台账' }] },
- { name: '设备运维', children: [] },
- { name: '闸门控制', children: [] },
- { name: '水雨情监测', children: [{ id: 'hydro-realtime', name: '实时监测' }, { id: 'hydro-history', name: '历史数据' }] },
- { name: '水资源调度', children: [{ id: 'water-supply', name: '供水水量' }, { id: 'water-eco', name: '生态补水' }] },
- { name: '工程效益', children: [] },
- { name: '资料档案', children: [{ id: 'archive-files', name: '工程档案' }, { id: 'archive-orders', name: '调令文件' }, { id: 'archive-lifecycle', name: '全生命周期' }] },
- { name: '系统权限', children: [{ id: 'sys-role', name: '角色管理' }, { id: 'sys-user', name: '用户账号' }, { id: 'sys-log', name: '操作日志' }] }
- ],
- // 水位状态
- waterLevelStatus: {
- type: 'success',
- text: '正常蓄水位'
- },
- // 实时水情数据
- waterDataCards: [
- { title: '库水位', value: '18.52', unit: 'm', icon: '🌊', iconBg: 'linear-gradient(135deg, #dbeafe, #93c5fd)', updateTime: '14:30 更新' },
- { title: '汛限水位', value: '22.00', unit: 'm', icon: '📏', iconBg: 'linear-gradient(135deg, #fef3c7, #fcd34d)', updateTime: '设计值' },
- { title: '库容', value: '2350.8', unit: '万m³', icon: '💧', iconBg: 'linear-gradient(135deg, #cffafe, #67e8f9)', updateTime: '14:30 更新' },
- { title: '入库流量', value: '8.5', unit: 'm³/s', icon: '📥', iconBg: 'linear-gradient(135deg, #dcfce7, #86efac)', updateTime: '14:30 更新' },
- { title: '出库流量', value: '12.8', unit: 'm³/s', icon: '📤', iconBg: 'linear-gradient(135deg, #fce7f3, #f9a8d4)', updateTime: '14:30 更新' },
- { title: '实时雨量', value: '2.5', unit: 'mm', icon: '🌧️', iconBg: 'linear-gradient(135deg, #e0e7ff, #a5b4fc)', updateTime: '14:30 更新' }
- ],
- // 预警信息
- warningList: [
- { level: 'danger', levelText: '一级', title: '库水位接近汛限水位', location: '主坝监测点', time: '14:25' },
- { level: 'warning', levelText: '二级', title: '3号渗压计数据异常', location: '副坝渗压监测', time: '13:40' },
- { level: 'info', levelText: '三级', title: '视频监控离线', location: '溢洪道摄像头', time: '12:15' }
- ],
- // 设备统计
- deviceStats: [
- { icon: '📡', label: '传感器总数', value: '156', color: 'linear-gradient(135deg, #dbeafe, #93c5fd)' },
- { icon: '✅', label: '在线设备', value: '148', color: 'linear-gradient(135deg, #dcfce7, #86efac)' },
- { icon: '⚠️', label: '故障设备', value: '5', color: 'linear-gradient(135deg, #fef3c7, #fcd34d)' },
- { icon: '❌', label: '离线设备', value: '3', color: 'linear-gradient(135deg, #fee2e2, #fca5a5)' }
- ],
- // 设备列表
- deviceList: [
- { name: '主坝水位计', location: '大坝坝顶', status: 'online', statusText: '在线' },
- { name: '副坝渗压计', location: '副坝坝体', status: 'warning', statusText: '异常' },
- { name: '溢洪道闸门', location: '溢洪道', status: 'online', statusText: '运行' },
- { name: '入库流量计', location: '进水口', status: 'offline', statusText: '离线' }
- ],
- // 气象信息
- weatherData: {
- icon: '⛅',
- temperature: 28,
- description: '多云',
- humidity: 65,
- windSpeed: 3.2,
- rainProbability: 30,
- updateTime: '14:00'
- },
- // 天气预报
- weatherForecast: [
- { day: '今天', icon: '⛅', high: 32, low: 22 },
- { day: '明天', icon: '🌧️', high: 28, low: 20 },
- { day: '后天', icon: '☀️', high: 35, low: 24 }
- ],
- // 待办工单
- todoList: [
- { type: '巡检待完成', location: '大坝坝顶', reportTime: '2024-01-15 09:00', responsible: '张三', status: '待处理' },
- { type: '隐患待整改', location: '溢洪道闸门', reportTime: '2024-01-14 16:30', responsible: '李四', status: '处理中' },
- { type: '设备维保到期', location: '输水闸启闭机', reportTime: '2024-01-14 10:15', responsible: '王五', status: '已完成' },
- { type: '用水审批待处理', location: '灌溉渠道A段', reportTime: '2024-01-15 08:45', responsible: '赵六', status: '待处理' },
- { type: '预警待处置', location: '库区水位监测点', reportTime: '2024-01-15 11:20', responsible: '张三', status: '已逾期' }
- ],
- // 今日调度
- todaySchedule: [
- { time: '08:00', title: '灌溉供水调度', description: '灌溉渠道A段开闸放水,流量5m³/s', status: 'completed', statusText: '已完成' },
- { time: '10:00', title: '人饮水量调节', description: '水厂取水量调整至3m³/s', status: 'completed', statusText: '已完成' },
- { time: '14:00', title: '生态补水', description: '下游河道生态补水,流量2m³/s', status: 'inProgress', statusText: '执行中' },
- { time: '16:00', title: '闸门检修', description: '3号闸门例行检修,预计2小时', status: 'pending', statusText: '待执行' }
- ],
- // 快捷功能
- quickAccess: [
- { name: '视频监控', icon: '📹', gradient: 'linear-gradient(135deg, #e0f2fe, #bae6fd)' },
- { name: '巡检上报', icon: '🔍', gradient: 'linear-gradient(135deg, #dcfce7, #bbf7d0)' },
- { name: '设备报修', icon: '🔧', gradient: 'linear-gradient(135deg, #fef9c3, #fef08a)' },
- { name: '用水调度', icon: '💧', gradient: 'linear-gradient(135deg, #cffafe, #a5f3fc)' },
- { name: '隐患台账', icon: '📋', gradient: 'linear-gradient(135deg, #f3e8ff, #e9d5ff)' },
- { name: '报表导出', icon: '📊', gradient: 'linear-gradient(135deg, #fce7f3, #fbcfe8)' }
- ],
- // 月度统计
- monthlyStats: [
- { name: '月度灌溉水量', value: '125.6', unit: '万m³', trend: 5.2 },
- { name: '人饮水量', value: '18.3', unit: '万m³', trend: -2.1 },
- { name: '工业水量', value: '8.7', unit: '万m³', trend: 3.8 },
- { name: '生态补水量', value: '15.2', unit: '万m³', trend: 12.5 },
- { name: '防汛处置次数', value: '3', unit: '次', trend: -25.0 }
- ]
- }
- },
- computed: {
- isHomePage() {
- const subPages = ['设备运维', '闸门控制', '工程效益', 'patrol-plan', 'patrol-record', 'patrol-hidden', 'hydro-realtime', 'hydro-history', 'archive-files', 'archive-orders', 'archive-lifecycle', 'sys-role', 'sys-user', 'sys-log']
- const waterPages = ['water-supply', 'water-eco']
- return ![...subPages, ...waterPages].includes(this.activeMenu)
- },
- isWaterActive() {
- return ['water-supply', 'water-eco'].includes(this.activeMenu)
- },
- isBenefitActive() {
- return this.activeMenu === '工程效益'
- }
- },
- mounted() {
- this.updateDateTime()
- this.timer = setInterval(this.updateDateTime, 1000)
- },
- beforeUnmount() {
- if (this.timer) clearInterval(this.timer)
- },
- methods: {
- updateDateTime() {
- const now = new Date()
- this.currentDate = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}`
- this.currentTime = `${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}:${String(now.getSeconds()).padStart(2, '0')}`
- },
- handleMenuSelect(index) {
- this.activeMenu = index
- },
- getStatusType(status) {
- return { '待处理': 'primary', '处理中': 'warning', '已完成': 'success', '已逾期': 'danger' }[status] || 'info'
- },
- getWarningType(level) {
- return { 'danger': 'danger', 'warning': 'warning', 'info': 'info' }[level] || 'info'
- },
- getDeviceStatusType(status) {
- return { 'online': 'success', 'warning': 'warning', 'offline': 'danger' }[status] || 'info'
- },
- getScheduleType(status) {
- return { 'completed': 'success', 'inProgress': 'primary', 'pending': 'info' }[status] || 'info'
- },
- handleQuickAccess(name) {
- console.log('快捷功能:', name)
- }
- }
- }
- </script>
- <style scoped>
- /* ==================== 全局重置 ==================== */
- * { box-sizing: border-box; margin: 0; padding: 0; }
- /* ==================== 整体容器 ==================== */
- .workspace-container {
- width: 100%;
- height: 100%;
- background: linear-gradient(180deg, #f0f5fa 0%, #e8eef5 100%);
- display: flex;
- flex-direction: column;
- overflow: hidden;
- font-family: 'Alibaba PuHuiTi', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif;
- }
- /* ==================== Header 头部栏 ==================== */
- .oa-header {
- height: 70px;
- background: linear-gradient(135deg, rgba(59, 130, 246, 0.9) 0%, rgba(37, 99, 235, 0.95) 100%);
- backdrop-filter: blur(20px);
- color: white;
- padding: 0 32px;
- display: flex;
- justify-content: space-between;
- align-items: center;
- box-shadow: 0 4px 24px rgba(59, 130, 246, 0.15);
- flex-shrink: 0;
- position: relative;
- z-index: 10;
- }
- .oa-header::after {
- content: '';
- position: absolute;
- bottom: 0;
- left: 0;
- right: 0;
- height: 1px;
- background: linear-gradient(90deg, transparent, rgba(255,255,255,0.3), transparent);
- }
- .header-left {
- display: flex;
- align-items: center;
- gap: 16px;
- }
- .system-title {
- font-family: 'Alibaba PuHuiTi', sans-serif;
- font-size: 28px;
- font-weight: 700;
- margin: 0;
- line-height: 70px;
- letter-spacing: 1px;
- text-shadow: 0 2px 4px rgba(0,0,0,0.1);
- }
- .header-search {
- width: 280px;
- }
- .header-search :deep(.el-input__wrapper) {
- background: rgba(255, 255, 255, 0.2);
- border: 1px solid rgba(255, 255, 255, 0.3);
- border-radius: 20px;
- box-shadow: none;
- }
- .header-search :deep(.el-input__wrapper:hover),
- .header-search :deep(.el-input__wrapper.is-focus) {
- background: rgba(255, 255, 255, 0.3);
- border-color: rgba(255, 255, 255, 0.5);
- box-shadow: none;
- }
- .header-search :deep(.el-input__inner) {
- color: white;
- }
- .header-search :deep(.el-input__inner::placeholder) {
- color: rgba(255, 255, 255, 0.6);
- }
- .header-search :deep(.el-input__prefix .el-icon) {
- color: rgba(255, 255, 255, 0.7);
- }
- .header-right {
- display: flex;
- align-items: center;
- gap: 12px;
- font-size: 14px;
- opacity: 0.95;
- }
- .back-bigscreen-btn {
- width: 36px;
- height: 36px;
- border-radius: 50%;
- background: rgba(255,255,255,0.15);
- border: 1px solid rgba(255,255,255,0.3);
- display: flex;
- align-items: center;
- justify-content: center;
- cursor: pointer;
- transition: all 0.25s;
- color: rgba(255,255,255,0.85);
- flex-shrink: 0;
- }
- .back-bigscreen-btn:hover {
- background: rgba(255,255,255,0.3);
- color: #fff;
- transform: scale(1.05);
- }
- .header-time {
- font-size: 20px;
- font-weight: 600;
- letter-spacing: 1px;
- }
- /* ==================== 主体区域 ==================== */
- .oa-body {
- flex: 1;
- display: flex;
- overflow: hidden;
- }
- /* ==================== 左侧菜单 ==================== */
- .sidebar {
- width: 220px;
- background: rgba(255, 255, 255, 0.85);
- backdrop-filter: blur(20px);
- border-right: 1px solid rgba(226, 232, 240, 0.8);
- display: flex;
- flex-direction: column;
- flex-shrink: 0;
- }
- .sidebar-menu {
- flex: 1;
- overflow-y: auto;
- border-right: none;
- background: transparent;
- }
- .sidebar-menu :deep(.el-sub-menu__title),
- .sidebar-menu :deep(.el-menu-item) {
- height: 48px;
- line-height: 48px;
- font-family: 'Alibaba PuHuiTi', sans-serif;
- font-size: 15px;
- font-weight: 400;
- letter-spacing: 1px;
- color: #475569;
- transition: all 0.25s ease;
- }
- .sidebar-menu :deep(.el-sub-menu__title) {
- font-weight: 400;
- color: #334155;
- }
- .sidebar-menu :deep(.el-menu-item) {
- padding-left: 48px !important;
- color: #64748b;
- }
- .sidebar-menu :deep(.el-menu-item.is-active) {
- background: linear-gradient(135deg, #dbeafe, #bfdbfe);
- color: #1d4ed8;
- font-weight: 600;
- border-right: 3px solid #3b82f6;
- }
- .sidebar-menu :deep(.el-menu-item:hover) {
- background: rgba(219, 234, 254, 0.5);
- color: #2563eb;
- }
- .sidebar-menu :deep(.el-sub-menu__title:hover) {
- background: rgba(219, 234, 254, 0.3);
- color: #2563eb;
- }
- .menu-top-item {
- font-size: 15px;
- font-weight: 400;
- color: #334155;
- }
- .sidebar-menu :deep(.el-menu-item):has(.menu-top-item) {
- padding-left: 20px !important;
- }
- /* ==================== 右侧内容区 ==================== */
- .oa-main {
- flex: 1;
- display: flex;
- flex-direction: column;
- padding: 20px;
- gap: 20px;
- overflow-y: auto;
- overflow-x: hidden;
- }
- /* ==================== 玻璃拟态白色卡片 ==================== */
- .glass-card {
- background: rgba(255, 255, 255, 0.75);
- backdrop-filter: blur(20px);
- border-radius: 16px;
- border: 1px solid rgba(255, 255, 255, 0.8);
- box-shadow:
- 0 4px 6px -1px rgba(0, 0, 0, 0.03),
- 0 2px 4px -2px rgba(0, 0, 0, 0.03),
- inset 0 1px 0 rgba(255, 255, 255, 0.6);
- display: flex;
- flex-direction: column;
- overflow: hidden;
- transition: box-shadow 0.3s ease;
- }
- .glass-card:hover {
- box-shadow:
- 0 10px 15px -3px rgba(0, 0, 0, 0.05),
- 0 4px 6px -4px rgba(0, 0, 0, 0.05),
- inset 0 1px 0 rgba(255, 255, 255, 0.6);
- }
- .card-header {
- height: 52px;
- padding: 0 20px;
- border-bottom: 1px solid rgba(226, 232, 240, 0.6);
- display: flex;
- justify-content: space-between;
- align-items: center;
- flex-shrink: 0;
- }
- .card-title {
- font-family: 'Alibaba PuHuiTi', sans-serif;
- font-size: 16px;
- font-weight: 600;
- color: #1e293b;
- position: relative;
- padding-left: 12px;
- }
- .card-title::before {
- content: '';
- position: absolute;
- left: 0;
- top: 50%;
- transform: translateY(-50%);
- width: 4px;
- height: 18px;
- background: linear-gradient(180deg, #3b82f6, #60a5fa);
- border-radius: 2px;
- }
- .card-actions {
- display: flex;
- gap: 8px;
- }
- .card-body {
- flex: 1;
- overflow: auto;
- padding: 12px 16px;
- }
- /* ==================== 核心数据卡片 ==================== */
- .stats-section {
- min-height: 180px;
- flex-shrink: 0;
- padding: 16px 20px;
- }
- .stats-section .card-header {
- height: 36px;
- padding: 0;
- margin-bottom: 12px;
- border-bottom: none;
- }
- .stats-grid {
- flex: 1;
- display: flex;
- gap: 16px;
- }
- .stat-card {
- flex: 1;
- background: linear-gradient(135deg, rgba(255,255,255,0.9) 0%, rgba(239,246,255,0.9) 100%);
- backdrop-filter: blur(10px);
- border-radius: 12px;
- border: 1px solid rgba(186, 230, 253, 0.5);
- display: flex;
- justify-content: space-between;
- align-items: center;
- padding: 16px;
- transition: all 0.3s ease;
- }
- .stat-card:hover {
- transform: translateY(-4px);
- box-shadow: 0 8px 25px rgba(59, 130, 246, 0.12);
- border-color: rgba(96, 165, 250, 0.5);
- }
- .stat-card-left {
- display: flex;
- align-items: center;
- gap: 12px;
- }
- .stat-icon-wrap {
- width: 44px;
- height: 44px;
- background: linear-gradient(135deg, #dbeafe, #bfdbfe);
- border-radius: 12px;
- display: flex;
- align-items: center;
- justify-content: center;
- box-shadow: 0 2px 8px rgba(59, 130, 246, 0.1);
- }
- .stat-icon { font-size: 22px; }
- .stat-label { font-size: 14px; color: #64748b; font-weight: 500; }
- .stat-card-right { display: flex; flex-direction: column; align-items: flex-end; gap: 4px; }
- .stat-card-value { display: flex; align-items: baseline; gap: 4px; }
- .stat-value { font-size: 28px; font-weight: 700; color: #1d4ed8; line-height: 1; }
- .stat-unit { font-size: 14px; color: #94a3b8; }
- .stat-time { font-size: 12px; color: #94a3b8; }
- /* ==================== Element Plus 表格样式覆盖 ==================== */
- .card-body :deep(.el-table) {
- background: transparent;
- --el-table-bg-color: transparent;
- --el-table-tr-bg-color: transparent;
- --el-table-header-bg-color: rgba(241, 245, 249, 0.8);
- --el-table-row-hover-bg-color: rgba(219, 234, 254, 0.3);
- --el-table-border-color: rgba(226, 232, 240, 0.6);
- --el-table-text-color: #64748b;
- --el-table-header-text-color: #475569;
- font-size: 14px;
- }
- .card-body :deep(.el-table__header th) {
- font-weight: 600;
- }
- .value-highlight { font-weight: 600; color: #1d4ed8; }
- /* ==================== 快捷功能网格 ==================== */
- .quick-grid {
- flex: 1;
- display: grid;
- grid-template-columns: repeat(3, 1fr);
- grid-template-rows: repeat(2, 1fr);
- gap: 14px;
- padding: 16px 20px;
- }
- .quick-item {
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- gap: 10px;
- background: rgba(248, 250, 252, 0.8);
- border: 1px solid rgba(226, 232, 240, 0.6);
- border-radius: 12px;
- cursor: pointer;
- transition: all 0.3s ease;
- }
- .quick-item:hover {
- background: rgba(219, 234, 254, 0.5);
- border-color: rgba(96, 165, 250, 0.4);
- transform: translateY(-3px);
- box-shadow: 0 6px 20px rgba(59, 130, 246, 0.1);
- }
- .quick-icon {
- width: 48px;
- height: 48px;
- border-radius: 14px;
- display: flex;
- align-items: center;
- justify-content: center;
- font-size: 24px;
- box-shadow: 0 2px 8px rgba(0,0,0,0.05);
- }
- .quick-label { font-size: 13px; font-weight: 500; color: #475569; }
- /* ==================== 中间区域布局 ==================== */
- .middle-section { display: flex; gap: 20px; min-height: 600px; flex-shrink: 0; }
- .middle-left { flex: 55; display: flex; flex-direction: column; gap: 20px; }
- .middle-right { flex: 45; display: flex; flex-direction: column; gap: 20px; }
- .warning-panel { min-height: 220px; }
- .todo-panel { flex: 1; min-height: 0; }
- .todo-panel .card-body { overflow: hidden; }
- .device-panel { min-height: 280px; }
- .weather-panel { flex-shrink: 0; }
- .quick-panel { flex-shrink: 0; }
- /* ==================== 预警信息样式 ==================== */
- .warning-list {
- display: flex;
- flex-direction: column;
- gap: 12px;
- }
- .warning-item {
- display: flex;
- align-items: center;
- gap: 12px;
- padding: 12px;
- border-radius: 8px;
- background: rgba(248, 250, 252, 0.8);
- border: 1px solid rgba(226, 232, 240, 0.6);
- transition: all 0.2s ease;
- }
- .warning-item:hover {
- background: rgba(241, 245, 249, 0.9);
- }
- .warning-danger {
- border-left: 4px solid #ef4444;
- }
- .warning-warning {
- border-left: 4px solid #f59e0b;
- }
- .warning-info {
- border-left: 4px solid #3b82f6;
- }
- .warning-icon {
- width: 36px;
- height: 36px;
- border-radius: 8px;
- display: flex;
- align-items: center;
- justify-content: center;
- font-size: 18px;
- }
- .warning-danger .warning-icon {
- background: linear-gradient(135deg, #fee2e2, #fca5a5);
- color: #dc2626;
- }
- .warning-warning .warning-icon {
- background: linear-gradient(135deg, #fef3c7, #fcd34d);
- color: #d97706;
- }
- .warning-info .warning-icon {
- background: linear-gradient(135deg, #dbeafe, #93c5fd);
- color: #2563eb;
- }
- .warning-content {
- flex: 1;
- min-width: 0;
- }
- .warning-title {
- font-size: 14px;
- font-weight: 500;
- color: #1e293b;
- margin-bottom: 4px;
- }
- .warning-meta {
- display: flex;
- gap: 12px;
- font-size: 12px;
- color: #94a3b8;
- }
- .warning-badge :deep(.el-badge__content) {
- top: -2px;
- right: 8px;
- }
- /* ==================== 设备状态样式 ==================== */
- .device-stats {
- display: grid;
- grid-template-columns: repeat(2, 1fr);
- gap: 10px;
- padding: 14px 16px;
- border-bottom: 1px solid rgba(226, 232, 240, 0.6);
- }
- .device-stat-item {
- display: flex;
- align-items: center;
- gap: 10px;
- }
- .device-stat-icon {
- width: 40px;
- height: 40px;
- border-radius: 10px;
- display: flex;
- align-items: center;
- justify-content: center;
- font-size: 20px;
- }
- .device-stat-info {
- display: flex;
- flex-direction: column;
- }
- .device-stat-value {
- font-size: 18px;
- font-weight: 600;
- color: #1e293b;
- line-height: 1.2;
- }
- .device-stat-label {
- font-size: 12px;
- color: #94a3b8;
- }
- .device-list {
- flex: 1;
- overflow-y: auto;
- padding: 12px 16px;
- }
- .device-item {
- display: flex;
- justify-content: space-between;
- align-items: center;
- padding: 10px 12px;
- border-radius: 6px;
- background: rgba(248, 250, 252, 0.5);
- margin-bottom: 8px;
- transition: background 0.2s ease;
- }
- .device-item:hover {
- background: rgba(241, 245, 249, 0.8);
- }
- .device-info {
- display: flex;
- flex-direction: column;
- gap: 2px;
- }
- .device-name {
- font-size: 14px;
- font-weight: 500;
- color: #334155;
- }
- .device-location {
- font-size: 12px;
- color: #94a3b8;
- }
- /* ==================== 气象信息样式 ==================== */
- .weather-content {
- padding: 16px 20px;
- }
- .weather-main {
- display: flex;
- align-items: center;
- gap: 16px;
- margin-bottom: 16px;
- }
- .weather-icon {
- font-size: 48px;
- line-height: 1;
- }
- .weather-info {
- display: flex;
- flex-direction: column;
- }
- .weather-temp {
- font-size: 32px;
- font-weight: 700;
- color: #1e293b;
- line-height: 1.2;
- }
- .weather-desc {
- font-size: 14px;
- color: #64748b;
- }
- .weather-update {
- font-size: 12px;
- color: #94a3b8;
- }
- .weather-details {
- display: grid;
- grid-template-columns: repeat(3, 1fr);
- gap: 12px;
- padding-bottom: 16px;
- border-bottom: 1px solid rgba(226, 232, 240, 0.6);
- margin-bottom: 16px;
- }
- .weather-detail-item {
- display: flex;
- flex-direction: column;
- align-items: center;
- gap: 4px;
- }
- .detail-label {
- font-size: 12px;
- color: #94a3b8;
- }
- .detail-value {
- font-size: 14px;
- font-weight: 600;
- color: #334155;
- }
- .weather-forecast {
- display: grid;
- grid-template-columns: repeat(3, 1fr);
- gap: 12px;
- }
- .forecast-item {
- display: flex;
- flex-direction: column;
- align-items: center;
- gap: 6px;
- padding: 10px;
- border-radius: 8px;
- background: rgba(248, 250, 252, 0.8);
- }
- .forecast-day {
- font-size: 12px;
- color: #64748b;
- font-weight: 500;
- }
- .forecast-icon {
- font-size: 24px;
- }
- .forecast-temp {
- font-size: 12px;
- color: #475569;
- }
- /* ==================== 今日调度样式 ==================== */
- .schedule-panel {
- min-height: 200px;
- }
- .stats-table-panel {
- min-height: 250px;
- }
- /* ==================== 底部区域(快捷功能 + 气象) ==================== */
- .bottom-section {
- display: flex;
- gap: 20px;
- min-height: 200px;
- flex-shrink: 0;
- }
- .bottom-section .quick-panel {
- flex: 40;
- }
- .bottom-section .weather-panel {
- flex: 60;
- }
- .schedule-list {
- display: flex;
- flex-direction: column;
- gap: 12px;
- }
- .schedule-item {
- display: flex;
- align-items: center;
- gap: 16px;
- padding: 12px;
- border-radius: 8px;
- background: rgba(248, 250, 252, 0.8);
- border: 1px solid rgba(226, 232, 240, 0.6);
- }
- .schedule-time {
- font-size: 14px;
- font-weight: 600;
- color: #3b82f6;
- min-width: 50px;
- }
- .schedule-content {
- flex: 1;
- min-width: 0;
- }
- .schedule-title {
- font-size: 14px;
- font-weight: 500;
- color: #1e293b;
- margin-bottom: 4px;
- }
- .schedule-desc {
- font-size: 12px;
- color: #94a3b8;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- }
- /* ==================== 趋势样式 ==================== */
- .trend-up {
- color: #52c41a;
- }
- .trend-down {
- color: #ff4d4f;
- }
- /* ==================== 迷你图表 ==================== */
- .mini-chart {
- height: 30px;
- display: flex;
- align-items: flex-end;
- }
- .chart-bar {
- width: 16px;
- min-height: 4px;
- border-radius: 2px 2px 0 0;
- }
- /* ==================== 底部区域 ==================== */
- .bottom-section .card-header {
- height: 48px;
- padding: 0 20px;
- border-bottom: 1px solid rgba(226, 232, 240, 0.6);
- display: flex;
- justify-content: space-between;
- align-items: center;
- }
- .bottom-section .card-body {
- flex: 1;
- overflow: auto;
- padding: 12px 16px;
- }
- .trend { font-weight: 600; font-size: 13px; }
- /* ==================== 滚动条美化 ==================== */
- ::-webkit-scrollbar { width: 6px; height: 6px; }
- ::-webkit-scrollbar-track { background: transparent; }
- ::-webkit-scrollbar-thumb { background: rgba(148, 163, 184, 0.3); border-radius: 3px; }
- ::-webkit-scrollbar-thumb:hover { background: rgba(148, 163, 184, 0.5); }
- </style>
|