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.
 
 
 
 
 

359 lines
8.4 KiB

<template>
<div>
<bottom-timeline ref="timeline" @timeline-hidden="onTimelineHidden" :room-id="roomId" />
<div class="bottom-left-panel" v-show="showPanel">
<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="showSixSteps">
<i class="el-icon-s-operation"></i>
<span>六步法</span>
</div>
</div>
</div>
<div class="sixsteps-bar" v-if="showSixStepsBar">
<div class="close-btn" @click="hideSixStepsBar">
<i class="el-icon-close"></i>
</div>
<div class="steps-bar-container">
<div
v-for="(step, index) in sixStepsData"
:key="index"
class="step-bar-item"
:class="{ active: step.active, completed: step.completed }"
@click="selectStep(index)"
>
<div class="step-bar-number">{{ index + 1 }}</div>
<div class="step-bar-content">
<div class="step-bar-title">{{ step.title }}</div>
<div class="step-bar-desc">{{ step.desc }}</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import BottomTimeline from './BottomTimeline.vue'
export default {
name: 'BottomLeftPanel',
components: {
BottomTimeline
},
props: {
roomId: {
type: Number,
default: null
}
},
data() {
return {
isExpanded: false,
showPanel: true,
showSixStepsBar: false,
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() {
if (this.$refs.timeline) {
this.$refs.timeline.isVisible = true
this.isExpanded = false
this.showPanel = false
this.$emit('bottom-panel-visible', true)
}
},
onTimelineHidden() {
this.showPanel = true
this.$emit('bottom-panel-visible', false)
},
showSixSteps() {
this.showSixStepsBar = true
this.isExpanded = false
this.showPanel = false
this.$emit('bottom-panel-visible', true)
},
hideSixStepsBar() {
this.showSixStepsBar = false
this.showPanel = true
this.$emit('bottom-panel-visible', false)
},
selectStep(index) {
const clickedStep = this.sixStepsData[index]
if (clickedStep.completed && !clickedStep.active) {
this.sixStepsData.forEach((step, i) => {
if (i >= index) {
step.completed = false
}
})
}
this.sixStepsData.forEach((step, i) => {
step.active = i === index
if (i < index) {
step.completed = true
}
})
const url = `/stepEditor.html?title=${encodeURIComponent(this.sixStepsData[index].title)}&index=${index}`
window.open(url, '_blank')
}
}
}
</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: 0;
left: 60px;
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: translateX(-20px);
pointer-events: none;
transition: all 0.3s;
}
.panel-content.expanded {
opacity: 1;
transform: translateX(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;
}
.sixsteps-bar {
position: fixed;
bottom: 0;
left: 0;
right: 0;
background: linear-gradient(180deg, rgba(255, 255, 255, 0.98) 0%, rgba(248, 250, 252, 0.98) 100%);
backdrop-filter: blur(20px);
box-shadow: 0 -8px 32px rgba(0, 0, 0, 0.08);
padding: 2px 60px 4px 60px;
z-index: 1000;
animation: slideUp 0.4s cubic-bezier(0.4, 0, 0.2, 1);
border-top: 1px solid rgba(0, 0, 0, 0.05);
}
@keyframes slideUp {
from {
transform: translateY(100%);
opacity: 0;
}
to {
transform: translateY(0);
opacity: 1;
}
}
.close-btn {
position: absolute;
top: 50%;
right: 20px;
transform: translateY(-50%);
width: 32px;
height: 32px;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
color: #94a3b8;
font-size: 18px;
border-radius: 8px;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
background: transparent;
}
.close-btn:hover {
background: rgba(239, 68, 68, 0.1);
color: #ef4444;
transform: translateY(-50%) rotate(90deg);
}
.steps-bar-container {
display: flex;
gap: 12px;
height: 62px;
align-items: center;
}
.step-bar-item {
flex: 1;
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
padding: 0 16px;
background: rgba(255, 255, 255, 0.6);
border-radius: 12px;
cursor: pointer;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
border: 1px solid rgba(226, 232, 240, 0.8);
min-width: 0;
position: relative;
overflow: hidden;
}
.step-bar-item:hover {
background: rgba(255, 255, 255, 0.9);
transform: translateY(-2px);
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08);
border-color: rgba(148, 163, 184, 0.4);
}
.step-bar-item.active {
background: linear-gradient(135deg, rgba(59, 130, 246, 0.08) 0%, rgba(59, 130, 246, 0.02) 100%);
border-color: rgba(59, 130, 246, 0.3);
box-shadow: 0 8px 24px rgba(59, 130, 246, 0.15);
}
.step-bar-item.completed {
background: linear-gradient(135deg, rgba(34, 197, 94, 0.06) 0%, rgba(34, 197, 94, 0.01) 100%);
border-color: rgba(34, 197, 94, 0.25);
}
.step-bar-number {
width: 24px;
height: 24px;
background: linear-gradient(135deg, #f1f5f9 0%, #e2e8f0 100%);
border-radius: 8px;
display: flex;
justify-content: center;
align-items: center;
font-size: 12px;
font-weight: 700;
color: #64748b;
margin-right: 10px;
flex-shrink: 0;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
.step-bar-item.active .step-bar-number {
background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%);
color: white;
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.3);
}
.step-bar-item.completed .step-bar-number {
background: linear-gradient(135deg, #22c55e 0%, #16a34a 100%);
color: white;
box-shadow: 0 4px 12px rgba(34, 197, 94, 0.25);
}
.step-bar-content {
text-align: left;
width: 100%;
overflow: hidden;
}
.step-bar-title {
font-size: 12px;
font-weight: 600;
color: #1e293b;
margin-bottom: 1px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
letter-spacing: 0.3px;
}
.step-bar-item.active .step-bar-title {
color: #1e40af;
}
.step-bar-desc {
font-size: 10px;
color: #64748b;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
letter-spacing: 0.2px;
}
</style>