fix: 聊天页面

This commit is contained in:
2025-12-23 08:31:21 +08:00
parent 588f2ec85b
commit 72848ff2f6
7 changed files with 1417 additions and 1054 deletions

View File

@@ -84,16 +84,43 @@
<!-- 模拟<u-divider>在线问诊</u-divider>效果-->
<!-- 标题 -->
<view v-if="checkDev('open-im')" class="title">
<text>在线问诊</text>
<!-- <view class="clear" @click="getClearInfo">-->
<!-- <text class="iconfont icon-qingchu"></text>-->
<!-- 清除未读-->
<!-- </view>-->
<!-- 标题 - 在线咨询 -->
<view v-if="checkDev('open-im') && onlineConsultationList.length > 0" class="title">
<text>在线咨询</text>
</view>
<!-- 在线问诊 - 用户-->
<view v-if="checkDev('open-im')" v-for="(item, index) in imChat" :key="item.id" class="list" @click="goChat(item, index)">
<!-- 在线咨询 - 用户 (type=1) -->
<view v-if="checkDev('open-im')" v-for="(item, index) in onlineConsultationList" :key="item.id" class="list" @click="goChat(item, index)">
<!-- 头像 -->
<view class="avator">
<view class="img">
<image :src="item.avatar" mode=""></image>
</view>
<u-badge size="default" v-if="item.un_read_count>=0" :count="item.un_read_count"
:is-dot="item.un_read_count==0?true:false"
type="error" :offset="item.un_read_count>0?[-4,-8]:[0,0]"></u-badge>
</view>
<!-- 描述 -->
<view class="info">
<view class="infos_title">
<text class="infos">{{ item.nick_name }}</text>
<text class="time">{{ item.last_message_time }}</text>
</view>
<view class="preview">
<p>{{ item.last_message }}</p>
<!-- <p v-if="item.un_read_count>0">您有{{item.un_read_count}}条新的消息</p>-->
</view>
<view class="preview" v-if="item.last_message===''">
暂无新消息
</view>
</view>
</view>
<!-- 标题 - 在线复诊 -->
<view v-if="checkDev('open-im') && onlineReconsultationList.length > 0" class="title">
<text>在线复诊</text>
</view>
<!-- 在线复诊 - 用户 (type=3) -->
<view v-if="checkDev('open-im')" v-for="(item, index) in onlineReconsultationList" :key="item.id" class="list" @click="goChat(item, index)">
<!-- 头像 -->
<view class="avator">
<view class="img">
@@ -136,6 +163,8 @@ export default {
system: [],
doctor: [],
imChat: [],
onlineConsultationList: [], // 在线咨询列表 (type=1)
onlineReconsultationList: [], // 在线复诊列表 (type=3)
type: ""
}
},
@@ -240,7 +269,12 @@ export default {
},
getMyChatFriendsList() {
getChatFriendsListApi().then((res) => {
this.imChat = res.data.result
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的为在线复诊
// 保持imChat兼容性包含所有
this.imChat = allChatList
})
}
},
@@ -251,6 +285,8 @@ export default {
this.order = []
this.system = []
this.doctor = []
this.onlineConsultationList = []
this.onlineReconsultationList = []
this.getInfo()
this.getMyChatFriendsList()
}

View File

