You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
392 lines
8.5 KiB
392 lines
8.5 KiB
|
2 months ago
|
<template>
|
||
|
|
<div class="bottom-left-panel">
|
||
|
|
<div class="panel-toggle" @click="togglePanel" :title="isExpanded ? '收起' : '展开'">
|
||
|
|
<i :class="isExpanded ? 'el-icon-s-fold' : 'el-icon-s-unfold'"></i>
|
||
|
|
<span v-if="!isExpanded" class="toggle-text">工具</span>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="panel-content" :class="{ expanded: isExpanded }">
|
||
|
|
<div class="panel-item" @click="showTimeline">
|
||
|
|
<i class="el-icon-time"></i>
|
||
|
|
<span>时间线</span>
|
||
|
|
</div>
|
||
|
|
<div class="panel-item" @click="showProgress">
|
||
|
|
<i class="el-icon-s-data"></i>
|
||
|
|
<span>进度检查</span>
|
||
|
|
</div>
|
||
|
|
<div class="panel-item" @click="showSixSteps">
|
||
|
|
<i class="el-icon-s-operation"></i>
|
||
|
|
<span>六步法</span>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<el-dialog
|
||
|
|
:visible.sync="dialogVisible"
|
||
|
|
:title="dialogTitle"
|
||
|
|
width="350px"
|
||
|
|
:modal="false"
|
||
|
|
custom-class="panel-dialog"
|
||
|
|
>
|
||
|
|
<div class="dialog-content">
|
||
|
|
<div v-if="activeTab === 'timeline'" class="timeline-content">
|
||
|
|
<h3>时间线</h3>
|
||
|
|
<div class="timeline-list">
|
||
|
|
<div v-for="(item, index) in timelineData" :key="index" class="timeline-item">
|
||
|
|
<div class="timeline-dot"></div>
|
||
|
|
<div class="timeline-info">
|
||
|
|
<div class="timeline-time">{{ item.time }}</div>
|
||
|
|
<div class="timeline-event">{{ item.event }}</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div v-if="activeTab === 'progress'" class="progress-content">
|
||
|
|
<h3>进度检查</h3>
|
||
|
|
<div class="progress-list">
|
||
|
|
<div v-for="(item, index) in progressData" :key="index" class="progress-item">
|
||
|
|
<div class="progress-label">{{ item.label }}</div>
|
||
|
|
<el-progress :percentage="item.percentage" :status="item.status"></el-progress>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div v-if="activeTab === 'sixsteps'" class="sixsteps-content">
|
||
|
|
<h3>六步法</h3>
|
||
|
|
<div class="steps-container">
|
||
|
|
<div v-for="(step, index) in sixStepsData" :key="index" class="step-item" :class="{ active: step.active, completed: step.completed }">
|
||
|
|
<div class="step-number">{{ index + 1 }}</div>
|
||
|
|
<div class="step-content">
|
||
|
|
<div class="step-title">{{ step.title }}</div>
|
||
|
|
<div class="step-desc">{{ step.desc }}</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</el-dialog>
|
||
|
|
</div>
|
||
|
|
</template>
|
||
|
|
|
||
|
|
<script>
|
||
|
|
export default {
|
||
|
|
name: 'BottomLeftPanel',
|
||
|
|
data() {
|
||
|
|
return {
|
||
|
|
isExpanded: false,
|
||
|
|
dialogVisible: false,
|
||
|
|
dialogTitle: '',
|
||
|
|
activeTab: '',
|
||
|
|
timelineData: [
|
||
|
|
{ time: 'K-02:00', event: '任务准备阶段' },
|
||
|
|
{ time: 'K-01:00', event: '资源调配' },
|
||
|
|
{ time: 'K时', event: '任务执行' },
|
||
|
|
{ time: 'K+01:00', event: '任务监控' },
|
||
|
|
{ time: 'K+02:00', event: '任务完成' }
|
||
|
|
],
|
||
|
|
progressData: [
|
||
|
|
{ label: '任务准备', percentage: 100, status: 'success' },
|
||
|
|
{ label: '资源调配', percentage: 80, status: '' },
|
||
|
|
{ label: '任务执行', percentage: 45, status: '' },
|
||
|
|
{ label: '任务监控', percentage: 20, status: 'exception' },
|
||
|
|
{ label: '任务完成', percentage: 0, status: '' }
|
||
|
|
],
|
||
|
|
sixStepsData: [
|
||
|
|
{ title: '理解', desc: '明确任务目标和要求', active: true, completed: true },
|
||
|
|
{ title: '判断', desc: '评估可用资源和能力', active: false, completed: true },
|
||
|
|
{ title: '规划', desc: '制定详细执行方案', active: false, completed: false },
|
||
|
|
{ title: '准备', desc: '识别和评估潜在风险', active: false, completed: false },
|
||
|
|
{ title: '执行', desc: '实时监控执行过程', active: false, completed: false },
|
||
|
|
{ title: '评估', desc: '评估任务完成效果', active: false, completed: false }
|
||
|
|
]
|
||
|
|
}
|
||
|
|
},
|
||
|
|
methods: {
|
||
|
|
togglePanel() {
|
||
|
|
this.isExpanded = !this.isExpanded
|
||
|
|
},
|
||
|
|
showTimeline() {
|
||
|
|
this.activeTab = 'timeline'
|
||
|
|
this.dialogTitle = '时间线'
|
||
|
|
this.dialogVisible = true
|
||
|
|
},
|
||
|
|
showProgress() {
|
||
|
|
this.activeTab = 'progress'
|
||
|
|
this.dialogTitle = '进度检查'
|
||
|
|
this.dialogVisible = true
|
||
|
|
},
|
||
|
|
showSixSteps() {
|
||
|
|
this.activeTab = 'sixsteps'
|
||
|
|
this.dialogTitle = '六步法'
|
||
|
|
this.dialogVisible = true
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
</script>
|
||
|
|
|
||
|
|
<style scoped>
|
||
|
|
.bottom-left-panel {
|
||
|
|
position: absolute;
|
||
|
|
bottom: 20px;
|
||
|
|
left: 20px;
|
||
|
|
z-index: 100;
|
||
|
|
}
|
||
|
|
|
||
|
|
.panel-toggle {
|
||
|
|
width: 50px;
|
||
|
|
height: 50px;
|
||
|
|
background: rgba(0, 138, 255, 0.9);
|
||
|
|
border-radius: 50%;
|
||
|
|
display: flex;
|
||
|
|
flex-direction: column;
|
||
|
|
justify-content: center;
|
||
|
|
align-items: center;
|
||
|
|
cursor: pointer;
|
||
|
|
color: white;
|
||
|
|
font-size: 20px;
|
||
|
|
box-shadow: 0 4px 12px rgba(0, 138, 255, 0.4);
|
||
|
|
transition: all 0.3s;
|
||
|
|
}
|
||
|
|
|
||
|
|
.panel-toggle:hover {
|
||
|
|
transform: scale(1.1);
|
||
|
|
box-shadow: 0 6px 16px rgba(0, 138, 255, 0.6);
|
||
|
|
}
|
||
|
|
|
||
|
|
.toggle-text {
|
||
|
|
font-size: 10px;
|
||
|
|
margin-top: 2px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.panel-content {
|
||
|
|
position: absolute;
|
||
|
|
bottom: 60px;
|
||
|
|
left: 0;
|
||
|
|
background: rgba(255, 255, 255, 0.95);
|
||
|
|
backdrop-filter: blur(10px);
|
||
|
|
border-radius: 12px;
|
||
|
|
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
|
||
|
|
padding: 10px;
|
||
|
|
min-width: 150px;
|
||
|
|
opacity: 0;
|
||
|
|
transform: translateY(20px);
|
||
|
|
pointer-events: none;
|
||
|
|
transition: all 0.3s;
|
||
|
|
}
|
||
|
|
|
||
|
|
.panel-content.expanded {
|
||
|
|
opacity: 1;
|
||
|
|
transform: translateY(0);
|
||
|
|
pointer-events: auto;
|
||
|
|
}
|
||
|
|
|
||
|
|
.panel-item {
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
padding: 12px 15px;
|
||
|
|
cursor: pointer;
|
||
|
|
border-radius: 8px;
|
||
|
|
transition: all 0.3s;
|
||
|
|
color: #333;
|
||
|
|
}
|
||
|
|
|
||
|
|
.panel-item:hover {
|
||
|
|
background: rgba(0, 138, 255, 0.1);
|
||
|
|
color: #008aff;
|
||
|
|
transform: translateX(5px);
|
||
|
|
}
|
||
|
|
|
||
|
|
.panel-item i {
|
||
|
|
font-size: 18px;
|
||
|
|
margin-right: 10px;
|
||
|
|
color: #008aff;
|
||
|
|
}
|
||
|
|
|
||
|
|
.panel-item span {
|
||
|
|
font-size: 14px;
|
||
|
|
font-weight: 500;
|
||
|
|
}
|
||
|
|
|
||
|
|
.dialog-content {
|
||
|
|
padding: 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
.timeline-content h3,
|
||
|
|
.progress-content h3,
|
||
|
|
.sixsteps-content h3 {
|
||
|
|
margin: 0 0 15px 0;
|
||
|
|
font-size: 14px;
|
||
|
|
color: #333;
|
||
|
|
border-bottom: 2px solid #409EFF;
|
||
|
|
padding-bottom: 8px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.timeline-list {
|
||
|
|
max-height: 280px;
|
||
|
|
overflow-y: auto;
|
||
|
|
}
|
||
|
|
|
||
|
|
.timeline-item {
|
||
|
|
display: flex;
|
||
|
|
align-items: flex-start;
|
||
|
|
margin-bottom: 12px;
|
||
|
|
position: relative;
|
||
|
|
}
|
||
|
|
|
||
|
|
.timeline-item::before {
|
||
|
|
content: '';
|
||
|
|
position: absolute;
|
||
|
|
left: 5px;
|
||
|
|
top: 15px;
|
||
|
|
bottom: -12px;
|
||
|
|
width: 2px;
|
||
|
|
background: #e0e0e0;
|
||
|
|
}
|
||
|
|
|
||
|
|
.timeline-item:last-child::before {
|
||
|
|
display: none;
|
||
|
|
}
|
||
|
|
|
||
|
|
.timeline-dot {
|
||
|
|
width: 12px;
|
||
|
|
height: 12px;
|
||
|
|
background: #409EFF;
|
||
|
|
border-radius: 50%;
|
||
|
|
margin-right: 10px;
|
||
|
|
flex-shrink: 0;
|
||
|
|
box-shadow: 0 0 0 3px rgba(64, 158, 255, 0.2);
|
||
|
|
}
|
||
|
|
|
||
|
|
.timeline-info {
|
||
|
|
flex: 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
.timeline-time {
|
||
|
|
font-size: 12px;
|
||
|
|
color: #409EFF;
|
||
|
|
font-weight: 600;
|
||
|
|
margin-bottom: 3px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.timeline-event {
|
||
|
|
font-size: 12px;
|
||
|
|
color: #666;
|
||
|
|
}
|
||
|
|
|
||
|
|
.progress-list {
|
||
|
|
max-height: 280px;
|
||
|
|
overflow-y: auto;
|
||
|
|
}
|
||
|
|
|
||
|
|
.progress-item {
|
||
|
|
margin-bottom: 15px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.progress-label {
|
||
|
|
font-size: 12px;
|
||
|
|
color: #333;
|
||
|
|
margin-bottom: 5px;
|
||
|
|
font-weight: 500;
|
||
|
|
}
|
||
|
|
|
||
|
|
.steps-container {
|
||
|
|
display: flex;
|
||
|
|
flex-direction: column;
|
||
|
|
gap: 8px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.step-item {
|
||
|
|
display: flex;
|
||
|
|
align-items: flex-start;
|
||
|
|
padding: 10px;
|
||
|
|
background: #f5f7fa;
|
||
|
|
border-radius: 6px;
|
||
|
|
transition: all 0.3s;
|
||
|
|
border-left: 3px solid #dcdfe6;
|
||
|
|
}
|
||
|
|
|
||
|
|
.step-item.active {
|
||
|
|
background: rgba(64, 158, 255, 0.1);
|
||
|
|
border-left-color: #409EFF;
|
||
|
|
}
|
||
|
|
|
||
|
|
.step-item.completed {
|
||
|
|
background: rgba(103, 194, 58, 0.1);
|
||
|
|
border-left-color: #67c23a;
|
||
|
|
}
|
||
|
|
|
||
|
|
.step-number {
|
||
|
|
width: 24px;
|
||
|
|
height: 24px;
|
||
|
|
background: #dcdfe6;
|
||
|
|
border-radius: 50%;
|
||
|
|
display: flex;
|
||
|
|
justify-content: center;
|
||
|
|
align-items: center;
|
||
|
|
font-size: 12px;
|
||
|
|
font-weight: 600;
|
||
|
|
color: #909399;
|
||
|
|
margin-right: 10px;
|
||
|
|
flex-shrink: 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
.step-item.active .step-number {
|
||
|
|
background: #409EFF;
|
||
|
|
color: white;
|
||
|
|
}
|
||
|
|
|
||
|
|
.step-item.completed .step-number {
|
||
|
|
background: #67c23a;
|
||
|
|
color: white;
|
||
|
|
}
|
||
|
|
|
||
|
|
.step-content {
|
||
|
|
flex: 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
.step-title {
|
||
|
|
font-size: 13px;
|
||
|
|
font-weight: 600;
|
||
|
|
color: #333;
|
||
|
|
margin-bottom: 3px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.step-desc {
|
||
|
|
font-size: 11px;
|
||
|
|
color: #666;
|
||
|
|
}
|
||
|
|
</style>
|
||
|
|
|
||
|
|
<style>
|
||
|
|
.panel-dialog {
|
||
|
|
position: absolute !important;
|
||
|
|
left: 170px !important;
|
||
|
|
bottom: 20px !important;
|
||
|
|
top: auto !important;
|
||
|
|
margin: 0 !important;
|
||
|
|
max-height: 400px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.panel-dialog .el-dialog__header {
|
||
|
|
padding: 12px 15px;
|
||
|
|
background: #409EFF;
|
||
|
|
color: white;
|
||
|
|
}
|
||
|
|
|
||
|
|
.panel-dialog .el-dialog__title {
|
||
|
|
color: white;
|
||
|
|
font-size: 14px;
|
||
|
|
font-weight: 600;
|
||
|
|
}
|
||
|
|
|
||
|
|
.panel-dialog .el-dialog__headerbtn .el-dialog__close {
|
||
|
|
color: white;
|
||
|
|
}
|
||
|
|
|
||
|
|
.panel-dialog .el-dialog__body {
|
||
|
|
padding: 15px;
|
||
|
|
max-height: 350px;
|
||
|
|
overflow-y: auto;
|
||
|
|
}
|
||
|
|
</style>
|