ai咨询服务优化

This commit is contained in:
wangdongbo 2026-08-07 18:15:14 +08:00
parent 1654b4267e
commit dace2bb2da
3 changed files with 32 additions and 19 deletions

View File

@ -4,9 +4,9 @@
<view class="message-list"> <view class="message-list">
<view v-for="(item, index) in messages" :key="item._id" :id="`message-${item._id}`" class="message-item" :class="`message-${item.sender}`"> <view v-for="(item, index) in messages" :key="item._id" :id="`message-${item._id}`" class="message-item" :class="`message-${item.sender}`">
<view v-if="shouldShowTime(item, index)" class="time-divider">{{ formatMessageTime(item.createTime) }}</view> <view v-if="shouldShowTime(item, index)" class="time-divider">{{ formatMessageTime(item.createTime) }}</view>
<view v-if="item.sender === 'system'" class="system-message" :class="{ warn: item.messageType === 'sensitive_notice' }">{{ displayContent(item) }}</view> <view v-if="item.sender === 'system' && item.messageType !== 'risk_notice'" class="system-message" :class="{ warn: item.messageType === 'sensitive_notice' }">{{ displayContent(item) }}</view>
<evaluation-card v-if="item.messageType === 'consult_ended' && (item.rateId || session?.rateId)" class="rate-card" :extension="{ rateId: item.rateId || session.rateId }" :doctor-info="rateAssistantInfo" /> <evaluation-card v-else-if="item.messageType === 'consult_ended' && (item.rateId || session?.rateId)" class="rate-card" :extension="{ rateId: item.rateId || session.rateId }" :corp-id="corpId" :doctor-info="rateAssistantInfo" />
<view v-else class="message-content"> <view v-else-if="item.messageType !== 'risk_notice'" class="message-content">
<view v-if="item.sender === 'assistant'" class="avatar assistant-avatar">AI</view> <view v-if="item.sender === 'assistant'" class="avatar assistant-avatar">AI</view>
<view class="message-bubble-container"> <view class="message-bubble-container">
<view v-if="item.sender === 'assistant'" class="username-label">{{ session?.assistantName || 'AI咨询助理' }}</view> <view v-if="item.sender === 'assistant'" class="username-label">{{ session?.assistantName || 'AI咨询助理' }}</view>
@ -25,8 +25,8 @@
</view> </view>
</scroll-view> </scroll-view>
<view v-if="active" class="input-section"> <view v-if="active" class="input-section">
<textarea v-model="content" class="text-input" maxlength="1000" auto-height confirm-type="send" :show-confirm-bar="false" :disabled="sending" placeholder="请输入消息" @confirm="send" /> <textarea v-model="content" class="text-input" maxlength="1000" auto-height confirm-type="send" :show-confirm-bar="false" placeholder="请输入消息" @confirm="send" />
<button class="send-btn" :loading="sending" :disabled="!content.trim() || sending" @click="send">发送</button> <button class="send-btn" :disabled="!content.trim()" @click="send">发送</button>
</view> </view>
<view v-else class="ended">本次AI咨询已结束</view> <view v-else class="ended">本次AI咨询已结束</view>
</view> </view>
@ -46,7 +46,7 @@ const sessionId = ref('');
const session = ref(null); const session = ref(null);
const messages = ref([]); const messages = ref([]);
const content = ref(''); const content = ref('');
const sending = ref(false); const pendingRequestCount = ref(0);
const waitingAi = ref(false); const waitingAi = ref(false);
const bottomId = ref(''); const bottomId = ref('');
const active = ref(false); const active = ref(false);
@ -92,12 +92,12 @@ async function detail() {
await scrollToBottom(); await scrollToBottom();
} }
async function send() { async function send() {
if (!active.value || sending.value || !content.value.trim()) return; if (!active.value || !content.value.trim()) return;
const value = content.value.trim(); const value = content.value.trim();
const localMessage = { _id: `local-${Date.now()}`, sender: 'patient', content: value, messageType: 'text', createTime: Date.now(), _sendStatus: 'pending' }; const localMessage = { _id: `local-${Date.now()}`, sender: 'patient', content: value, messageType: 'text', createTime: Date.now(), _sendStatus: 'pending' };
messages.value.push(localMessage); messages.value.push(localMessage);
content.value = ''; content.value = '';
sending.value = true; pendingRequestCount.value += 1;
waitingAi.value = true; waitingAi.value = true;
await scrollToBottom(); await scrollToBottom();
try { try {
@ -112,8 +112,8 @@ async function send() {
localMessage._sendStatus = 'failed'; localMessage._sendStatus = 'failed';
uni.showToast({ title: '发送失败,请重试', icon: 'none' }); uni.showToast({ title: '发送失败,请重试', icon: 'none' });
} finally { } finally {
sending.value = false; pendingRequestCount.value -= 1;
waitingAi.value = false; waitingAi.value = pendingRequestCount.value > 0;
await scrollToBottom(); await scrollToBottom();
} }
} }

View File

@ -85,7 +85,7 @@
<script setup> <script setup>
import { ref, computed } from 'vue'; import { ref, computed } from 'vue';
import { getRate, submitRate } from '@/api/corp/rate'; import api from '@/utils/api';
import { toast } from '@/utils/widget'; import { toast } from '@/utils/widget';
// Props // Props
@ -98,6 +98,10 @@ const props = defineProps({
type: Object, type: Object,
default: () => ({}) default: () => ({})
}, },
corpId: {
type: String,
default: ''
},
}); });
// Emits // Emits
@ -121,12 +125,15 @@ const ratingText = computed(() => {
const openEvaluationPopup = async () => { const openEvaluationPopup = async () => {
evaluationRating.value = 0 evaluationRating.value = 0
evaluationComment.value = '' evaluationComment.value = ''
const res = await getRate(props.extension.rateId); const res = await api('getRateRecord', {
id: props.extension.rateId,
corpId: props.extension.corpId || props.corpId
});
if (res && res.success) { if (res && res.success) {
record.value = res.data; record.value = res.record || {};
evaluationRating.value = typeof res.data.rate === 'number' ? res.data.rate : 0; evaluationRating.value = typeof record.value.rate === 'number' ? record.value.rate : 0;
evaluationComment.value = typeof res.data.words === 'string' ? res.data.words : ''; evaluationComment.value = typeof record.value.words === 'string' ? record.value.words : '';
if (record.value.status === 'init') { if (!res.rated && res.enable) {
evaluationPopup.value.open(); evaluationPopup.value.open();
emit('popupStatusChange', true); // emit('popupStatusChange', true); //
} else { } else {
@ -158,8 +165,9 @@ const submitEvaluation = async () => {
} }
if (loading.value) return; if (loading.value) return;
loading.value = true; loading.value = true;
const res = await submitRate({ const res = await api('submitRateRecord', {
id: props.extension.rateId, id: props.extension.rateId,
corpId: props.extension.corpId || props.corpId,
rate: evaluationRating.value, rate: evaluationRating.value,
words: evaluationComment.value words: evaluationComment.value
}); });

View File

@ -3,6 +3,7 @@
v-if="payload.description === 'PATIENT_RATE_MESSAGE'" v-if="payload.description === 'PATIENT_RATE_MESSAGE'"
:doctorInfo="doctorInfo" :doctorInfo="doctorInfo"
:extension="extension" :extension="extension"
:corpId="corpId"
@popupStatusChange="handlePopupStatusChange" @popupStatusChange="handlePopupStatusChange"
/> />
</template> </template>
@ -17,6 +18,10 @@ const props = defineProps({
doctorInfo:{ doctorInfo:{
type: Object, type: Object,
default: () => ({}) default: () => ({})
},
corpId: {
type: String,
default: ''
} }
}); });