Merge remote-tracking branch 'origin/dev-wdb' into dev-hjf
This commit is contained in:
commit
150c6072d7
@ -6,13 +6,15 @@ $text-color-sub: #999;
|
||||
$primary-color: #0877F1;
|
||||
|
||||
.chat-page {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100vh;
|
||||
background-color: #f5f5f5;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* 患者信息栏样式 - 固定在顶部 */
|
||||
@ -24,10 +26,8 @@ $primary-color: #0877F1;
|
||||
background: #fff;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
padding: 20rpx 32rpx;
|
||||
z-index: 100;
|
||||
flex-shrink: 0; /* 防止被压缩 */
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
z-index: 10;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.patient-info-content {
|
||||
@ -91,15 +91,14 @@ $primary-color: #0877F1;
|
||||
}
|
||||
|
||||
.chat-content {
|
||||
flex: 1;
|
||||
position: fixed;
|
||||
top: 100rpx; /* 患者信息栏高度,根据实际调整 */
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 200rpx; /* 输入框高度,根据实际调整 */
|
||||
box-sizing: border-box;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
min-height: 0;
|
||||
margin-top: 120rpx;
|
||||
margin-bottom: 0;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.chat-content-compressed {
|
||||
@ -364,19 +363,31 @@ $primary-color: #0877F1;
|
||||
}
|
||||
|
||||
.input-section {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: #fff;
|
||||
border-top: 1rpx solid #e0e0e0;
|
||||
position: relative;
|
||||
z-index: 200;
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
flex-shrink: 0;
|
||||
transform: translateZ(0); /* 开启硬件加速,提升性能 */
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.ai-assistant-slot {
|
||||
width: 100%;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.input-toolbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 16rpx 20rpx;
|
||||
padding: 12rpx 20rpx;
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
gap: 12rpx;
|
||||
border-top: 1rpx solid #e0e0e0;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.voice-toggle-btn {
|
||||
@ -499,7 +510,8 @@ $primary-color: #0877F1;
|
||||
justify-content: flex-start;
|
||||
background: #fff;
|
||||
border-top: 1rpx solid #eee;
|
||||
padding: 20rpx 0 40rpx 60rpx;
|
||||
padding: 20rpx 0 20rpx 60rpx;
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
gap: 40rpx 50rpx;
|
||||
flex-wrap: wrap;
|
||||
background-color: #f5f5f5;
|
||||
|
||||
@ -383,7 +383,6 @@ defineExpose({
|
||||
gap: 16rpx;
|
||||
padding: 16rpx 24rpx;
|
||||
background-color: #f8f9fa;
|
||||
border-bottom: 1rpx solid #e5e5e5;
|
||||
|
||||
.ai-button {
|
||||
display: flex;
|
||||
|
||||
@ -1,5 +1,10 @@
|
||||
<template>
|
||||
<view class="input-section">
|
||||
<!-- AI助手按钮组 -->
|
||||
<view class="ai-assistant-slot">
|
||||
<slot name="ai-assistant"></slot>
|
||||
</view>
|
||||
|
||||
<view class="input-toolbar">
|
||||
<view @click="toggleVoiceInput" class="voice-toggle-btn">
|
||||
<image v-if="showVoiceInput" src="/static/jianpan.png" class="voice-toggle-icon" mode="aspectFit"></image>
|
||||
@ -8,7 +13,8 @@
|
||||
<view class="input-area">
|
||||
<textarea v-if="!showVoiceInput" class="text-input" v-model="inputText" placeholder="我来说两句..."
|
||||
@confirm="sendTextMessage" @focus="handleInputFocus" @input="handleInput"
|
||||
:auto-height="true" :show-confirm-bar="false" :adjust-position="true" :cursor-spacing="30"
|
||||
:auto-height="true" :show-confirm-bar="false" :hold-keyboard="true"
|
||||
ref="textareaRef"
|
||||
/>
|
||||
<input v-else class="voice-input-btn" :class="{ recording: isRecording }" @touchstart="startRecord"
|
||||
@touchmove="onRecordTouchMove" @touchend="stopRecord" @touchcancel="cancelRecord" :placeholder="isRecording ? '松开发送' : '按住说话'" disabled>
|
||||
@ -100,6 +106,7 @@ const showVoiceInput = ref(false);
|
||||
const showMorePanel = ref(false);
|
||||
const isRecording = ref(false);
|
||||
const recordingText = ref("录音中...");
|
||||
const textareaRef = ref(null);
|
||||
const cloudCustomData = computed(() => {
|
||||
const arr = [
|
||||
props.chatRoomBusiness.businessType,
|
||||
@ -167,8 +174,19 @@ const initRecorderManager = () => {
|
||||
const sendTextMessage = async () => {
|
||||
if (!inputText.value.trim()) return;
|
||||
|
||||
await sendMessage("text", inputText.value);
|
||||
const textToSend = inputText.value;
|
||||
inputText.value = "";
|
||||
|
||||
await sendMessage("text", textToSend);
|
||||
|
||||
// 发送后保持焦点,不收起键盘
|
||||
nextTick(() => {
|
||||
// 通过设置 focus 属性来保持键盘显示
|
||||
// 注意:在某些情况下可能需要延迟执行
|
||||
setTimeout(() => {
|
||||
// 这里不需要手动聚焦,因为 hold-keyboard 会保持键盘
|
||||
}, 50);
|
||||
});
|
||||
};
|
||||
|
||||
// 从常用语发送文本消息
|
||||
|
||||
@ -133,23 +133,6 @@
|
||||
@cancel="handleRejectReasonCancel"
|
||||
/>
|
||||
|
||||
<!-- AI助手按钮组 -->
|
||||
<AIAssistantButtons
|
||||
v-if="
|
||||
!isEvaluationPopupOpen &&
|
||||
!showConsultAccept &&
|
||||
orderStatus === 'processing'
|
||||
"
|
||||
ref="aiAssistantRef"
|
||||
:groupId="groupId"
|
||||
:patientAccountId="chatInfo.userID || ''"
|
||||
:patientId="patientId"
|
||||
:corpId="corpId"
|
||||
@streamText="handleStreamText"
|
||||
@clearInput="handleClearInput"
|
||||
@generatingStateChange="handleGeneratingStateChange"
|
||||
/>
|
||||
|
||||
<!-- 聊天输入组件 -->
|
||||
<ChatInput
|
||||
v-if="!isEvaluationPopupOpen && !showConsultAccept"
|
||||
@ -172,7 +155,22 @@
|
||||
@messageSent="() => scrollToBottom(true)"
|
||||
@endConsult="handleEndConsult"
|
||||
@openConsult="handleOpenConsult"
|
||||
/>
|
||||
>
|
||||
<!-- AI助手按钮组插槽 -->
|
||||
<template #ai-assistant>
|
||||
<AIAssistantButtons
|
||||
v-if="orderStatus === 'processing'"
|
||||
ref="aiAssistantRef"
|
||||
:groupId="groupId"
|
||||
:patientAccountId="chatInfo.userID || ''"
|
||||
:patientId="patientId"
|
||||
:corpId="corpId"
|
||||
@streamText="handleStreamText"
|
||||
@clearInput="handleClearInput"
|
||||
@generatingStateChange="handleGeneratingStateChange"
|
||||
/>
|
||||
</template>
|
||||
</ChatInput>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
@ -214,6 +212,7 @@ const timChatManager = globalTimChatManager;
|
||||
const PENDING_FOLLOWUP_SEND_STORAGE_KEY = "ykt_followup_pending_send";
|
||||
const pendingFollowUpSendConsumed = ref(false);
|
||||
const initialMessageListLoaded = ref(false);
|
||||
const isCallbacksInitialized = ref(false); // 标记回调是否已初始化
|
||||
|
||||
function normalizeGroupId(v) {
|
||||
const s = String(v || "").trim();
|
||||
@ -302,6 +301,7 @@ const chatInfo = ref({
|
||||
userID: "",
|
||||
avatar: "/static/home/avatar.svg",
|
||||
});
|
||||
|
||||
// 评价弹窗状态
|
||||
const isEvaluationPopupOpen = ref(false);
|
||||
|
||||
@ -492,6 +492,9 @@ const checkLoginAndInitTIM = async () => {
|
||||
|
||||
// 初始化IM回调函数
|
||||
const initTIMCallbacks = async () => {
|
||||
// 标记回调已初始化
|
||||
isCallbacksInitialized.value = true;
|
||||
|
||||
timChatManager.setCallback("onSDKReady", () => {
|
||||
if (messageList.value.length === 0 && !isLoading.value) {
|
||||
loadMessageList();
|
||||
@ -878,26 +881,49 @@ onShow(() => {
|
||||
if (!isIMInitialized.value) {
|
||||
checkLoginAndInitTIM();
|
||||
} else if (timChatManager.tim && !timChatManager.isLoggedIn) {
|
||||
timChatManager.ensureIMConnection();
|
||||
// IM未登录,尝试重连
|
||||
timChatManager.ensureIMConnection().then(() => {
|
||||
// 重连成功后重新注册回调
|
||||
if (timChatManager.isLoggedIn && chatInfo.value.conversationID) {
|
||||
console.log("✓ 重连成功,重新注册消息监听回调");
|
||||
initTIMCallbacks();
|
||||
timChatManager.setConversationID(chatInfo.value.conversationID);
|
||||
}
|
||||
});
|
||||
} else if (
|
||||
timChatManager.tim &&
|
||||
timChatManager.isLoggedIn &&
|
||||
chatInfo.value.conversationID
|
||||
)
|
||||
) {
|
||||
// IM已登录,只需要重新设置会话ID,不重新注册回调(避免影响正在发送的消息)
|
||||
console.log("✓ 页面显示,重新设置当前会话ID");
|
||||
timChatManager.setConversationID(chatInfo.value.conversationID);
|
||||
|
||||
// 如果回调未初始化,才进行初始化
|
||||
if (!isCallbacksInitialized.value) {
|
||||
console.log("✓ 回调未初始化,进行初始化");
|
||||
initTIMCallbacks();
|
||||
}
|
||||
|
||||
// 标记会话为已读
|
||||
if (timChatManager.tim && timChatManager.isLoggedIn) {
|
||||
timChatManager.tim
|
||||
.setMessageRead({
|
||||
conversationID: chatInfo.value.conversationID,
|
||||
})
|
||||
.then(() => {
|
||||
console.log("✓ 页面显示时已标记会话为已读");
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("✗ 标记会话已读失败:", error);
|
||||
});
|
||||
}
|
||||
|
||||
startIMMonitoring(30000);
|
||||
}
|
||||
|
||||
// 监听回访任务发送事件
|
||||
uni.$on("send-followup-message", handleSendFollowUpMessage);
|
||||
|
||||
// 监听键盘高度变化,自动滚动到底部
|
||||
uni.onKeyboardHeightChange((res) => {
|
||||
if (res.height > 0) {
|
||||
// 键盘弹出,延迟滚动到底部
|
||||
setTimeout(() => {
|
||||
scrollToBottom(true);
|
||||
}, 100);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// 处理发送回访任务消息
|
||||
|
||||
@ -96,4 +96,8 @@ onLoad((opt) => {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
}
|
||||
|
||||
.pt-12 {
|
||||
padding-top: 24rpx;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -192,6 +192,7 @@ export async function sendArticleMessage(article, options = {}) {
|
||||
userId: options.userId,
|
||||
customerId: options.customerId,
|
||||
corpId: options.corpId,
|
||||
uniqueRecord: 'YES'
|
||||
};
|
||||
if (options.teamId) {
|
||||
params.teamId = options.teamId;
|
||||
@ -424,7 +425,7 @@ export async function handleFollowUpMessages(messages, context = {}) {
|
||||
corpId: context.corpId,
|
||||
});
|
||||
} else if (msg.type === 'questionnaire') {
|
||||
|
||||
|
||||
success = await sendSurveyMessage(msg.content, {
|
||||
userId: context.userId,
|
||||
customerId: context.customerId,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user