| | |
| | | <div class="donation-process-detail"> |
| | | <el-card class="process-card"> |
| | | <div class="process-container"> |
| | | <!-- 左侧时间线 - 独立固定,内部可滚动 --> |
| | | <!-- 左侧时间线 --> |
| | | <div class="timeline-section"> |
| | | <div class="section-header"> |
| | | <h3>捐献进程时间线</h3> |
| | | <el-tag :type="getOverallStatusTag(caseInfo.status)"> |
| | | {{ getStatusText(caseInfo.status) }} |
| | | </el-tag> |
| | | </div> |
| | | |
| | | <div class="timeline-scroll-container"> |
| | |
| | | :key="stage.key" |
| | | class="timeline-item" |
| | | :class="{ |
| | | active: activeStage === stage.key, |
| | | completed: stage.status === 'completed', |
| | | 'in-progress': stage.status === 'in_progress', |
| | | pending: stage.status === 'pending' |
| | | active: stage.status == 'active', |
| | | completed: stage.status == 'completed', |
| | | progress: stage.status == 'progress', |
| | | pending: stage.status == 'pending' |
| | | }" |
| | | @click="handleStageClick(stage)" |
| | | > |
| | | <div class="timeline-marker"> |
| | | <i |
| | | v-if="stage.status === 'completed'" |
| | | v-if="stage.status == 'completed'" |
| | | class="el-icon-check" |
| | | ></i> |
| | | <i |
| | | v-else-if="stage.status === 'in_progress'" |
| | | v-else-if="stage.status == 'progress'" |
| | | class="el-icon-loading" |
| | | ></i> |
| | | <i v-else class="el-icon-time"></i> |
| | |
| | | <div class="timeline-content"> |
| | | <div class="stage-header"> |
| | | <span class="stage-name">{{ stage.name }}</span> |
| | | <el-tag |
| | | size="small" |
| | | :type="getStageStatusTag(stage.status)" |
| | | > |
| | | {{ getStageStatusText(stage.status) }} |
| | | </el-tag> |
| | | <dict-tag |
| | | :options="dict.type[stage.dict]" |
| | | :value="stage.state" |
| | | /> |
| | | </div> |
| | | |
| | | <div class="stage-info"> |
| | | <div v-if="stage.completeTime" class="time-info"> |
| | | <span |
| | | >完成时间: {{ formatTime(stage.completeTime) }}</span |
| | | > |
| | | <div v-if="stage.createtime" class="time-info"> |
| | | 创建时间: {{ formatTime(stage.createtime) }} |
| | | </div> |
| | | <div v-if="stage.updateTime" class="time-info"> |
| | | <span>最近更新: {{ formatTime(stage.updateTime) }}</span> |
| | | 最近更新: {{ formatTime(stage.updateTime) }} |
| | | </div> |
| | | <div v-if="stage.operator" class="operator-info"> |
| | | <span>负责人: {{ stage.operator }}</span> |
| | | 负责人: {{ stage.operator }} |
| | | </div> |
| | | </div> |
| | | </div> |
| | |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- 右侧内容区域 - 独立滚动 --> |
| | | <!-- 右侧内容 --> |
| | | <div class="content-section"> |
| | | <!-- 案例基本信息 - 固定高度,可滚动 --> |
| | | <case-basic-info :case-id="caseId" :show-attachment="true" /> |
| | | |
| | | <!-- 阶段详情内容 - 自适应高度,可滚动 --> |
| | | <div class="stage-detail-section"> |
| | | <div class="section-header"> |
| | | <h3>{{ activeStageName }} - 阶段详情</h3> |
| | | <div class="stage-actions"></div> |
| | | </div> |
| | | |
| | | <!-- 动态阶段内容 --> |
| | | <div class="stage-content-wrapper"> |
| | | <component |
| | | :is="getStageComponent()" |
| | |
| | | </template> |
| | | |
| | | <script> |
| | | // ===================== 字典 Label → UI 主题 ===================== |
| | | function mapDictLabelToTheme(label) { |
| | | if (!label) return "pending"; |
| | | |
| | | const l = label.trim(); |
| | | |
| | | // 待 XX |
| | | if (/^待/.test(l)) { |
| | | return "progress"; |
| | | } |
| | | |
| | | // XX中 |
| | | if (/中$/.test(l)) { |
| | | return "active"; |
| | | } |
| | | |
| | | // 完成 / 完成XX |
| | | if (/完成/.test(l)) { |
| | | return "completed"; |
| | | } |
| | | |
| | | // 弃用 / 放弃 |
| | | if (/弃用|放弃/.test(l)) { |
| | | return "danger"; |
| | | } |
| | | |
| | | return "pending"; |
| | | } |
| | | import { getDonatebaseinfoflow } from "@/api/project/donatebaseinfo"; |
| | | import { getDonationProcessDetail } from "./donationProcess"; |
| | | import CaseBasicInfo from "@/components/CaseBasicInfo"; |
| | | |
| | | import DonorMaintenanceStage from "./components/DonorMaintenanceStage"; |
| | | import MedicalAssessmentStage from "./components/MedicalAssessmentStage"; |
| | | import DeathJudgmentStage from "./components/DeathJudgmentStage"; |
| | | import MedicalAssessmentStage from "./components/MedicalAssessmentStage"; |
| | | import DonationConfirmStage from "./components/DonationConfirmStage"; |
| | | import EthicalReviewStage from "./components/EthicalReviewStage"; |
| | | import OrganAllocationStage from "./components/OrganAllocationStage"; |
| | | import OrganProcurementStage from "./components/OrganProcurementStage"; |
| | | import OrganUtilizationStage from "./components/OrganUtilizationStage"; |
| | | import CaseBasicInfo from "@/components/CaseBasicInfo"; |
| | | |
| | | import dayjs from "dayjs"; |
| | | |
| | | // ============== 字典映射(你后面自己改) ============== |
| | | const STAGE_DICT_MAP = { |
| | | donatemaintenance: "maintain_type", |
| | | deathinfo: "decide_type", |
| | | medicalevaluation: "state_Evaluation", |
| | | relativesconfirmation: "affirm_type", |
| | | donateflowcharts: "sys_ethical", |
| | | donateorgansService: "allocation_Status", |
| | | donationwitness: "Obtain_status", |
| | | donatecompletioninfo: "utilize_statue" |
| | | }; |
| | | |
| | | // state -> 流程状态 |
| | | const STATE_MAP = { |
| | | 0: "pending", |
| | | 1: "progress", |
| | | 2: "completed", |
| | | 3: "terminated" |
| | | }; |
| | | |
| | | // 阶段配置 |
| | | const STAGE_CONFIG = [ |
| | | { key: "donor_maintenance", name: "供者维护", apiKey: "donatemaintenance" }, |
| | | { key: "death_judgment", name: "死亡判定", apiKey: "deathinfo" }, |
| | | { key: "medical_assessment", name: "医学评估", apiKey: "medicalevaluation" }, |
| | | { |
| | | key: "donation_confirm", |
| | | name: "捐献确认", |
| | | apiKey: "relativesconfirmation" |
| | | }, |
| | | { key: "ethical_review", name: "伦理审查", apiKey: "donateflowcharts" }, |
| | | { key: "organ_allocation", name: "器官分配", apiKey: "donateorgansService" }, |
| | | { key: "organ_procurement", name: "器官获取", apiKey: "donationwitness" }, |
| | | { key: "organ_utilization", name: "器官利用", apiKey: "donatecompletioninfo" } |
| | | ]; |
| | | |
| | | export default { |
| | | name: "DonationProcessDetail", |
| | | components: { |
| | | CaseBasicInfo, |
| | | DonorMaintenanceStage, |
| | | MedicalAssessmentStage, |
| | | DeathJudgmentStage, |
| | | MedicalAssessmentStage, |
| | | DonationConfirmStage, |
| | | EthicalReviewStage, |
| | | OrganAllocationStage, |
| | | OrganProcurementStage, |
| | | OrganUtilizationStage, |
| | | CaseBasicInfo |
| | | OrganUtilizationStage |
| | | }, |
| | | dicts: ["sys_user_sex", "sys_BloodType", "sys_0_1"], |
| | | dicts: [ |
| | | "decide_type", |
| | | "maintain_type", |
| | | "state_Evaluation", |
| | | "affirm_type", |
| | | "sys_ethical", |
| | | "allocation_Status", |
| | | "Obtain_status", |
| | | "utilize_statue" |
| | | ], // 这里只声明一个即可,其余通过 dict.type[xxx] 使用 |
| | | data() { |
| | | return { |
| | | caseId: null, |
| | | infoid: null, |
| | | caseInfo: { |
| | | id: "", |
| | | caseNo: "", |
| | | hospitalNo: "", |
| | | donorName: "", |
| | | gender: "", |
| | | age: "", |
| | | bloodType: "", |
| | | diagnosis: "", |
| | | status: "in_progress", |
| | | createTime: "", |
| | | registrant: "", |
| | | currentStage: "donor_maintenance" |
| | | }, |
| | | processStages: [ |
| | | { |
| | | key: "donor_maintenance", |
| | | name: "供者维护", |
| | | status: "completed", |
| | | completeTime: "2025-12-01 10:00:00", |
| | | updateTime: "2025-12-01 10:00:00", |
| | | operator: "张医生" |
| | | }, |
| | | { |
| | | key: "death_judgment", |
| | | name: "死亡判定", |
| | | status: "completed", |
| | | completeTime: "2025-12-02 14:30:00", |
| | | updateTime: "2025-12-02 14:30:00", |
| | | operator: "王医生" |
| | | }, |
| | | { |
| | | key: "medical_assessment", |
| | | name: "医学评估", |
| | | status: "completed", |
| | | |
| | | completeTime: "2025-12-03 09:15:00", |
| | | updateTime: "2025-12-03 09:15:00", |
| | | operator: "李主任" |
| | | }, |
| | | { |
| | | key: "donation_confirm", |
| | | name: "捐献确认", |
| | | status: "completed", |
| | | completeTime: "2025-12-03 11:00:00", |
| | | updateTime: "2025-12-03 11:00:00", |
| | | operator: "赵协调员" |
| | | }, |
| | | { |
| | | key: "ethical_review", |
| | | name: "伦理审查", |
| | | status: "completed", |
| | | completeTime: "2025-12-03 15:20:00", |
| | | updateTime: "2025-12-03 15:20:00", |
| | | operator: "伦理委员会" |
| | | }, |
| | | { |
| | | key: "organ_allocation", |
| | | name: "器官分配", |
| | | status: "in_progress", |
| | | updateTime: "2025-12-04 10:00:00", |
| | | operator: "分配系统" |
| | | }, |
| | | { |
| | | key: "organ_procurement", |
| | | name: "器官获取", |
| | | status: "in_progress", |
| | | operator: "待分配" |
| | | }, |
| | | { |
| | | key: "organ_utilization", |
| | | name: "器官利用", |
| | | status: "in_progress", |
| | | operator: "待分配" |
| | | } |
| | | ], |
| | | activeStage: "organ_allocation", |
| | | activeStageName: "器官分配", |
| | | activeStageData: {}, |
| | | loading: false |
| | | caseInfo: {}, |
| | | processStages: [], |
| | | activeStage: "", |
| | | activeStageName: "", |
| | | activeStageData: {} |
| | | }; |
| | | }, |
| | | computed: {}, |
| | | created() { |
| | | this.caseId = this.$route.query.id; |
| | | this.infoid = this.$route.query.id; |
| | | |
| | | if (this.caseId) { |
| | | this.getDetail(); |
| | | } else { |
| | | this.generateMockData(); |
| | | } |
| | | this.setActiveStage(this.activeStage); |
| | | }, |
| | | methods: { |
| | | async getDetail() { |
| | | try { |
| | | const res = await getDonatebaseinfoflow(this.caseId); |
| | | |
| | | const data = res; |
| | | |
| | | this.caseInfo = data.donatebaseinfo || {}; |
| | | |
| | | this.processStages = STAGE_CONFIG.map(stage => { |
| | | const obj = data[stage.apiKey] || {}; |
| | | console.log(stage.apiKey, "stage.apiKey"); |
| | | console.log(this.dict?.type?.[STAGE_DICT_MAP[stage.apiKey]]); |
| | | |
| | | const dictLabel = |
| | | this.dict?.type?.[STAGE_DICT_MAP[stage.apiKey]]?.find( |
| | | d => d.value == obj.state |
| | | )?.label || ""; |
| | | |
| | | const theme = mapDictLabelToTheme(dictLabel); |
| | | |
| | | return { |
| | | key: stage.key, |
| | | name: stage.name, |
| | | dict: STAGE_DICT_MAP[stage.apiKey], |
| | | state: obj.state, |
| | | dictLabel, |
| | | status: theme, // ✅ 核心:UI 主题由 dictLabel 决定 |
| | | createtime: obj.createtime, |
| | | updateTime: obj.updatetime, |
| | | operator: obj.updateperson || obj.createperson |
| | | }; |
| | | }); |
| | | |
| | | const active = |
| | | this.processStages.find(s => s.status == "progress") || |
| | | [...this.processStages].reverse().find(s => s.status == "completed"); |
| | | |
| | | this.setActiveStage(active?.key || STAGE_CONFIG[0].key); |
| | | } catch (e) { |
| | | console.error(e); |
| | | this.$message.error("获取流程详情失败"); |
| | | } |
| | | }, |
| | | |
| | | setActiveStage(key) { |
| | | const stage = this.processStages.find(s => s.key == key); |
| | | if (!stage) return; |
| | | this.activeStage = key; |
| | | this.activeStageName = stage.name; |
| | | this.activeStageData = stage; |
| | | }, |
| | | |
| | | getStageComponent() { |
| | | const componentMap = { |
| | | const map = { |
| | | donor_maintenance: "DonorMaintenanceStage", |
| | | death_judgment: "DeathJudgmentStage", |
| | | medical_assessment: "MedicalAssessmentStage", |
| | |
| | | organ_procurement: "OrganProcurementStage", |
| | | organ_utilization: "OrganUtilizationStage" |
| | | }; |
| | | return componentMap[this.activeStage]; |
| | | return map[this.activeStage]; |
| | | }, |
| | | // 获取详情数据 |
| | | async getDetail() { |
| | | this.loading = true; |
| | | try { |
| | | const response = await getDonatebaseinfoflow(this.caseId); |
| | | if (response.code === 200) { |
| | | this.caseInfo = response.data.caseInfo; |
| | | this.processStages = response.data.processStages; |
| | | this.setActiveStage(response.data.currentStage); |
| | | } |
| | | } catch (error) { |
| | | console.error("获取捐献进程详情失败:", error); |
| | | this.$message.error("获取详情失败"); |
| | | } finally { |
| | | this.loading = false; |
| | | } |
| | | }, |
| | | // 生成模拟数据 |
| | | generateMockData() { |
| | | this.caseInfo = { |
| | | id: "202512001", |
| | | caseNo: "C202512001", |
| | | hospitalNo: "D202512001", |
| | | donorName: "张三", |
| | | gender: "0", |
| | | age: 45, |
| | | bloodType: "A", |
| | | diagnosis: "脑外伤", |
| | | status: "in_progress", |
| | | createTime: "2025-12-01 08:00:00", |
| | | registrant: "李协调员", |
| | | currentStage: "organ_allocation" |
| | | }; |
| | | }, |
| | | // 设置当前激活阶段 |
| | | setActiveStage(stageKey) { |
| | | this.activeStage = stageKey; |
| | | const stage = this.processStages.find(s => s.key === stageKey); |
| | | if (stage) { |
| | | this.activeStageName = stage.name; |
| | | this.activeStageData = stage; |
| | | console.log(this.activeStageData, "this.activeStageData"); |
| | | } |
| | | }, |
| | | // 处理阶段点击 |
| | | |
| | | handleStageClick(stage) { |
| | | if (stage.status !== "pending") { |
| | | if (stage.status == "pending") { |
| | | this.$message.warning("该阶段尚未开始"); |
| | | return; |
| | | } |
| | | this.setActiveStage(stage.key); |
| | | } else { |
| | | this.$message.warning("该阶段尚未开始,无法查看详情"); |
| | | } |
| | | }, |
| | | // 获取阶段状态标签类型 |
| | | getStageStatusTag(status) { |
| | | const map = { |
| | | completed: "success", |
| | | in_progress: "warning", |
| | | pending: "info" |
| | | }; |
| | | return map[status] || "info"; |
| | | }, |
| | | // 获取阶段状态文本 |
| | | getStageStatusText(status) { |
| | | const map = { |
| | | completed: "已完成", |
| | | in_progress: "进行中", |
| | | pending: "未开始" |
| | | }; |
| | | return map[status] || "未知"; |
| | | }, |
| | | // 获取整体状态标签类型 |
| | | getOverallStatusTag(status) { |
| | | const map = { |
| | | completed: "success", |
| | | in_progress: "warning", |
| | | pending: "info", |
| | | terminated: "danger" |
| | | }; |
| | | return map[status] || "info"; |
| | | }, |
| | | // 获取整体状态文本 |
| | | getStatusText(status) { |
| | | const map = { |
| | | completed: "已完成", |
| | | in_progress: "进行中", |
| | | pending: "未开始", |
| | | terminated: "已终止" |
| | | }; |
| | | return map[status] || "未知"; |
| | | }, |
| | | // 时间格式化 |
| | | |
| | | formatTime(time) { |
| | | if (!time) return "-"; |
| | | return dayjs(time).format("YYYY-MM-DD HH:mm"); |
| | | }, |
| | | |
| | | // 获取当前阶段名称 |
| | | getCurrentStageName() { |
| | | const currentStage = this.processStages.find( |
| | | stage => stage.status === "in_progress" |
| | | ); |
| | | return currentStage ? currentStage.name : "已完成"; |
| | | }, |
| | | // 编辑基本信息 |
| | | handleEditBasicInfo() { |
| | | this.$message.info("编辑基本信息功能"); |
| | | }, |
| | | // 完成阶段 |
| | | handleCompleteStage() { |
| | | this.$confirm(`确定要完成【${this.activeStageName}】阶段吗?`, "提示", { |
| | | confirmButtonText: "确定", |
| | | cancelButtonText: "取消", |
| | | type: "warning" |
| | | }).then(() => { |
| | | // 更新当前阶段状态 |
| | | const currentIndex = this.processStages.findIndex( |
| | | stage => stage.key === this.activeStage |
| | | ); |
| | | |
| | | if (currentIndex !== -1) { |
| | | this.processStages[currentIndex].status = "completed"; |
| | | this.processStages[ |
| | | currentIndex |
| | | ].completeTime = new Date().toISOString(); |
| | | |
| | | // 激活下一个阶段 |
| | | if (currentIndex < this.processStages.length - 1) { |
| | | this.processStages[currentIndex + 1].status = "in_progress"; |
| | | this.setActiveStage(this.processStages[currentIndex + 1].key); |
| | | } else { |
| | | this.caseInfo.status = "completed"; |
| | | } |
| | | |
| | | this.$message.success("阶段已完成"); |
| | | } |
| | | }); |
| | | }, |
| | | // 查看详情 |
| | | handleViewDetail() { |
| | | const routeMap = { |
| | | donor_maintenance: "/case/donorMaintenance/detail", |
| | | death_judgment: "/case/deathJudgment/detail", |
| | | medical_assessment: "/case/medicalAssessment/detail", |
| | | donation_confirm: "/case/donationConfirm/detail", |
| | | ethical_review: "/case/ethicalReview/detail", |
| | | organ_allocation: "/case/organAllocation/detail", |
| | | organ_procurement: "/case/organProcurement/detail", |
| | | organ_utilization: "/case/organUtilization/detail" |
| | | }; |
| | | |
| | | const route = routeMap[this.activeStage]; |
| | | if (route) { |
| | | this.$router.push({ |
| | | path: route, |
| | | query: { id: this.caseId } |
| | | }); |
| | | } |
| | | }, |
| | | // 修改阶段信息 |
| | | handleModifyStage() { |
| | | this.$message.info(`修改${this.activeStageName}信息功能`); |
| | | return time ? dayjs(time).format("YYYY-MM-DD HH:mm") : "-"; |
| | | } |
| | | } |
| | | }; |
| | |
| | | |
| | | .process-container { |
| | | display: flex; |
| | | min-height: 600px; /* 设置一个最小高度 */ |
| | | min-height: 600px; |
| | | /* 设置一个最小高度 */ |
| | | gap: 20px; |
| | | align-items: flex-start; /* 顶部对齐 */ |
| | | align-items: flex-start; |
| | | /* 顶部对齐 */ |
| | | } |
| | | |
| | | /* 左侧时间线样式 - 固定高度,内部滚动 */ |
| | | .timeline-section { |
| | | flex: 0 0 320px; /* 固定宽度 */ |
| | | flex: 0 0 320px; |
| | | /* 固定宽度 */ |
| | | display: flex; |
| | | flex-direction: column; |
| | | background: white; |
| | | border-radius: 6px; |
| | | padding: 20px; |
| | | box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1); |
| | | height: calc(120vh - 120px); /* 根据视口高度自适应 */ |
| | | max-height: 1200px; /* 设置最大高度 */ |
| | | position: sticky; /* 使用 sticky 定位 */ |
| | | top: 20px; /* 距离顶部 20px */ |
| | | height: calc(120vh - 120px); |
| | | /* 根据视口高度自适应 */ |
| | | max-height: 1200px; |
| | | /* 设置最大高度 */ |
| | | position: sticky; |
| | | /* 使用 sticky 定位 */ |
| | | top: 20px; |
| | | /* 距离顶部 20px */ |
| | | } |
| | | |
| | | .timeline-scroll-container { |
| | | flex: 1; |
| | | overflow-y: auto; /* 内部可滚动 */ |
| | | overflow-y: auto; |
| | | /* 内部可滚动 */ |
| | | margin-top: 20px; |
| | | padding-right: 8px; /* 为滚动条留出空间 */ |
| | | padding-right: 8px; |
| | | /* 为滚动条留出空间 */ |
| | | } |
| | | |
| | | .timeline-scroll-container::-webkit-scrollbar { |
| | |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 20px; |
| | | min-height: 0; /* 重要:允许flex子项压缩 */ |
| | | min-height: 0; |
| | | /* 重要:允许flex子项压缩 */ |
| | | } |
| | | |
| | | .basic-info-section { |
| | |
| | | box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1); |
| | | display: flex; |
| | | flex-direction: column; |
| | | min-height: 0; /* 重要 */ |
| | | min-height: 0; |
| | | /* 重要 */ |
| | | } |
| | | |
| | | .basic-info-content { |
| | | flex: 1; |
| | | max-height: 300px; /* 基本信息区域最大高度 */ |
| | | overflow-y: auto; /* 基本信息内部可滚动 */ |
| | | max-height: 300px; |
| | | /* 基本信息区域最大高度 */ |
| | | overflow-y: auto; |
| | | /* 基本信息内部可滚动 */ |
| | | margin-top: 20px; |
| | | padding-right: 8px; |
| | | } |
| | |
| | | } |
| | | |
| | | .stage-detail-section { |
| | | flex: 1; /* 占据剩余空间 */ |
| | | flex: 1; |
| | | /* 占据剩余空间 */ |
| | | background: white; |
| | | border-radius: 6px; |
| | | padding: 20px; |
| | | box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1); |
| | | display: flex; |
| | | flex-direction: column; |
| | | min-height: 400px; /* 最小高度 */ |
| | | max-height: 800px; /* 最大高度,可根据需要调整 */ |
| | | overflow: hidden; /* 隐藏外层溢出 */ |
| | | min-height: 400px; |
| | | /* 最小高度 */ |
| | | max-height: 800px; |
| | | /* 最大高度,可根据需要调整 */ |
| | | overflow: hidden; |
| | | /* 隐藏外层溢出 */ |
| | | } |
| | | |
| | | .stage-content-wrapper { |
| | | flex: 1; |
| | | overflow-y: auto; /* 阶段详情内部可滚动 */ |
| | | overflow-y: auto; |
| | | /* 阶段详情内部可滚动 */ |
| | | margin-top: 20px; |
| | | padding-right: 8px; |
| | | min-height: 0; /* 重要 */ |
| | | min-height: 0; |
| | | /* 重要 */ |
| | | } |
| | | |
| | | .stage-content-wrapper::-webkit-scrollbar { |
| | |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | flex-shrink: 0; /* 防止被压缩 */ |
| | | flex-shrink: 0; |
| | | /* 防止被压缩 */ |
| | | } |
| | | |
| | | .section-header h3 { |
| | |
| | | cursor: pointer; |
| | | transition: all 0.3s ease; |
| | | border: 1px solid #e4e7ed; |
| | | flex-shrink: 0; /* 防止被压缩 */ |
| | | flex-shrink: 0; |
| | | /* 防止被压缩 */ |
| | | } |
| | | |
| | | .timeline-item:hover { |
| | | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); |
| | | transform: translateY(-1px); |
| | | } |
| | | .timeline-item.danger { |
| | | border-color: #f56c6c; |
| | | background-color: #fef0f0; |
| | | } |
| | | |
| | | .timeline-item.danger .timeline-marker { |
| | | background-color: #f56c6c; |
| | | } |
| | | .timeline-item.active { |
| | | border-color: #409eff; |
| | | background-color: #f0f9ff; |
| | |
| | | background-color: #f0f9e8; |
| | | } |
| | | |
| | | .timeline-item.in-progress { |
| | | .timeline-item.progress { |
| | | border-color: #e6a23c; |
| | | background-color: #fdf6ec; |
| | | } |
| | |
| | | .timeline-item.completed .timeline-marker { |
| | | background-color: #67c23a; |
| | | } |
| | | .timeline-item.active .timeline-marker { |
| | | background-color: #409eff; |
| | | } |
| | | |
| | | .timeline-item.in-progress .timeline-marker { |
| | | .timeline-item.progress .timeline-marker { |
| | | background-color: #e6a23c; |
| | | } |
| | | |
| | |
| | | width: 100%; |
| | | height: auto; |
| | | max-height: 300px; |
| | | position: static; /* 小屏幕取消 sticky */ |
| | | position: static; |
| | | /* 小屏幕取消 sticky */ |
| | | } |
| | | |
| | | .timeline-scroll-container { |