no message
This commit is contained in:
parent
5d22b06b4b
commit
2363e17cc1
@ -384,7 +384,7 @@ $primary-color: #0877F1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 12rpx 20rpx;
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
padding-bottom: 60rpx;
|
||||
gap: 12rpx;
|
||||
border-top: 1rpx solid #e0e0e0;
|
||||
background: #fff;
|
||||
@ -511,7 +511,7 @@ $primary-color: #0877F1;
|
||||
background: #fff;
|
||||
border-top: 1rpx solid #eee;
|
||||
padding: 20rpx 0 20rpx 60rpx;
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
padding-bottom: 60rpx;
|
||||
gap: 40rpx 50rpx;
|
||||
flex-wrap: wrap;
|
||||
background-color: #f5f5f5;
|
||||
@ -541,7 +541,7 @@ $primary-color: #0877F1;
|
||||
background-color: white;
|
||||
border-top: 1rpx solid #e0e0e0;
|
||||
padding: 16rpx;
|
||||
margin-bottom: env(safe-area-inset-bottom);
|
||||
margin-bottom: 60rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
@ -686,7 +686,7 @@ $primary-color: #0877F1;
|
||||
width: 100%;
|
||||
max-height: 80vh;
|
||||
padding: 20rpx;
|
||||
padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
|
||||
padding-bottom: 80rpx;
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
@ -818,7 +818,7 @@ $primary-color: #0877F1;
|
||||
background-color: white;
|
||||
width: auto;
|
||||
padding: 32rpx 20rpx 48rpx 20rpx;
|
||||
padding-bottom: calc(48rpx + env(safe-area-inset-bottom));
|
||||
padding-bottom: 108rpx;
|
||||
text-align: center;
|
||||
margin: 0 auto;
|
||||
position: relative;
|
||||
|
||||
@ -12,19 +12,6 @@
|
||||
button.loading && button.loadingText ? button.loadingText : button.text
|
||||
}}</text>
|
||||
</view>
|
||||
|
||||
<!-- 病历类型选择弹窗 -->
|
||||
<medical-case-type-selector
|
||||
ref="typeSelectorRef"
|
||||
@select="handleCaseTypeSelect"
|
||||
/>
|
||||
|
||||
<!-- 进度显示弹窗 -->
|
||||
<medical-case-progress
|
||||
ref="progressRef"
|
||||
@regenerate="handleRegenerateFromProgress"
|
||||
@next="handleNextFromProgress"
|
||||
/>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
@ -32,8 +19,6 @@
|
||||
import { ref, onMounted, onUnmounted } from "vue";
|
||||
import request from "@/utils/http.js";
|
||||
import api from "@/utils/api.js";
|
||||
import MedicalCaseTypeSelector from "./medical-case-type-selector.vue";
|
||||
import MedicalCaseProgress from "./medical-case-progress.vue";
|
||||
|
||||
const props = defineProps({
|
||||
groupId: {
|
||||
@ -56,11 +41,24 @@ const props = defineProps({
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
typeSelectorRef: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
progressRef: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
const emit = defineEmits(["streamText", "clearInput", "generatingStateChange"]);
|
||||
const emit = defineEmits([
|
||||
"streamText",
|
||||
"clearInput",
|
||||
"generatingStateChange",
|
||||
"caseTypeSelect",
|
||||
"regenerateFromProgress",
|
||||
"nextFromProgress",
|
||||
]);
|
||||
|
||||
const typeSelectorRef = ref(null);
|
||||
const progressRef = ref(null);
|
||||
const isGenerating = ref(false);
|
||||
|
||||
const buttons = ref([
|
||||
@ -217,143 +215,22 @@ const handleAIAssistant = (button) => {
|
||||
|
||||
// 处理补充病历
|
||||
const handleSupplementRecord = (button) => {
|
||||
typeSelectorRef.value?.open();
|
||||
props.typeSelectorRef?.open();
|
||||
};
|
||||
|
||||
// 处理病历类型选择
|
||||
const handleCaseTypeSelect = async (type) => {
|
||||
try {
|
||||
// 打开进度弹窗
|
||||
progressRef.value?.open(type.id);
|
||||
progressRef.value?.updateProgress(10);
|
||||
|
||||
// 调用补充病历接口(流式处理)
|
||||
await requestWithStream({
|
||||
url: "/getYoucanData/im",
|
||||
data: {
|
||||
type: "supplementMedicalCase",
|
||||
groupId: props.groupId,
|
||||
patientAccountId: props.patientAccountId || props.customerId,
|
||||
corpId: props.corpId,
|
||||
caseType: type.id,
|
||||
},
|
||||
onProgress: (data) => {
|
||||
// 处理流式数据
|
||||
handleStreamData(data, type.id);
|
||||
},
|
||||
onComplete: (finalData) => {
|
||||
// 完成后跳转
|
||||
handleComplete(finalData, type.id);
|
||||
},
|
||||
onError: (error) => {
|
||||
progressRef.value?.close();
|
||||
uni.showToast({
|
||||
title: error.message || "生成病历失败",
|
||||
icon: "none",
|
||||
});
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("补充病历失败:", error);
|
||||
progressRef.value?.close();
|
||||
uni.showToast({
|
||||
title: "操作失败,请重试",
|
||||
icon: "none",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 流式请求处理
|
||||
const requestWithStream = async ({
|
||||
url,
|
||||
data,
|
||||
onProgress,
|
||||
onComplete,
|
||||
onError,
|
||||
}) => {
|
||||
try {
|
||||
// 调用接口时不显示全局 loading(第二个参数为 false)
|
||||
const result = await request(
|
||||
{
|
||||
url,
|
||||
data,
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
if (result.success && result.data) {
|
||||
// 模拟流式处理(如果后端返回的是完整数据)
|
||||
const extractedData = result.data.extractedData || {};
|
||||
|
||||
// 逐个字段动态显示(包括空值字段)
|
||||
let progressValue = 20;
|
||||
const fields = Object.entries(extractedData);
|
||||
const delay = 300; // 每个字段显示间隔
|
||||
|
||||
for (let i = 0; i < fields.length; i++) {
|
||||
const [key, value] = fields[i];
|
||||
|
||||
// 显示所有字段,包括空值(会在组件中显示为"暂无")
|
||||
await new Promise((resolve) => setTimeout(resolve, delay));
|
||||
onProgress({ key, value });
|
||||
progressValue += Math.floor(60 / fields.length);
|
||||
progressRef.value?.updateProgress(Math.min(progressValue, 80));
|
||||
}
|
||||
|
||||
// 完成
|
||||
onComplete(result.data);
|
||||
} else {
|
||||
onError(new Error(result.message || "请求失败"));
|
||||
}
|
||||
} catch (error) {
|
||||
onError(error);
|
||||
}
|
||||
};
|
||||
|
||||
// 处理流式数据
|
||||
const handleStreamData = (data, caseType) => {
|
||||
const { key, value } = data;
|
||||
|
||||
// 添加检测到的信息
|
||||
progressRef.value?.addDetectedInfo(key, value);
|
||||
};
|
||||
|
||||
// 处理完成
|
||||
const handleComplete = (finalData, caseType) => {
|
||||
progressRef.value?.updateProgress(90);
|
||||
progressRef.value?.setGenerating(true);
|
||||
|
||||
// 延迟后完成
|
||||
setTimeout(() => {
|
||||
progressRef.value?.updateProgress(100);
|
||||
progressRef.value?.setGenerating(false);
|
||||
|
||||
// 延迟后显示操作按钮(不自动跳转)
|
||||
setTimeout(() => {
|
||||
progressRef.value?.setCompleted(true, finalData);
|
||||
}, 500);
|
||||
}, 800);
|
||||
emit("caseTypeSelect", type);
|
||||
};
|
||||
|
||||
// 处理从进度弹窗点击重新生成
|
||||
const handleRegenerateFromProgress = (data) => {
|
||||
const type = { id: data.caseType };
|
||||
handleCaseTypeSelect(type);
|
||||
emit("regenerateFromProgress", data);
|
||||
};
|
||||
|
||||
// 处理从进度弹窗点击下一步
|
||||
const handleNextFromProgress = (data) => {
|
||||
// 根据病历类型动态构建表单数据
|
||||
const extractedData = data.data?.extractedData || {};
|
||||
|
||||
// 跳转到病历填写页面
|
||||
uni.navigateTo({
|
||||
url: `/pages/case/ai-medical-case-form?caseType=${data.caseType}&patientId=${
|
||||
props.patientId
|
||||
}&groupId=${props.groupId}&formData=${encodeURIComponent(
|
||||
JSON.stringify(extractedData)
|
||||
)}`,
|
||||
});
|
||||
emit("nextFromProgress", data);
|
||||
};
|
||||
|
||||
// 监听重新生成事件
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
<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" :hold-keyboard="true"
|
||||
:auto-height="true" :show-confirm-bar="false" :hold-keyboard="true"
|
||||
ref="textareaRef"
|
||||
/>
|
||||
<input v-else class="voice-input-btn" :class="{ recording: isRecording }" @touchstart="startRecord"
|
||||
|
||||
@ -165,12 +165,30 @@
|
||||
:patientAccountId="chatInfo.userID || ''"
|
||||
:patientId="patientId"
|
||||
:corpId="corpId"
|
||||
:typeSelectorRef="typeSelectorRef"
|
||||
:progressRef="progressRef"
|
||||
@streamText="handleStreamText"
|
||||
@clearInput="handleClearInput"
|
||||
@generatingStateChange="handleGeneratingStateChange"
|
||||
@caseTypeSelect="handleCaseTypeSelect"
|
||||
@regenerateFromProgress="handleRegenerateFromProgress"
|
||||
@nextFromProgress="handleNextFromProgress"
|
||||
/>
|
||||
</template>
|
||||
</ChatInput>
|
||||
|
||||
<!-- 病历类型选择弹窗 -->
|
||||
<MedicalCaseTypeSelector
|
||||
ref="typeSelectorRef"
|
||||
@select="handleCaseTypeSelect"
|
||||
/>
|
||||
|
||||
<!-- 进度显示弹窗 -->
|
||||
<MedicalCaseProgress
|
||||
ref="progressRef"
|
||||
@regenerate="handleRegenerateFromProgress"
|
||||
@next="handleNextFromProgress"
|
||||
/>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
@ -206,6 +224,9 @@ import SystemMessage from "./components/system-message.vue";
|
||||
import ConsultAccept from "./components/consult-accept.vue";
|
||||
import RejectReasonModal from "./components/reject-reason-modal.vue";
|
||||
import AIAssistantButtons from "./components/ai-assistant-buttons.vue";
|
||||
import MedicalCaseTypeSelector from "./components/medical-case-type-selector.vue";
|
||||
import MedicalCaseProgress from "./components/medical-case-progress.vue";
|
||||
import request from "@/utils/http.js";
|
||||
|
||||
const timChatManager = globalTimChatManager;
|
||||
|
||||
@ -283,6 +304,8 @@ const { initIMAfterLogin } = useAccountStore();
|
||||
// 聊天输入组件引用
|
||||
const chatInputRef = ref(null);
|
||||
const aiAssistantRef = ref(null);
|
||||
const typeSelectorRef = ref(null);
|
||||
const progressRef = ref(null);
|
||||
const isGenerating = ref(false);
|
||||
|
||||
const groupId = ref("");
|
||||
@ -983,6 +1006,142 @@ const handleGeneratingStateChange = (generating) => {
|
||||
isGenerating.value = generating;
|
||||
};
|
||||
|
||||
// 处理病历类型选择
|
||||
const handleCaseTypeSelect = async (type) => {
|
||||
try {
|
||||
// 打开进度弹窗
|
||||
progressRef.value?.open(type.id);
|
||||
progressRef.value?.updateProgress(10);
|
||||
|
||||
// 调用补充病历接口(流式处理)
|
||||
await requestWithStream({
|
||||
url: "/getYoucanData/im",
|
||||
data: {
|
||||
type: "supplementMedicalCase",
|
||||
groupId: groupId.value,
|
||||
patientAccountId: chatInfo.value.userID || "",
|
||||
corpId: corpId,
|
||||
caseType: type.id,
|
||||
},
|
||||
onProgress: (data) => {
|
||||
// 处理流式数据
|
||||
handleStreamData(data, type.id);
|
||||
},
|
||||
onComplete: (finalData) => {
|
||||
// 完成后跳转
|
||||
handleComplete(finalData, type.id);
|
||||
},
|
||||
onError: (error) => {
|
||||
progressRef.value?.close();
|
||||
uni.showToast({
|
||||
title: error.message || "生成病历失败",
|
||||
icon: "none",
|
||||
});
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("补充病历失败:", error);
|
||||
progressRef.value?.close();
|
||||
uni.showToast({
|
||||
title: "操作失败,请重试",
|
||||
icon: "none",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 流式请求处理
|
||||
const requestWithStream = async ({
|
||||
url,
|
||||
data,
|
||||
onProgress,
|
||||
onComplete,
|
||||
onError,
|
||||
}) => {
|
||||
try {
|
||||
// 调用接口时不显示全局 loading(第二个参数为 false)
|
||||
const result = await request(
|
||||
{
|
||||
url,
|
||||
data,
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
if (result.success && result.data) {
|
||||
// 模拟流式处理(如果后端返回的是完整数据)
|
||||
const extractedData = result.data.extractedData || {};
|
||||
|
||||
// 逐个字段动态显示(包括空值字段)
|
||||
let progressValue = 20;
|
||||
const fields = Object.entries(extractedData);
|
||||
const delay = 300; // 每个字段显示间隔
|
||||
|
||||
for (let i = 0; i < fields.length; i++) {
|
||||
const [key, value] = fields[i];
|
||||
|
||||
// 显示所有字段,包括空值(会在组件中显示为"暂无")
|
||||
await new Promise((resolve) => setTimeout(resolve, delay));
|
||||
onProgress({ key, value });
|
||||
progressValue += Math.floor(60 / fields.length);
|
||||
progressRef.value?.updateProgress(Math.min(progressValue, 80));
|
||||
}
|
||||
|
||||
// 完成
|
||||
onComplete(result.data);
|
||||
} else {
|
||||
onError(new Error(result.message || "请求失败"));
|
||||
}
|
||||
} catch (error) {
|
||||
onError(error);
|
||||
}
|
||||
};
|
||||
|
||||
// 处理流式数据
|
||||
const handleStreamData = (data, caseType) => {
|
||||
const { key, value } = data;
|
||||
|
||||
// 添加检测到的信息
|
||||
progressRef.value?.addDetectedInfo(key, value);
|
||||
};
|
||||
|
||||
// 处理完成
|
||||
const handleComplete = (finalData, caseType) => {
|
||||
progressRef.value?.updateProgress(90);
|
||||
progressRef.value?.setGenerating(true);
|
||||
|
||||
// 延迟后完成
|
||||
setTimeout(() => {
|
||||
progressRef.value?.updateProgress(100);
|
||||
progressRef.value?.setGenerating(false);
|
||||
|
||||
// 延迟后显示操作按钮(不自动跳转)
|
||||
setTimeout(() => {
|
||||
progressRef.value?.setCompleted(true, finalData);
|
||||
}, 500);
|
||||
}, 800);
|
||||
};
|
||||
|
||||
// 处理从进度弹窗点击重新生成
|
||||
const handleRegenerateFromProgress = (data) => {
|
||||
const type = { id: data.caseType };
|
||||
handleCaseTypeSelect(type);
|
||||
};
|
||||
|
||||
// 处理从进度弹窗点击下一步
|
||||
const handleNextFromProgress = (data) => {
|
||||
// 根据病历类型动态构建表单数据
|
||||
const extractedData = data.data?.extractedData || {};
|
||||
|
||||
// 跳转到病历填写页面
|
||||
uni.navigateTo({
|
||||
url: `/pages/case/ai-medical-case-form?caseType=${data.caseType}&patientId=${
|
||||
patientId.value
|
||||
}&groupId=${groupId.value}&formData=${encodeURIComponent(
|
||||
JSON.stringify(extractedData)
|
||||
)}`,
|
||||
});
|
||||
};
|
||||
|
||||
// 暴露方法给常用语页面调用
|
||||
defineExpose({
|
||||
sendCommonPhrase,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user