转诊方功能
This commit is contained in:
@@ -468,6 +468,13 @@
|
||||
"navigationBarTitleText": "在线问诊",
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "transfer/transfer-message",
|
||||
"style": {
|
||||
"navigationBarTitleText": "转诊消息",
|
||||
"enablePullDownRefresh": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -85,6 +85,32 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 转诊消息 -->
|
||||
<view class="list" @click="goTransfer">
|
||||
<!-- 头像 -->
|
||||
<view class="avator">
|
||||
<view class="img">
|
||||
<image src="/static/xx/ysxx.png" mode=""></image>
|
||||
<!-- <image src="/static/xx/zhuanzhen.png" mode=""></image>-->
|
||||
</view>
|
||||
<u-badge size="default" v-if="transfer.num>=0" :count="transfer.num" :is-dot="transfer.num==0?true:false"
|
||||
type="error" :offset="transfer.num>0?[-4,-8]:[0,0]"></u-badge>
|
||||
</view>
|
||||
<!-- 描述 -->
|
||||
<view class="info">
|
||||
<view class="infos_title">
|
||||
<text class="infos">转诊消息</text>
|
||||
<text class="time">{{ transfer.time }}</text>
|
||||
</view>
|
||||
<view class="preview" v-if="transfer.num>0">
|
||||
您有{{ transfer.num }}条转诊消息待处理
|
||||
</view>
|
||||
<view class="preview" v-if="transfer.num==undefined || transfer.num==0">
|
||||
暂无转诊消息
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 模拟<u-divider>在线问诊</u-divider>效果-->
|
||||
|
||||
<!-- 标题 - 在线咨询 -->
|
||||
@@ -157,6 +183,7 @@ import {
|
||||
} from '../../request/api/api'
|
||||
import {getSystemNoticeIndexApi} from '../../request/api/systemNotice'
|
||||
import {getChatFriendsListApi} from "@/request/api/im";
|
||||
import {getTransferPrescriptionListApi} from "@/request/api/transferPrescription";
|
||||
import {checkDev} from "@/utils/utils";
|
||||
import MessageNotification from "@/components/MessageNotification/MessageNotification.vue";
|
||||
|
||||
@@ -169,6 +196,10 @@ export default {
|
||||
order: [],
|
||||
system: [],
|
||||
doctor: [],
|
||||
transfer: {
|
||||
num: 0,
|
||||
time: ''
|
||||
},
|
||||
imChat: [],
|
||||
onlineConsultationList: [], // 在线咨询列表 (type=1)
|
||||
onlineReconsultationList: [], // 在线复诊列表 (type=3)
|
||||
@@ -258,6 +289,12 @@ export default {
|
||||
// console.log(res, 'res');
|
||||
})
|
||||
},
|
||||
// 转诊消息
|
||||
goTransfer() {
|
||||
uni.navigateTo({
|
||||
url: '/subPackages/transfer/transfer-message'
|
||||
})
|
||||
},
|
||||
goChat(item, index) {
|
||||
uni.navigateTo({
|
||||
url: `/subPackages/chat/chat?room_id=${item.room_id}&nick_name=${item.nick_name}&user_id=${item.id}&avatar=${encodeURIComponent(item.avatar || '')}&room_status=${item.room_status || 0}`
|
||||
@@ -292,10 +329,33 @@ export default {
|
||||
const allChatList = res.data.result || []
|
||||
// 根据type字段区分在线咨询和在线复诊
|
||||
this.onlineConsultationList = allChatList.filter(item => item.type === 1 || !item.type) // type=1或未设置type的为在线咨询
|
||||
this.onlineReconsultationList = allChatList.filter(item => item.type === 3) // type=3的为在线复诊
|
||||
this.onlineReconsultationList = allChatList.filter(item => (item.type === 3 || item.type === 2)) // type=3的为在线复诊
|
||||
// 保持imChat兼容性(包含所有)
|
||||
this.imChat = allChatList
|
||||
})
|
||||
},
|
||||
// 获取转诊消息列表
|
||||
getTransferList() {
|
||||
getTransferPrescriptionListApi().then((res) => {
|
||||
if (res.data && res.data.code == 0) {
|
||||
const transferList = res.data.result || []
|
||||
// 统计待确认的转诊消息数量
|
||||
const pendingCount = transferList.filter(item => item.status === 0).length
|
||||
this.transfer.num = pendingCount
|
||||
|
||||
// 获取最新的转诊时间
|
||||
if (transferList.length > 0) {
|
||||
const latestTransfer = transferList[0]
|
||||
if (latestTransfer.transfer_time) {
|
||||
this.transfer.time = latestTransfer.transfer_time
|
||||
} else if (latestTransfer.created_at) {
|
||||
this.transfer.time = latestTransfer.created_at
|
||||
}
|
||||
}
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.error('获取转诊消息列表失败:', error)
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
@@ -305,10 +365,15 @@ export default {
|
||||
this.order = []
|
||||
this.system = []
|
||||
this.doctor = []
|
||||
this.transfer = {
|
||||
num: 0,
|
||||
time: ''
|
||||
}
|
||||
this.onlineConsultationList = []
|
||||
this.onlineReconsultationList = []
|
||||
this.getInfo()
|
||||
this.getMyChatFriendsList()
|
||||
this.getTransferList()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -153,7 +153,8 @@ function request(url, params, method = 0) {
|
||||
if (url.split('/').indexOf('xkApi') !== -1) {
|
||||
baseURL = envUrls.xkApi;
|
||||
// 如果是guest模式且是xkApi请求,添加/guest/前缀(但避免重复添加)
|
||||
if (isGuestRequest && url.indexOf('/guest/') === -1) {
|
||||
// 转诊相关接口需要登录,不转换为guest路由
|
||||
if (isGuestRequest && url.indexOf('/guest/') === -1 && url.indexOf('/transfer-prescription') === -1) {
|
||||
url = url.replace('/xkApi', '/guest/xkApi');
|
||||
}
|
||||
}
|
||||
|
||||
36
request/api/transferPrescription.js
Normal file
36
request/api/transferPrescription.js
Normal file
@@ -0,0 +1,36 @@
|
||||
import {post, get} from './http'
|
||||
|
||||
/**
|
||||
* 获取转诊消息列表
|
||||
* @returns {Promise<*>}
|
||||
*/
|
||||
export async function getTransferPrescriptionListApi() {
|
||||
return await post('/transfer-prescription/list', {}, 3)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取转诊详情
|
||||
* @param params { id: number }
|
||||
* @returns {Promise<*>}
|
||||
*/
|
||||
export async function getTransferPrescriptionDetailApi(params) {
|
||||
return await get('/transfer-prescription/detail', params, 3)
|
||||
}
|
||||
|
||||
/**
|
||||
* 同意转诊
|
||||
* @param params { id: number }
|
||||
* @returns {Promise<*>}
|
||||
*/
|
||||
export async function agreeTransferPrescriptionApi(params) {
|
||||
return await post('/transfer-prescription/agree', params, 3)
|
||||
}
|
||||
|
||||
/**
|
||||
* 拒绝转诊
|
||||
* @param params { id: number, reason?: string }
|
||||
* @returns {Promise<*>}
|
||||
*/
|
||||
export async function rejectTransferPrescriptionApi(params) {
|
||||
return await post('/transfer-prescription/reject', params, 3)
|
||||
}
|
||||
@@ -202,6 +202,15 @@
|
||||
</view>
|
||||
</block>
|
||||
|
||||
<!-- 类型14: 转诊消息 -->
|
||||
<block v-else-if="msg.message_type === 14">
|
||||
<TransferMessageBubble
|
||||
:message-data="parsedContent"
|
||||
@agree="handleTransferAgree"
|
||||
@reject="handleTransferReject"
|
||||
/>
|
||||
</block>
|
||||
|
||||
<block v-else>
|
||||
<view class="card-body"><text>不支持的消息类型</text></view>
|
||||
</block>
|
||||
@@ -217,8 +226,17 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import TransferMessageBubble from './TransferMessageBubble.vue'
|
||||
import {
|
||||
agreeTransferPrescriptionApi,
|
||||
rejectTransferPrescriptionApi
|
||||
} from '@/request/api/transferPrescription'
|
||||
|
||||
export default {
|
||||
name: "MessageBubble",
|
||||
components: {
|
||||
TransferMessageBubble
|
||||
},
|
||||
props: {
|
||||
msg: {
|
||||
type: Object,
|
||||
@@ -240,20 +258,20 @@ export default {
|
||||
computed: {
|
||||
// 纯文本、图片、语音、视频以外的特殊类型,不需要默认的气泡背景/Padding
|
||||
isMediaOrCard() {
|
||||
// 1:图片, 3:视频, 4,10,11,12,13: 卡片 (9单独处理)
|
||||
return [1, 3, 4, 10, 11, 12, 13].includes(this.msg.message_type);
|
||||
// 1:图片, 3:视频, 4,10,11,12,13,14: 卡片 (9单独处理)
|
||||
return [1, 3, 4, 10, 11, 12, 13, 14].includes(this.msg.message_type);
|
||||
},
|
||||
// 是否是系统消息且为价格变动(需要独立卡片样式)
|
||||
isSystemPriceUpdate() {
|
||||
return this.msg.message_type === 9 && (this.parsedContent.type === 'price_update' || this.parsedContent.type === 'price_adjust');
|
||||
},
|
||||
isCardType() {
|
||||
return [4, 10, 11, 12, 13].includes(this.msg.message_type);
|
||||
return [4, 10, 11, 12, 13, 14].includes(this.msg.message_type);
|
||||
},
|
||||
parsedContent() {
|
||||
const { message_type, message_content } = this.msg;
|
||||
// 包含9(System)在内的复杂类型尝试解析 JSON
|
||||
if ([4, 9, 10, 11, 12, 13].includes(message_type)) {
|
||||
if ([4, 9, 10, 11, 12, 13, 14].includes(message_type)) {
|
||||
try {
|
||||
return typeof message_content === 'object' ? message_content : JSON.parse(message_content);
|
||||
} catch (e) {
|
||||
@@ -274,6 +292,86 @@ export default {
|
||||
},
|
||||
getStatusText(status) { const map = { 0: '待审核', 1: '已审核', 2: '未通过' }; return map[status] || '状态未知'; },
|
||||
getRegisterStatusText(status) { const map = { 0: '待就诊', 1: '已缴费', 2: '已就诊', 3: '已取消', 4: '已退费' }; return map[status] || '状态未知'; },
|
||||
// 处理转诊同意
|
||||
handleTransferAgree(messageData) {
|
||||
if (!messageData || !messageData.transfer_id) {
|
||||
uni.showToast({
|
||||
title: '转诊信息不完整',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
uni.showModal({
|
||||
title: '确认转诊',
|
||||
content: '确定同意转诊吗?',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
agreeTransferPrescriptionApi({ id: messageData.transfer_id }).then((result) => {
|
||||
if (result.data.code == 0) {
|
||||
uni.showToast({
|
||||
title: '同意转诊成功',
|
||||
icon: 'success'
|
||||
})
|
||||
// 触发消息更新事件
|
||||
uni.$emit('chat-message-update')
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: result.data.message || '操作失败',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.error('同意转诊失败:', error)
|
||||
uni.showToast({
|
||||
title: '操作失败,请重试',
|
||||
icon: 'none'
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
// 处理转诊拒绝
|
||||
handleTransferReject(messageData) {
|
||||
if (!messageData || !messageData.transfer_id) {
|
||||
uni.showToast({
|
||||
title: '转诊信息不完整',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
uni.showModal({
|
||||
title: '拒绝转诊',
|
||||
content: '确定拒绝转诊吗?',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
rejectTransferPrescriptionApi({ id: messageData.transfer_id }).then((result) => {
|
||||
if (result.data.code == 0) {
|
||||
uni.showToast({
|
||||
title: '已拒绝转诊',
|
||||
icon: 'success'
|
||||
})
|
||||
// 触发消息更新事件
|
||||
uni.$emit('chat-message-update')
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: result.data.message || '操作失败',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.error('拒绝转诊失败:', error)
|
||||
uni.showToast({
|
||||
title: '操作失败,请重试',
|
||||
icon: 'none'
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
171
subPackages/chat/components/TransferMessageBubble.vue
Normal file
171
subPackages/chat/components/TransferMessageBubble.vue
Normal file
@@ -0,0 +1,171 @@
|
||||
<template>
|
||||
<view class="transfer-message-bubble">
|
||||
<view class="bubble-header">
|
||||
<view class="header-icon">
|
||||
<text class="iconfont icon-zhuanzhen"></text>
|
||||
</view>
|
||||
<view class="header-title">转诊消息</view>
|
||||
</view>
|
||||
|
||||
<view class="bubble-body">
|
||||
<view class="info-item" v-if="messageData.transfer_store">
|
||||
<text class="label">转诊诊所:</text>
|
||||
<text class="value">{{ messageData.transfer_store.name || '未知诊所' }}</text>
|
||||
</view>
|
||||
|
||||
<view class="info-item" v-if="messageData.delegate_store">
|
||||
<text class="label">委托诊所:</text>
|
||||
<text class="value">{{ messageData.delegate_store.name || '未知诊所' }}</text>
|
||||
</view>
|
||||
|
||||
<view class="info-item" v-if="messageData.prescription_no">
|
||||
<text class="label">处方编号:</text>
|
||||
<text class="value">{{ messageData.prescription_no }}</text>
|
||||
</view>
|
||||
|
||||
<view class="info-item" v-if="messageData.transfer_reason">
|
||||
<text class="label">转诊原因:</text>
|
||||
<text class="value">{{ messageData.transfer_reason }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="bubble-footer" v-if="messageData.status === 0">
|
||||
<button class="action-btn agree" @click="handleAgree">同意转诊</button>
|
||||
<button class="action-btn reject" @click="handleReject">拒绝转诊</button>
|
||||
</view>
|
||||
|
||||
<view class="bubble-footer" v-else-if="messageData.status === 1">
|
||||
<text class="status-text confirmed">已同意转诊</text>
|
||||
</view>
|
||||
|
||||
<view class="bubble-footer" v-else-if="messageData.status === 3">
|
||||
<text class="status-text cancelled">已拒绝转诊</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'TransferMessageBubble',
|
||||
props: {
|
||||
messageData: {
|
||||
type: Object,
|
||||
required: true,
|
||||
default: () => ({})
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleAgree() {
|
||||
this.$emit('agree', this.messageData);
|
||||
},
|
||||
handleReject() {
|
||||
this.$emit('reject', this.messageData);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.transfer-message-bubble {
|
||||
background: linear-gradient(135deg, #fff7ed 0%, #ffedd5 100%);
|
||||
border-radius: 16rpx;
|
||||
border: 2rpx solid #fed7aa;
|
||||
padding: 24rpx;
|
||||
margin: 20rpx 0;
|
||||
max-width: 600rpx;
|
||||
}
|
||||
|
||||
.bubble-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16rpx;
|
||||
margin-bottom: 20rpx;
|
||||
padding-bottom: 16rpx;
|
||||
border-bottom: 2rpx solid #fed7aa;
|
||||
}
|
||||
|
||||
.header-icon {
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
background: linear-gradient(135deg, #f97316 0%, #ea580c 100%);
|
||||
border-radius: 8rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: white;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.header-title {
|
||||
font-size: 30rpx;
|
||||
font-weight: 600;
|
||||
color: #1e293b;
|
||||
}
|
||||
|
||||
.bubble-body {
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
margin-bottom: 16rpx;
|
||||
font-size: 26rpx;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.info-item:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.label {
|
||||
color: #64748b;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.value {
|
||||
color: #1e293b;
|
||||
}
|
||||
|
||||
.bubble-footer {
|
||||
display: flex;
|
||||
gap: 20rpx;
|
||||
justify-content: flex-end;
|
||||
padding-top: 16rpx;
|
||||
border-top: 2rpx solid #fed7aa;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
padding: 12rpx 32rpx;
|
||||
border-radius: 8rpx;
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.action-btn.agree {
|
||||
background: linear-gradient(135deg, #f97316 0%, #ea580c 100%);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.action-btn.reject {
|
||||
background: white;
|
||||
color: #64748b;
|
||||
border: 2rpx solid #cbd5e1;
|
||||
}
|
||||
|
||||
.status-text {
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
padding: 12rpx 32rpx;
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
|
||||
.status-text.confirmed {
|
||||
background: rgba(34, 197, 94, 0.1);
|
||||
color: #16a34a;
|
||||
}
|
||||
|
||||
.status-text.cancelled {
|
||||
background: rgba(239, 68, 68, 0.1);
|
||||
color: #dc2626;
|
||||
}
|
||||
</style>
|
||||
247
subPackages/my/components/TransferPrescriptionCard.vue
Normal file
247
subPackages/my/components/TransferPrescriptionCard.vue
Normal file
@@ -0,0 +1,247 @@
|
||||
<template>
|
||||
<view class="transfer-card">
|
||||
<view class="card-header">
|
||||
<view class="header-icon">
|
||||
<text class="iconfont icon-zhuanzhen"></text>
|
||||
</view>
|
||||
<view class="header-title">转诊处方</view>
|
||||
<view class="status-tag" :class="statusClass">
|
||||
{{ statusText }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="card-body">
|
||||
<view class="info-row" v-if="transferData.transfer_store">
|
||||
<view class="info-icon">
|
||||
<text class="iconfont icon-yiyuan"></text>
|
||||
</view>
|
||||
<view class="info-content">
|
||||
<view class="info-label">转诊诊所</view>
|
||||
<view class="info-value">{{ transferData.transfer_store.name || '未知诊所' }}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="info-row" v-if="transferData.delegate_store">
|
||||
<view class="info-icon">
|
||||
<text class="iconfont icon-zhensuo"></text>
|
||||
</view>
|
||||
<view class="info-content">
|
||||
<view class="info-label">委托诊所</view>
|
||||
<view class="info-value">{{ transferData.delegate_store.name || '未知诊所' }}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="info-row" v-if="transferData.prescription_no">
|
||||
<view class="info-icon">
|
||||
<text class="iconfont icon-chufang"></text>
|
||||
</view>
|
||||
<view class="info-content">
|
||||
<view class="info-label">处方编号</view>
|
||||
<view class="info-value">{{ transferData.prescription_no }}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="info-row" v-if="transferData.transfer_time">
|
||||
<view class="info-icon">
|
||||
<text class="iconfont icon-shijian"></text>
|
||||
</view>
|
||||
<view class="info-content">
|
||||
<view class="info-label">转诊时间</view>
|
||||
<view class="info-value">{{ transferData.transfer_time }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="card-footer" v-if="transferData.status === 0">
|
||||
<button class="agree-btn" @click="handleAgree">同意转诊</button>
|
||||
<button class="reject-btn" @click="handleReject">拒绝转诊</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'TransferPrescriptionCard',
|
||||
props: {
|
||||
transferData: {
|
||||
type: Object,
|
||||
required: true,
|
||||
default: () => ({})
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
statusText() {
|
||||
const status = this.transferData.status;
|
||||
const statusMap = {
|
||||
0: '待确认',
|
||||
1: '已确认',
|
||||
2: '已导入',
|
||||
3: '已取消'
|
||||
};
|
||||
return statusMap[status] || '未知';
|
||||
},
|
||||
statusClass() {
|
||||
const status = this.transferData.status;
|
||||
const classMap = {
|
||||
0: 'status-pending',
|
||||
1: 'status-confirmed',
|
||||
2: 'status-imported',
|
||||
3: 'status-cancelled'
|
||||
};
|
||||
return classMap[status] || '';
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleAgree() {
|
||||
this.$emit('agree', this.transferData);
|
||||
},
|
||||
handleReject() {
|
||||
this.$emit('reject', this.transferData);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.transfer-card {
|
||||
width: 100%;
|
||||
background: linear-gradient(135deg, #fff7ed 0%, #ffedd5 100%);
|
||||
border-radius: 16rpx;
|
||||
border: 2rpx solid #fed7aa;
|
||||
margin: 20rpx 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20rpx;
|
||||
padding: 24rpx 30rpx;
|
||||
background: linear-gradient(135deg, #f97316 0%, #ea580c 100%);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.header-icon {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
border-radius: 12rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
|
||||
.header-title {
|
||||
flex: 1;
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.status-tag {
|
||||
padding: 8rpx 20rpx;
|
||||
border-radius: 40rpx;
|
||||
font-size: 24rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.status-pending {
|
||||
background: rgba(251, 191, 36, 0.2);
|
||||
color: #fcd34d;
|
||||
}
|
||||
|
||||
.status-confirmed {
|
||||
background: rgba(59, 130, 246, 0.2);
|
||||
color: #93c5fd;
|
||||
}
|
||||
|
||||
.status-imported {
|
||||
background: rgba(34, 197, 94, 0.2);
|
||||
color: #86efac;
|
||||
}
|
||||
|
||||
.status-cancelled {
|
||||
background: rgba(239, 68, 68, 0.2);
|
||||
color: #fca5a5;
|
||||
}
|
||||
|
||||
.card-body {
|
||||
padding: 30rpx;
|
||||
}
|
||||
|
||||
.info-row {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 24rpx;
|
||||
padding: 24rpx 30rpx;
|
||||
background: white;
|
||||
border-radius: 16rpx;
|
||||
margin-bottom: 20rpx;
|
||||
border: 2rpx solid #fed7aa;
|
||||
}
|
||||
|
||||
.info-row:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.info-icon {
|
||||
width: 56rpx;
|
||||
height: 56rpx;
|
||||
background: linear-gradient(135deg, #fff7ed 0%, #ffedd5 100%);
|
||||
border-radius: 12rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #f97316;
|
||||
font-size: 28rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.info-content {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.info-label {
|
||||
font-size: 24rpx;
|
||||
color: #64748b;
|
||||
margin-bottom: 8rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.info-value {
|
||||
font-size: 28rpx;
|
||||
color: #1e293b;
|
||||
line-height: 1.6;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.card-footer {
|
||||
padding: 24rpx 30rpx;
|
||||
background: #fff7ed;
|
||||
border-top: 2rpx solid #fed7aa;
|
||||
display: flex;
|
||||
gap: 20rpx;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.agree-btn,
|
||||
.reject-btn {
|
||||
padding: 16rpx 40rpx;
|
||||
border-radius: 12rpx;
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.agree-btn {
|
||||
background: linear-gradient(135deg, #f97316 0%, #ea580c 100%);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.reject-btn {
|
||||
background: white;
|
||||
color: #64748b;
|
||||
border: 2rpx solid #cbd5e1;
|
||||
}
|
||||
</style>
|
||||
@@ -62,6 +62,15 @@
|
||||
</view>
|
||||
<text>{{item.store}}</text>
|
||||
</view>
|
||||
|
||||
<!-- 转诊卡片 -->
|
||||
<TransferPrescriptionCard
|
||||
v-if="item.is_from_transfer == 1 && item.transfer_prescription"
|
||||
:transfer-data="item.transfer_prescription"
|
||||
@agree="handleTransferAgree"
|
||||
@reject="handleTransferReject"
|
||||
/>
|
||||
|
||||
<!-- 查看详情 -->
|
||||
<view class="detail" @click="getInfo(item.id)"><text>查看详情</text></view>
|
||||
</view>
|
||||
@@ -78,7 +87,15 @@
|
||||
import {
|
||||
getRegisterListApi
|
||||
} from '../../request/api/register'
|
||||
import {
|
||||
agreeTransferPrescriptionApi,
|
||||
rejectTransferPrescriptionApi
|
||||
} from '../../request/api/transferPrescription'
|
||||
import TransferPrescriptionCard from './components/TransferPrescriptionCard.vue'
|
||||
export default {
|
||||
components: {
|
||||
TransferPrescriptionCard
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
status: 'nomore',
|
||||
@@ -112,6 +129,74 @@
|
||||
url: "/subPackages/register/register-info?id=" + id + '&type=' + 1
|
||||
})
|
||||
},
|
||||
// 同意转诊
|
||||
handleTransferAgree(transferData) {
|
||||
uni.showModal({
|
||||
title: '确认转诊',
|
||||
content: '确定同意转诊吗?',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
agreeTransferPrescriptionApi({ id: transferData.id }).then((result) => {
|
||||
if (result.data.code == 0) {
|
||||
uni.showToast({
|
||||
title: '同意转诊成功',
|
||||
icon: 'success'
|
||||
})
|
||||
// 刷新列表
|
||||
this.page = 1
|
||||
this.infoList = []
|
||||
this.getInfos()
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: result.data.message || '操作失败',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.error('同意转诊失败:', error)
|
||||
uni.showToast({
|
||||
title: '操作失败,请重试',
|
||||
icon: 'none'
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
// 拒绝转诊
|
||||
handleTransferReject(transferData) {
|
||||
uni.showModal({
|
||||
title: '拒绝转诊',
|
||||
content: '确定拒绝转诊吗?',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
rejectTransferPrescriptionApi({ id: transferData.id }).then((result) => {
|
||||
if (result.data.code == 0) {
|
||||
uni.showToast({
|
||||
title: '已拒绝转诊',
|
||||
icon: 'success'
|
||||
})
|
||||
// 刷新列表
|
||||
this.page = 1
|
||||
this.infoList = []
|
||||
this.getInfos()
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: result.data.message || '操作失败',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.error('拒绝转诊失败:', error)
|
||||
uni.showToast({
|
||||
title: '操作失败,请重试',
|
||||
icon: 'none'
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
// 就诊人列表
|
||||
getInfolist() {
|
||||
userList({
|
||||
|
||||
356
subPackages/transfer/transfer-message.vue
Normal file
356
subPackages/transfer/transfer-message.vue
Normal file
@@ -0,0 +1,356 @@
|
||||
<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="@/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-zhuanzhen"></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' })
|
||||
this.getTransferList()
|
||||
} else {
|
||||
uni.showToast({ title: response.data.message, icon: 'none' })
|
||||
}
|
||||
} catch (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>
|
||||
Reference in New Issue
Block a user