This commit is contained in:
huxuejian 2026-02-08 10:41:55 +08:00
commit dae3b4d125
10 changed files with 80 additions and 79 deletions

View File

@ -6,14 +6,11 @@ $text-color-sub: #999;
$primary-color: #0877F1; $primary-color: #0877F1;
.chat-page { .chat-page {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
height: 100vh;
background-color: #f5f5f5; background-color: #f5f5f5;
overflow: hidden;
} }
/* 患者信息栏样式 */ /* 患者信息栏样式 */
@ -90,6 +87,7 @@ $primary-color: #0877F1;
flex: 1; flex: 1;
box-sizing: border-box; box-sizing: border-box;
overflow-x: hidden; overflow-x: hidden;
min-height: 0;
} }
.chat-content-compressed { .chat-content-compressed {
@ -359,6 +357,7 @@ $primary-color: #0877F1;
position: relative; position: relative;
z-index: 200; z-index: 200;
padding-bottom: env(safe-area-inset-bottom); padding-bottom: env(safe-area-inset-bottom);
flex-shrink: 0;
} }
.input-toolbar { .input-toolbar {
@ -378,6 +377,14 @@ $primary-color: #0877F1;
padding: 0; padding: 0;
} }
.voice-toggle-icon {
width: 56rpx;
height: 56rpx;
display: flex;
align-items: center;
justify-content: center;
}
.plus-btn { .plus-btn {
width: 56rpx; width: 56rpx;
height: 56rpx; height: 56rpx;

View File

@ -2,13 +2,13 @@
<view class="input-section"> <view class="input-section">
<view class="input-toolbar"> <view class="input-toolbar">
<view @click="toggleVoiceInput" class="voice-toggle-btn"> <view @click="toggleVoiceInput" class="voice-toggle-btn">
<uni-icons v-if="showVoiceInput" fontFamily="keyboard" :size="28">{{ '&#xe61a;' }}</uni-icons> <image v-if="showVoiceInput" src="/static/jianpan.png" class="voice-toggle-icon" mode="aspectFit"></image>
<uni-icons v-else type="mic" size="28" color="#666" /> <uni-icons v-else type="mic" size="28" color="#666" />
</view> </view>
<view class="input-area"> <view class="input-area">
<textarea v-if="!showVoiceInput" class="text-input" v-model="inputText" placeholder="我来说两句..." <textarea v-if="!showVoiceInput" class="text-input" v-model="inputText" placeholder="我来说两句..."
@confirm="sendTextMessage" @focus="handleInputFocus" @input="handleInput" @confirm="sendTextMessage" @focus="handleInputFocus" @input="handleInput"
:auto-height="true" :show-confirm-bar="false" :adjust-position="true" :cursor-spacing="40" :auto-height="true" :show-confirm-bar="false" :adjust-position="true" :cursor-spacing="60"
/> />
<input v-else class="voice-input-btn" :class="{ recording: isRecording }" @touchstart="startRecord" <input v-else class="voice-input-btn" :class="{ recording: isRecording }" @touchstart="startRecord"
@touchmove="onRecordTouchMove" @touchend="stopRecord" @touchcancel="cancelRecord" :placeholder="isRecording ? '松开发送' : '按住说话'" disabled> @touchmove="onRecordTouchMove" @touchend="stopRecord" @touchcancel="cancelRecord" :placeholder="isRecording ? '松开发送' : '按住说话'" disabled>
@ -463,7 +463,7 @@ const morePanelButtons = computed(() => {
// "" // ""
buttons.push({ buttons.push({
text: "开启会话", text: "开启会话",
icon: "/static/icon/kaiqihuihua.png", icon: "/static/icon/openChat.png",
action: handleOpenConsult, action: handleOpenConsult,
}); });
} else { } else {

View File

@ -10,13 +10,13 @@
</template> </template>
<script setup> <script setup>
import { computed } from 'vue'; import { computed } from "vue";
const props = defineProps({ const props = defineProps({
message: { message: {
type: Object, type: Object,
default: () => ({}) default: () => ({}),
} },
}); });
const payload = computed(() => props.message?.payload || {}); const payload = computed(() => props.message?.payload || {});
@ -26,16 +26,17 @@ const systemMessageData = computed(() => {
try { try {
// payload.data // payload.data
if (payload.value.data) { if (payload.value.data) {
const data = typeof payload.value.data === 'string' const data =
? JSON.parse(payload.value.data) typeof payload.value.data === "string"
: payload.value.data; ? JSON.parse(payload.value.data)
: payload.value.data;
if (data.type === 'system_message') {
if (data.type === "system_message") {
return data; return data;
} }
} }
} catch (e) { } catch (e) {
console.error('解析系统消息失败:', e); console.error("解析系统消息失败:", e);
} }
return null; return null;
}); });
@ -44,12 +45,12 @@ const systemMessageData = computed(() => {
const extension = computed(() => { const extension = computed(() => {
try { try {
if (payload.value.extension) { if (payload.value.extension) {
return typeof payload.value.extension === 'string' return typeof payload.value.extension === "string"
? JSON.parse(payload.value.extension) ? JSON.parse(payload.value.extension)
: payload.value.extension; : payload.value.extension;
} }
} catch (e) { } catch (e) {
console.error('解析扩展信息失败:', e); console.error("解析扩展信息失败:", e);
} }
return {}; return {};
}); });
@ -65,20 +66,20 @@ const text = computed(() => {
if (systemMessageData.value?.messageType) { if (systemMessageData.value?.messageType) {
const messageType = systemMessageData.value.messageType; const messageType = systemMessageData.value.messageType;
switch (messageType) { switch (messageType) {
case 'consult_pending': case "consult_pending":
return '患者已发起咨询申请,请及时接诊'; return "患者已发起咨询申请,请及时接诊";
case 'consult_accepted': case "consult_accepted":
return '医生已接诊'; return "医生已接诊";
case 'consult_rejected': case "consult_rejected":
return '医生暂时无法接诊'; return "医生暂时无法接诊";
case 'consult_ended': case "consult_ended":
return '问诊已结束'; return "问诊已结束";
case 'consult_timeout': case "consult_timeout":
return '问诊已超时'; return "问诊已超时";
case 'consult_reopened': case "consult_reopened":
return '会话已重新开启'; return "会话已重新开启";
default: default:
return systemMessageData.value.content || '[系统消息]'; return systemMessageData.value.content || "[系统消息]";
} }
} }
@ -88,7 +89,7 @@ const text = computed(() => {
} }
// payload.data // payload.data
if (payload.value.data && typeof payload.value.data === 'string') { if (payload.value.data && typeof payload.value.data === "string") {
// data JSON // data JSON
try { try {
JSON.parse(payload.value.data); JSON.parse(payload.value.data);
@ -97,7 +98,7 @@ const text = computed(() => {
} }
} }
return '[系统消息]'; return "[系统消息]";
}); });
// //
@ -111,24 +112,23 @@ const notifyText = computed(() => {
if (systemMessageData.value) { if (systemMessageData.value) {
const messageType = systemMessageData.value.messageType; const messageType = systemMessageData.value.messageType;
switch (messageType) { switch (messageType) {
case 'consult_pending': case "consult_pending":
return '待接诊'; return "待接诊";
case 'consult_rejected': case "consult_rejected":
return '已拒绝'; return "已拒绝";
case 'consult_timeout': case "consult_timeout":
return '已超时'; return "已超时";
case 'consult_accepted': case "consult_accepted":
return '已接诊'; return "已接诊";
case 'consult_ended': case "consult_ended":
return '已结束'; return "已结束";
default: default:
return ''; return "";
} }
} }
return ''; return "";
}); });
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">

View File

@ -886,7 +886,7 @@ const handleRejectReasonConfirm = async (reason) => {
const currentGroupId = chatInfo.value.conversationID.replace("GROUP", ""); const currentGroupId = chatInfo.value.conversationID.replace("GROUP", "");
// //
const result = await api("sendConsultRejectedMessage", { const result = await api("rejectConsultation", {
groupId: currentGroupId, groupId: currentGroupId,
memberName, memberName,
reason, reason,

BIN
static/icon/openChat.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 752 B

BIN
static/jianpan.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

View File

@ -24,8 +24,8 @@ export default defineStore("accountStore", () => {
// IM 相关 // IM 相关
const openid = ref(cache.get(CACHE_KEYS.OPENID, "")); const openid = ref(cache.get(CACHE_KEYS.OPENID, ""));
const isIMInitialized = ref(false); const isIMInitialized = ref(false);
// 医生信息 // 医生信息 - 不做缓冲处理,每次都重新获取
const doctorInfo = ref(cache.get(CACHE_KEYS.DOCTOR_INFO, null)); const doctorInfo = ref(null);
function getLoginPromise(phoneCode = '') { function getLoginPromise(phoneCode = '') {
if (loginPromise.value) return loginPromise.value; if (loginPromise.value) return loginPromise.value;
@ -87,13 +87,20 @@ export default defineStore("accountStore", () => {
weChatOpenId: account.value.openid, weChatOpenId: account.value.openid,
}); });
doctorInfo.value = res?.data || null; doctorInfo.value = res?.data || null;
if (doctorInfo.value.accountState && doctorInfo.value.accountState == "disable") {
uni.redirectTo({ url: "/pages/login/login" }); // 检查账号是否被禁用
if (doctorInfo.value?.accountState === "disable") {
uni.showModal({
title: '账号被禁用',
content: '您的账号已被禁用,请联系管理员',
showCancel: false,
confirmText: '确定',
success: () => {
uni.redirectTo({ url: "/pages/login/login" });
}
});
return; return;
} }
if (res?.data) {
cache.set(CACHE_KEYS.DOCTOR_INFO, res.data);
}
} catch (e) { } catch (e) {
console.error('获取医生信息失败:', e); console.error('获取医生信息失败:', e);
@ -137,7 +144,6 @@ export default defineStore("accountStore", () => {
// 清空缓存 // 清空缓存
cache.remove(CACHE_KEYS.ACCOUNT); cache.remove(CACHE_KEYS.ACCOUNT);
cache.remove(CACHE_KEYS.OPENID); cache.remove(CACHE_KEYS.OPENID);
cache.remove(CACHE_KEYS.DOCTOR_INFO);
} }
return { account, openid, isIMInitialized, doctorInfo, login, getDoctorInfo, initIMAfterLogin, logout } return { account, openid, isIMInitialized, doctorInfo, login, getDoctorInfo, initIMAfterLogin, logout }

View File

@ -104,7 +104,8 @@ const urlsConfig = {
getChatRecordsByGroupId: "getChatRecordsByGroupId", getChatRecordsByGroupId: "getChatRecordsByGroupId",
getGroupList: "getGroupList", getGroupList: "getGroupList",
followUpInquiry: "followUpInquiry", followUpInquiry: "followUpInquiry",
supplementMedicalCase: "supplementMedicalCase" supplementMedicalCase: "supplementMedicalCase",
rejectConsultation: "rejectConsultation"
}, },
todo: { todo: {
getCustomerTodos: 'getCustomerTodos', getCustomerTodos: 'getCustomerTodos',

View File

@ -5,7 +5,7 @@
import { globalTimChatManager } from './tim-chat.js'; import { globalTimChatManager } from './tim-chat.js';
import api from './api.js'; import api from './api.js';
import { toast } from './widget.js'; import { toast } from './widget.js';
const env = __VITE_ENV__;
/** /**
* 发送文字消息 * 发送文字消息
* @param {string} content - 文字内容 * @param {string} content - 文字内容
@ -137,7 +137,7 @@ export async function sendArticleMessage(article, options = {}) {
/** /**
* 发送问卷消息 * 发送问卷消息
* @param {Object} survey - 问卷对象 { _id, name, surveryId, url, createBy } * @param {Object} survey - 问卷对象 { _id, name, surveryId, url, createBy }
* @param {Object} options - 额外选项 { userId, customerId, customerName, corpId, env } * @param {Object} options - 额外选项 { userId, customerId, customerName, corpId }
* @returns {Promise<boolean>} 发送是否成功 * @returns {Promise<boolean>} 发送是否成功
*/ */
export async function sendSurveyMessage(survey, options = {}) { export async function sendSurveyMessage(survey, options = {}) {
@ -186,8 +186,7 @@ export async function sendSurveyMessage(survey, options = {}) {
sendSurveyId, sendSurveyId,
{ {
corpId: options.corpId, corpId: options.corpId,
userId: options.userId, userId: options.userId
env: options.env,
} }
); );
@ -235,10 +234,10 @@ function generateRandomString(length) {
* @returns {string} 问卷链接 * @returns {string} 问卷链接
*/ */
function generateSendLink(survey, answerId, customerId, customerName, sendSurveyId, context = {}) { function generateSendLink(survey, answerId, customerId, customerName, sendSurveyId, context = {}) {
const { corpId, userId, env } = context; const { corpId, userId } = context;
const isSystem = survey.createBy === 'system'; const isSystem = survey.createBy === 'system';
let url = ''; let url = '';
debugger
if (isSystem) { if (isSystem) {
// 系统问卷:使用 VITE_SURVEY_URL // 系统问卷:使用 VITE_SURVEY_URL
url = `${env?.MP_SURVEY_URL}?corpId=${corpId}&surveryId=${survey.surveryId}&memberId=${customerId}&sendSurveyId=${sendSurveyId}&userId=${userId}`; url = `${env?.MP_SURVEY_URL}?corpId=${corpId}&surveryId=${survey.surveryId}&memberId=${customerId}&sendSurveyId=${sendSurveyId}&userId=${userId}`;
@ -318,8 +317,7 @@ export async function handleFollowUpMessages(messages, context = {}) {
userId: context.userId, userId: context.userId,
customerId: context.customerId, customerId: context.customerId,
customerName: context.customerName, customerName: context.customerName,
corpId: context.corpId, corpId: context.corpId
env: context.env,
}); });
} }

View File

@ -2728,20 +2728,9 @@ class TimChatManager {
if (!conversationID.startsWith('GROUP')) { if (!conversationID.startsWith('GROUP')) {
formattedConversationID = `GROUP${conversationID}` formattedConversationID = `GROUP${conversationID}`
} }
this.triggerCallback('onConversationListUpdated', {
console.log('📖 标记会话为已读:', formattedConversationID); conversationID: formattedConversationID,
unreadCount: 0
this.tim.setMessageRead({
conversationID: formattedConversationID
}).then(() => {
console.log('✓ 会话已标记为已读:', formattedConversationID);
// 触发会话列表更新回调,通知消息列表页面清空未读数
this.triggerCallback('onConversationListUpdated', {
conversationID: formattedConversationID,
unreadCount: 0
})
}).catch(error => {
console.error('✗ 标记会话已读失败:', error)
}) })
} catch (error) { } catch (error) {
console.error('✗ 标记会话已读异常:', error) console.error('✗ 标记会话已读异常:', error)