Compare commits
3 Commits
3196876bac
...
384111d6aa
| Author | SHA1 | Date | |
|---|---|---|---|
| 384111d6aa | |||
| 1df86154c8 | |||
| 15ded03ffb |
@@ -1,152 +1,174 @@
|
||||
<!-- 机构端 - AI问诊页面 -->
|
||||
<template>
|
||||
<view class="ai-page">
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<view class="detail-navbar">
|
||||
<view class="detail-navbar-back" @click="uni.navigateBack()">
|
||||
<text class="back-arrow">‹</text>
|
||||
<text class="back-text">返回</text>
|
||||
</view>
|
||||
<text class="detail-navbar-title">AI问诊</text>
|
||||
<view style="width: 120rpx;"></view>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
|
||||
<!-- 高风险提示横幅(始终显示) -->
|
||||
<view class="risk-banner">
|
||||
<text class="risk-banner-icon">⚠️</text>
|
||||
<text class="risk-banner-text">AI问诊仅供参考,不能代替专业医生诊断,紧急情况请立即拨打120</text>
|
||||
</view>
|
||||
|
||||
<!-- 症状快捷选择 -->
|
||||
<view v-if="!hasConversation" class="quick-select-area">
|
||||
<text class="qs-title">请选择主要症状(可多选)</text>
|
||||
<view class="qs-tags">
|
||||
<view
|
||||
v-for="sym in symptomOptions"
|
||||
:key="sym"
|
||||
class="qs-tag"
|
||||
:class="selectedSymptoms.includes(sym) ? 'qs-tag-selected' : ''"
|
||||
@click="toggleSymptom(sym)"
|
||||
>
|
||||
{{ sym }}
|
||||
<!-- ===== 顶部固定区 ===== -->
|
||||
<view class="top-fixed">
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<view class="detail-navbar">
|
||||
<view class="detail-navbar-back" @click="uni.navigateBack()">
|
||||
<text class="back-arrow">‹</text>
|
||||
<text class="back-text">返回</text>
|
||||
</view>
|
||||
<text class="detail-navbar-title">AI问诊</text>
|
||||
<view style="width: 120rpx;"></view>
|
||||
</view>
|
||||
<view v-if="selectedSymptoms.length > 0" class="qs-confirm-row">
|
||||
<view class="qs-confirm-btn" @click="startWithSymptoms">开始问诊</view>
|
||||
<!-- #endif -->
|
||||
|
||||
<!-- 高风险提示横幅(始终显示) -->
|
||||
<view class="risk-banner">
|
||||
<text class="risk-banner-icon">⚠️</text>
|
||||
<text class="risk-banner-text">AI问诊仅供参考,不能代替专业医生诊断,紧急情况请立即拨打120</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 对话区域 -->
|
||||
<scroll-view
|
||||
class="chat-scroll"
|
||||
direction="vertical"
|
||||
:scroll-into-view="lastMsgId"
|
||||
:scroll-with-animation="true"
|
||||
>
|
||||
<!-- 欢迎提示 -->
|
||||
<view class="welcome-msg" v-if="messages.length === 0 && !hasConversation">
|
||||
<view class="welcome-avatar">🤖</view>
|
||||
<view class="welcome-bubble">
|
||||
<text class="welcome-title">您好!我是医养AI助手</text>
|
||||
<text class="welcome-desc">我可以帮助您初步了解用户症状、进行健康风险评估,以及提供护理建议。请选择上方症状或直接输入描述。</text>
|
||||
<text class="welcome-disclaimer">⚠ 本工具仅供辅助参考,最终诊疗请遵循医嘱。</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 消息列表 -->
|
||||
<view
|
||||
v-for="(msg, idx) in messages"
|
||||
:key="idx"
|
||||
:id="'msg-' + idx"
|
||||
class="msg-row"
|
||||
:class="msg.role === 'user' ? 'msg-row-right' : 'msg-row-left'"
|
||||
<!-- ===== 中间自适应聊天区 ===== -->
|
||||
<view class="middle-flex">
|
||||
<scroll-view
|
||||
class="chat-scroll"
|
||||
direction="vertical"
|
||||
:scroll-into-view="lastMsgId"
|
||||
:scroll-with-animation="true"
|
||||
>
|
||||
<!-- AI头像 -->
|
||||
<view v-if="msg.role === 'ai'" class="msg-avatar ai-avatar">🤖</view>
|
||||
|
||||
<view class="msg-bubble-wrap" :class="msg.role === 'user' ? 'mbw-right' : 'mbw-left'">
|
||||
<!-- 高风险提醒卡片 -->
|
||||
<view v-if="msg.riskLevel === 'high'" class="risk-card">
|
||||
<view class="risk-card-header">
|
||||
<text class="risk-card-icon">🚨</text>
|
||||
<text class="risk-card-title">高风险提示</text>
|
||||
</view>
|
||||
<text class="risk-card-body">{{ msg.content }}</text>
|
||||
<view class="risk-card-actions">
|
||||
<view class="risk-action-btn rca-call" @click="callEmergency">一键拨打120</view>
|
||||
<view class="risk-action-btn rca-notify" @click="notifyFamily">通知家属</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 普通气泡 -->
|
||||
<view v-else class="msg-bubble" :class="msg.role === 'user' ? 'bubble-user' : 'bubble-ai'">
|
||||
<text class="msg-text">{{ msg.content }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 建议操作列表(AI回复带操作) -->
|
||||
<view v-if="msg.suggestions && msg.suggestions.length > 0" class="suggestion-list">
|
||||
<!-- 症状快捷选择(在聊天区顶部,随聊天区滚动) -->
|
||||
<view v-if="!hasConversation" class="quick-select-area">
|
||||
<text class="qs-title">请选择主要症状(可多选)</text>
|
||||
<view class="qs-tags">
|
||||
<view
|
||||
v-for="sug in msg.suggestions"
|
||||
:key="sug"
|
||||
class="suggestion-item"
|
||||
@click="sendMessage(sug)"
|
||||
v-for="sym in symptomOptions"
|
||||
:key="sym"
|
||||
class="qs-tag"
|
||||
:class="selectedSymptoms.includes(sym) ? 'qs-tag-selected' : ''"
|
||||
@click="toggleSymptom(sym)"
|
||||
>
|
||||
{{ sug }}
|
||||
{{ sym }}
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="selectedSymptoms.length > 0" class="qs-confirm-row">
|
||||
<view class="qs-confirm-btn" @click="startWithSymptoms">开始问诊</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 用户头像 -->
|
||||
<view v-if="msg.role === 'user'" class="msg-avatar user-avatar">👩⚕️</view>
|
||||
</view>
|
||||
|
||||
<!-- AI加载中 -->
|
||||
<view v-if="isLoading" class="msg-row msg-row-left">
|
||||
<view class="msg-avatar ai-avatar">🤖</view>
|
||||
<view class="loading-bubble">
|
||||
<view class="loading-dot"></view>
|
||||
<view class="loading-dot"></view>
|
||||
<view class="loading-dot"></view>
|
||||
<!-- 欢迎提示 -->
|
||||
<view class="welcome-msg" v-if="messages.length === 0 && !hasConversation">
|
||||
<view class="welcome-avatar">🤖</view>
|
||||
<view class="welcome-bubble">
|
||||
<text class="welcome-title">您好!我是医养AI助手</text>
|
||||
<text class="welcome-desc">我可以帮助您初步了解用户症状、进行健康风险评估,以及提供护理建议。请选择上方症状或直接输入描述。</text>
|
||||
<text class="welcome-disclaimer">⚠ 本工具仅供辅助参考,最终诊疗请遵循医嘱。</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view id="msg-bottom" style="height: 20rpx;"></view>
|
||||
</scroll-view>
|
||||
|
||||
<!-- 快捷问题(有对话后显示) -->
|
||||
<view v-if="hasConversation && quickReplies.length > 0" class="quick-replies">
|
||||
<scroll-view direction="horizontal" class="qr-scroll">
|
||||
<!-- 消息列表 -->
|
||||
<view
|
||||
v-for="qr in quickReplies"
|
||||
:key="qr"
|
||||
class="qr-chip"
|
||||
@click="sendMessage(qr)"
|
||||
v-for="(msg, idx) in messages"
|
||||
:key="idx"
|
||||
:id="'msg-' + idx"
|
||||
class="msg-row"
|
||||
:class="msg.role === 'user' ? 'msg-row-right' : 'msg-row-left'"
|
||||
>
|
||||
{{ qr }}
|
||||
<!-- AI头像 -->
|
||||
<view v-if="msg.role === 'ai'" class="msg-avatar ai-avatar">🤖</view>
|
||||
|
||||
<view class="msg-bubble-wrap" :class="msg.role === 'user' ? 'mbw-right' : 'mbw-left'">
|
||||
<!-- 高风险提醒卡片 -->
|
||||
<view v-if="msg.riskLevel === 'high'" class="risk-card">
|
||||
<view class="risk-card-header">
|
||||
<text class="risk-card-icon">🚨</text>
|
||||
<text class="risk-card-title">高风险提示</text>
|
||||
</view>
|
||||
<text class="risk-card-body">{{ msg.content }}</text>
|
||||
<view class="risk-card-actions">
|
||||
<view class="risk-action-btn rca-call" @click="callEmergency">一键拨打120</view>
|
||||
<view class="risk-action-btn rca-notify" @click="notifyFamily">通知家属</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 普通气泡 -->
|
||||
<view v-else class="msg-bubble" :class="msg.role === 'user' ? 'bubble-user' : 'bubble-ai'">
|
||||
<text class="msg-text">{{ msg.content }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 建议操作列表(AI回复带操作) -->
|
||||
<view v-if="msg.suggestions && msg.suggestions.length > 0" class="suggestion-list">
|
||||
<view
|
||||
v-for="sug in msg.suggestions"
|
||||
:key="sug"
|
||||
class="suggestion-item"
|
||||
@click="sendMessage(sug)"
|
||||
>
|
||||
{{ sug }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 用户头像 -->
|
||||
<view v-if="msg.role === 'user'" class="msg-avatar user-avatar">👩⚕️</view>
|
||||
</view>
|
||||
|
||||
<!-- AI加载中 -->
|
||||
<view v-if="isLoading" class="msg-row msg-row-left">
|
||||
<view class="msg-avatar ai-avatar">🤖</view>
|
||||
<view class="loading-bubble">
|
||||
<view class="loading-dot"></view>
|
||||
<view class="loading-dot"></view>
|
||||
<view class="loading-dot"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view id="msg-bottom" style="height: 20rpx;"></view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
|
||||
<!-- 输入区 -->
|
||||
<view class="input-bar">
|
||||
<view class="input-bar-inner">
|
||||
<input
|
||||
class="chat-input"
|
||||
v-model="inputText"
|
||||
placeholder="描述症状或询问护理建议..."
|
||||
:confirm-type="'send'"
|
||||
@confirm="onSend"
|
||||
:maxlength="200"
|
||||
/>
|
||||
<view class="send-btn" :class="inputText.trim() ? 'send-btn-active' : ''" @click="onSend">
|
||||
发送
|
||||
<!-- ===== 底部固定区 ===== -->
|
||||
<view class="bottom-fixed">
|
||||
<!-- 快捷问题模块 -->
|
||||
<view v-if="quickReplies.length > 0" class="quick-replies">
|
||||
<view class="quick-replies-header" @click="toggleQuickReplies">
|
||||
<view class="qr-header-left">
|
||||
<text class="qr-header-icon">💬</text>
|
||||
<text class="qr-title">快捷问题</text>
|
||||
</view>
|
||||
<view class="qr-toggle">
|
||||
<text class="qr-toggle-text">{{ quickRepliesExpanded ? '收起' : '展开' }}</text>
|
||||
<text class="qr-toggle-icon">{{ quickRepliesExpanded ? '▾' : '▸' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="quickRepliesExpanded" class="quick-replies-body">
|
||||
<scroll-view class="qr-scroll" :scroll-x="true" :scroll-y="false">
|
||||
<view class="qr-scroll-inner">
|
||||
<view
|
||||
v-for="qr in quickReplies"
|
||||
:key="qr"
|
||||
class="qr-chip"
|
||||
@click="sendMessage(qr)"
|
||||
>
|
||||
{{ qr }}
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="input-actions">
|
||||
<view class="ia-btn" @click="clearConversation">清空对话</view>
|
||||
<view class="ia-btn" @click="exportRecord">导出记录</view>
|
||||
<view class="ia-btn ia-btn-primary" @click="referToDoctor">转诊医生</view>
|
||||
|
||||
<!-- 输入区 -->
|
||||
<view class="input-bar">
|
||||
<view class="input-bar-inner">
|
||||
<input
|
||||
class="chat-input"
|
||||
v-model="inputText"
|
||||
placeholder="描述症状或询问护理建议..."
|
||||
:confirm-type="'send'"
|
||||
@confirm="onSend"
|
||||
:maxlength="200"
|
||||
/>
|
||||
<view class="send-btn" :class="inputText.trim() ? 'send-btn-active' : ''" @click="onSend">
|
||||
发送
|
||||
</view>
|
||||
</view>
|
||||
<view class="input-actions">
|
||||
<view class="ia-btn" @click="clearConversation">清空对话</view>
|
||||
<view class="ia-btn" @click="exportRecord">导出记录</view>
|
||||
<view class="ia-btn ia-btn-primary" @click="referToDoctor">转诊医生</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -194,7 +216,8 @@
|
||||
lastMsgId: '' as string,
|
||||
selectedSymptoms: [] as string[],
|
||||
symptomOptions: ['头晕', '胸痛', '发烧', '呼吸困难', '腹痛', '跌倒', '意识模糊', '血压异常', '血糖异常', '情绪异常'] as string[],
|
||||
quickReplies: ['症状加重了', '需要上门服务', '联系家属', '转诊医生', '今日用药'] as string[]
|
||||
quickReplies: ['症状加重了', '需要上门服务', '联系家属', '转诊医生', '今日用药'] as string[],
|
||||
quickRepliesExpanded: false as boolean
|
||||
}
|
||||
},
|
||||
|
||||
@@ -282,11 +305,16 @@
|
||||
this.messages = []
|
||||
this.hasConversation = false
|
||||
this.lastMsgId = ''
|
||||
this.quickRepliesExpanded = false
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
toggleQuickReplies() {
|
||||
this.quickRepliesExpanded = !this.quickRepliesExpanded
|
||||
},
|
||||
|
||||
exportRecord() {
|
||||
uni.showToast({ title: '导出功能开发中', icon: 'none' })
|
||||
},
|
||||
@@ -309,9 +337,34 @@
|
||||
<style>
|
||||
.ai-page {
|
||||
background-color: #f0f2f7;
|
||||
min-height: 100vh;
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* ===== 三段式布局容器 ===== */
|
||||
.top-fixed {
|
||||
flex: none;
|
||||
z-index: 10;
|
||||
background-color: #f0f2f7;
|
||||
}
|
||||
|
||||
.middle-flex {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.bottom-fixed {
|
||||
flex: none;
|
||||
z-index: 10;
|
||||
background-color: #ffffff;
|
||||
border-top-width: 1rpx;
|
||||
border-top-style: solid;
|
||||
border-top-color: #eeeeee;
|
||||
}
|
||||
|
||||
/* ===== 导航栏 ===== */
|
||||
@@ -444,7 +497,9 @@
|
||||
/* ===== 聊天滚动区 ===== */
|
||||
.chat-scroll {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
padding: 20rpx 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* ===== 欢迎消息 ===== */
|
||||
@@ -686,34 +741,98 @@
|
||||
margin: 0 4rpx;
|
||||
}
|
||||
|
||||
/* ===== 快捷回复 ===== */
|
||||
/* ===== 快捷问题模块 ===== */
|
||||
.quick-replies {
|
||||
background-color: #ffffff;
|
||||
flex: none;
|
||||
background-color: #f8f9ff;
|
||||
border-top-width: 1rpx;
|
||||
border-top-style: solid;
|
||||
border-top-color: #f0f0f0;
|
||||
border-top-color: #dde3f8;
|
||||
}
|
||||
|
||||
.quick-replies-header {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 16rpx 24rpx;
|
||||
}
|
||||
|
||||
.qr-header-left {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.qr-header-icon {
|
||||
font-size: 26rpx;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
|
||||
.qr-title {
|
||||
font-size: 26rpx;
|
||||
font-weight: 600;
|
||||
color: #444444;
|
||||
}
|
||||
|
||||
.qr-toggle {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
background-color: rgb(66,121,240);
|
||||
border-radius: 24rpx;
|
||||
padding: 8rpx 20rpx;
|
||||
}
|
||||
|
||||
.qr-toggle-text {
|
||||
font-size: 22rpx;
|
||||
color: #ffffff;
|
||||
margin-right: 6rpx;
|
||||
}
|
||||
|
||||
.qr-toggle-icon {
|
||||
font-size: 24rpx;
|
||||
color: #ffffff;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.quick-replies-body {
|
||||
padding-bottom: 12rpx;
|
||||
}
|
||||
|
||||
.qr-scroll {
|
||||
white-space: nowrap;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.qr-scroll-inner {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
align-items: center;
|
||||
padding: 0 16rpx;
|
||||
}
|
||||
|
||||
.qr-chip {
|
||||
display: inline-flex;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
font-size: 24rpx;
|
||||
color: rgb(66,121,240);
|
||||
background-color: #eef2fe;
|
||||
border-radius: 20rpx;
|
||||
padding: 10rpx 24rpx;
|
||||
margin: 12rpx 8rpx;
|
||||
background-color: #ffffff;
|
||||
border-width: 1rpx;
|
||||
border-style: solid;
|
||||
border-color: rgb(66,121,240);
|
||||
border-radius: 24rpx;
|
||||
padding: 10rpx 28rpx;
|
||||
margin: 0 8rpx;
|
||||
height: 60rpx;
|
||||
line-height: 60rpx;
|
||||
}
|
||||
|
||||
/* ===== 输入区 ===== */
|
||||
.input-bar {
|
||||
background-color: #ffffff;
|
||||
border-top-width: 1rpx;
|
||||
border-top-style: solid;
|
||||
border-top-color: #eeeeee;
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
}
|
||||
|
||||
|
||||
@@ -849,7 +849,6 @@
|
||||
background: #eeeeee;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.btn.confirm {
|
||||
background: rgb(66, 121, 240);
|
||||
color: #ffffff;
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
unpackage/cache/.app-android/class/ktClasss.ser
vendored
BIN
unpackage/cache/.app-android/class/ktClasss.ser
vendored
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user