ykt-wxapp/pages/case/medical-case-form.vue

474 lines
10 KiB
Vue
Raw Normal View History

2026-01-29 18:03:40 +08:00
<template>
<view class="medical-case-form">
<view class="form-container">
2026-02-02 13:27:48 +08:00
<!-- 动态渲染表单字段 -->
<view
v-for="field in currentFields"
:key="field.key"
class="form-item"
:class="{ required: field.required }"
>
<view class="item-label">{{ field.label }}</view>
<!-- 日期选择器 -->
<picker
v-if="field.type === 'date'"
mode="date"
:value="formData[field.key]"
@change="onDateChange(field.key, $event)"
:disabled="!isEditing"
>
<view class="picker-value">
{{ formData[field.key] || "暂无" }}
</view>
</picker>
<!-- 多行文本 -->
<textarea
v-else-if="field.type === 'textarea'"
class="item-textarea"
v-model="formData[field.key]"
placeholder="请输入"
:disabled="!isEditing"
/>
<!-- 单行文本 -->
<input
v-else
class="item-input"
v-model="formData[field.key]"
placeholder="暂无"
:disabled="!isEditing"
/>
2026-01-29 18:03:40 +08:00
</view>
</view>
2026-02-02 13:27:48 +08:00
2026-01-29 18:03:40 +08:00
<view class="footer-buttons">
<view class="btn-regenerate" @click="handleRegenerate">
<text class="btn-text">重新生成</text>
</view>
<view class="btn-save" @click="handleSave">
<text class="btn-text">保存至档案</text>
</view>
</view>
</view>
</template>
<script setup>
2026-02-02 13:27:48 +08:00
import { ref, computed, onMounted } from "vue";
import { storeToRefs } from "pinia";
import useAccountStore from "@/store/account";
import api from "@/utils/api.js";
const caseType = ref("");
2026-01-29 18:03:40 +08:00
const formData = ref({});
const isEditing = ref(true);
2026-02-02 13:27:48 +08:00
const customerId = 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] || [];
});
2026-01-29 18:03:40 +08:00
onMounted(() => {
const pages = getCurrentPages();
const currentPage = pages[pages.length - 1];
const options = currentPage.options;
2026-02-02 13:27:48 +08:00
caseType.value = options.caseType || "";
customerId.value = options.patientId || "";
groupId.value = options.groupId || "";
2026-01-29 18:03:40 +08:00
// 从 options 中解析表单数据
if (options.formData) {
try {
formData.value = JSON.parse(decodeURIComponent(options.formData));
} catch (e) {
2026-02-02 13:27:48 +08:00
console.error("解析表单数据失败:", e);
2026-01-29 18:03:40 +08:00
}
}
2026-02-02 13:27:48 +08:00
2026-01-29 18:03:40 +08:00
// 设置页面标题
2026-02-02 13:27:48 +08:00
const title = CASE_TYPE_NAMES[caseType.value]
? `添加${CASE_TYPE_NAMES[caseType.value]}`
: "添加病历";
uni.setNavigationBarTitle({ title });
2026-01-29 18:03:40 +08:00
});
const onDateChange = (field, event) => {
formData.value[field] = event.detail.value;
};
const handleRegenerate = () => {
uni.showModal({
2026-02-02 13:27:48 +08:00
title: "提示",
content: "确定要重新生成吗?当前编辑的内容将被覆盖",
2026-01-29 18:03:40 +08:00
success: (res) => {
if (res.confirm) {
// 返回上一页并触发重新生成
uni.navigateBack({
success: () => {
2026-02-02 13:27:48 +08:00
uni.$emit("regenerateMedicalCase", {
2026-01-29 18:03:40 +08:00
caseType: caseType.value,
customerId: customerId.value,
2026-02-02 13:27:48 +08:00
groupId: groupId.value,
2026-01-29 18:03:40 +08:00
});
2026-02-02 13:27:48 +08:00
},
2026-01-29 18:03:40 +08:00
});
}
2026-02-02 13:27:48 +08:00
},
2026-01-29 18:03:40 +08:00
});
};
const handleSave = async () => {
// 验证必填项
const requiredFields = getRequiredFields();
2026-02-02 13:27:48 +08:00
const missingFields = requiredFields.filter(
(field) => !formData.value[field.key]
);
2026-01-29 18:03:40 +08:00
if (missingFields.length > 0) {
uni.showToast({
title: `请填写${missingFields[0].label}`,
2026-02-02 13:27:48 +08:00
icon: "none",
2026-01-29 18:03:40 +08:00
});
return;
}
2026-02-02 13:27:48 +08:00
2026-01-29 18:03:40 +08:00
try {
2026-02-02 13:27:48 +08:00
uni.showLoading({ title: "保存中..." });
const result = await api("addMedicalRecord", {
medicalType: caseType.value,
memberId: customerId.value,
creator: doctorInfo.value.userid,
...formData.value,
2026-01-29 18:03:40 +08:00
});
2026-02-02 13:27:48 +08:00
2026-01-29 18:03:40 +08:00
uni.hideLoading();
2026-02-02 13:27:48 +08:00
2026-01-29 18:03:40 +08:00
if (result.success) {
uni.showToast({
2026-02-02 13:27:48 +08:00
title: "保存成功",
icon: "success",
2026-01-29 18:03:40 +08:00
});
2026-02-02 13:27:48 +08:00
2026-01-29 18:03:40 +08:00
setTimeout(() => {
uni.navigateBack();
}, 1500);
} else {
uni.showToast({
2026-02-02 13:27:48 +08:00
title: result.message || "保存失败",
icon: "none",
2026-01-29 18:03:40 +08:00
});
}
} catch (error) {
uni.hideLoading();
2026-02-02 13:27:48 +08:00
console.error("保存病历失败:", error);
2026-01-29 18:03:40 +08:00
uni.showToast({
2026-02-02 13:27:48 +08:00
title: "保存失败,请重试",
icon: "none",
2026-01-29 18:03:40 +08:00
});
}
};
const getRequiredFields = () => {
2026-02-02 13:27:48 +08:00
return currentFields.value.filter((field) => field.required);
2026-01-29 18:03:40 +08:00
};
</script>
<style scoped lang="scss">
.medical-case-form {
min-height: 100vh;
background-color: #f5f5f5;
padding-bottom: 120rpx;
2026-02-02 13:27:48 +08:00
2026-01-29 18:03:40 +08:00
.form-container {
background-color: #ffffff;
padding: 32rpx;
2026-02-02 13:27:48 +08:00
2026-01-29 18:03:40 +08:00
.form-item {
margin-bottom: 32rpx;
2026-02-02 13:27:48 +08:00
2026-01-29 18:03:40 +08:00
&.required .item-label::before {
2026-02-02 13:27:48 +08:00
content: "*";
2026-01-29 18:03:40 +08:00
color: #ff4d4f;
margin-right: 8rpx;
}
2026-02-02 13:27:48 +08:00
2026-01-29 18:03:40 +08:00
.item-label {
font-size: 28rpx;
color: #333333;
margin-bottom: 16rpx;
}
2026-02-02 13:27:48 +08:00
2026-01-29 18:03:40 +08:00
.item-input,
.picker-value {
width: 100%;
height: 80rpx;
padding: 0 24rpx;
background-color: #f8f9fa;
border-radius: 8rpx;
font-size: 28rpx;
color: #333333;
2026-02-02 13:27:48 +08:00
2026-01-29 18:03:40 +08:00
&[disabled] {
color: #999999;
}
}
2026-02-02 13:27:48 +08:00
2026-01-29 18:03:40 +08:00
.picker-value {
display: flex;
align-items: center;
color: #999999;
}
2026-02-02 13:27:48 +08:00
2026-01-29 18:03:40 +08:00
.item-textarea {
width: 100%;
2026-02-02 13:27:48 +08:00
min-height: 100rpx;
2026-01-29 18:03:40 +08:00
padding: 20rpx 24rpx;
background-color: #f8f9fa;
border-radius: 8rpx;
font-size: 28rpx;
color: #333333;
2026-02-02 13:27:48 +08:00
height: 100px;
2026-01-29 18:03:40 +08:00
&[disabled] {
color: #999999;
}
}
}
2026-02-02 13:27:48 +08:00
2026-01-29 18:03:40 +08:00
.tips-box {
margin-top: 32rpx;
padding: 24rpx;
background-color: #fffbe6;
border-radius: 8rpx;
2026-02-02 13:27:48 +08:00
2026-01-29 18:03:40 +08:00
.tips-text {
display: block;
font-size: 24rpx;
color: #666666;
line-height: 1.6;
margin-bottom: 8rpx;
2026-02-02 13:27:48 +08:00
2026-01-29 18:03:40 +08:00
&:last-child {
margin-bottom: 0;
}
}
}
}
2026-02-02 13:27:48 +08:00
2026-01-29 18:03:40 +08:00
.footer-buttons {
position: fixed;
bottom: 0;
left: 0;
right: 0;
2026-02-02 13:27:48 +08:00
z-index: 100;
2026-01-29 18:03:40 +08:00
display: flex;
gap: 24rpx;
padding: 24rpx 32rpx;
background-color: #ffffff;
box-shadow: 0 -4rpx 16rpx rgba(0, 0, 0, 0.08);
2026-02-02 13:27:48 +08:00
2026-01-29 18:03:40 +08:00
.btn-regenerate,
.btn-save {
flex: 1;
height: 88rpx;
display: flex;
align-items: center;
justify-content: center;
border-radius: 44rpx;
2026-02-02 13:27:48 +08:00
2026-01-29 18:03:40 +08:00
.btn-text {
font-size: 32rpx;
font-weight: 500;
}
}
2026-02-02 13:27:48 +08:00
2026-01-29 18:03:40 +08:00
.btn-regenerate {
background-color: #ffffff;
border: 2rpx solid #1890ff;
2026-02-02 13:27:48 +08:00
2026-01-29 18:03:40 +08:00
.btn-text {
color: #1890ff;
}
}
2026-02-02 13:27:48 +08:00
2026-01-29 18:03:40 +08:00
.btn-save {
background-color: #1890ff;
2026-02-02 13:27:48 +08:00
2026-01-29 18:03:40 +08:00
.btn-text {
color: #ffffff;
}
}
}
}
</style>