|
|
@@ -1,6 +1,14 @@
|
|
|
<!-- 巡检计划管理页面 - 卡片仪表盘风格 -->
|
|
|
<template>
|
|
|
- <div class="patrol-plan-container">
|
|
|
+ <!-- 创建模式 -->
|
|
|
+ <PatrolPlanCreateView
|
|
|
+ v-if="showCreate"
|
|
|
+ @created="onPlanCreated"
|
|
|
+ @cancel="showCreate = false"
|
|
|
+ />
|
|
|
+
|
|
|
+ <!-- 列表模式 -->
|
|
|
+ <div v-else class="patrol-plan-container">
|
|
|
<!-- 顶部横幅统计 -->
|
|
|
<section class="hero-stats">
|
|
|
<div class="hero-main">
|
|
|
@@ -20,31 +28,39 @@
|
|
|
<div class="main-area">
|
|
|
<!-- 左侧:计划卡片网格 -->
|
|
|
<div class="plan-grid">
|
|
|
- <div class="plan-card" v-for="item in planList" :key="item.id"
|
|
|
- :class="{ active: selectedPlan && selectedPlan.id === item.id }"
|
|
|
- @click="selectPlan(item)">
|
|
|
+ <div
|
|
|
+ v-for="item in planList"
|
|
|
+ :key="item.id"
|
|
|
+ class="plan-card"
|
|
|
+ :class="{ active: selectedPlan?.id === item.id }"
|
|
|
+ @click="selectPlan(item)"
|
|
|
+ >
|
|
|
<div class="pcard-header">
|
|
|
- <el-tag :type="getPlanStatusType(item.status)" size="small" effect="light" round>{{ item.statusText }}</el-tag>
|
|
|
- <el-tag :type="getTypeTag(item.type)" size="small" effect="plain" round>{{ item.type }}</el-tag>
|
|
|
+ <el-tag :type="getPlanStatusType(item.status)" size="small" effect="light" round>
|
|
|
+ {{ item.statusText }}
|
|
|
+ </el-tag>
|
|
|
+ <el-tag :type="getTypeTag(item.type)" size="small" effect="plain" round>
|
|
|
+ {{ item.type }}
|
|
|
+ </el-tag>
|
|
|
</div>
|
|
|
<div class="pcard-name">{{ item.name }}</div>
|
|
|
- <div class="pcard-route">🗺️ {{ item.route }}</div>
|
|
|
+ <div class="pcard-route">
|
|
|
+ <el-icon style="margin-right:4px;vertical-align:-2px"><Location /></el-icon>
|
|
|
+ {{ item.route }}
|
|
|
+ </div>
|
|
|
<div class="pcard-progress">
|
|
|
- <div class="progress-bar">
|
|
|
- <div class="progress-fill" :style="{ width: item.completionRate + '%', background: getProgressColor(item.completionRate) }"></div>
|
|
|
- </div>
|
|
|
- <span class="progress-text">{{ item.completionRate }}%</span>
|
|
|
+ <el-progress :percentage="item.completionRate" :color="getProgressColor" :stroke-width="6" />
|
|
|
</div>
|
|
|
<div class="pcard-footer">
|
|
|
- <span>👤 {{ item.responsible }}</span>
|
|
|
- <span>📍 {{ item.checkpointCount }} 节点</span>
|
|
|
- <span>{{ item.frequency }}</span>
|
|
|
+ <span><el-icon><User /></el-icon> {{ item.responsible }}</span>
|
|
|
+ <span><el-icon><List /></el-icon> {{ item.checkpointCount }} 节点</span>
|
|
|
+ <span><el-icon><Clock /></el-icon> {{ item.frequency }}</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<!-- 新建卡片 -->
|
|
|
<div class="plan-card add-card" @click="handleAddPlan">
|
|
|
- <div class="add-icon">+</div>
|
|
|
+ <el-icon class="add-icon"><Plus /></el-icon>
|
|
|
<div class="add-text">新建巡检计划</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
@@ -54,63 +70,91 @@
|
|
|
<div class="dp-header">
|
|
|
<div class="dp-title">{{ selectedPlan.name }}</div>
|
|
|
<div class="dp-actions">
|
|
|
- <el-button size="small" @click="handleEditPlan(selectedPlan)">编辑</el-button>
|
|
|
- <el-button size="small" type="danger" plain @click="handleDeletePlan(selectedPlan)">删除</el-button>
|
|
|
+ <el-button size="small" @click="handleEditPlan(selectedPlan)">
|
|
|
+ <el-icon><Edit /></el-icon> 编辑
|
|
|
+ </el-button>
|
|
|
+ <el-button size="small" type="danger" plain @click="handleDeletePlan(selectedPlan)">
|
|
|
+ <el-icon><Delete /></el-icon> 删除
|
|
|
+ </el-button>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
- <div class="dp-info-grid">
|
|
|
- <div class="dp-info-item">
|
|
|
- <span class="dp-label">计划类型</span>
|
|
|
- <span class="dp-value">{{ selectedPlan.type }}</span>
|
|
|
- </div>
|
|
|
- <div class="dp-info-item">
|
|
|
- <span class="dp-label">巡检路线</span>
|
|
|
- <span class="dp-value">{{ selectedPlan.route }}</span>
|
|
|
+ <!-- 计划概览卡片 -->
|
|
|
+ <div class="dp-overview">
|
|
|
+ <div class="dp-o-item">
|
|
|
+ <span class="dp-o-label">类型</span>
|
|
|
+ <el-tag :type="getTypeTag(selectedPlan.type)" size="small" effect="plain" round>
|
|
|
+ {{ selectedPlan.type }}
|
|
|
+ </el-tag>
|
|
|
</div>
|
|
|
- <div class="dp-info-item">
|
|
|
- <span class="dp-label">巡检频次</span>
|
|
|
- <span class="dp-value">{{ selectedPlan.frequency }}</span>
|
|
|
+ <div class="dp-o-item">
|
|
|
+ <span class="dp-o-label">状态</span>
|
|
|
+ <el-tag :type="getPlanStatusType(selectedPlan.status)" size="small" effect="light" round>
|
|
|
+ {{ selectedPlan.statusText }}
|
|
|
+ </el-tag>
|
|
|
</div>
|
|
|
- <div class="dp-info-item">
|
|
|
- <span class="dp-label">检查节点</span>
|
|
|
- <span class="dp-value">{{ selectedPlan.checkpointCount }} 个</span>
|
|
|
+ <div class="dp-o-item">
|
|
|
+ <span class="dp-o-label">完成率</span>
|
|
|
+ <el-progress :percentage="selectedPlan.completionRate" :color="getProgressColor" :stroke-width="6" width="120px" type="line" />
|
|
|
</div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 详细信息 -->
|
|
|
+ <div class="dp-info-grid">
|
|
|
<div class="dp-info-item">
|
|
|
- <span class="dp-label">责任人</span>
|
|
|
- <span class="dp-value">{{ selectedPlan.responsible }}</span>
|
|
|
+ <el-icon><Location /></el-icon>
|
|
|
+ <div>
|
|
|
+ <div class="dp-label">巡检路线</div>
|
|
|
+ <div class="dp-value">{{ selectedPlan.route }}</div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
<div class="dp-info-item">
|
|
|
- <span class="dp-label">计划周期</span>
|
|
|
- <span class="dp-value">{{ selectedPlan.startDate }} ~ {{ selectedPlan.endDate }}</span>
|
|
|
+ <el-icon><Clock /></el-icon>
|
|
|
+ <div>
|
|
|
+ <div class="dp-label">巡检频次</div>
|
|
|
+ <div class="dp-value">{{ selectedPlan.frequency }}</div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
<div class="dp-info-item">
|
|
|
- <span class="dp-label">完成率</span>
|
|
|
- <span class="dp-value">{{ selectedPlan.completionRate }}%</span>
|
|
|
+ <el-icon><User /></el-icon>
|
|
|
+ <div>
|
|
|
+ <div class="dp-label">责任人</div>
|
|
|
+ <div class="dp-value">{{ selectedPlan.responsible }}</div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
<div class="dp-info-item">
|
|
|
- <span class="dp-label">状态</span>
|
|
|
- <el-tag :type="getPlanStatusType(selectedPlan.status)" size="small" effect="light" round>{{ selectedPlan.statusText }}</el-tag>
|
|
|
+ <el-icon><Calendar /></el-icon>
|
|
|
+ <div>
|
|
|
+ <div class="dp-label">计划周期</div>
|
|
|
+ <div class="dp-value">{{ selectedPlan.startDate }} ~ {{ selectedPlan.endDate }}</div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
- <!-- 路线节点列表 -->
|
|
|
- <div class="dp-section-title">巡检路线节点</div>
|
|
|
- <div class="checkpoint-list">
|
|
|
- <div class="checkpoint-item" v-for="(cp, idx) in checkpoints" :key="idx">
|
|
|
- <div class="cp-index">{{ idx + 1 }}</div>
|
|
|
- <div class="cp-info">
|
|
|
- <div class="cp-name">{{ cp.name }}</div>
|
|
|
- <div class="cp-desc">{{ cp.desc }}</div>
|
|
|
- </div>
|
|
|
- <el-tag :type="cp.done ? 'success' : 'info'" size="small" effect="light" round>
|
|
|
- {{ cp.done ? '已完成' : '待巡检' }}
|
|
|
- </el-tag>
|
|
|
- </div>
|
|
|
+ <!-- 巡检时间轴 -->
|
|
|
+ <div class="dp-section-title">
|
|
|
+ <el-icon><Timer /></el-icon> 巡检时间轴
|
|
|
</div>
|
|
|
+ <el-timeline>
|
|
|
+ <el-timeline-item
|
|
|
+ v-for="(cp, idx) in getPlanCheckpoints(selectedPlan)"
|
|
|
+ :key="idx"
|
|
|
+ :timestamp="cp.time || '--:--'"
|
|
|
+ placement="top"
|
|
|
+ size="large"
|
|
|
+ :color="cp.done ? '#67c23a' : '#409eff'"
|
|
|
+ >
|
|
|
+ <div class="dp-timeline-node">
|
|
|
+ <div class="dp-tn-name">{{ cp.name }}</div>
|
|
|
+ <div class="dp-tn-desc">{{ cp.desc }}</div>
|
|
|
+ <el-tag v-if="cp.done" type="success" size="small" effect="light" round>已完成</el-tag>
|
|
|
+ <el-tag v-else type="info" size="small" effect="light" round>待巡检</el-tag>
|
|
|
+ </div>
|
|
|
+ </el-timeline-item>
|
|
|
+ </el-timeline>
|
|
|
</div>
|
|
|
<div class="detail-panel empty" v-else>
|
|
|
- <div class="empty-icon">👈</div>
|
|
|
+ <el-icon class="empty-icon"><ArrowLeft /></el-icon>
|
|
|
<div class="empty-text">选择一个计划查看详情</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
@@ -118,10 +162,16 @@
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
+import { Delete, Plus, Location, User, Clock, List, Document, Timer, Edit, Calendar, ArrowLeft } from '@element-plus/icons-vue'
|
|
|
+import { ElMessage, ElMessageBox } from 'element-plus'
|
|
|
+import PatrolPlanCreateView from './PatrolPlanCreateView.vue'
|
|
|
+
|
|
|
export default {
|
|
|
name: 'PatrolPlanView',
|
|
|
+ components: { PatrolPlanCreateView },
|
|
|
data() {
|
|
|
return {
|
|
|
+ showCreate: false,
|
|
|
selectedPlan: null,
|
|
|
heroItems: [
|
|
|
{ title: '待执行', value: '6', color: '#f59e0b' },
|
|
|
@@ -129,21 +179,20 @@ export default {
|
|
|
{ title: '已完成', value: '12', color: '#22c55e' },
|
|
|
{ title: '已逾期', value: '3', color: '#ef4444' }
|
|
|
],
|
|
|
- checkpoints: [
|
|
|
- { name: '坝顶起点 K0+000', desc: '坝体外观、路面状况', done: true },
|
|
|
- { name: '坝顶中部 K0+200', desc: '坝体裂缝、沉降检查', done: true },
|
|
|
- { name: '溢洪道进口', desc: '水位、漂浮物、闸门状态', done: true },
|
|
|
- { name: '坝体下游坡 K0+350', desc: '护坡完整性、渗水检查', done: true },
|
|
|
- { name: '坝脚渗流监测点', desc: '渗流量、水质观测', done: false },
|
|
|
- { name: '副坝 K0+050', desc: '副坝坝体完整性', done: false }
|
|
|
- ],
|
|
|
planList: [
|
|
|
- { id: 1, name: '大坝日常巡检-2026年6月', type: '日常巡检', route: '大坝全线巡检', checkpointCount: 12, frequency: '每日1次', responsible: '张三', startDate: '2026-06-01', endDate: '2026-06-30', completionRate: 45, status: 'executing', statusText: '执行中' },
|
|
|
- { id: 2, name: '汛前专项检查', type: '专项巡检', route: '溢洪道+泄洪闸', checkpointCount: 8, frequency: '一次性', responsible: '李四', startDate: '2026-05-15', endDate: '2026-05-20', completionRate: 100, status: 'completed', statusText: '已完成' },
|
|
|
- { id: 3, name: '副坝渗流巡检', type: '定期巡检', route: '副坝渗流监测点', checkpointCount: 6, frequency: '每周2次', responsible: '王五', startDate: '2026-06-01', endDate: '2026-08-31', completionRate: 30, status: 'executing', statusText: '执行中' },
|
|
|
- { id: 4, name: '库区岸线巡查', type: '定期巡检', route: '库区左右岸', checkpointCount: 10, frequency: '每周1次', responsible: '赵六', startDate: '2026-06-01', endDate: '2026-09-30', completionRate: 20, status: 'executing', statusText: '执行中' },
|
|
|
- { id: 5, name: '输水设施检查', type: '定期巡检', route: '输水隧洞+渠道', checkpointCount: 7, frequency: '每月2次', responsible: '张三', startDate: '2026-06-01', endDate: '2026-12-31', completionRate: 0, status: 'pending', statusText: '待执行' },
|
|
|
- { id: 6, name: '防汛物资盘点', type: '专项巡检', route: '防汛仓库', checkpointCount: 3, frequency: '一次性', responsible: '李四', startDate: '2026-05-01', endDate: '2026-05-05', completionRate: 100, status: 'completed', statusText: '已完成' }
|
|
|
+ { id: 1, name: '大坝日常巡检-2026年6月', type: '日常巡检', route: '大坝全线巡检', checkpointCount: 6, frequency: '每日1次', responsible: '张三', startDate: '2026-06-01', endDate: '2026-06-30', completionRate: 45, status: 'executing', statusText: '执行中', checkpoints: [
|
|
|
+ { name: '坝顶起点 K0+000', desc: '坝体外观、路面状况检查', time: '08:00', done: true },
|
|
|
+ { name: '坝顶中部 K0+200', desc: '坝体裂缝、沉降检查', time: '08:45', done: true },
|
|
|
+ { name: '溢洪道进口', desc: '水位、漂浮物、闸门状态', time: '09:30', done: true },
|
|
|
+ { name: '坝体下游坡 K0+350', desc: '护坡完整性、渗水检查', time: '10:15', done: true },
|
|
|
+ { name: '坝脚渗流监测点', desc: '渗流量、水质观测', time: '11:00', done: false },
|
|
|
+ { name: '副坝 K0+050', desc: '副坝坝体完整性检查', time: '14:00', done: false }
|
|
|
+ ]},
|
|
|
+ { id: 2, name: '汛前专项检查', type: '专项巡检', route: '溢洪道+泄洪闸', checkpointCount: 8, frequency: '一次性', responsible: '李四', startDate: '2026-05-15', endDate: '2026-05-20', completionRate: 100, status: 'completed', statusText: '已完成', checkpoints: [] },
|
|
|
+ { id: 3, name: '副坝渗流巡检', type: '定期巡检', route: '副坝渗流监测点', checkpointCount: 6, frequency: '每周2次', responsible: '王五', startDate: '2026-06-01', endDate: '2026-08-31', completionRate: 30, status: 'executing', statusText: '执行中', checkpoints: [] },
|
|
|
+ { id: 4, name: '库区岸线巡查', type: '定期巡检', route: '库区左右岸', checkpointCount: 10, frequency: '每周1次', responsible: '赵六', startDate: '2026-06-01', endDate: '2026-09-30', completionRate: 20, status: 'executing', statusText: '执行中', checkpoints: [] },
|
|
|
+ { id: 5, name: '输水设施检查', type: '定期巡检', route: '输水隧洞+渠道', checkpointCount: 7, frequency: '每月2次', responsible: '张三', startDate: '2026-06-01', endDate: '2026-12-31', completionRate: 0, status: 'pending', statusText: '待执行', checkpoints: [] },
|
|
|
+ { id: 6, name: '防汛物资盘点', type: '专项巡检', route: '防汛仓库', checkpointCount: 3, frequency: '一次性', responsible: '李四', startDate: '2026-05-01', endDate: '2026-05-05', completionRate: 100, status: 'completed', statusText: '已完成', checkpoints: [] }
|
|
|
]
|
|
|
}
|
|
|
},
|
|
|
@@ -155,14 +204,40 @@ export default {
|
|
|
return { '日常巡检': '', '定期巡检': 'success', '专项巡检': 'warning', '汛期巡检': 'danger' }[type] || ''
|
|
|
},
|
|
|
getProgressColor(rate) {
|
|
|
- if (rate >= 80) return 'linear-gradient(90deg, #22c55e, #16a34a)'
|
|
|
- if (rate >= 50) return 'linear-gradient(90deg, #3b82f6, #2563eb)'
|
|
|
- return 'linear-gradient(90deg, #f59e0b, #d97706)'
|
|
|
+ if (rate >= 80) return '#22c55e'
|
|
|
+ if (rate >= 50) return '#3b82f6'
|
|
|
+ return '#f59e0b'
|
|
|
+ },
|
|
|
+ getPlanCheckpoints(plan) {
|
|
|
+ return plan.checkpoints && plan.checkpoints.length ? plan.checkpoints : this.defaultCheckpoints
|
|
|
},
|
|
|
selectPlan(item) { this.selectedPlan = item },
|
|
|
- handleAddPlan() { console.log('新建计划') },
|
|
|
+ handleAddPlan() { this.showCreate = true },
|
|
|
handleEditPlan(row) { console.log('编辑:', row) },
|
|
|
- handleDeletePlan(row) { console.log('删除:', row) }
|
|
|
+ handleDeletePlan(row) {
|
|
|
+ ElMessageBox.confirm(`确定删除计划「${row.name}」吗?删除后不可恢复。`, '确认删除', {
|
|
|
+ confirmButtonText: '确定',
|
|
|
+ cancelButtonText: '取消',
|
|
|
+ type: 'warning',
|
|
|
+ confirmButtonClass: 'el-button--danger'
|
|
|
+ }).then(() => {
|
|
|
+ this.planList = this.planList.filter(p => p.id !== row.id)
|
|
|
+ if (this.selectedPlan?.id === row.id) this.selectedPlan = null
|
|
|
+ ElMessage.success('计划已删除')
|
|
|
+ }).catch(() => {})
|
|
|
+ },
|
|
|
+ onPlanCreated(newPlan) {
|
|
|
+ this.planList.unshift(newPlan)
|
|
|
+ this.showCreate = false
|
|
|
+ }
|
|
|
+ },
|
|
|
+ computed: {
|
|
|
+ defaultCheckpoints() {
|
|
|
+ return [
|
|
|
+ { name: '起点', desc: '检查准备', time: '08:00', done: false },
|
|
|
+ { name: '终点', desc: '检查总结', time: '17:00', done: false }
|
|
|
+ ]
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
</script>
|
|
|
@@ -176,7 +251,7 @@ export default {
|
|
|
font-family: 'Alibaba PuHuiTi', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif;
|
|
|
}
|
|
|
|
|
|
-/* 顶部横幅 */
|
|
|
+/* ========== 顶部横幅 ========== */
|
|
|
.hero-stats {
|
|
|
flex-shrink: 0;
|
|
|
background: linear-gradient(135deg, #1e40af, #3b82f6);
|
|
|
@@ -194,10 +269,10 @@ export default {
|
|
|
.hero-count { font-size: 24px; font-weight: 700; }
|
|
|
.hero-name { font-size: 13px; opacity: 0.7; }
|
|
|
|
|
|
-/* 主体 */
|
|
|
+/* ========== 主体 ========== */
|
|
|
.main-area { flex: 1; display: flex; gap: 16px; min-height: 0; }
|
|
|
|
|
|
-/* 左侧卡片网格 */
|
|
|
+/* ========== 左侧卡片网格 ========== */
|
|
|
.plan-grid {
|
|
|
flex: 1; overflow-y: auto;
|
|
|
display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
|
|
|
@@ -217,33 +292,30 @@ export default {
|
|
|
.plan-card.active { border-color: #3b82f6; box-shadow: 0 4px 16px rgba(59, 130, 246, 0.15); }
|
|
|
.pcard-header { display: flex; gap: 8px; margin-bottom: 10px; }
|
|
|
.pcard-name { font-size: 15px; font-weight: 600; color: #1e293b; margin-bottom: 6px; }
|
|
|
-.pcard-route { font-size: 12px; color: #64748b; margin-bottom: 12px; }
|
|
|
-.pcard-progress { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; }
|
|
|
-.progress-bar {
|
|
|
- flex: 1; height: 6px; background: #f1f5f9; border-radius: 3px; overflow: hidden;
|
|
|
-}
|
|
|
-.progress-fill { height: 100%; border-radius: 3px; transition: width 0.3s ease; }
|
|
|
-.progress-text { font-size: 12px; font-weight: 600; color: #3b82f6; min-width: 36px; }
|
|
|
+.pcard-route { font-size: 12px; color: #64748b; margin-bottom: 12px; display: flex; align-items: center; }
|
|
|
+.pcard-progress { margin-bottom: 12px; }
|
|
|
.pcard-footer {
|
|
|
- display: flex; gap: 12px; font-size: 11px; color: #94a3b8;
|
|
|
+ display: flex; gap: 16px; font-size: 12px; color: #94a3b8;
|
|
|
}
|
|
|
+.pcard-footer .el-icon { vertical-align: -2px; margin-right: 2px; }
|
|
|
|
|
|
/* 新建卡片 */
|
|
|
.add-card {
|
|
|
display: flex; flex-direction: column; align-items: center; justify-content: center;
|
|
|
- min-height: 160px;
|
|
|
+ min-height: 180px;
|
|
|
border: 2px dashed #cbd5e1;
|
|
|
background: transparent;
|
|
|
box-shadow: none;
|
|
|
+ gap: 8px;
|
|
|
}
|
|
|
.add-card:hover { border-color: #3b82f6; background: rgba(59, 130, 246, 0.03); transform: none; }
|
|
|
-.add-icon { font-size: 36px; color: #94a3b8; line-height: 1; }
|
|
|
-.add-text { font-size: 13px; color: #94a3b8; margin-top: 4px; }
|
|
|
+.add-icon { font-size: 40px; color: #94a3b8; }
|
|
|
+.add-text { font-size: 14px; color: #94a3b8; font-weight: 500; }
|
|
|
|
|
|
-/* 右侧详情面板 */
|
|
|
+/* ========== 右侧详情面板 ========== */
|
|
|
.detail-panel {
|
|
|
- width: 360px; flex-shrink: 0;
|
|
|
- background: rgba(255, 255, 255, 0.85);
|
|
|
+ width: 400px; flex-shrink: 0;
|
|
|
+ background: rgba(255, 255, 255, 0.88);
|
|
|
backdrop-filter: blur(20px);
|
|
|
border-radius: 12px;
|
|
|
border: 1px solid rgba(255, 255, 255, 0.8);
|
|
|
@@ -253,31 +325,47 @@ export default {
|
|
|
}
|
|
|
.detail-panel.empty {
|
|
|
display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px;
|
|
|
+ color: #94a3b8;
|
|
|
+}
|
|
|
+.empty-icon { font-size: 40px; }
|
|
|
+.empty-text { font-size: 14px; }
|
|
|
+.dp-header { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 16px; gap: 12px; }
|
|
|
+.dp-title { font-size: 17px; font-weight: 700; color: #1e293b; flex: 1; line-height: 1.4; }
|
|
|
+.dp-actions { display: flex; gap: 6px; flex-shrink: 0; }
|
|
|
+
|
|
|
+/* 详情概览卡片 */
|
|
|
+.dp-overview {
|
|
|
+ display: flex; gap: 12px; padding: 12px 16px;
|
|
|
+ background: #f8fafc; border-radius: 10px;
|
|
|
+ margin-bottom: 16px;
|
|
|
+}
|
|
|
+.dp-o-item {
|
|
|
+ flex: 1; display: flex; flex-direction: column; gap: 4px; align-items: center;
|
|
|
}
|
|
|
-.empty-icon { font-size: 40px; opacity: 0.3; }
|
|
|
-.empty-text { font-size: 13px; color: #94a3b8; }
|
|
|
-.dp-header { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 20px; }
|
|
|
-.dp-title { font-size: 17px; font-weight: 700; color: #1e293b; flex: 1; }
|
|
|
-.dp-actions { display: flex; gap: 6px; }
|
|
|
-.dp-info-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; margin-bottom: 20px; }
|
|
|
-.dp-info-item { display: flex; flex-direction: column; gap: 2px; }
|
|
|
+.dp-o-label { font-size: 11px; color: #94a3b8; }
|
|
|
+
|
|
|
+/* 详情的键值网格 */
|
|
|
+.dp-info-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-bottom: 20px; }
|
|
|
+.dp-info-item {
|
|
|
+ display: flex; align-items: flex-start; gap: 8px;
|
|
|
+ padding: 8px; background: #f8fafc; border-radius: 8px;
|
|
|
+}
|
|
|
+.dp-info-item .el-icon { margin-top: 2px; color: #3b82f6; font-size: 16px; }
|
|
|
.dp-label { font-size: 11px; color: #94a3b8; }
|
|
|
.dp-value { font-size: 13px; color: #1e293b; font-weight: 500; }
|
|
|
-.dp-section-title { font-size: 14px; font-weight: 600; color: #1e293b; margin-bottom: 12px; padding-top: 12px; border-top: 1px solid rgba(0,0,0,0.06); }
|
|
|
|
|
|
-/* 节点列表 */
|
|
|
-.checkpoint-list { display: flex; flex-direction: column; gap: 10px; }
|
|
|
-.checkpoint-item {
|
|
|
- display: flex; align-items: center; gap: 12px;
|
|
|
- padding: 10px 12px; background: #f8fafc; border-radius: 8px;
|
|
|
-}
|
|
|
-.cp-index {
|
|
|
- width: 24px; height: 24px; border-radius: 50%;
|
|
|
- background: #e0e7ff; color: #4f46e5;
|
|
|
- display: flex; align-items: center; justify-content: center;
|
|
|
- font-size: 12px; font-weight: 700; flex-shrink: 0;
|
|
|
+.dp-section-title {
|
|
|
+ font-size: 14px; font-weight: 600; color: #1e293b;
|
|
|
+ margin-bottom: 12px; padding-top: 12px; border-top: 1px solid rgba(0,0,0,0.06);
|
|
|
+ display: flex; align-items: center; gap: 6px;
|
|
|
}
|
|
|
-.cp-info { flex: 1; }
|
|
|
-.cp-name { font-size: 13px; font-weight: 500; color: #1e293b; }
|
|
|
-.cp-desc { font-size: 11px; color: #94a3b8; }
|
|
|
+
|
|
|
+/* 详情时间轴节点 */
|
|
|
+.dp-timeline-node { }
|
|
|
+.dp-tn-name { font-size: 14px; font-weight: 600; color: #1e293b; margin-bottom: 4px; }
|
|
|
+.dp-tn-desc { font-size: 12px; color: #64748b; margin-bottom: 6px; }
|
|
|
+
|
|
|
+/* Element Plus 时间轴间距修正 */
|
|
|
+.detail-panel :deep(.el-timeline) { padding-left: 4px; }
|
|
|
+.detail-panel :deep(.el-timeline-item__wrapper) { padding-left: 18px; }
|
|
|
</style>
|