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 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="item.sender === 'system'" 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" />
<view v-else class="message-content">
<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-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-if="item.messageType !== 'risk_notice'" class="message-content">
<view v-if="item.sender === 'assistant'" class="avatar assistant-avatar">AI</view>
<view class="message-bubble-container">
<view v-if="item.sender === 'assistant'" class="username-label">{{ session?.assistantName || 'AI咨询助理' }}</view>
@ -25,8 +25,8 @@
</view>
</scroll-view>
<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" />
<button class="send-btn" :loading="sending" :disabled="!content.trim() || sending" @click="send">发送</button>
<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" :disabled="!content.trim()" @click="send">发送</button>
</view>
<view v-else class="ended">本次AI咨询已结束</view>
</view>
@ -46,7 +46,7 @@ const sessionId = ref('');
const session = ref(null);
const messages = ref([]);
const content = ref('');
const sending = ref(false);
const pendingRequestCount = ref(0);
const waitingAi = ref(false);
const bottomId = ref('');
const active = ref(false);
@ -92,12 +92,12 @@ async function detail() {
await scrollToBottom();
}
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 localMessage = { _id: `local-${Date.now()}`, sender: 'patient', content: value, messageType: 'text', createTime: Date.now(), _sendStatus: 'pending' };
messages.value.push(localMessage);
content.value = '';
sending.value = true;
pendingRequestCount.value += 1;
waitingAi.value = true;
await scrollToBottom();
try {
@ -112,8 +112,8 @@ async function send() {
localMessage._sendStatus = 'failed';
uni.showToast({ title: '发送失败,请重试', icon: 'none' });
} finally {
sending.value = false;
waitingAi.value = false;
pendingRequestCount.value -= 1;
waitingAi.value = pendingRequestCount.value > 0;
await scrollToBottom();
}
}

View File

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

View File

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