Files
xk-client-wx/subPackages/transfer/transfer-message.vue

366 lines
9.8 KiB
Vue
Raw Normal View History

2026-02-07 09:42:08 +08:00
<template>
<view class="container safe-area-inset-bottom">
<view class="header">
<text class="title">转诊消息</text>
</view>
<!-- 空页:仅在非加载中且列表为空时显示 -->
<view class="empty" v-if="!loading && transferList.length === 0">
2026-05-15 16:42:32 +08:00
<image src="https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/empty/orders.png" mode="aspectFit" @error="handleImageError"></image>
2026-02-07 09:42:08 +08:00
<view class="word">暂无转诊消息~</view>
</view>
<!-- 转诊消息列表 -->
<!-- 修复:使用显式 v-if 替代 v-else,确保逻辑清晰 -->
<view class="list-container" v-if="transferList.length > 0">
<!-- 修复::key 绑定改为简单的 item.id,解决 wx:key 警告 -->
<view class="list-item" v-for="(item, index) in transferList" :key="item.id">
<view class="card">
<view class="card-header">
<view class="header-icon">
2026-02-07 13:02:15 +08:00
<text class="iconfont icon-mendian"></text>
2026-02-07 09:42:08 +08:00
</view>
<view class="header-title">转诊处方</view>
<!-- 修复:不直接调用方法,而是使用预处理好的属性 -->
<view class="status-tag" :class="item.statusClass">
{{ item.statusText }}
</view>
</view>
<view class="card-body">
<view class="info-row" v-if="item.transfer_store">
<view class="info-label">转诊诊所:</view>
<view class="info-value">{{ item.transfer_store.name || '未知诊所' }}</view>
</view>
<view class="info-row" v-if="item.delegate_store">
<view class="info-label">委托诊所:</view>
<view class="info-value">{{ item.delegate_store.name || '未知诊所' }}</view>
</view>
<view class="info-row" v-if="item.prescription_no">
<view class="info-label">处方编号:</view>
<view class="info-value">{{ item.prescription_no }}</view>
</view>
<view class="info-row" v-if="item.transfer_time">
<view class="info-label">转诊时间:</view>
<!-- 优化:同样使用预处理的时间字符串 -->
<view class="info-value">{{ item.transferTimeStr }}</view>
</view>
</view>
<!-- 仅在待确认状态显示操作按钮 -->
<view class="card-footer" v-if="item.status === 0">
<button class="reject-btn" @click="handleReject(item)">拒绝转诊</button>
<button class="agree-btn" @click="handleAgree(item)">同意转诊</button>
</view>
</view>
</view>
</view>
<view v-if="transferList.length > 0" class="loadmore">
<u-loadmore :status="status" />
</view>
</view>
</template>
<script>
import {
getTransferPrescriptionListApi,
agreeTransferPrescriptionApi,
rejectTransferPrescriptionApi
} from '@/request/api/transferPrescription'
export default {
data() {
return {
transferList: [],
loading: false,
status: 'nomore',
page: 1
}
},
onLoad() {
this.getTransferList()
},
// 如下拉刷新等场景可增加
onPullDownRefresh() {
this.getTransferList().finally(() => {
uni.stopPullDownRefresh()
})
},
methods: {
getStatusText(status) {
const statusMap = {
0: '待确认',
1: '已确认',
2: '已导入',
3: '已取消'
}
return statusMap[status] || '未知'
},
getStatusClass(status) {
const classMap = {
0: 'status-pending',
1: 'status-confirmed',
2: 'status-imported',
3: 'status-cancelled'
}
return classMap[status] || ''
},
formatTransferTime(time) {
if (!time) return '未知时间'
// 兼容时间戳(秒级)
if (!isNaN(time) && typeof time !== 'object') {
const date = new Date(Number(time) * 1000)
const y = date.getFullYear()
const m = String(date.getMonth() + 1).padStart(2, '0')
const d = String(date.getDate()).padStart(2, '0')
const h = String(date.getHours()).padStart(2, '0')
const mm = String(date.getMinutes()).padStart(2, '0')
return `${y}-${m}-${d} ${h}:${mm}`
}
return time
},
async getTransferList() {
this.loading = true
try {
const res = await getTransferPrescriptionListApi()
// 关键:请确认 res.data.result 是否为数组
// 如果后端返回的是 res.data.data,请修改此处
if (res.data && res.data.code === 0) {
const list = res.data.result || []
// 核心修复:预处理数据,直接将 class 和 text 计算好放入 item 中
// 避免在 template 中使用函数调用导致小程序渲染异常
this.transferList = Array.isArray(list) ? list.map(item => {
return {
...item,
statusClass: this.getStatusClass(item.status),
statusText: this.getStatusText(item.status),
transferTimeStr: this.formatTransferTime(item.transfer_time)
}
}) : []
console.log('转诊列表加载成功:', this.transferList)
} else {
throw new Error(res.data.message || '获取数据失败')
}
} catch (error) {
console.error('获取转诊列表异常:', error)
uni.showToast({
title: error.message || '网络异常',
icon: 'none'
})
} finally {
this.loading = false
}
},
handleAgree(item) {
uni.showModal({
title: '提示',
content: '确定要同意该转诊申请吗?',
confirmColor: '#f97316',
success: async (res) => {
if (res.confirm) {
try {
const response = await agreeTransferPrescriptionApi({ id: item.id })
if (response.data.code === 0) {
uni.showToast({ title: '已同意', icon: 'success' })
2026-02-07 11:12:18 +08:00
// 跳转到咨询页面,直接使用transfer_id传参
setTimeout(() => {
uni.redirectTo({
url: `/subPackages/transfer/transfer-consultation?transfer_id=${item.id}`,
fail: (err) => {
console.error('跳转失败:', err)
uni.showToast({ title: '跳转失败,请重试', icon: 'none' })
}
})
}, 1000)
2026-02-07 09:42:08 +08:00
} else {
uni.showToast({ title: response.data.message, icon: 'none' })
}
} catch (e) {
2026-02-07 11:12:18 +08:00
console.error('同意转诊异常:', e)
2026-02-07 09:42:08 +08:00
uni.showToast({ title: '操作失败', icon: 'none' })
}
}
}
})
},
handleReject(item) {
uni.showModal({
title: '提示',
content: '确定要拒绝该转诊申请吗?',
confirmColor: '#64748b',
success: async (res) => {
if (res.confirm) {
try {
const response = await rejectTransferPrescriptionApi({ id: item.id })
if (response.data.code === 0) {
uni.showToast({ title: '已拒绝', icon: 'success' })
this.getTransferList()
} else {
uni.showToast({ title: response.data.message, icon: 'none' })
}
} catch (e) {
uni.showToast({ title: '操作失败', icon: 'none' })
}
}
}
})
},
handleImageError(e) {
console.error('图片加载失败', e)
}
}
}
</script>
<style lang="scss" scoped>
.container {
width: 100%;
min-height: 100vh;
background-color: #F8FAFC;
padding: 30rpx;
box-sizing: border-box;
}
.header {
margin-bottom: 30rpx;
.title {
font-size: 36rpx;
font-weight: bold;
color: #1e293b;
}
}
.empty {
padding-top: 200rpx;
text-align: center;
image {
width: 240rpx;
height: 240rpx;
}
.word {
margin-top: 20rpx;
color: #94a3b8;
font-size: 28rpx;
}
}
/* 确保列表容器有宽度,防止塌陷 */
.list-container {
width: 100%;
}
.list-item {
margin-bottom: 30rpx;
width: 100%;
}
.card {
background: #ffffff;
border-radius: 20rpx;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
overflow: hidden;
border: 1rpx solid #f1f5f9;
}
.card-header {
display: flex;
align-items: center;
padding: 24rpx 30rpx;
background: #fff;
border-bottom: 1rpx solid #f1f5f9;
}
.header-icon {
width: 48rpx;
height: 48rpx;
background: #fff7ed;
border-radius: 8rpx;
display: flex;
align-items: center;
justify-content: center;
margin-right: 16rpx;
.iconfont {
color: #f97316;
font-size: 28rpx;
}
}
.header-title {
flex: 1;
font-size: 30rpx;
font-weight: 600;
color: #334155;
}
.status-tag {
padding: 6rpx 16rpx;
border-radius: 8rpx;
font-size: 22rpx;
}
.status-pending { background: #fef3c7; color: #d97706; }
.status-confirmed { background: #dcfce7; color: #16a34a; }
.status-imported { background: #dbeafe; color: #2563eb; }
.status-cancelled { background: #f1f5f9; color: #64748b; }
.card-body {
padding: 20rpx 30rpx;
}
.info-row {
display: flex;
padding: 12rpx 0;
font-size: 28rpx;
line-height: 1.4;
}
.info-label {
color: #64748b;
width: 150rpx;
flex-shrink: 0;
}
.info-value {
color: #1e293b;
word-break: break-all;
}
.card-footer {
padding: 24rpx 30rpx;
display: flex;
justify-content: flex-end;
gap: 20rpx;
border-top: 1rpx solid #f1f5f9;
background: #fafafa;
}
.agree-btn, .reject-btn {
margin: 0;
padding: 0 36rpx;
height: 64rpx;
line-height: 64rpx;
font-size: 26rpx;
border-radius: 32rpx;
}
.agree-btn {
background: #f97316;
color: #fff;
}
.reject-btn {
background: #fff;
color: #64748b;
border: 1rpx solid #cbd5e1;
}
.loadmore {
padding: 30rpx 0;
}
</style>