| | |
| | | <view class="header"> |
| | | <view class="case-info"> |
| | | <view class="info"> |
| | | <text class="case-no">{{ item.caseNo }}</text> |
| | | <text class="case-no">{{ item.caseNo || item.reportId }}</text> |
| | | <text class="patient" |
| | | >{{ item.donorName }} | {{ item.gender }} | |
| | | >{{ item.patName }} | {{ getGenderText(item.sex) }} | |
| | | {{ item.age }}岁</text |
| | | > |
| | | </view> |
| | | </view> |
| | | <text class="status" :class="item.status">{{ item.statusText }}</text> |
| | | <text class="status" :class="getStatusClass(item.transitStatus)">{{ |
| | | getStatusText(item.transitStatus) |
| | | }}</text> |
| | | </view> |
| | | |
| | | <view class="detail-info"> |
| | | <view class="info-item"> |
| | | <text class="label">疾病诊断</text> |
| | | <text class="value">{{ item.diagnosis }}</text> |
| | | <text class="value">{{ item.diagnosisname || "未填写" }}</text> |
| | | </view> |
| | | <view class="info-item"> |
| | | <text class="label">所在医疗机构</text> |
| | | <text class="value">{{ item.hospitalName }}</text> |
| | | <text class="value">{{ |
| | | item.treatmentHospitalName || "未填写" |
| | | }}</text> |
| | | </view> |
| | | <view class="info-item"> |
| | | <text class="label">计划转运时间</text> |
| | | <text class="value">{{ item.transportTime }}</text> |
| | | <text class="value">{{ formatTime(item.transportStartTime) }}</text> |
| | | </view> |
| | | <view class="info-item"> |
| | | <text class="label">负责协调员</text> |
| | | <text class="value">{{ item.coordinator }}</text> |
| | | <text class="value">{{ item.contactPerson || "未指定" }}</text> |
| | | </view> |
| | | <view class="info-item"> |
| | | <text class="label">创建时间</text> |
| | | <text class="value">{{ item.createTime }}</text> |
| | | <text class="value">{{ formatTime(item.createTime) }}</text> |
| | | </view> |
| | | </view> |
| | | |
| | | <view class="footer"> |
| | | <view class="action-info"> |
| | | <text class="label">转运状态</text> |
| | | <text class="transport-status">{{ item.statusText }}</text> |
| | | <text class="transport-status">{{ |
| | | getStatusText(item.transitStatus) |
| | | }}</text> |
| | | </view> |
| | | <view class="actions"> |
| | | <button |
| | | class="action-btn" |
| | | v-if="item.status === 'pending'" |
| | | v-if="item.transitStatus === 1" |
| | | @tap.stop="startTransport(item)" |
| | | > |
| | | 开始转运 |
| | | </button> |
| | | <button |
| | | class="action-btn" |
| | | v-if="item.status === 'transporting'" |
| | | v-if="item.transitStatus === 2" |
| | | @tap.stop="completeTransport(item)" |
| | | > |
| | | 完成转运 |
| | | </button> |
| | | <button |
| | | class="action-btn secondary" |
| | | v-if="item.transitStatus === 1 || item.transitStatus === 5" |
| | | @tap.stop="editTransport(item)" |
| | | > |
| | | 编辑 |
| | |
| | | </view> |
| | | |
| | | <!-- 加载更多 --> |
| | | <view class="load-more" v-if="hasMore"> |
| | | <text>加载中...</text> |
| | | <view class="load-more" v-if="loading"> |
| | | <u-loading-icon text="加载中..."></u-loading-icon> |
| | | </view> |
| | | |
| | | <!-- 空状态 --> |
| | | <view class="empty-state" v-if="filteredTransports.length === 0"> |
| | | <view |
| | | class="empty-state" |
| | | v-if="!loading && filteredTransports.length === 0" |
| | | > |
| | | <image src="/static/empty/no-transport.png" mode="aspectFit" /> |
| | | <text>暂无转运单记录</text> |
| | | </view> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, computed } from "vue"; |
| | | import { onLoad } from "@dcloudio/uni-app"; |
| | | import { ref, computed, onMounted } from "vue"; |
| | | import { onLoad, onShow } from "@dcloudio/uni-app"; |
| | | import { useDict } from "@/utils/dict"; |
| | | |
| | | // 字典数据 |
| | | const dict = ref({}); |
| | | |
| | | // 统计数据 |
| | | const stats = ref({ |
| | | totalTransports: 12, |
| | | pendingTransports: 4, |
| | | completedTransports: 6, |
| | | totalTransports: 0, |
| | | pendingTransports: 0, |
| | | completedTransports: 0, |
| | | }); |
| | | |
| | | // 转运单数据 |
| | | const transports = ref([]); |
| | | const loading = ref(false); |
| | | const refreshing = ref(false); |
| | | const hasMore = ref(true); |
| | | const pageNum = ref(1); |
| | | const pageSize = ref(10); |
| | | |
| | | // 操作确认弹窗相关 |
| | | const showActionModal = ref(false); |
| | | const currentTransport = ref({}); |
| | | const modalTitle = ref(""); |
| | | const modalAction = ref(""); |
| | | |
| | | onLoad(async (options) => { |
| | | // 初始化数据 |
| | | loadTransports(); |
| | | }); |
| | | |
| | | // 筛选相关 |
| | | const transportTypes = [ |
| | | { label: "全部", value: "all" }, |
| | | { label: "待出发", value: "pending" }, |
| | | { label: "转运中", value: "transporting" }, |
| | | { label: "已完成", value: "completed" }, |
| | | { label: "已取消", value: "cancelled" }, |
| | | { label: "全部", value: "" }, |
| | | { label: "待转运", value: 1 }, |
| | | { label: "转运中", value: 2 }, |
| | | { label: "已完成", value: 3 }, |
| | | { label: "已取消", value: 4 }, |
| | | { label: "暂存", value: 5 }, |
| | | ]; |
| | | const currentType = ref("all"); |
| | | const currentType = ref(""); |
| | | const startDate = ref(""); |
| | | const endDate = ref(""); |
| | | |
| | | // 转运单数据 |
| | | const transports = ref([ |
| | | { |
| | | id: "T20241217001", |
| | | caseNo: "DON20241216001", |
| | | donorName: "张三", |
| | | gender: "男", |
| | | age: 38, |
| | | diagnosis: "脑外伤导致脑死亡", |
| | | hospitalName: "青岛镜湖医院", |
| | | transportTime: "2024-12-17 14:30", |
| | | coordinator: "张医生", |
| | | createTime: "2024-12-16 09:30", |
| | | status: "pending", |
| | | statusText: "待出发", |
| | | departureLocation: "青岛市立医院急诊科", |
| | | destinationHospital: "青岛镜湖医院", |
| | | }, |
| | | { |
| | | id: "T20241217002", |
| | | caseNo: "DON20241216002", |
| | | donorName: "李四", |
| | | gender: "女", |
| | | age: 45, |
| | | diagnosis: "脑梗死", |
| | | hospitalName: "青岛大学附属医院", |
| | | transportTime: "2024-12-17 16:00", |
| | | coordinator: "李医生", |
| | | createTime: "2024-12-16 11:20", |
| | | status: "transporting", |
| | | statusText: "转运中", |
| | | departureLocation: "青岛大学附属医院ICU", |
| | | destinationHospital: "青岛器官移植中心", |
| | | }, |
| | | { |
| | | id: "T20241216003", |
| | | caseNo: "DON20241215001", |
| | | donorName: "王五", |
| | | gender: "男", |
| | | age: 52, |
| | | diagnosis: "心脏骤停", |
| | | hospitalName: "青岛市立医院", |
| | | transportTime: "2024-12-16 10:15", |
| | | coordinator: "王医生", |
| | | createTime: "2024-12-15 14:45", |
| | | status: "completed", |
| | | statusText: "已完成", |
| | | departureLocation: "青岛市立医院心内科", |
| | | destinationHospital: "青岛器官移植中心", |
| | | }, |
| | | { |
| | | id: "T20241216004", |
| | | caseNo: "DON20241214001", |
| | | donorName: "赵六", |
| | | gender: "女", |
| | | age: 29, |
| | | diagnosis: "急性肝衰竭", |
| | | hospitalName: "青岛科大医院", |
| | | transportTime: "2024-12-16 08:30", |
| | | coordinator: "赵医生", |
| | | createTime: "2024-12-14 16:20", |
| | | status: "cancelled", |
| | | statusText: "已取消", |
| | | departureLocation: "青岛科大医院消化科", |
| | | destinationHospital: "青岛器官移植中心", |
| | | }, |
| | | ]); |
| | | onLoad(async (options) => { |
| | | // 获取字典数据 |
| | | dict.value = await useDict("sys_user_sex"); |
| | | // 初始化数据 |
| | | loadTransports(); |
| | | // 加载统计数据 |
| | | loadStats(); |
| | | }); |
| | | |
| | | onShow(() => { |
| | | // 检查是否有转运状态更新 |
| | | const update = uni.getStorageSync("transportStatusUpdate"); |
| | | if (update) { |
| | | handleStatusUpdate(update); |
| | | uni.removeStorageSync("transportStatusUpdate"); |
| | | } |
| | | }); |
| | | |
| | | // 数据映射函数 |
| | | const mapApiDataToTransportItem = (apiData) => { |
| | | return { |
| | | id: apiData.id, |
| | | reportId: apiData.reportId, |
| | | caseNo: apiData.caseNo, |
| | | patName: apiData.patName, |
| | | sex: apiData.sex, |
| | | age: apiData.age, |
| | | diagnosisname: apiData.diagnosisname, |
| | | treatmentHospitalName: apiData.treatmentHospitalName, |
| | | transportStartTime: apiData.transportStartTime, |
| | | contactPerson: apiData.contactPerson, |
| | | createTime: apiData.createTime, |
| | | transitStatus: apiData.transitStatus, |
| | | // 医护人员信息 |
| | | doctor: apiData.doctor, |
| | | nurse: apiData.nurse, |
| | | driver: apiData.driver, |
| | | // 其他字段 |
| | | transportStartPlace: apiData.transportStartPlace, |
| | | remark: apiData.remark, |
| | | }; |
| | | }; |
| | | |
| | | // 筛选记录 |
| | | const filteredTransports = computed(() => { |
| | | let result = transports.value; |
| | | |
| | | // 状态筛选 |
| | | if (currentType.value !== "all") { |
| | | result = result.filter((item) => item.status === currentType.value); |
| | | if (currentType.value !== "") { |
| | | result = result.filter((item) => item.transitStatus === currentType.value); |
| | | } |
| | | |
| | | // 日期筛选 |
| | | if (startDate.value && endDate.value) { |
| | | result = result.filter((item) => { |
| | | const transportDate = item.createTime.split(" ")[0]; |
| | | const transportDate = item.createTime |
| | | ? item.createTime.split(" ")[0] |
| | | : ""; |
| | | return transportDate >= startDate.value && transportDate <= endDate.value; |
| | | }); |
| | | } |
| | |
| | | return result; |
| | | }); |
| | | |
| | | // 分页相关 |
| | | const hasMore = ref(true); |
| | | const refreshing = ref(false); |
| | | // 获取状态样式 |
| | | const getStatusClass = (status) => { |
| | | const map = { |
| | | 1: "pending", // 待转运 |
| | | 2: "transporting", // 转运中 |
| | | 3: "completed", // 已完成 |
| | | 4: "cancelled", // 已取消 |
| | | 5: "cancelled", // 暂存 |
| | | }; |
| | | return map[status] || "pending"; |
| | | }; |
| | | |
| | | // 获取状态文本 |
| | | const getStatusText = (status) => { |
| | | const map = { |
| | | 1: "待出发", |
| | | 2: "转运中", |
| | | 3: "已完成", |
| | | 4: "已取消", |
| | | 5: "暂存", |
| | | }; |
| | | return map[status] || "未知"; |
| | | }; |
| | | |
| | | // 获取性别文本 |
| | | const getGenderText = (gender) => { |
| | | if (!gender) return "未知"; |
| | | 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 formatTime = (timeStr) => { |
| | | if (!timeStr) return "未设置"; |
| | | return timeStr.replace("T", " ").substring(0, 16); |
| | | }; |
| | | |
| | | // 选择类型 |
| | | const selectType = (type) => { |
| | |
| | | |
| | | // 查看详情 |
| | | const viewDetail = (item) => { |
| | | viewDetails(item); |
| | | }; |
| | | |
| | | // 查看详情 |
| | | const viewDetails = (item) => { |
| | | uni.navigateTo({ |
| | | url: `/pages/transport/detail?id=${item.id}`, |
| | | }); |
| | | }; |
| | | |
| | | // 编辑转运单 |
| | | const editTransport = (item) => { |
| | | uni.navigateTo({ |
| | | url: `/pages/transport/detail?id=${item.id}&edit=true`, |
| | | }); |
| | | }; |
| | | |
| | |
| | | }; |
| | | |
| | | // 确认操作 |
| | | const confirmAction = () => { |
| | | const index = transports.value.findIndex( |
| | | (item) => item.id === currentTransport.value.id |
| | | ); |
| | | if (index !== -1) { |
| | | const confirmAction = async () => { |
| | | try { |
| | | if (modalAction.value === "开始") { |
| | | transports.value[index].status = "transporting"; |
| | | transports.value[index].statusText = "转运中"; |
| | | stats.value.pendingTransports -= 1; |
| | | await updateTransportStatus(2, "开始转运"); |
| | | } else if (modalAction.value === "完成") { |
| | | transports.value[index].status = "completed"; |
| | | transports.value[index].statusText = "已完成"; |
| | | stats.value.completedTransports += 1; |
| | | await updateTransportStatus(3, "完成转运"); |
| | | } |
| | | |
| | | uni.showToast({ |
| | | title: `${modalAction.value}成功`, |
| | | icon: "success", |
| | | }); |
| | | } catch (error) { |
| | | console.error(`${modalAction.value}失败:`, error); |
| | | uni.showToast({ |
| | | title: `${modalAction.value}失败,请重试`, |
| | | icon: "none", |
| | | }); |
| | | } finally { |
| | | showActionModal.value = false; |
| | | } |
| | | showActionModal.value = false; |
| | | }; |
| | | |
| | | // 取消操作 |
| | |
| | | showActionModal.value = false; |
| | | }; |
| | | |
| | | // 查看详情 |
| | | const viewDetails = (item) => { |
| | | uni.navigateTo({ |
| | | url: `/pages/case/transferinfo?id=${item.id}`, |
| | | }); |
| | | }; |
| | | |
| | | // 编辑转运单 |
| | | const editTransport = (item) => { |
| | | uni.navigateTo({ |
| | | url: `/pages/case/transferinfo?id=${item.id}`, |
| | | }); |
| | | }; |
| | | |
| | | // 下拉刷新 |
| | | const onRefresh = () => { |
| | | refreshing.value = true; |
| | | pageNum.value = 1; |
| | | loadTransports(); |
| | | loadStats(); |
| | | setTimeout(() => { |
| | | refreshing.value = false; |
| | | }, 1000); |
| | |
| | | |
| | | // 加载更多 |
| | | const onLoadMore = () => { |
| | | if (!hasMore.value) return; |
| | | if (!hasMore.value || loading.value) return; |
| | | pageNum.value++; |
| | | loadTransports(); |
| | | }; |
| | | |
| | | // 加载记录 |
| | | const loadTransports = async () => { |
| | | if (loading.value) return; |
| | | |
| | | // 这里调用API加载数据 |
| | | setTimeout(() => { |
| | | hasMore.value = false; |
| | | }, 1000); |
| | | loading.value = true; |
| | | try { |
| | | const params = { |
| | | pageNum: pageNum.value, |
| | | pageSize: pageSize.value, |
| | | }; |
| | | |
| | | if (currentType.value) { |
| | | params.transitStatus = currentType.value; |
| | | } |
| | | |
| | | if (startDate.value && endDate.value) { |
| | | params.startDate = startDate.value; |
| | | params.endDate = endDate.value; |
| | | } |
| | | |
| | | const res = await uni.$uapi.post("/project/transport/list", params); |
| | | |
| | | if (res) { |
| | | const data = res || []; |
| | | const mappedData = data.map((item) => mapApiDataToTransportItem(item)); |
| | | |
| | | if (pageNum.value === 1) { |
| | | transports.value = mappedData; |
| | | } else { |
| | | transports.value = [...transports.value, ...mappedData]; |
| | | } |
| | | |
| | | hasMore.value = (res.rows || []).length >= pageSize.value; |
| | | } else { |
| | | throw new Error(res.msg || "加载失败"); |
| | | } |
| | | } catch (error) { |
| | | console.error("加载转运单列表失败:", error); |
| | | uni.showToast({ |
| | | title: "网络请求失败", |
| | | icon: "none", |
| | | }); |
| | | } finally { |
| | | loading.value = false; |
| | | } |
| | | }; |
| | | |
| | | // 加载统计数据 |
| | | const loadStats = async () => { |
| | | try { |
| | | const res = await uni.$uapi.post("/api/totalServiceTransportState"); |
| | | if (res) { |
| | | stats.value = { |
| | | totalTransports: res.reduce((sum, item) => sum + item.count, 0) || 0, |
| | | pendingTransports: res[0].count || 0, |
| | | completedTransports: res[3].count || 0, |
| | | }; |
| | | } |
| | | } catch (error) { |
| | | console.error("加载统计失败:", error); |
| | | } |
| | | }; |
| | | |
| | | // 更新转运状态 |
| | | const updateTransportStatus = async (newStatus, actionName) => { |
| | | try { |
| | | const updateData = { |
| | | id: currentTransport.value.id, |
| | | transitStatus: newStatus, |
| | | }; |
| | | |
| | | const res = await uni.$uapi.post("/project/transport/edit", updateData); |
| | | |
| | | if (res.code === 200) { |
| | | // 更新本地数据 |
| | | const index = transports.value.findIndex( |
| | | (item) => item.id === currentTransport.value.id, |
| | | ); |
| | | if (index !== -1) { |
| | | transports.value[index].transitStatus = newStatus; |
| | | } |
| | | |
| | | // 更新统计数据 |
| | | await loadStats(); |
| | | |
| | | // 存储状态更新 |
| | | uni.setStorageSync("transportStatusUpdate", { |
| | | orderId: currentTransport.value.id, |
| | | status: newStatus, |
| | | }); |
| | | |
| | | return true; |
| | | } else { |
| | | throw new Error(res.msg || `${actionName}失败`); |
| | | } |
| | | } catch (error) { |
| | | console.error(`${actionName}失败:`, error); |
| | | throw error; |
| | | } |
| | | }; |
| | | |
| | | // 处理状态更新 |
| | | const handleStatusUpdate = (update) => { |
| | | const index = transports.value.findIndex( |
| | | (item) => item.id === update.orderId, |
| | | ); |
| | | if (index !== -1) { |
| | | transports.value[index].transitStatus = update.status; |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | /* 保持原有样式完全不变 */ |
| | | .transport-record { |
| | | min-height: 100vh; |
| | | background: linear-gradient(135deg, #fafdff 0%, #e3f0ff 100%); |