<template>
|
<view class="case-detail">
|
<!-- 头部信息卡片 -->
|
<view class="header-card">
|
<view class="case-header">
|
<view class="hospital-info">
|
<image :src="caseDetail.hospitalLogo" mode="aspectFit" class="hospital-logo" />
|
<view class="hospital-details">
|
<text class="hospital-name">{{ caseDetail.hospitalName }}</text>
|
<text class="case-type">{{ caseDetail.caseType }}</text>
|
</view>
|
</view>
|
<view class="case-status" :class="caseDetail.status">
|
{{ caseDetail.statusText }}
|
</view>
|
</view>
|
|
<view class="case-basic-info">
|
<view class="info-row">
|
<view class="info-item">
|
<text class="label">捐献编号</text>
|
<text class="value">{{ caseDetail.donorNo }}</text>
|
</view>
|
<view class="info-item">
|
<text class="label">上报时间</text>
|
<text class="value">{{ caseDetail.reportTime }}</text>
|
</view>
|
</view>
|
</view>
|
</view>
|
|
<!-- 选项卡导航 -->
|
<view class="tab-navigation">
|
<text
|
v-for="tab in tabs"
|
:key="tab.id"
|
:class="{ active: activeTab === tab.id }"
|
@tap="switchTab(tab.id)"
|
class="tab-item"
|
>
|
{{ tab.label }}
|
</text>
|
</view>
|
|
<!-- 捐献者基本信息 -->
|
<view v-if="activeTab === 'basic'" class="info-section fade-in-up">
|
<view class="section-card">
|
<view class="section-header">
|
<text class="section-title">捐献者基本信息</text>
|
</view>
|
<view class="info-grid">
|
<view class="info-item">
|
<text class="label">姓名</text>
|
<text class="value">{{ caseDetail.donorName }}</text>
|
</view>
|
<view class="info-item">
|
<text class="label">性别</text>
|
<text class="value">{{ caseDetail.gender }}</text>
|
</view>
|
<view class="info-item">
|
<text class="label">年龄</text>
|
<text class="value">{{ caseDetail.age }}岁</text>
|
</view>
|
<view class="info-item">
|
<text class="label">证件号码</text>
|
<text class="value">{{ caseDetail.idCardNo }}</text>
|
</view>
|
<view class="info-item">
|
<text class="label">血型</text>
|
<text class="value">{{ caseDetail.bloodType }}</text>
|
</view>
|
<view class="info-item">
|
<text class="label">民族</text>
|
<text class="value">{{ caseDetail.nation }}</text>
|
</view>
|
<view class="info-item full-width">
|
<text class="label">住址</text>
|
<text class="value">{{ caseDetail.address }}</text>
|
</view>
|
</view>
|
</view>
|
</view>
|
|
<!-- 医疗信息 -->
|
<view v-if="activeTab === 'medical'" class="info-section fade-in-up">
|
<view class="section-card">
|
<view class="section-header">
|
<text class="section-title">医疗信息</text>
|
</view>
|
<view class="info-content">
|
<view class="info-group">
|
<text class="group-title">疾病诊断</text>
|
<text class="group-content">{{ caseDetail.diagnosis }}</text>
|
</view>
|
<view class="info-group">
|
<text class="group-title">住院号</text>
|
<text class="group-content">{{ caseDetail.inpatientNo }}</text>
|
</view>
|
<view class="info-group">
|
<text class="group-title">所在科室</text>
|
<text class="group-content">{{ caseDetail.departmentName }}</text>
|
</view>
|
<view class="info-group">
|
<text class="group-title">传染病情况</text>
|
<text class="group-content">{{ caseDetail.infectiousDisease || '无' }}</text>
|
</view>
|
</view>
|
</view>
|
</view>
|
|
<!-- 捐献流程信息 -->
|
<view v-if="activeTab === 'process'" class="info-section fade-in-up">
|
<view class="section-card">
|
<view class="section-header">
|
<text class="section-title">捐献流程信息</text>
|
</view>
|
<view class="process-timeline">
|
<view class="timeline-item" v-for="step in processSteps" :key="step.id">
|
<view class="timeline-marker" :class="{ active: step.completed }"></view>
|
<view class="timeline-content">
|
<text class="step-title">{{ step.title }}</text>
|
<text class="step-time" v-if="step.time">{{ step.time }}</text>
|
<text class="step-person" v-if="step.person">经办人:{{ step.person }}</text>
|
</view>
|
</view>
|
</view> +
|
</view>
|
</view>
|
|
<!-- 操作按钮 -->
|
<view class="action-bar">
|
<button class="action-btn secondary" @tap="goBack">返回</button>
|
<button class="action-btn primary" v-if="caseDetail.status === 'reported'"
|
@tap="withdrawCase">撤回案例</button>
|
<button class="action-btn primary" v-else @tap="contactCoordinator">联系协调员</button>
|
</view>
|
</view>
|
</template>
|
|
<script setup>
|
import { ref, computed, onMounted } from 'vue'
|
|
import { onLoad } from '@dcloudio/uni-app'
|
|
const caseDetail = ref({
|
id: 1,
|
donorNo: 'DON20240325001',
|
hospitalName: '青岛镜湖医院',
|
hospitalLogo: '/static/hospital/kiang-wu.jpg',
|
caseType: '器官捐献案例',
|
donorName: '张三',
|
idCardNo: '370203198510123456',
|
gender: '男',
|
age: 38,
|
bloodType: 'A型',
|
nation: '汉族',
|
address: '山东省青岛市市南区香港中路100号',
|
diagnosis: '脑外伤导致脑死亡',
|
inpatientNo: 'ZY20240325001',
|
departmentName: '神经外科',
|
infectiousDisease: '无',
|
reportTime: '2024-03-25 09:30:00',
|
status: 'reported',
|
statusText: '已上报'
|
})
|
|
const tabs = ref([
|
{ id: 'basic', label: '基本信息' },
|
{ id: 'medical', label: '医疗信息' },
|
{ id: 'process', label: '流程信息' }
|
])
|
|
const activeTab = ref('basic')
|
|
const processSteps = ref([
|
{ id: 1, title: '案例上报', completed: true, time: '2024-03-25 09:30', person: '李医生' },
|
{ id: 2, title: '信息审核', completed: false, time: null, person: null },
|
{ id: 3, title: '家属沟通', completed: false, time: null, person: null },
|
{ id: 4, title: '捐献确认', completed: false, time: null, person: null },
|
{ id: 5, title: '器官获取', completed: false, time: null, person: null }
|
])
|
|
onLoad((options) => {
|
if (options.id) {
|
// 根据ID加载案例详情
|
loadCaseDetail(options.id)
|
}
|
})
|
|
const switchTab = (tabId) => {
|
activeTab.value = tabId
|
}
|
|
const goBack = () => {
|
uni.navigateBack()
|
}
|
|
const withdrawCase = () => {
|
uni.showModal({
|
title: '确认撤回',
|
content: '确定要撤回这个捐献案例吗?',
|
success: (res) => {
|
if (res.confirm) {
|
uni.showToast({ title: '撤回成功', icon: 'success' })
|
setTimeout(() => {
|
uni.navigateBack()
|
}, 1500)
|
}
|
}
|
})
|
}
|
|
const contactCoordinator = () => {
|
uni.makePhoneCall({
|
phoneNumber: '13800138000'
|
})
|
}
|
|
const loadCaseDetail = (id) => {
|
// 模拟API调用
|
console.log('加载案例详情:', id)
|
}
|
</script>
|
|
<style lang="scss" scoped>
|
.case-detail {
|
min-height: 100vh;
|
background: linear-gradient(135deg, #fafdff 0%, #e3f0ff 100%);
|
padding: 20rpx;
|
}
|
|
.header-card {
|
background: linear-gradient(135deg, #fff 60%, #f5f6fa 100%);
|
border-radius: 32rpx;
|
padding: 40rpx 30rpx;
|
margin-bottom: 30rpx;
|
box-shadow: 0 12px 48px 0 rgba(0, 113, 227, 0.10);
|
border: 1.5px solid #e5eaf0;
|
}
|
|
.case-header {
|
display: flex;
|
justify-content: space-between;
|
align-items: flex-start;
|
margin-bottom: 30rpx;
|
}
|
|
.hospital-info {
|
display: flex;
|
align-items: center;
|
}
|
|
.hospital-logo {
|
width: 80rpx;
|
height: 80rpx;
|
border-radius: 16rpx;
|
margin-right: 20rpx;
|
}
|
|
.hospital-details {
|
display: flex;
|
flex-direction: column;
|
}
|
|
.hospital-name {
|
font-size: 32rpx;
|
font-weight: 600;
|
color: #1d1d1f;
|
margin-bottom: 8rpx;
|
}
|
|
.case-type {
|
font-size: 24rpx;
|
color: #86868b;
|
}
|
|
.case-status {
|
padding: 8rpx 20rpx;
|
border-radius: 20rpx;
|
font-size: 24rpx;
|
font-weight: 500;
|
|
&.reported {
|
background: rgba(255, 149, 0, 0.1);
|
color: #ff9500;
|
}
|
|
&.read {
|
background: rgba(0, 122, 255, 0.1);
|
color: #007aff;
|
}
|
|
&.agreed {
|
background: rgba(52, 199, 89, 0.1);
|
color: #34c759;
|
}
|
}
|
|
.case-basic-info {
|
.info-row {
|
display: flex;
|
justify-content: space-between;
|
}
|
|
.info-item {
|
display: flex;
|
flex-direction: column;
|
}
|
|
.label {
|
font-size: 24rpx;
|
color: #86868b;
|
margin-bottom: 8rpx;
|
}
|
|
.value {
|
font-size: 28rpx;
|
color: #1d1d1f;
|
font-weight: 500;
|
}
|
}
|
|
.tab-navigation {
|
display: flex;
|
background: #fff;
|
border-radius: 16rpx;
|
padding: 8rpx;
|
margin-bottom: 30rpx;
|
box-shadow: 0 4px 16px 0 rgba(0, 0, 0, 0.05);
|
}
|
|
.tab-item {
|
flex: 1;
|
text-align: center;
|
padding: 20rpx;
|
font-size: 28rpx;
|
color: #86868b;
|
transition: all 0.3s ease;
|
|
&.active {
|
color: #007aff;
|
background: #f0f7ff;
|
border-radius: 12rpx;
|
font-weight: 600;
|
}
|
}
|
|
.section-card {
|
background: linear-gradient(135deg, #fff 60%, #f5f6fa 100%);
|
border-radius: 32rpx;
|
padding: 40rpx 30rpx;
|
margin-bottom: 30rpx;
|
box-shadow: 0 12px 48px 0 rgba(0, 113, 227, 0.10);
|
border: 1.5px solid #e5eaf0;
|
}
|
|
.section-header {
|
margin-bottom: 30rpx;
|
}
|
|
.section-title {
|
font-size: 32rpx;
|
font-weight: 600;
|
background: linear-gradient(90deg, #0071e3 0%, #2997ff 100%);
|
-webkit-background-clip: text;
|
-webkit-text-fill-color: transparent;
|
color: #0071e3;
|
}
|
|
.info-grid {
|
display: grid;
|
grid-template-columns: 1fr 1fr;
|
gap: 24rpx;
|
}
|
|
.info-item {
|
display: flex;
|
flex-direction: column;
|
|
&.full-width {
|
grid-column: 1 / -1;
|
}
|
|
.label {
|
font-size: 24rpx;
|
color: #86868b;
|
margin-bottom: 8rpx;
|
}
|
|
.value {
|
font-size: 28rpx;
|
color: #1d1d1f;
|
font-weight: 500;
|
}
|
}
|
|
.info-content {
|
.info-group {
|
margin-bottom: 32rpx;
|
|
&:last-child {
|
margin-bottom: 0;
|
}
|
}
|
|
.group-title {
|
font-size: 26rpx;
|
color: #86868b;
|
margin-bottom: 12rpx;
|
display: block;
|
}
|
|
.group-content {
|
font-size: 28rpx;
|
color: #1d1d1f;
|
line-height: 1.6;
|
}
|
}
|
|
.process-timeline {
|
position: relative;
|
padding-left: 40rpx;
|
|
&::before {
|
content: '';
|
position: absolute;
|
left: 15rpx;
|
top: 0;
|
bottom: 0;
|
width: 2rpx;
|
background: #e5e5e7;
|
}
|
}
|
|
.timeline-item {
|
position: relative;
|
margin-bottom: 40rpx;
|
|
&:last-child {
|
margin-bottom: 0;
|
}
|
}
|
|
.timeline-marker {
|
position: absolute;
|
left: -40rpx;
|
top: 8rpx;
|
width: 32rpx;
|
height: 32rpx;
|
border-radius: 50%;
|
background: #e5e5e7;
|
border: 4rpx solid #fff;
|
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
|
&.active {
|
background: #007aff;
|
}
|
}
|
|
.timeline-content {
|
padding-bottom: 20rpx;
|
}
|
|
.step-title {
|
display: block;
|
font-size: 28rpx;
|
font-weight: 600;
|
color: #1d1d1f;
|
margin-bottom: 8rpx;
|
}
|
|
.step-time, .step-person {
|
display: block;
|
font-size: 24rpx;
|
color: #86868b;
|
margin-bottom: 4rpx;
|
}
|
|
.action-bar {
|
display: flex;
|
gap: 20rpx;
|
padding: 40rpx 0;
|
background: transparent;
|
}
|
|
.action-btn {
|
flex: 1;
|
height: 80rpx;
|
border-radius: 20rpx;
|
font-size: 28rpx;
|
font-weight: 600;
|
border: none;
|
transition: all 0.3s ease;
|
|
&.secondary {
|
background: #f5f5f7;
|
color: #1d1d1f;
|
|
&:active {
|
background: #e5e5e7;
|
}
|
}
|
|
&.primary {
|
background: linear-gradient(90deg, #0071e3 0%, #2997ff 100%);
|
color: #fff;
|
|
&:active {
|
transform: scale(0.98);
|
}
|
}
|
}
|
|
.fade-in-up {
|
opacity: 0;
|
transform: translateY(40rpx);
|
animation: fadeInUp 0.6s ease forwards;
|
}
|
|
@keyframes fadeInUp {
|
to {
|
opacity: 1;
|
transform: translateY(0);
|
}
|
}
|
</style>
|