366 lines
9.8 KiB
Vue
366 lines
9.8 KiB
Vue
<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">
|
||
<image src="https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/empty/orders.png" mode="aspectFit" @error="handleImageError"></image>
|
||
<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">
|
||
<text class="iconfont icon-mendian"></text>
|
||
</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' })
|
||
// 跳转到咨询页面,直接使用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)
|
||
} else {
|
||
uni.showToast({ title: response.data.message, icon: 'none' })
|
||
}
|
||
} catch (e) {
|
||
console.error('同意转诊异常:', e)
|
||
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> |