@@ -107,42 +107,45 @@ const ChatManager = {
checkMessage(message, type = 0) {
if (type === 1) {
// 直接返回数据库字段,不进行转换
return {
id: message.id,
sender: message.sender_user_id,
type: this.getMessageType(message.message_type),
// type: message.type,
content:
item.message_type === 4 || item.message_type === 10
? JSON.parse(item.message_content)
: item.message_content,
sender_user_id: message.sender_user_id,
receiver_user_id: message.receiver_user_id,
message_type: message.message_type,
message_content: message.message_content,
duration: message.duration,
time: this.formatTime(message.send_time),
timestamp: message.send_time
room_id: message.room_id,
created_at: message.created_at || message.send_time,
created_at_text: message.created_at_text || this.formatTime(message.send_time || message.created_at),
timestamp: message.send_time || message.created_at
};
}
return message.map((item, index) => {
let msg = item.message_type === 4 || item.message_type === 10
? JSON.parse(item.message_content)
: item.message_content;
if (item.message_type === 10) {
this.getChatRegisterInfo(msg, index)
}
return {
// 直接返回数据库字段,不进行转换
const result = {
id: item.id,
sender: item.sender_user_id,
type: this.getMessageType(item.message_type),
content: msg,
sender_user_id: item.sender_user_id,
receiver_user_id: item.receiver_user_id,
message_type: item.message_type,
message_content: item.message_content,
duration: item.duration,
time: item?.created_at_text || item.send_time,
timestamp: item?.created_at || item.send_time
room_id: item.room_id,
created_at: item.created_at || item.send_time,
created_at_text: item.created_at_text || this.formatTime(item.send_time || item.created_at),
timestamp: item.send_time || item.created_at
};
// 对于挂号消息,仍然需要异步获取详细信息
if (item.message_type === 10) {
this.getChatRegisterInfo(result, index)
}
return result;
});
},
// 根据消息类型ID获取类型名称
getMessageType(typeId) {
// 根据消息类型ID获取类型名称(辅助函数,不转换字段名)
getMessageTypeName(typeId) {
const types = {
0: 'text',
1: 'image',
@@ -150,9 +153,30 @@ const ChatManager = {
3: 'video',
4: 'prescription',
5: 'file',
6: 'video-call',
7: 'audio-call',
8: 'file',
9: 'system',
10: 'register',
11: 'patient-experience',
12: 'product-card',
13: 'end-consultation',
};
return types[typeId];
return types[typeId] || 'unknown';
},
// 按需解析消息内容(辅助函数)
getParsedContent(messageType, messageContent) {
// 对于需要 JSON 解析的消息类型4, 10, 11, 12, 13
if ([4, 10, 11, 12, 13].includes(messageType)) {
try {
return JSON.parse(messageContent);
} catch (e) {
console.error('解析消息内容失败:', e);
return messageContent;
}
}
return messageContent;
},
/**

File diff suppressed because it is too large Load Diff

View File

@@ -192,10 +192,24 @@ export default {
onLoad(e) {
this.Did = e.id
if (e.r_type) {
this.registerType = e.r_type
// this.registerType = '1'
// 对 r_info 进行 URL 解码(如果它是字符串)
if (e.r_info) {
try {
// 如果是字符串,先解码再解析 JSON
if (typeof e.r_info === 'string') {
this.rInfo = JSON.parse(decodeURIComponent(e.r_info))
} else {
// 如果已经是对象,直接使用
this.rInfo = e.r_info
}
} catch (error) {
console.error('解析 r_info 失败:', error)
this.rInfo = {}
}
} else {
this.rInfo = {}
}
}
console.log(e)
@@ -336,32 +350,34 @@ export default {
this.register_id = res.data.data.register_id
// if (this.registerType === "3" || this.registerType === "2") {
if (this.registerType === "3") {
let params = JSON.parse(this.rInfo);
// this.rInfo 在 onLoad 中已经解析为对象,直接使用
let params = typeof this.rInfo === 'string' ? JSON.parse(this.rInfo) : this.rInfo;
// 保存病患信息
saveRegisterInfoApi({
register_id: this.register_id,
doctor_id: params.doctor_id,
drug_id: params.id,
has_visited: params.hasVisited,
has_used_drug: params.hasUsedDrug,
illnessInfo: params.illnessInfo,
doctor_id: params.doctor_id || this.Did,
drug_id: params.drug_id || params.id,
has_visited: params.has_visited || params.hasVisited,
has_used_drug: params.has_used_drug || params.hasUsedDrug,
illnessInfo: params.illness_info || params.illnessInfo,
type: params.type,
number: params.number,
store_id: uni.getStorageSync('store_id') || '11001',
}).then(() => {
// 直接跳转到付款页面
genOrderApi({
register_id: this.register_id,
register_info: this.rInfo,
}).then((resOrder) => {
console.log(resOrder);
// 跳转到挂号页面,让用户确认挂号并支付
// 将 rInfo 对象转换为 JSON 字符串并 URL 编码
const rInfoStr = typeof this.rInfo === 'string' ? this.rInfo : JSON.stringify(this.rInfo);
uni.navigateTo({
url: `/subPackages/register/register?id=${this.register_id}&doctor_id=${this.Did}&r_info=${encodeURIComponent(rInfoStr)}`
});
}).catch((error) => {
console.error('保存患者就诊信息失败:', error);
// 即使保存失败,也跳转到挂号页面
uni.navigateTo({
url: `/subPackages/my/my-drug/drug-info?id=${resOrder.data.result.id}&order_type=${resOrder.data.result.order_type}`
})
})
})
url: `/subPackages/register/register?id=${this.register_id}&doctor_id=${this.Did}&r_info=${this.rInfo}`
});
});
return;
}
uni.setStorageSync('register_id', this.register_id)

View File

@@ -301,6 +301,8 @@
import { getOrderTextApi, getStoreDrugDetailApi } from "@/request/api/product";
import { genOrderApi } from "@/request/api/order";
import { getCartCountsApi, saveCartApi } from "@/request/api/cart";
import { sendToUserApi } from "@/request/api/im";
import request from "@/request/api/request";
export default {
data() {
@@ -505,7 +507,7 @@ export default {
});
})
},
submitPrescriptionForm() {
async submitPrescriptionForm() {
if (!this.prescriptionFormData.hasVisited || !this.prescriptionFormData.hasUsedDrug || !this.prescriptionFormData.illnessInfo) {
uni.showToast({
title: '请填写完整信息',
@@ -515,21 +517,50 @@ export default {
}
this.submitted = true;
this.closePrescriptionFormPopup();
try {
// 1. 获取默认医生ID=39
const doctorRes = await this.getDefaultDoctorId();
const doctorId = doctorRes.data.result?.doctor_id || '39';
// 2. 准备患者就诊信息
const rInfo = {
id: this.productDetail.id,
has_visited: this.prescriptionFormData.hasVisited,
has_used_drug: this.prescriptionFormData.hasUsedDrug,
illness_info: this.prescriptionFormData.illnessInfo,
drug_name: this.productDetail.drug_name,
image: this.productDetail.image,
price: this.productPrice,
drug_id: this.productDetail.id,
number: this.prescriptionQuantity,
hasVisited: this.prescriptionFormData.hasVisited,
hasUsedDrug: this.prescriptionFormData.hasUsedDrug,
illnessInfo: this.prescriptionFormData.illnessInfo,
doctor_id: this.formData.doctor_id,
type: this.formData.type
};
type: this.productDetail.type || 2, // 2=西药3=保健食品
created_at: new Date().toLocaleString('zh-CN')
};
// 3. 跳转到就诊人选择页面,传递 register_type=3 和患者就诊信息
// 用户选择就诊人后,会创建挂号记录并跳转到 register.vue
uni.navigateTo({
url: `/subPackages/doctor/doctor-userinfo?id=${this.formData.doctor_id}&r_info=${JSON.stringify(rInfo)}&r_type=${this.formData.type}`
});
url: `/subPackages/doctor/doctor-userinfo?id=${doctorId}&r_type=3&r_info=${encodeURIComponent(JSON.stringify(rInfo))}`
});
} catch (error) {
console.error('提交处方药信息失败:', error);
uni.showToast({
title: '提交失败,请重试',
icon: 'none'
});
}
},
// 获取默认医生ID
async getDefaultDoctorId() {
try {
const res = await request('/xkApi/online-consultation/get-default-doctor-id', {
method: 'GET'
}, 0);
return res;
} catch (error) {
console.error('获取默认医生ID失败:', error);
// 如果接口失败返回默认值39
return { data: { result: { doctor_id: '39' } } };
}
},
goToCart() {
uni.navigateTo({

View File

@@ -133,11 +133,13 @@
import {
registeInfo,
registePay,
registe,
service
} from '../../request/api/api';
import {createRoomByDoctorIdApi, sendToUserApi} from "@/request/api/im";
import {checkDev} from "@/utils/utils";
import {genOrderApi} from "@/request/api/order";
import {genOrderApi, saveRegisterInfoApi} from "@/request/api/order";
import request from "@/request/api/request";
export default {
data() {
return {
@@ -164,14 +166,18 @@
},
onLoad(e) {
// console.log(e, 'role');
this.register_id = e.id
this.rInfo = e.r_info
this.currentUserId = 'user-' + uni.getStorageSync('user_id') || 'user-2512';
this.currentDoctorId = 'doctor-' + e.doctor_id;
// if (this.currentDoctorId == null) {
//
// }
uni.setStorageSync('register_id', this.register_id)
// 原有逻辑:已有 register_id
this.register_id = e.id;
this.rInfo = e.r_info ? (typeof e.r_info === 'string' ? JSON.parse(decodeURIComponent(e.r_info)) : e.r_info) : {};
this.currentDoctorId = e.doctor_id ? ('doctor-' + e.doctor_id.replace('doctor-', '')) : 'doctor-39';
uni.setStorageSync('register_id', this.register_id);
// 获取挂号信息
if (this.register_id) {
this.getInfo();
}
},
methods: {
// 挂号信息
@@ -191,6 +197,86 @@
}
})
},
// 处理在线复诊支付后的流程
async handleOnlineConsultationAfterPayment() {
let that = this;
try {
// 1. 获取医生ID从 currentDoctorId 中提取)
const doctorId = that.currentDoctorId.replace('doctor-', '');
// 2. 获取患者ID
const patientId = that.currentUserId.replace('user-', '');
// 3. 创建或获取聊天房间
const roomRes = await request('/xkApi/online-consultation/get-or-create-chat-room', {
method: 'POST',
data: {
doctor_id: doctorId,
patient_id: patientId
}
}, 1);
const roomId = roomRes.data?.result?.room_id || roomRes.data?.room_id;
if (!roomId) {
uni.hideLoading();
uni.showToast({
title: '创建聊天房间失败',
icon: 'none'
});
return;
}
// 4. 准备患者就诊经历数据
const patientExperienceData = {
symptom_description: that.rInfo.illness_info || '',
has_visited: that.rInfo.has_visited || '0',
has_used_drug: that.rInfo.has_used_drug || '0',
drug_name: that.rInfo.drug_name || '',
illness_info: that.rInfo.illness_info || '',
doctor_id: doctorId,
user_id: patientId,
register_id: that.register_id,
created_at: new Date().toLocaleString('zh-CN')
};
// 5. 发送患者就诊经历消息消息类型11
// 使用纯数字ID格式与房间创建时的格式保持一致
await sendToUserApi({
room_id: roomId,
sender_user_id: patientId, // 纯数字ID'252'
receiver_user_id: doctorId, // 纯数字ID'39'
message_type: 11, // 患者就诊经历卡片
message_content: JSON.stringify(patientExperienceData),
duration: 0
});
// 6. 生成订单(如果需要)
genOrderApi({
register_id: that.register_id,
register_info: typeof that.rInfo === 'string' ? that.rInfo : JSON.stringify(that.rInfo),
}).then((resOrder) => {
uni.hideLoading();
// 跳转到聊天页面
uni.navigateTo({
url: `/subPackages/chat/chat?user_id=${that.currentDoctorId}&room_id=${roomId}&register_id=${that.register_id}`
});
}).catch((error) => {
console.error('生成订单失败:', error);
uni.hideLoading();
// 即使生成订单失败,也跳转到聊天页面
uni.navigateTo({
url: `/subPackages/chat/chat?user_id=${that.currentDoctorId}&room_id=${roomId}&register_id=${that.register_id}`
});
});
} catch (error) {
uni.hideLoading();
console.error('处理在线复诊流程失败:', error);
uni.showToast({
title: '处理失败,请重试',
icon: 'none'
});
}
},
// 确认挂号
next() {
@@ -243,15 +329,8 @@
if (res.data.data.is_paid == 1) {
if (that.registList.register_type === 3) {
genOrderApi({
register_id: that.register_id,
register_info: that.rInfo,
}).then((resOrder) => {
console.log(res);
uni.navigateTo({
url: `/subPackages/my/my-drug/drug-info?id=${resOrder.data.result.id}&order_type=${resOrder.data.result.order_type}`
})
})
// 在线复诊流程:创建聊天房间并发送患者就诊经历消息
that.handleOnlineConsultationAfterPayment();
return;
}
setTimeout(() => {

View File

@@ -6,10 +6,11 @@ export function checkDev(key = '') {
// 判断某些模块是否开启
switch (key) {
case 'dev':
return false;
// return true;
// return false;
return true;
case 'open-im':
return false;
// return false;
return true;
default:
return false;
}