<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.treatmenthospitalname || '未填写治疗医院' }}</text>
|
<text class="case-type">{{ caseDetail.donorNo ? '器官捐献案例' : '案例详情' }}</text>
|
</view>
|
</view>
|
<view class="case-status" :class="getStatusClass(caseDetail.reportStatus)">
|
{{ getStatusText(caseDetail.reportStatus) }}
|
</view>
|
</view>
|
|
<view class="case-basic-info">
|
<view class="info-row">
|
<view class="info-item">
|
<text class="label">案例编号</text>
|
<text class="value">{{ caseDetail.caseNo || '未生成' }}</text>
|
</view>
|
<view class="info-item">
|
<text class="label">上报时间</text>
|
<text class="value">{{ formatDateTime(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.name || '未填写' }}</text>
|
</view>
|
<view class="info-item">
|
<text class="label">性别</text>
|
<text class="value">{{ getGenderText(caseDetail.sex) }}</text>
|
</view>
|
<view class="info-item">
|
<text class="label">年龄</text>
|
<text class="value">{{ caseDetail.age || '0' }} {{ getAgeUnitText(caseDetail.ageunit) }}</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">{{ getBloodTypeText(caseDetail.bloodType) }}</text>
|
</view>
|
<view class="info-item">
|
<text class="label">民族</text>
|
<text class="value">{{ caseDetail.nation || '未填写' }}</text>
|
</view>
|
<view class="info-item">
|
<text class="label">国籍</text>
|
<text class="value">{{ caseDetail.nationality || '未填写' }}</text>
|
</view>
|
<view class="info-item">
|
<text class="label">籍贯</text>
|
<text class="value">{{ caseDetail.nativeplace || '未填写' }}</text>
|
</view>
|
<view class="info-item">
|
<text class="label">学历</text>
|
<text class="value">{{ caseDetail.education || '未填写' }}</text>
|
</view>
|
<view class="info-item">
|
<text class="label">职业</text>
|
<text class="value">{{ caseDetail.occupation || '未填写' }}</text>
|
</view>
|
<view class="info-item full-width">
|
<text class="label">户籍地址</text>
|
<text class="value">{{ getFullRegisterAddress() || '未填写' }}</text>
|
</view>
|
<view class="info-item full-width">
|
<text class="label">现住地址</text>
|
<text class="value">{{ getFullResidenceAddress() || '未填写' }}</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.diagnosisname || '未填写' }}</text>
|
</view>
|
<view class="info-group">
|
<text class="group-title">病情概况</text>
|
<text class="group-content">{{ caseDetail.illnessoverview || '未填写' }}</text>
|
</view>
|
<view class="info-group">
|
<text class="group-title">病人状况</text>
|
<text class="group-content">{{ caseDetail.patientstate || '未填写' }}</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">GCS评分</text>
|
<text class="group-content">{{ caseDetail.gcsScore || '未评估' }}</text>
|
</view>
|
<view class="info-group">
|
<text class="group-title">传染病情况</text>
|
<text class="group-content">{{ caseDetail.infectious || '无' }}{{ caseDetail.infectiousOther ? `(${caseDetail.infectiousOther})` : '' }}</text>
|
</view>
|
<view class="info-group">
|
<text class="group-title">Rh阴性</text>
|
<text class="group-content">{{ caseDetail.rhYin === '1' ? '是' : '否' }}</text>
|
</view>
|
</view>
|
</view>
|
</view>
|
|
<!-- 医院与联系信息 -->
|
<view v-if="activeTab === 'contact'" 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 full-width">
|
<text class="label">治疗医院</text>
|
<text class="value">{{ caseDetail.treatmenthospitalname || '未填写' }}</text>
|
</view>
|
<view class="info-item">
|
<text class="label">治疗科室</text>
|
<text class="value">{{ caseDetail.treatmentdeptname || '未填写' }}</text>
|
</view>
|
<view class="info-item">
|
<text class="label">上报医院</text>
|
<text class="value">{{ caseDetail.toHospital || '未填写' }}</text>
|
</view>
|
<view class="info-item full-width">
|
<text class="label">联系电话</text>
|
<text class="value">{{ caseDetail.phone || '未填写' }}</text>
|
</view>
|
<view class="info-item">
|
<text class="label">信息员</text>
|
<text class="value">{{ caseDetail.infoName || '未填写' }}</text>
|
</view>
|
<view class="info-item">
|
<text class="label">信息员编号</text>
|
<text class="value">{{ caseDetail.infoNo || '未填写' }}</text>
|
</view>
|
<view class="info-item">
|
<text class="label">报告者</text>
|
<text class="value">{{ caseDetail.reportername || '未填写' }}</text>
|
</view>
|
<view class="info-item">
|
<text class="label">报告者电话</text>
|
<text class="value">{{ caseDetail.reporterphone || '未填写' }}</text>
|
</view>
|
<view class="info-item">
|
<text class="label">协调员</text>
|
<text class="value">{{ caseDetail.coordinatorName || '未填写' }}</text>
|
</view>
|
<view class="info-item">
|
<text class="label">协调员编号</text>
|
<text class="value">{{ caseDetail.coordinatorNo || '未填写' }}</text>
|
</view>
|
</view>
|
</view>
|
</view>
|
|
<!-- 转运信息 -->
|
<view v-if="activeTab === 'transport'" class="info-section fade-in-up">
|
<view class="section-card">
|
<view class="section-header">
|
<view style="display: flex; justify-content: space-between; align-items: center;">
|
<text class="section-title">转运信息</text>
|
<!-- 转运操作按钮 -->
|
<view v-if="caseDetail.reportStatus === '3'" style="display: flex; gap: 20rpx;">
|
<button
|
v-if="caseDetail.isTransport === '2' && !hasTransport"
|
class="small-btn primary"
|
@tap.stop="createTransport"
|
>
|
创建转运单
|
</button>
|
<button
|
v-if="hasTransport"
|
class="small-btn secondary"
|
@tap.stop="viewTransportDetail"
|
>
|
查看转运单
|
</button>
|
</view>
|
</view>
|
</view>
|
|
<view class="info-content">
|
<view class="info-group">
|
<text class="group-title">是否需要转运</text>
|
<text class="group-content">{{ caseDetail.isTransport === '2' ? '需要' : '不需要' }}</text>
|
</view>
|
|
<!-- 有转运信息时显示 -->
|
<view v-if="hasTransport && caseDetail.serviceTransport" class="transport-info">
|
<view class="info-group" v-for="transport in caseDetail.serviceTransport" :key="transport.id">
|
<view class="sub-group">
|
<text class="sub-label">转运单号:</text>
|
<text class="sub-value">{{ transport.reportId || transport.id }}</text>
|
</view>
|
<view class="sub-group">
|
<text class="sub-label">出发地点:</text>
|
<text class="sub-value">{{ transport.transportStartPlace }}</text>
|
</view>
|
<view class="sub-group">
|
<text class="sub-label">出发时间:</text>
|
<text class="sub-value">{{ formatDateTime(transport.transportStartTime) }}</text>
|
</view>
|
<view class="sub-group">
|
<text class="sub-label">负责协调员:</text>
|
<text class="sub-value">{{ transport.contactPerson }}</text>
|
</view>
|
<view class="sub-group">
|
<text class="sub-label">转运状态:</text>
|
<text class="sub-value status" :class="getTransportStatusClass(transport.transitStatus)">
|
{{ getTransportStatusText(transport.transitStatus) }}
|
</text>
|
</view>
|
<view class="sub-group" v-if="transport.doctor">
|
<text class="sub-label">急诊科医生:</text>
|
<text class="sub-value">{{ transport.doctor }}</text>
|
</view>
|
<view class="sub-group" v-if="transport.nurse">
|
<text class="sub-label">护士:</text>
|
<text class="sub-value">{{ transport.nurse }}</text>
|
</view>
|
<view class="sub-group" v-if="transport.driver">
|
<text class="sub-label">驾驶员:</text>
|
<text class="sub-value">{{ transport.driver }}</text>
|
</view>
|
<view class="sub-group" v-if="transport.icuDoctor">
|
<text class="sub-label">ICU评估医生:</text>
|
<text class="sub-value">{{ transport.icuDoctor }}</text>
|
</view>
|
</view>
|
</view>
|
|
<!-- 无转运信息但需要转运 -->
|
<view v-else-if="caseDetail.isTransport === '2'" class="transport-info">
|
<view class="empty-transport">
|
<text>该案例需要转运,但尚未创建转运单</text>
|
<text v-if="caseDetail.reportStatus !== '3'" style="color: #f0ad4e; font-size: 24rpx; margin-top: 10rpx;">
|
需先审批同意才能创建转运单
|
</text>
|
</view>
|
</view>
|
|
<!-- 无需转运 -->
|
<view v-else class="transport-info">
|
<view class="empty-transport">
|
<text>该案例无需转运</text>
|
</view>
|
</view>
|
</view>
|
</view>
|
</view>
|
|
<!-- 操作按钮 -->
|
<view class="action-bar">
|
<button class="action-btn secondary" @tap="goBack">返回</button>
|
|
<!-- 根据状态显示不同操作 -->
|
<button v-if="caseDetail.reportStatus === '1' || caseDetail.reportStatus === '2'"
|
class="action-btn primary"
|
@tap="handleEdit">
|
编辑案例
|
</button>
|
|
<!-- <button v-if="canDelete"
|
class="action-btn error"
|
@tap="handleDelete">
|
删除案例
|
</button> -->
|
</view>
|
|
<!-- 加载状态 -->
|
<u-loading-icon v-if="loading" :show="loading" text="加载中..." />
|
</view>
|
</template>
|
|
<script setup>
|
import { ref, computed, onMounted } from 'vue'
|
import { onLoad } from '@dcloudio/uni-app'
|
import { useDict } from "@/utils/dict"
|
|
// 字典数据
|
const dict = ref({})
|
|
// 数据
|
const caseDetail = ref({})
|
const loading = ref(false)
|
const activeTab = ref('basic')
|
const caseId = ref(null)
|
|
// 选项卡
|
const tabs = ref([
|
{ id: 'basic', label: '基本信息' },
|
{ id: 'medical', label: '医疗信息' },
|
{ id: 'contact', label: '联系信息' },
|
{ id: 'transport', label: '转运信息' }
|
])
|
|
// 计算属性
|
const hasTransport = computed(() => {
|
return caseDetail.value.serviceTransport
|
})
|
|
const canDelete = computed(() => {
|
// 允许删除未审批或已驳回的案例
|
return caseDetail.value.reportStatus === '1' ||
|
caseDetail.value.reportStatus === '2' ||
|
caseDetail.value.reportStatus === '4'
|
})
|
|
onLoad(async (options) => {
|
if (options.id) {
|
caseId.value = options.id
|
// 获取字典数据
|
dict.value = await useDict(
|
"sys_user_sex",
|
"sys_BloodType",
|
"sys_IDType",
|
"sys_AgeUnit"
|
)
|
// 加载案例详情
|
await loadCaseDetail(options.id)
|
}
|
})
|
|
// 加载案例详情
|
const loadCaseDetail = async (id) => {
|
loading.value = true
|
try {
|
const res = await uni.$uapi.get(`/project/donatebaseinforeport/getInfo/${id}`)
|
|
if (res.data) {
|
caseDetail.value = res.data
|
|
// 如果状态是"已上报"(1),自动更新为"已阅读"(2)
|
if (caseDetail.value.reportStatus === '1') {
|
await updateCaseStatus('2')
|
}
|
} else {
|
throw new Error(res.msg || '数据加载失败')
|
}
|
} catch (error) {
|
console.error('加载案例详情失败:', error)
|
uni.showToast({
|
title: '数据加载失败,请重试',
|
icon: 'none'
|
})
|
} finally {
|
loading.value = false
|
}
|
}
|
|
// 更新案例状态
|
const updateCaseStatus = async (newStatus) => {
|
try {
|
const updateData = {
|
...caseDetail.value,
|
reportStatus: newStatus,
|
updateTime: new Date().toISOString().replace('T', ' ').substring(0, 19),
|
updateBy: '移动端用户'
|
}
|
|
const res = await uni.$uapi.post("/project/donatebaseinforeport/edit", updateData)
|
|
if (res.code === 200) {
|
caseDetail.value.reportStatus = newStatus
|
}
|
} catch (error) {
|
console.error('更新状态失败:', error)
|
}
|
}
|
|
// 获取状态样式
|
const getStatusClass = (status) => {
|
const map = {
|
'1': 'reported',
|
'2': 'read',
|
'3': 'agreed',
|
'4': 'rejected'
|
}
|
return map[status] || 'reported'
|
}
|
|
// 获取状态文本
|
const getStatusText = (status) => {
|
const map = {
|
'1': '已上报',
|
'2': '已阅读',
|
'3': '已同意',
|
'4': '已驳回'
|
}
|
return map[status] || '已上报'
|
}
|
|
// 获取性别文本
|
const getGenderText = (gender) => {
|
if (!dict.value.sys_user_sex) return gender
|
const genderItem = dict.value.sys_user_sex.find(item => item.dictValue === gender)
|
return genderItem ? genderItem.dictLabel : gender
|
}
|
|
// 获取血型文本
|
const getBloodTypeText = (bloodType) => {
|
if (!dict.value.sys_BloodType) return bloodType
|
const bloodTypeItem = dict.value.sys_BloodType.find(item => item.dictValue === bloodType)
|
return bloodTypeItem ? bloodTypeItem.dictLabel : bloodType
|
}
|
|
// 获取年龄单位文本
|
const getAgeUnitText = (ageunit) => {
|
if (!ageunit) return ''
|
const unitMap = {
|
'year': '岁',
|
'month': '个月',
|
'day': '天'
|
}
|
return unitMap[ageunit] || ageunit
|
}
|
|
// 获取完整户籍地址
|
const getFullRegisterAddress = () => {
|
const {
|
registerprovincename,
|
registercityname,
|
registertownname,
|
registercommunityname,
|
registeraddress
|
} = caseDetail.value
|
|
const parts = [
|
registerprovincename,
|
registercityname,
|
registertownname,
|
registercommunityname,
|
registeraddress
|
]
|
return parts.filter(part => part).join('')
|
}
|
|
// 获取完整现住地址
|
const getFullResidenceAddress = () => {
|
const {
|
residenceprovincename,
|
residencecountyname,
|
residencetownname,
|
residencecommunityname,
|
residenceaddress
|
} = caseDetail.value
|
|
const parts = [
|
residenceprovincename,
|
residencecountyname,
|
residencetownname,
|
residencecommunityname,
|
residenceaddress
|
]
|
return parts.filter(part => part).join('')
|
}
|
|
// 获取转运状态文本
|
const getTransportStatusText = (status) => {
|
const map = {
|
1: '待转运',
|
2: '转运中',
|
3: '转运完成',
|
4: '转运取消',
|
5: '暂存'
|
}
|
return map[status] || '未知'
|
}
|
|
// 获取转运状态样式
|
const getTransportStatusClass = (status) => {
|
const map = {
|
1: 'pending',
|
2: 'transporting',
|
3: 'completed',
|
4: 'cancelled',
|
5: 'draft'
|
}
|
return map[status] || 'pending'
|
}
|
|
// 格式化日期时间
|
const formatDateTime = (dateTime) => {
|
if (!dateTime) return ''
|
return dateTime.replace('T', ' ').substring(0, 16)
|
}
|
|
// 选项卡切换
|
const switchTab = (tabId) => {
|
activeTab.value = tabId
|
}
|
|
// 返回
|
const goBack = () => {
|
uni.navigateBack()
|
}
|
|
// 编辑案例
|
const handleEdit = () => {
|
uni.navigateTo({
|
url: `/pages/case/CaseDetails?id=${caseId.value}&edit=true`
|
})
|
}
|
|
|
|
// 删除案例
|
const handleDelete = () => {
|
uni.showModal({
|
title: '确认删除',
|
content: `确定要删除案例 ${caseDetail.value.caseNo} 吗?`,
|
success: async (res) => {
|
if (res.confirm) {
|
try {
|
const result = await uni.$uapi.delete(`/project/donatebaseinforeport/${caseId.value}`)
|
if (result.code === 200) {
|
uni.showToast({ title: '删除成功', icon: 'success' })
|
setTimeout(() => {
|
uni.navigateBack()
|
}, 1500)
|
} else {
|
uni.showToast({ title: result.msg || '删除失败', icon: 'none' })
|
}
|
} catch (error) {
|
console.error('删除失败:', error)
|
uni.showToast({ title: '删除失败', icon: 'none' })
|
}
|
}
|
}
|
})
|
}
|
|
// 创建转运单
|
const createTransport = () => {
|
if (caseDetail.value.reportStatus !== '3') {
|
uni.showToast({ title: '案例需先审批同意', icon: 'none' })
|
return
|
}
|
|
uni.navigateTo({
|
url: `/pages/transport/create?caseId=${caseId.value}&caseNo=${caseDetail.value.caseNo}`
|
})
|
}
|
|
// 查看转运单详情
|
const viewTransportDetail = () => {
|
if (hasTransport.value && caseDetail.value.serviceTransport[0]) {
|
const transport = caseDetail.value.serviceTransport[0]
|
uni.navigateTo({
|
url: `/pages/transport/detail?id=${transport.id}`
|
})
|
}
|
}
|
</script>
|
|
<style lang="scss" scoped>
|
.case-detail {
|
min-height: 100vh;
|
background: linear-gradient(135deg, #fafdff 0%, #e3f0ff 100%);
|
padding: 20rpx;
|
padding-bottom: 120rpx; /* 为操作栏留出空间 */
|
}
|
|
.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;
|
background: #f5f5f7;
|
}
|
|
.hospital-details {
|
display: flex;
|
flex-direction: column;
|
}
|
|
.hospital-name {
|
font-size: 32rpx;
|
font-weight: 600;
|
color: #1d1d1f;
|
margin-bottom: 8rpx;
|
max-width: 400rpx;
|
overflow: hidden;
|
text-overflow: ellipsis;
|
white-space: nowrap;
|
}
|
|
.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;
|
}
|
|
&.rejected {
|
background: rgba(255, 59, 48, 0.1);
|
color: #ff3b30;
|
}
|
}
|
|
.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);
|
overflow-x: auto;
|
white-space: nowrap;
|
|
&::-webkit-scrollbar {
|
display: none;
|
}
|
}
|
|
.tab-item {
|
flex: 1;
|
min-width: 140rpx;
|
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;
|
word-break: break-all;
|
}
|
}
|
|
.info-content {
|
.info-group {
|
margin-bottom: 32rpx;
|
padding-bottom: 20rpx;
|
border-bottom: 1rpx solid #f0f0f0;
|
|
&:last-child {
|
margin-bottom: 0;
|
padding-bottom: 0;
|
border-bottom: none;
|
}
|
}
|
|
.group-title {
|
font-size: 26rpx;
|
color: #86868b;
|
margin-bottom: 12rpx;
|
display: block;
|
font-weight: 500;
|
}
|
|
.group-content {
|
font-size: 28rpx;
|
color: #1d1d1f;
|
line-height: 1.6;
|
}
|
}
|
|
/* 转运信息样式 */
|
.transport-info {
|
.info-group {
|
border: 2rpx solid #f0f0f0;
|
border-radius: 12rpx;
|
padding: 20rpx;
|
margin-bottom: 20rpx;
|
background: #fafafa;
|
|
&:last-child {
|
margin-bottom: 0;
|
}
|
}
|
|
.sub-group {
|
display: flex;
|
margin-bottom: 12rpx;
|
align-items: center;
|
|
&:last-child {
|
margin-bottom: 0;
|
}
|
}
|
|
.sub-label {
|
font-size: 26rpx;
|
color: #606266;
|
min-width: 160rpx;
|
margin-right: 10rpx;
|
}
|
|
.sub-value {
|
font-size: 26rpx;
|
color: #303133;
|
flex: 1;
|
|
&.status {
|
padding: 4rpx 12rpx;
|
border-radius: 6rpx;
|
font-size: 24rpx;
|
|
&.pending {
|
background: rgba(240, 173, 78, 0.1);
|
color: #f0ad4e;
|
}
|
|
&.transporting {
|
background: rgba(0, 122, 255, 0.1);
|
color: #007aff;
|
}
|
|
&.completed {
|
background: rgba(76, 217, 100, 0.1);
|
color: #4cd964;
|
}
|
|
&.cancelled {
|
background: rgba(220, 223, 230, 0.1);
|
color: #dcdfe6;
|
}
|
|
&.draft {
|
background: rgba(144, 147, 153, 0.1);
|
color: #909399;
|
}
|
}
|
}
|
|
.empty-transport {
|
text-align: center;
|
padding: 40rpx 0;
|
color: #909399;
|
font-size: 28rpx;
|
}
|
}
|
|
/* 小型按钮 */
|
.small-btn {
|
padding: 8rpx 20rpx;
|
font-size: 24rpx;
|
border-radius: 6rpx;
|
border: none;
|
|
&.primary {
|
background: #007aff;
|
color: #fff;
|
}
|
|
&.secondary {
|
background: #ecf5ff;
|
color: #007aff;
|
border: 1rpx solid #007aff;
|
}
|
|
&:active {
|
opacity: 0.8;
|
}
|
}
|
|
.action-bar {
|
display: flex;
|
gap: 20rpx;
|
padding: 20rpx 0;
|
background: #fff;
|
position: fixed;
|
bottom: 0;
|
left: 0;
|
right: 0;
|
padding: 20rpx 30rpx;
|
padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
|
box-shadow: 0 -2rpx 20rpx rgba(0, 0, 0, 0.08);
|
z-index: 100;
|
}
|
|
.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);
|
}
|
}
|
|
&.success {
|
background: linear-gradient(90deg, #34c759 0%, #4cd964 100%);
|
color: #fff;
|
|
&:active {
|
transform: scale(0.98);
|
}
|
}
|
|
&.error {
|
background: linear-gradient(90deg, #ff3b30 0%, #ff5a5a 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>
|