| | |
| | | <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> |
| | | </div> |
| | | |
| | | <div class="timeline-container"> |
| | | <div |
| | | v-for="stage in processStages" |
| | | :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' |
| | | }" |
| | | @click="handleStageClick(stage)" |
| | | > |
| | | <div class="timeline-marker"> |
| | | <i v-if="stage.status === 'completed'" class="el-icon-check"></i> |
| | | <i v-else-if="stage.status === 'in_progress'" class="el-icon-loading"></i> |
| | | <i v-else class="el-icon-time"></i> |
| | | </div> |
| | | |
| | | <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> |
| | | <div class="timeline-scroll-container"> |
| | | <div class="timeline-container"> |
| | | <div |
| | | v-for="stage in processStages" |
| | | :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' |
| | | }" |
| | | @click="handleStageClick(stage)" |
| | | > |
| | | <div class="timeline-marker"> |
| | | <i |
| | | v-if="stage.status === 'completed'" |
| | | class="el-icon-check" |
| | | ></i> |
| | | <i |
| | | v-else-if="stage.status === 'in_progress'" |
| | | class="el-icon-loading" |
| | | ></i> |
| | | <i v-else class="el-icon-time"></i> |
| | | </div> |
| | | |
| | | <div class="stage-info"> |
| | | <div v-if="stage.completeTime" class="time-info"> |
| | | <span>完成时间: {{ formatTime(stage.completeTime) }}</span> |
| | | <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> |
| | | </div> |
| | | <div v-if="stage.updateTime" class="time-info"> |
| | | <span>最近更新: {{ formatTime(stage.updateTime) }}</span> |
| | | </div> |
| | | <div v-if="stage.operator" class="operator-info"> |
| | | <span>负责人: {{ stage.operator }}</span> |
| | | |
| | | <div class="stage-info"> |
| | | <div v-if="stage.completeTime" class="time-info"> |
| | | <span |
| | | >完成时间: {{ formatTime(stage.completeTime) }}</span |
| | | > |
| | | </div> |
| | | <div v-if="stage.updateTime" class="time-info"> |
| | | <span>最近更新: {{ formatTime(stage.updateTime) }}</span> |
| | | </div> |
| | | <div v-if="stage.operator" class="operator-info"> |
| | | <span>负责人: {{ stage.operator }}</span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- 右侧内容区域 --> |
| | | <!-- 右侧内容区域 - 独立滚动 --> |
| | | <div class="content-section"> |
| | | <!-- 案例基本信息 --> |
| | | <!-- 案例基本信息 - 固定高度,可滚动 --> |
| | | <div class="basic-info-section"> |
| | | <div class="section-header"> |
| | | <h3>案例基本信息</h3> |
| | |
| | | </el-button> |
| | | </div> |
| | | |
| | | <el-descriptions :column="2" border> |
| | | <el-descriptions-item label="案例编号"> |
| | | {{ caseInfo.caseNo }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="住院号"> |
| | | {{ caseInfo.hospitalNo }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="捐献者姓名"> |
| | | {{ caseInfo.donorName }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="性别"> |
| | | <dict-tag |
| | | :options="dict.type.sys_user_sex" |
| | | :value="parseInt(caseInfo.gender)" |
| | | /> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="年龄"> |
| | | {{ caseInfo.age }} 岁 |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="血型"> |
| | | <dict-tag |
| | | :options="dict.type.sys_BloodType" |
| | | :value="caseInfo.bloodType" |
| | | /> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="疾病诊断"> |
| | | {{ caseInfo.diagnosis }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="案例状态"> |
| | | <el-tag :type="getOverallStatusTag(caseInfo.status)"> |
| | | {{ getStatusText(caseInfo.status) }} |
| | | </el-tag> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="创建时间"> |
| | | {{ formatTime(caseInfo.createTime) }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="登记人"> |
| | | {{ caseInfo.registrant }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="当前阶段"> |
| | | {{ getCurrentStageName() }} |
| | | </el-descriptions-item> |
| | | </el-descriptions> |
| | | <div class="basic-info-content"> |
| | | <el-descriptions :column="2" border> |
| | | <el-descriptions-item label="住院号"> |
| | | {{ caseInfo.caseNo }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="住院号"> |
| | | {{ caseInfo.hospitalNo }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="捐献者姓名"> |
| | | {{ caseInfo.donorName }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="性别"> |
| | | <dict-tag |
| | | :options="dict.type.sys_user_sex" |
| | | :value="parseInt(caseInfo.gender)" |
| | | /> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="年龄"> |
| | | {{ caseInfo.age }} 岁 |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="血型"> |
| | | <dict-tag |
| | | :options="dict.type.sys_BloodType" |
| | | :value="caseInfo.bloodType" |
| | | /> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="疾病诊断"> |
| | | {{ caseInfo.diagnosis }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="案例状态"> |
| | | <el-tag :type="getOverallStatusTag(caseInfo.status)"> |
| | | {{ getStatusText(caseInfo.status) }} |
| | | </el-tag> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="创建时间"> |
| | | {{ formatTime(caseInfo.createTime) }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="登记人"> |
| | | {{ caseInfo.registrant }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="当前阶段"> |
| | | {{ getCurrentStageName() }} |
| | | </el-descriptions-item> |
| | | </el-descriptions> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- 阶段详情内容 --> |
| | | <!-- 阶段详情内容 - 自适应高度,可滚动 --> |
| | | <div class="stage-detail-section"> |
| | | <div class="section-header"> |
| | | <h3>{{ activeStageName }} - 阶段详情</h3> |
| | | <div class="stage-actions"> |
| | | <el-button |
| | | v-if="activeStageData.status !== 'completed'" |
| | | type="success" |
| | | size="small" |
| | | @click="handleCompleteStage" |
| | | > |
| | | 完成阶段 |
| | | </el-button> |
| | | <el-button |
| | | type="primary" |
| | | size="small" |
| | | @click="handleViewDetail" |
| | | > |
| | | 查看详情 |
| | | </el-button> |
| | | <el-button |
| | | v-if="activeStageData.status === 'completed'" |
| | | type="warning" |
| | | size="small" |
| | | @click="handleModifyStage" |
| | | > |
| | | 修改信息 |
| | | </el-button> |
| | | </div> |
| | | <div class="stage-actions"></div> |
| | | </div> |
| | | |
| | | <!-- 动态阶段内容 --> |
| | | <div class="stage-content"> |
| | | <div class="stage-content-wrapper"> |
| | | <component |
| | | :is="getStageComponent()" |
| | | :stageData="activeStageData" |
| | | :caseInfo="caseInfo" |
| | | :infoid="caseId" |
| | | /> |
| | | </div> |
| | | </div> |
| | |
| | | </template> |
| | | |
| | | <script> |
| | | import { getDonationProcessDetail } from './donationProcess'; |
| | | import DonorMaintenanceStage from './components/DonorMaintenanceStage'; |
| | | import MedicalAssessmentStage from './components/MedicalAssessmentStage'; |
| | | import DeathJudgmentStage from './components/DeathJudgmentStage'; |
| | | 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 { getDonationProcessDetail } from "./donationProcess"; |
| | | import DonorMaintenanceStage from "./components/DonorMaintenanceStage"; |
| | | import MedicalAssessmentStage from "./components/MedicalAssessmentStage"; |
| | | import DeathJudgmentStage from "./components/DeathJudgmentStage"; |
| | | 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 dayjs from "dayjs"; |
| | | |
| | | export default { |
| | | name: 'DonationProcessDetail', |
| | | name: "DonationProcessDetail", |
| | | components: { |
| | | DonorMaintenanceStage, |
| | | MedicalAssessmentStage, |
| | |
| | | OrganProcurementStage, |
| | | OrganUtilizationStage |
| | | }, |
| | | dicts: ['sys_user_sex', 'sys_BloodType', 'sys_0_1'], |
| | | dicts: ["sys_user_sex", "sys_BloodType", "sys_0_1"], |
| | | data() { |
| | | return { |
| | | caseId: null, |
| | | caseInfo: { |
| | | id: '', |
| | | caseNo: '', |
| | | hospitalNo: '', |
| | | donorName: '', |
| | | gender: '', |
| | | age: '', |
| | | bloodType: '', |
| | | diagnosis: '', |
| | | status: 'in_progress', |
| | | createTime: '', |
| | | registrant: '', |
| | | currentStage: 'donor_maintenance' |
| | | 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: "donor_maintenance", |
| | | name: "供者维护", |
| | | status: "completed", |
| | | completeTime: "2025-12-01 10:00:00", |
| | | updateTime: "2025-12-01 10:00:00", |
| | | operator: "张医生" |
| | | }, |
| | | { |
| | | key: 'medical_assessment', |
| | | name: '医学评估', |
| | | status: 'completed', |
| | | completeTime: '2025-12-02 14:30:00', |
| | | updateTime: '2025-12-02 14:30:00', |
| | | operator: '李主任' |
| | | key: "death_judgment", |
| | | name: "死亡判定", |
| | | status: "completed", |
| | | completeTime: "2025-12-02 14:30:00", |
| | | updateTime: "2025-12-02 14:30:00", |
| | | operator: "王医生" |
| | | }, |
| | | { |
| | | key: 'death_judgment', |
| | | name: '死亡判定', |
| | | status: 'completed', |
| | | completeTime: '2025-12-03 09:15:00', |
| | | updateTime: '2025-12-03 09:15: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: "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: "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_allocation", |
| | | name: "器官分配", |
| | | status: "in_progress", |
| | | updateTime: "2025-12-04 10:00:00", |
| | | operator: "分配系统" |
| | | }, |
| | | { |
| | | key: 'organ_procurement', |
| | | name: '器官获取', |
| | | status: 'pending', |
| | | operator: '待分配' |
| | | key: "organ_procurement", |
| | | name: "器官获取", |
| | | status: "pending", |
| | | operator: "待分配" |
| | | }, |
| | | { |
| | | key: 'organ_utilization', |
| | | name: '器官利用', |
| | | status: 'pending', |
| | | operator: '待分配' |
| | | key: "organ_utilization", |
| | | name: "器官利用", |
| | | status: "pending", |
| | | operator: "待分配" |
| | | } |
| | | ], |
| | | activeStage: 'organ_allocation', |
| | | activeStageName: '器官分配', |
| | | activeStage: "organ_allocation", |
| | | activeStageName: "器官分配", |
| | | activeStageData: {}, |
| | | loading: false |
| | | }; |
| | | }, |
| | | computed: { |
| | | |
| | | }, |
| | | computed: {}, |
| | | created() { |
| | | this.caseId = this.$route.query.id; |
| | | console.log(this.caseId, "this.caseId"); |
| | | |
| | | if (this.caseId) { |
| | | this.getDetail(); |
| | | } else { |
| | |
| | | this.setActiveStage(this.activeStage); |
| | | }, |
| | | methods: { |
| | | getStageComponent() { |
| | | getStageComponent() { |
| | | const componentMap = { |
| | | 'donor_maintenance': 'DonorMaintenanceStage', |
| | | 'medical_assessment': 'MedicalAssessmentStage', |
| | | 'death_judgment': 'DeathJudgmentStage', |
| | | 'donation_confirm': 'DonationConfirmStage', |
| | | 'ethical_review': 'EthicalReviewStage', |
| | | 'organ_allocation': 'OrganAllocationStage', |
| | | 'organ_procurement': 'OrganProcurementStage', |
| | | 'organ_utilization': 'OrganUtilizationStage' |
| | | donor_maintenance: "DonorMaintenanceStage", |
| | | death_judgment: "DeathJudgmentStage", |
| | | medical_assessment: "MedicalAssessmentStage", |
| | | donation_confirm: "DonationConfirmStage", |
| | | ethical_review: "EthicalReviewStage", |
| | | organ_allocation: "OrganAllocationStage", |
| | | organ_procurement: "OrganProcurementStage", |
| | | organ_utilization: "OrganUtilizationStage" |
| | | }; |
| | | return componentMap[this.activeStage]; |
| | | }, |
| | |
| | | this.setActiveStage(response.data.currentStage); |
| | | } |
| | | } catch (error) { |
| | | console.error('获取捐献进程详情失败:', error); |
| | | this.$message.error('获取详情失败'); |
| | | console.error("获取捐献进程详情失败:", error); |
| | | this.$message.error("获取详情失败"); |
| | | } finally { |
| | | this.loading = false; |
| | | } |
| | |
| | | // 生成模拟数据 |
| | | generateMockData() { |
| | | this.caseInfo = { |
| | | id: '202512001', |
| | | caseNo: 'C202512001', |
| | | hospitalNo: 'D202512001', |
| | | donorName: '张三', |
| | | gender: '0', |
| | | 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' |
| | | bloodType: "A", |
| | | diagnosis: "脑外伤", |
| | | status: "in_progress", |
| | | createTime: "2025-12-01 08:00:00", |
| | | registrant: "李协调员", |
| | | currentStage: "organ_allocation" |
| | | }; |
| | | }, |
| | | // 设置当前激活阶段 |
| | |
| | | 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.setActiveStage(stage.key); |
| | | } else { |
| | | this.$message.warning('该阶段尚未开始,无法查看详情'); |
| | | this.$message.warning("该阶段尚未开始,无法查看详情"); |
| | | } |
| | | }, |
| | | // 获取阶段状态标签类型 |
| | | getStageStatusTag(status) { |
| | | const map = { |
| | | 'completed': 'success', |
| | | 'in_progress': 'warning', |
| | | 'pending': 'info' |
| | | completed: "success", |
| | | in_progress: "warning", |
| | | pending: "info" |
| | | }; |
| | | return map[status] || 'info'; |
| | | return map[status] || "info"; |
| | | }, |
| | | // 获取阶段状态文本 |
| | | getStageStatusText(status) { |
| | | const map = { |
| | | 'completed': '已完成', |
| | | 'in_progress': '进行中', |
| | | 'pending': '未开始' |
| | | completed: "已完成", |
| | | in_progress: "进行中", |
| | | pending: "未开始" |
| | | }; |
| | | return map[status] || '未知'; |
| | | return map[status] || "未知"; |
| | | }, |
| | | // 获取整体状态标签类型 |
| | | getOverallStatusTag(status) { |
| | | const map = { |
| | | 'completed': 'success', |
| | | 'in_progress': 'warning', |
| | | 'pending': 'info', |
| | | 'terminated': 'danger' |
| | | completed: "success", |
| | | in_progress: "warning", |
| | | pending: "info", |
| | | terminated: "danger" |
| | | }; |
| | | return map[status] || 'info'; |
| | | return map[status] || "info"; |
| | | }, |
| | | // 获取整体状态文本 |
| | | getStatusText(status) { |
| | | const map = { |
| | | 'completed': '已完成', |
| | | 'in_progress': '进行中', |
| | | 'pending': '未开始', |
| | | 'terminated': '已终止' |
| | | completed: "已完成", |
| | | in_progress: "进行中", |
| | | pending: "未开始", |
| | | terminated: "已终止" |
| | | }; |
| | | return map[status] || '未知'; |
| | | return map[status] || "未知"; |
| | | }, |
| | | // 时间格式化 |
| | | formatTime(time) { |
| | | if (!time) return '-'; |
| | | return dayjs(time).format('YYYY-MM-DD HH:mm'); |
| | | if (!time) return "-"; |
| | | return dayjs(time).format("YYYY-MM-DD HH:mm"); |
| | | }, |
| | | |
| | | // 获取当前阶段名称 |
| | | getCurrentStageName() { |
| | | const currentStage = this.processStages.find( |
| | | stage => stage.status === 'in_progress' |
| | | stage => stage.status === "in_progress" |
| | | ); |
| | | return currentStage ? currentStage.name : '已完成'; |
| | | return currentStage ? currentStage.name : "已完成"; |
| | | }, |
| | | // 编辑基本信息 |
| | | handleEditBasicInfo() { |
| | | this.$message.info('编辑基本信息功能'); |
| | | this.$message.info("编辑基本信息功能"); |
| | | }, |
| | | // 完成阶段 |
| | | handleCompleteStage() { |
| | | this.$confirm(`确定要完成【${this.activeStageName}】阶段吗?`, '提示', { |
| | | confirmButtonText: '确定', |
| | | cancelButtonText: '取消', |
| | | type: 'warning' |
| | | this.$confirm(`确定要完成【${this.activeStageName}】阶段吗?`, "提示", { |
| | | confirmButtonText: "确定", |
| | | cancelButtonText: "取消", |
| | | type: "warning" |
| | | }).then(() => { |
| | | // 更新当前阶段状态 |
| | | const currentIndex = this.processStages.findIndex( |
| | |
| | | ); |
| | | |
| | | if (currentIndex !== -1) { |
| | | this.processStages[currentIndex].status = 'completed'; |
| | | this.processStages[currentIndex].completeTime = new Date().toISOString(); |
| | | 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.processStages[currentIndex + 1].status = "in_progress"; |
| | | this.setActiveStage(this.processStages[currentIndex + 1].key); |
| | | } else { |
| | | this.caseInfo.status = 'completed'; |
| | | this.caseInfo.status = "completed"; |
| | | } |
| | | |
| | | this.$message.success('阶段已完成'); |
| | | this.$message.success("阶段已完成"); |
| | | } |
| | | }); |
| | | }, |
| | | // 查看详情 |
| | | handleViewDetail() { |
| | | const routeMap = { |
| | | 'donor_maintenance': '/case/donorMaintenance/detail', |
| | | 'medical_assessment': '/case/medicalAssessment/detail', |
| | | 'death_judgment': '/case/deathJudgment/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' |
| | | 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]; |
| | |
| | | padding: 20px; |
| | | background-color: #f5f7fa; |
| | | min-height: 100vh; |
| | | box-sizing: border-box; |
| | | } |
| | | |
| | | .process-card { |
| | | border-radius: 8px; |
| | | box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .process-container { |
| | | display: flex; |
| | | min-height: 800px; |
| | | min-height: 600px; /* 设置一个最小高度 */ |
| | | gap: 20px; |
| | | align-items: flex-start; /* 顶部对齐 */ |
| | | } |
| | | |
| | | /* 左侧时间线样式 */ |
| | | /* 左侧时间线样式 - 固定高度,内部滚动 */ |
| | | .timeline-section { |
| | | flex: 0 0 300px; |
| | | 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 */ |
| | | } |
| | | |
| | | .section-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 20px; |
| | | padding-bottom: 15px; |
| | | border-bottom: 1px solid #e4e7ed; |
| | | .timeline-scroll-container { |
| | | flex: 1; |
| | | overflow-y: auto; /* 内部可滚动 */ |
| | | margin-top: 20px; |
| | | padding-right: 8px; /* 为滚动条留出空间 */ |
| | | } |
| | | |
| | | .section-header h3 { |
| | | margin: 0; |
| | | color: #303133; |
| | | font-size: 16px; |
| | | .timeline-scroll-container::-webkit-scrollbar { |
| | | width: 6px; |
| | | } |
| | | |
| | | .timeline-scroll-container::-webkit-scrollbar-track { |
| | | background: #f1f1f1; |
| | | border-radius: 3px; |
| | | } |
| | | |
| | | .timeline-scroll-container::-webkit-scrollbar-thumb { |
| | | background: #c1c1c1; |
| | | border-radius: 3px; |
| | | } |
| | | |
| | | .timeline-scroll-container::-webkit-scrollbar-thumb:hover { |
| | | background: #a8a8a8; |
| | | } |
| | | |
| | | .timeline-container { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 15px; |
| | | padding-bottom: 10px; |
| | | } |
| | | |
| | | /* 右侧内容区域样式 - 自适应高度 */ |
| | | .content-section { |
| | | flex: 1; |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 20px; |
| | | min-height: 0; /* 重要:允许flex子项压缩 */ |
| | | } |
| | | |
| | | .basic-info-section { |
| | | 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: 0; /* 重要 */ |
| | | } |
| | | |
| | | .basic-info-content { |
| | | flex: 1; |
| | | max-height: 300px; /* 基本信息区域最大高度 */ |
| | | overflow-y: auto; /* 基本信息内部可滚动 */ |
| | | margin-top: 20px; |
| | | padding-right: 8px; |
| | | } |
| | | |
| | | .basic-info-content::-webkit-scrollbar { |
| | | width: 6px; |
| | | } |
| | | |
| | | .basic-info-content::-webkit-scrollbar-track { |
| | | background: #f1f1f1; |
| | | border-radius: 3px; |
| | | } |
| | | |
| | | .basic-info-content::-webkit-scrollbar-thumb { |
| | | background: #c1c1c1; |
| | | border-radius: 3px; |
| | | } |
| | | |
| | | .basic-info-content::-webkit-scrollbar-thumb:hover { |
| | | background: #a8a8a8; |
| | | } |
| | | |
| | | .basic-info-content .el-descriptions { |
| | | width: 100%; |
| | | } |
| | | |
| | | .stage-detail-section { |
| | | 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; /* 隐藏外层溢出 */ |
| | | } |
| | | |
| | | .stage-content-wrapper { |
| | | flex: 1; |
| | | overflow-y: auto; /* 阶段详情内部可滚动 */ |
| | | margin-top: 20px; |
| | | padding-right: 8px; |
| | | min-height: 0; /* 重要 */ |
| | | } |
| | | |
| | | .stage-content-wrapper::-webkit-scrollbar { |
| | | width: 6px; |
| | | } |
| | | |
| | | .stage-content-wrapper::-webkit-scrollbar-track { |
| | | background: #f1f1f1; |
| | | border-radius: 3px; |
| | | } |
| | | |
| | | .stage-content-wrapper::-webkit-scrollbar-thumb { |
| | | background: #c1c1c1; |
| | | border-radius: 3px; |
| | | } |
| | | |
| | | .stage-content-wrapper::-webkit-scrollbar-thumb:hover { |
| | | background: #a8a8a8; |
| | | } |
| | | |
| | | /* 原有样式保持不变 */ |
| | | .section-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | flex-shrink: 0; /* 防止被压缩 */ |
| | | } |
| | | |
| | | .section-header h3 { |
| | | margin: 0; |
| | | color: #303133; |
| | | font-size: 16px; |
| | | white-space: nowrap; |
| | | } |
| | | |
| | | .timeline-item { |
| | |
| | | cursor: pointer; |
| | | transition: all 0.3s ease; |
| | | border: 1px solid #e4e7ed; |
| | | flex-shrink: 0; /* 防止被压缩 */ |
| | | } |
| | | |
| | | .timeline-item:hover { |
| | |
| | | } |
| | | |
| | | .timeline-item.active { |
| | | border-color: #409EFF; |
| | | border-color: #409eff; |
| | | background-color: #f0f9ff; |
| | | } |
| | | |
| | | .timeline-item.completed { |
| | | border-color: #67C23A; |
| | | border-color: #67c23a; |
| | | background-color: #f0f9e8; |
| | | } |
| | | |
| | | .timeline-item.in-progress { |
| | | border-color: #E6A23C; |
| | | border-color: #e6a23c; |
| | | background-color: #fdf6ec; |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | .timeline-item.completed .timeline-marker { |
| | | background-color: #67C23A; |
| | | background-color: #67c23a; |
| | | } |
| | | |
| | | .timeline-item.in-progress .timeline-marker { |
| | | background-color: #E6A23C; |
| | | background-color: #e6a23c; |
| | | } |
| | | |
| | | .timeline-item.pending .timeline-marker { |
| | |
| | | font-weight: 600; |
| | | color: #303133; |
| | | font-size: 14px; |
| | | white-space: nowrap; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | max-width: 150px; |
| | | } |
| | | |
| | | .stage-info { |
| | |
| | | color: #606266; |
| | | } |
| | | |
| | | .time-info, .operator-info { |
| | | .time-info, |
| | | .operator-info { |
| | | margin-bottom: 4px; |
| | | } |
| | | |
| | | /* 右侧内容区域样式 */ |
| | | .content-section { |
| | | flex: 1; |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 20px; |
| | | } |
| | | |
| | | .basic-info-section, |
| | | .stage-detail-section { |
| | | background: white; |
| | | border-radius: 6px; |
| | | padding: 20px; |
| | | box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1); |
| | | white-space: nowrap; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | } |
| | | |
| | | .stage-actions { |
| | | display: flex; |
| | | gap: 10px; |
| | | } |
| | | |
| | | .stage-content { |
| | | margin-top: 20px; |
| | | flex-wrap: wrap; |
| | | } |
| | | |
| | | /* 响应式设计 */ |
| | |
| | | |
| | | .timeline-section { |
| | | flex: none; |
| | | margin-bottom: 20px; |
| | | width: 100%; |
| | | height: auto; |
| | | max-height: 300px; |
| | | position: static; /* 小屏幕取消 sticky */ |
| | | } |
| | | |
| | | .timeline-scroll-container { |
| | | max-height: 250px; |
| | | } |
| | | |
| | | .stage-detail-section { |
| | | max-height: 500px; |
| | | } |
| | | } |
| | | |
| | |
| | | gap: 10px; |
| | | } |
| | | |
| | | .stage-actions { |
| | | flex-wrap: wrap; |
| | | .stage-name { |
| | | max-width: 120px; |
| | | } |
| | | } |
| | | |
| | | /* 动画效果 */ |
| | | .timeline-item { |
| | | transition: all 0.3s ease; |
| | | } |
| | | .basic-info-content { |
| | | max-height: 250px; |
| | | } |
| | | |
| | | .timeline-item:hover { |
| | | transform: translateY(-2px); |
| | | } |
| | | |
| | | /* 进度条样式优化 */ |
| | | :deep(.el-progress-bar) { |
| | | padding-right: 0; |
| | | } |
| | | |
| | | :deep(.el-progress__text) { |
| | | font-size: 12px; |
| | | .stage-detail-section { |
| | | min-height: 300px; |
| | | max-height: 400px; |
| | | } |
| | | } |
| | | </style> |