no message

This commit is contained in:
wangdongbo 2026-02-02 13:27:48 +08:00
parent a7d3eeae3a
commit 3ccdc954c2
5 changed files with 394 additions and 395 deletions

View File

@ -1,211 +1,45 @@
<template> <template>
<view class="medical-case-form"> <view class="medical-case-form">
<view class="form-container"> <view class="form-container">
<!-- 门诊病历 --> <!-- 动态渲染表单字段 -->
<template v-if="caseType === 'outpatient'"> <view
<view class="form-item required"> v-for="field in currentFields"
<view class="item-label">就诊机构</view> :key="field.key"
<input class="form-item"
class="item-input" :class="{ required: field.required }"
v-model="formData.hospital" >
placeholder="暂无" <view class="item-label">{{ field.label }}</view>
:disabled="!isEditing"
/>
</view>
<view class="form-item required"> <!-- 日期选择器 -->
<view class="item-label">就诊日期</view> <picker
<picker v-if="field.type === 'date'"
mode="date" mode="date"
:value="formData.visitTime" :value="formData[field.key]"
@change="onDateChange('visitTime', $event)" @change="onDateChange(field.key, $event)"
:disabled="!isEditing" :disabled="!isEditing"
> >
<view class="picker-value"> <view class="picker-value">
{{ formData.visitTime || '暂无' }} {{ formData[field.key] || "暂无" }}
</view> </view>
</picker> </picker>
</view>
<view class="form-item required"> <!-- 多行文本 -->
<view class="item-label">门诊诊断</view> <textarea
<textarea v-else-if="field.type === 'textarea'"
class="item-textarea" class="item-textarea"
v-model="formData.diagnosisName" v-model="formData[field.key]"
placeholder="请输入" placeholder="请输入"
:disabled="!isEditing" :disabled="!isEditing"
/> />
</view>
<view class="form-item"> <!-- 单行文本 -->
<view class="item-label">治疗方案</view> <input
<textarea v-else
class="item-textarea" class="item-input"
v-model="formData.treatmentPlan" v-model="formData[field.key]"
placeholder="请输入" placeholder="暂无"
:disabled="!isEditing" :disabled="!isEditing"
/> />
</view>
</template>
<!-- 住院病历 -->
<template v-if="caseType === 'inpatient'">
<view class="form-item required">
<view class="item-label">就诊机构</view>
<input
class="item-input"
v-model="formData.hospital"
placeholder="暂无"
:disabled="!isEditing"
/>
</view>
<view class="form-item required">
<view class="item-label">入院日期</view>
<picker
mode="date"
:value="formData.inhosDate"
@change="onDateChange('inhosDate', $event)"
:disabled="!isEditing"
>
<view class="picker-value">
{{ formData.inhosDate || '暂无' }}
</view>
</picker>
</view>
<view class="form-item required">
<view class="item-label">住院主诊断</view>
<textarea
class="item-textarea"
v-model="formData.diagnosisName"
placeholder="请输入"
:disabled="!isEditing"
/>
</view>
<view class="form-item">
<view class="item-label">手术名称</view>
<textarea
class="item-textarea"
v-model="formData.operation"
placeholder="请输入"
:disabled="!isEditing"
/>
</view>
<view class="form-item">
<view class="item-label">手术日期</view>
<picker
mode="date"
:value="formData.operationDate"
@change="onDateChange('operationDate', $event)"
:disabled="!isEditing"
>
<view class="picker-value">
{{ formData.operationDate || '暂无' }}
</view>
</picker>
</view>
<view class="form-item">
<view class="item-label">治疗方案</view>
<textarea
class="item-textarea"
v-model="formData.treatmentPlan"
placeholder="请输入"
:disabled="!isEditing"
/>
</view>
</template>
<!-- 体检记录 -->
<template v-if="caseType === 'physicalExam'">
<view class="form-item required">
<view class="item-label">就诊机构</view>
<input
class="item-input"
v-model="formData.hospital"
placeholder="暂无"
:disabled="!isEditing"
/>
</view>
<view class="form-item required">
<view class="item-label">体检日期</view>
<picker
mode="date"
:value="formData.inspectTime"
@change="onDateChange('inspectTime', $event)"
:disabled="!isEditing"
>
<view class="picker-value">
{{ formData.inspectTime || '暂无' }}
</view>
</picker>
</view>
<view class="form-item">
<view class="item-label">体检小结</view>
<textarea
class="item-textarea"
v-model="formData.inspectSummary"
placeholder="请输入"
:disabled="!isEditing"
/>
</view>
<view class="form-item">
<view class="item-label">阳性发现及处理意见</view>
<textarea
class="item-textarea"
v-model="formData.positiveFind"
placeholder="请输入"
:disabled="!isEditing"
/>
</view>
</template>
<!-- 预问诊记录 -->
<template v-if="caseType === 'preConsultation'">
<view class="form-item">
<view class="item-label">主诉</view>
<textarea
class="item-textarea"
v-model="formData.chiefComplaint"
placeholder="请输入"
:disabled="!isEditing"
/>
</view>
<view class="form-item">
<view class="item-label">现病史</view>
<textarea
class="item-textarea"
v-model="formData.presentIllnessHistory"
placeholder="请输入"
:disabled="!isEditing"
/>
</view>
<view class="form-item">
<view class="item-label">既往史</view>
<textarea
class="item-textarea"
v-model="formData.pastMedicalHistory"
placeholder="请输入"
:disabled="!isEditing"
/>
</view>
</template>
<view class="tips-box">
<text class="tips-text">
1门诊住院病历记录生成生成后支持医生在线编辑并保存至档案或者重新生成
</text>
<text class="tips-text">
2若未来集到有效信息则以模板字段中默认项写无内容生成医生可以直接在存字段上进行编辑
</text>
</view> </view>
</view> </view>
@ -221,42 +55,212 @@
</template> </template>
<script setup> <script setup>
import { ref, onMounted } from 'vue'; import { ref, computed, onMounted } from "vue";
import { storeToRefs } from "pinia";
const caseType = ref(''); import useAccountStore from "@/store/account";
import api from "@/utils/api.js";
const caseType = ref("");
const formData = ref({}); const formData = ref({});
const isEditing = ref(true); const isEditing = ref(true);
const customerId = ref(''); const customerId = ref("");
const groupId = ref(''); const groupId = ref("");
const accountStore = useAccountStore();
const { doctorInfo } = storeToRefs(accountStore);
//
const CASE_TYPE_NAMES = {
outpatient: "门诊病历",
inhospital: "住院病历",
physicalExaminationTemplate: "体检记录",
preConsultation: "预问诊记录",
};
//
const FIELD_LABELS = {
//
visitTime: "就诊日期",
chiefComplaint: "主诉",
medicalHistorySummary: "病史概要",
examination: "检查",
diagnosisName: "门诊诊断",
//
inhosDate: "入院日期",
operation: "手术记录",
operationDate: "手术日期",
treatmentPlan: "治疗方案",
//
inspectTime: "体检日期",
inspectSummary: "体检小结",
positiveFind: "阳性发现及处理意见",
//
presentIllnessHistory: "现病史",
pastMedicalHistory: "既往史",
};
//
const FIELD_CONFIG = {
outpatient: [
{
key: "visitTime",
label: FIELD_LABELS.visitTime,
type: "date",
required: false,
},
{
key: "diagnosisName",
label: FIELD_LABELS.diagnosisName,
type: "textarea",
required: false,
},
{
key: "chiefComplaint",
label: FIELD_LABELS.chiefComplaint,
type: "textarea",
required: false,
},
{
key: "medicalHistorySummary",
label: FIELD_LABELS.medicalHistorySummary,
type: "textarea",
required: false,
},
{
key: "examination",
label: FIELD_LABELS.examination,
type: "textarea",
required: false,
},
{
key: "treatmentPlan",
label: "治疗方案",
type: "textarea",
required: false,
},
],
inhospital: [
{
key: "inhosDate",
label: FIELD_LABELS.inhosDate,
type: "date",
required: false,
},
{
key: "diagnosisName",
label: "住院主诊断",
type: "textarea",
required: false,
},
{
key: "operation",
label: FIELD_LABELS.operation,
type: "textarea",
required: false,
},
{
key: "operationDate",
label: FIELD_LABELS.operationDate,
type: "date",
required: false,
},
{
key: "treatmentPlan",
label: FIELD_LABELS.treatmentPlan,
type: "textarea",
required: false,
},
{
key: "chiefComplaint",
label: FIELD_LABELS.chiefComplaint,
type: "textarea",
required: false,
},
{
key: "medicalHistorySummary",
label: FIELD_LABELS.medicalHistorySummary,
type: "textarea",
required: false,
},
{
key: "examination",
label: FIELD_LABELS.examination,
type: "textarea",
required: false,
},
{
key: "treatmentPlan",
label: "治疗方案",
type: "textarea",
required: false,
},
],
physicalExaminationTemplate: [
{
key: "inspectTime",
label: FIELD_LABELS.inspectTime,
type: "date",
required: false,
},
{
key: "inspectSummary",
label: FIELD_LABELS.inspectSummary,
type: "textarea",
required: false,
},
{
key: "positiveFind",
label: FIELD_LABELS.positiveFind,
type: "textarea",
required: false,
},
],
preConsultation: [
{
key: "chiefComplaint",
label: FIELD_LABELS.chiefComplaint,
type: "textarea",
required: false,
},
{
key: "presentIllnessHistory",
label: FIELD_LABELS.presentIllnessHistory,
type: "textarea",
required: false,
},
{
key: "pastMedicalHistory",
label: FIELD_LABELS.pastMedicalHistory,
type: "textarea",
required: false,
},
],
};
//
const currentFields = computed(() => {
return FIELD_CONFIG[caseType.value] || [];
});
onMounted(() => { onMounted(() => {
const pages = getCurrentPages(); const pages = getCurrentPages();
const currentPage = pages[pages.length - 1]; const currentPage = pages[pages.length - 1];
const options = currentPage.options; const options = currentPage.options;
caseType.value = options.caseType || ''; caseType.value = options.caseType || "";
customerId.value = options.customerId || ''; customerId.value = options.patientId || "";
groupId.value = options.groupId || ''; groupId.value = options.groupId || "";
// options // options
if (options.formData) { if (options.formData) {
try { try {
formData.value = JSON.parse(decodeURIComponent(options.formData)); formData.value = JSON.parse(decodeURIComponent(options.formData));
} catch (e) { } catch (e) {
console.error('解析表单数据失败:', e); console.error("解析表单数据失败:", e);
} }
} }
// //
const titles = { const title = CASE_TYPE_NAMES[caseType.value]
outpatient: '添加门诊病历', ? `添加${CASE_TYPE_NAMES[caseType.value]}`
inpatient: '添加住院病历', : "添加病历";
physicalExam: '添加体检记录', uni.setNavigationBarTitle({ title });
preConsultation: '添加预问诊记录'
};
uni.setNavigationBarTitle({
title: titles[caseType.value] || '添加病历'
});
}); });
const onDateChange = (field, event) => { const onDateChange = (field, event) => {
@ -265,55 +269,55 @@ const onDateChange = (field, event) => {
const handleRegenerate = () => { const handleRegenerate = () => {
uni.showModal({ uni.showModal({
title: '提示', title: "提示",
content: '确定要重新生成吗?当前编辑的内容将被覆盖', content: "确定要重新生成吗?当前编辑的内容将被覆盖",
success: (res) => { success: (res) => {
if (res.confirm) { if (res.confirm) {
// //
uni.navigateBack({ uni.navigateBack({
success: () => { success: () => {
uni.$emit('regenerateMedicalCase', { uni.$emit("regenerateMedicalCase", {
caseType: caseType.value, caseType: caseType.value,
customerId: customerId.value, customerId: customerId.value,
groupId: groupId.value groupId: groupId.value,
}); });
} },
}); });
} }
} },
}); });
}; };
const handleSave = async () => { const handleSave = async () => {
// //
const requiredFields = getRequiredFields(); const requiredFields = getRequiredFields();
const missingFields = requiredFields.filter(field => !formData.value[field.key]); const missingFields = requiredFields.filter(
(field) => !formData.value[field.key]
);
if (missingFields.length > 0) { if (missingFields.length > 0) {
uni.showToast({ uni.showToast({
title: `请填写${missingFields[0].label}`, title: `请填写${missingFields[0].label}`,
icon: 'none' icon: "none",
}); });
return; return;
} }
try { try {
uni.showLoading({ title: '保存中...' }); uni.showLoading({ title: "保存中..." });
const result = await api("addMedicalRecord", {
// medicalType: caseType.value,
const api = (await import('@/utils/api.js')).default; memberId: customerId.value,
const result = await api('addMedicalRecord', { creator: doctorInfo.value.userid,
customerId: customerId.value, ...formData.value,
caseType: caseType.value,
...formData.value
}); });
uni.hideLoading(); uni.hideLoading();
if (result.success) { if (result.success) {
uni.showToast({ uni.showToast({
title: '保存成功', title: "保存成功",
icon: 'success' icon: "success",
}); });
setTimeout(() => { setTimeout(() => {
@ -321,40 +325,22 @@ const handleSave = async () => {
}, 1500); }, 1500);
} else { } else {
uni.showToast({ uni.showToast({
title: result.message || '保存失败', title: result.message || "保存失败",
icon: 'none' icon: "none",
}); });
} }
} catch (error) { } catch (error) {
uni.hideLoading(); uni.hideLoading();
console.error('保存病历失败:', error); console.error("保存病历失败:", error);
uni.showToast({ uni.showToast({
title: '保存失败,请重试', title: "保存失败,请重试",
icon: 'none' icon: "none",
}); });
} }
}; };
const getRequiredFields = () => { const getRequiredFields = () => {
const fieldsMap = { return currentFields.value.filter((field) => field.required);
outpatient: [
{ key: 'hospital', label: '就诊机构' },
{ key: 'visitTime', label: '就诊日期' },
{ key: 'diagnosisName', label: '门诊诊断' }
],
inpatient: [
{ key: 'hospital', label: '就诊机构' },
{ key: 'inhosDate', label: '入院日期' },
{ key: 'diagnosisName', label: '住院主诊断' }
],
physicalExam: [
{ key: 'hospital', label: '就诊机构' },
{ key: 'inspectTime', label: '体检日期' }
],
preConsultation: []
};
return fieldsMap[caseType.value] || [];
}; };
</script> </script>
@ -372,7 +358,7 @@ const getRequiredFields = () => {
margin-bottom: 32rpx; margin-bottom: 32rpx;
&.required .item-label::before { &.required .item-label::before {
content: '*'; content: "*";
color: #ff4d4f; color: #ff4d4f;
margin-right: 8rpx; margin-right: 8rpx;
} }
@ -406,13 +392,13 @@ const getRequiredFields = () => {
.item-textarea { .item-textarea {
width: 100%; width: 100%;
min-height: 160rpx; min-height: 100rpx;
padding: 20rpx 24rpx; padding: 20rpx 24rpx;
background-color: #f8f9fa; background-color: #f8f9fa;
border-radius: 8rpx; border-radius: 8rpx;
font-size: 28rpx; font-size: 28rpx;
color: #333333; color: #333333;
height: 100px;
&[disabled] { &[disabled] {
color: #999999; color: #999999;
} }
@ -444,6 +430,7 @@ const getRequiredFields = () => {
bottom: 0; bottom: 0;
left: 0; left: 0;
right: 0; right: 0;
z-index: 100;
display: flex; display: flex;
gap: 24rpx; gap: 24rpx;
padding: 24rpx 32rpx; padding: 24rpx 32rpx;

View File

@ -44,6 +44,10 @@ const props = defineProps({
type: String, type: String,
default: "", default: "",
}, },
patientId: {
type: String,
default: "",
},
corpId: { corpId: {
type: String, type: String,
default: "", default: "",
@ -333,12 +337,15 @@ const handleRegenerateFromProgress = (data) => {
// //
const handleNextFromProgress = (data) => { const handleNextFromProgress = (data) => {
//
const extractedData = data.data?.extractedData || {};
// //
uni.navigateTo({ uni.navigateTo({
url: `/pages/case/medical-case-form?caseType=${data.caseType}&customerId=${ url: `/pages/case/medical-case-form?caseType=${data.caseType}&patientId=${
props.customerId || props.patientAccountId props.patientId
}&groupId=${props.groupId}&formData=${encodeURIComponent( }&groupId=${props.groupId}&formData=${encodeURIComponent(
JSON.stringify(data.data?.extractedData || {}) JSON.stringify(extractedData)
)}`, )}`,
}); });
}; };

View File

@ -10,12 +10,15 @@
<view class="progress-bar-wrapper"> <view class="progress-bar-wrapper">
<view class="progress-bar"> <view class="progress-bar">
<view class="progress-fill" :style="{ width: progress + '%' }"></view> <view
class="progress-fill"
:style="{ width: progress + '%' }"
></view>
</view> </view>
<text class="progress-text">{{ progress }}%</text> <text class="progress-text">{{ progress }}%</text>
</view> </view>
<view class="detected-info"> <view class="detected-info">
<text class="detected-title">检测到以下{{ caseTypeName }}信息</text> <text class="detected-title">检测到以下{{ caseTypeName }}信息</text>
<view class="info-list"> <view class="info-list">
<view <view
@ -54,48 +57,47 @@
</template> </template>
<script setup> <script setup>
import { ref, computed } from 'vue'; import { ref, computed } from "vue";
const emit = defineEmits(['regenerate', 'next']); const emit = defineEmits(["regenerate", "next"]);
const popup = ref(null); const popup = ref(null);
const progress = ref(0); const progress = ref(0);
const detectedInfo = ref([]); const detectedInfo = ref([]);
const isGenerating = ref(false); const isGenerating = ref(false);
const isCompleted = ref(false); const isCompleted = ref(false);
const caseType = ref(''); const caseType = ref("");
const finalData = ref(null); const finalData = ref(null);
const CASE_TYPE_NAMES = { const CASE_TYPE_NAMES = {
outpatient: '门诊病历', outpatient: "门诊病历",
inpatient: '住院病历', inhospital: "住院病历",
physicalExam: '体检记录', physicalExaminationTemplate: "体检记录",
preConsultation: '预问诊记录' preConsultation: "预问诊记录",
}; };
const FIELD_LABELS = { const FIELD_LABELS = {
// //
visitTime: '就诊日期', visitTime: "就诊日期",
chiefComplaint: '主诉', chiefComplaint: "主诉",
medicalHistorySummary: '病史概要', medicalHistorySummary: "病史概要",
examination: '检查', examination: "检查",
diagnosisName: '门诊诊断', diagnosisName: "门诊诊断",
// //
inhosDate: '入院日期', inhosDate: "入院日期",
operation: '手术记录', operation: "手术名称",
operationDate: '手术日期', operationDate: "手术日期",
treatmentPlan: '术后病程', treatmentPlan: "治疗方案",
outhosAdvice: '出院医嘱',
// //
inspectTime: '体检日期', inspectTime: "体检日期",
inspectSummary: '体检小结', inspectSummary: "体检小结",
positiveFind: '阳性发现及处理意见', positiveFind: "阳性发现及处理意见",
// //
presentIllnessHistory: '现病史', presentIllnessHistory: "现病史",
pastMedicalHistory: '既往史' pastMedicalHistory: "既往史",
}; };
const caseTypeName = computed(() => CASE_TYPE_NAMES[caseType.value] || '病历'); const caseTypeName = computed(() => CASE_TYPE_NAMES[caseType.value] || "病历");
const progressTitle = computed(() => { const progressTitle = computed(() => {
if (progress.value < 100) { if (progress.value < 100) {
@ -125,11 +127,11 @@ const updateProgress = (value) => {
const addDetectedInfo = (fieldKey, fieldValue) => { const addDetectedInfo = (fieldKey, fieldValue) => {
const label = FIELD_LABELS[fieldKey] || fieldKey; const label = FIELD_LABELS[fieldKey] || fieldKey;
// "" // ""
const displayValue = (fieldValue && fieldValue.trim()) ? fieldValue : '暂无'; const displayValue = fieldValue && fieldValue.trim() ? fieldValue : "暂无";
detectedInfo.value.push({ detectedInfo.value.push({
label, label,
value: displayValue, value: displayValue,
animated: true animated: true,
}); });
}; };
@ -151,14 +153,14 @@ const reset = () => {
}; };
const handleRegenerate = () => { const handleRegenerate = () => {
emit('regenerate', { caseType: caseType.value }); emit("regenerate", { caseType: caseType.value });
close(); close();
}; };
const handleNext = () => { const handleNext = () => {
emit('next', { emit("next", {
caseType: caseType.value, caseType: caseType.value,
data: finalData.value data: finalData.value,
}); });
close(); close();
}; };
@ -170,7 +172,7 @@ defineExpose({
addDetectedInfo, addDetectedInfo,
setGenerating, setGenerating,
setCompleted, setCompleted,
reset reset,
}); });
</script> </script>
@ -295,7 +297,7 @@ defineExpose({
padding: 16rpx 0; padding: 16rpx 0;
.dot-animation::after { .dot-animation::after {
content: '...'; content: "...";
animation: dots 1.5s steps(4, end) infinite; animation: dots 1.5s steps(4, end) infinite;
} }
} }
@ -358,17 +360,19 @@ defineExpose({
} }
@keyframes dots { @keyframes dots {
0%, 20% { 0%,
content: ''; 20% {
content: "";
} }
40% { 40% {
content: '.'; content: ".";
} }
60% { 60% {
content: '..'; content: "..";
} }
80%, 100% { 80%,
content: '...'; 100% {
content: "...";
} }
} }
</style> </style>

View File

@ -23,29 +23,29 @@
</template> </template>
<script setup> <script setup>
import { ref } from 'vue'; import { ref } from "vue";
const emit = defineEmits(['select']); const emit = defineEmits(["select"]);
const popup = ref(null); const popup = ref(null);
const caseTypes = [ const caseTypes = [
{ {
id: 'outpatient', id: "outpatient",
name: '门诊病历' name: "门诊病历",
}, },
{ {
id: 'inpatient', id: "inhospital",
name: '住院病历' name: "住院病历",
}, },
{ {
id: 'physicalExam', id: "physicalExaminationTemplate",
name: '体检记录' name: "体检记录",
}, },
{ {
id: 'preConsultation', id: "preConsultation",
name: '预问诊记录' name: "预问诊记录",
} },
]; ];
const open = () => { const open = () => {
@ -57,13 +57,13 @@ const close = () => {
}; };
const selectType = (type) => { const selectType = (type) => {
emit('select', type); emit("select", type);
close(); close();
}; };
defineExpose({ defineExpose({
open, open,
close close,
}); });
</script> </script>

View File

@ -149,6 +149,7 @@
" "
:groupId="groupId" :groupId="groupId"
:patientAccountId="chatInfo.userID || ''" :patientAccountId="chatInfo.userID || ''"
:patientId="patientId"
:corpId="corpId" :corpId="corpId"
@streamText="handleStreamText" @streamText="handleStreamText"
@clearInput="handleClearInput" @clearInput="handleClearInput"