<template>
|
<view class="case-report-container">
|
<!-- 表单内容 -->
|
<scroll-view scroll-y class="form-scroll" :show-scrollbar="false">
|
<view class="form-content">
|
<view class="page-header">
|
<text class="page-title">{{
|
isEditMode ? "修改案例" : "上报案例"
|
}}</text>
|
</view>
|
<!-- 基本信息卡片 -->
|
<view class="form-section">
|
<view class="section-header">
|
<view class="section-icon">📋</view>
|
<text class="section-title">捐献案例基本信息</text>
|
</view>
|
|
<view class="form-grid">
|
<!-- 修改后:治疗医院输入框 -->
|
<view class="form-item">
|
<text class="item-label required">治疗医院</text>
|
<u-input
|
v-model="form.treatmenthospitalname"
|
placeholder="请输入治疗医院名称"
|
maxlength="100"
|
class="custom-input"
|
/>
|
</view>
|
|
<!-- 新增:上报医院 -->
|
<view class="form-item">
|
<text class="item-label">上报医院</text>
|
<u-input
|
v-model="form.toHospital"
|
placeholder="请输入上报医院"
|
maxlength="100"
|
class="custom-input"
|
/>
|
</view>
|
|
<!-- 新增:部门名称 -->
|
<view class="form-item">
|
<text class="item-label">部门名称</text>
|
<u-input
|
v-model="form.deptName"
|
placeholder="请输入部门名称"
|
maxlength="50"
|
class="custom-input"
|
/>
|
</view>
|
|
<view class="form-item">
|
<text class="item-label required">患者姓名</text>
|
<u-input
|
type="text"
|
v-model="form.name"
|
placeholder="请输入姓名"
|
maxlength="20"
|
class="custom-input"
|
/>
|
</view>
|
</view>
|
</view>
|
|
<!-- 个人信息卡片 -->
|
<view class="form-section">
|
<view class="section-header">
|
<view class="section-icon">👤</view>
|
<text class="section-title">捐献人信息</text>
|
</view>
|
|
<view class="form-grid">
|
<!-- 改造后的民族选择 -->
|
<view class="form-item">
|
<text class="item-label">民族</text>
|
<picker
|
mode="selector"
|
:range="nationLabels"
|
:value="nationIndex"
|
@change="onNationChange"
|
>
|
<view class="picker">
|
<text>{{ currentNation }}</text>
|
<text class="icon-arrow">›</text>
|
</view>
|
</picker>
|
</view>
|
|
<view class="form-item">
|
<text class="item-label">国籍</text>
|
<u-input
|
type="text"
|
v-model="form.nationality"
|
placeholder="请输入国籍"
|
class="custom-input"
|
/>
|
</view>
|
|
<!-- 改造后的证件类型选择 -->
|
<view class="form-item">
|
<text class="item-label">证件类型</text>
|
<picker
|
mode="selector"
|
:range="idCardTypeLabels"
|
:value="idCardTypeIndex"
|
@change="onIdCardTypeChange"
|
>
|
<view class="picker">
|
<text>{{ currentIdCardType }}</text>
|
<text class="icon-arrow">›</text>
|
</view>
|
</picker>
|
</view>
|
|
<view class="form-item">
|
<text class="item-label required">证件号码</text>
|
<u-input
|
type="idcard"
|
v-model="form.idcardno"
|
placeholder="请输入证件号码"
|
maxlength="18"
|
class="custom-input"
|
@blur="validateIdCard"
|
/>
|
<text class="error-text" v-if="idCardError">{{
|
idCardError
|
}}</text>
|
</view>
|
|
<!-- 改造后的性别选择 -->
|
<view class="form-item">
|
<text class="item-label">性别</text>
|
<view class="radio-options">
|
<view
|
v-for="gender in genderOptions"
|
:key="gender.value"
|
class="option-item"
|
:class="{ active: form.sex === gender.value }"
|
@click="form.sex = gender.value"
|
>
|
<text class="radio-dot"></text>
|
<text class="option-label">{{ gender.label }}</text>
|
</view>
|
</view>
|
</view>
|
|
<!-- 改造后的出生日期选择 -->
|
<view class="form-item">
|
<text class="item-label">出生日期</text>
|
<picker
|
mode="date"
|
:value="form.birthday"
|
@change="onBirthdayChange"
|
>
|
<view class="picker">
|
<text>{{ form.birthday || "选择出生日期" }}</text>
|
<text class="icon-arrow">›</text>
|
</view>
|
</picker>
|
</view>
|
|
<view class="form-item">
|
<text class="item-label">年龄</text>
|
<u-input
|
v-model="ageDisplay"
|
placeholder="自动计算"
|
disabled
|
:disabledColor="disabledColor"
|
border="none"
|
/>
|
</view>
|
</view>
|
</view>
|
|
<!-- 医疗信息卡片 -->
|
<view class="form-section">
|
<view class="section-header">
|
<view class="section-icon">🏥</view>
|
<text class="section-title">医疗信息</text>
|
</view>
|
|
<view class="form-grid">
|
<view class="form-item">
|
<text class="item-label">住院号</text>
|
<u-input
|
v-model="form.inpatientno"
|
placeholder="请输入住院号"
|
border="none"
|
/>
|
</view>
|
<view class="form-item">
|
<text class="item-label">GCS评分</text>
|
<u-input
|
v-model="form.gcsScore"
|
placeholder="请输入GCS评分"
|
border="none"
|
/>
|
</view>
|
|
<view class="form-item full-width">
|
<text class="item-label required">疾病诊断</text>
|
<u-textarea
|
v-model="form.diagnosisname"
|
placeholder="请输入疾病诊断名称"
|
count
|
maxlength="200"
|
:customStyle="textareaStyle(!form.diagnosisname)"
|
/>
|
</view>
|
|
<view class="form-item">
|
<text class="item-label">血型</text>
|
<view class="radio-group horizontal">
|
<view
|
v-for="bloodType in bloodTypeOptions"
|
:key="bloodType.value"
|
class="radio-item"
|
@click="form.bloodType = bloodType.value"
|
>
|
<view
|
class="radio-dot"
|
:class="{ active: form.bloodType === bloodType.value }"
|
></view>
|
<text class="radio-label">{{ bloodType.label }}</text>
|
</view>
|
</view>
|
</view>
|
<view class="form-item">
|
<text class="item-label">传染病</text>
|
<view class="radio-group horizontal">
|
<view
|
v-for="bloodType in infectiousDiseaselist"
|
:key="bloodType.value"
|
class="radio-item"
|
@click="form.infectious = bloodType.value"
|
>
|
<view
|
class="radio-dot"
|
:class="{ active: form.infectious == bloodType.value }"
|
></view>
|
<text class="radio-label">{{ bloodType.label }}</text>
|
</view>
|
</view>
|
</view>
|
<view class="form-item">
|
<text class="item-label">其他</text>
|
<u-input
|
v-model="form.infectiousOther"
|
placeholder="请输入住院号"
|
border="none"
|
/>
|
</view>
|
|
<view class="form-item">
|
<text class="item-label">Rh(D)</text>
|
<view class="radio-group horizontal">
|
<view
|
v-for="rh in rhOptions"
|
:key="rh.value"
|
class="radio-item"
|
@click="form.rhYin = rh.value"
|
>
|
<view
|
class="radio-dot"
|
:class="{ active: form.rhYin === rh.value }"
|
></view>
|
<text class="radio-label">{{ rh.label }}</text>
|
</view>
|
</view>
|
</view>
|
</view>
|
</view>
|
|
<!-- 联系信息卡片 -->
|
<view class="form-section">
|
<view class="section-header">
|
<view class="section-icon">📞</view>
|
<text class="section-title">联系信息</text>
|
</view>
|
|
<view class="form-grid">
|
<view class="form-item">
|
<text class="item-label">信息员</text>
|
<u-input
|
v-model="form.infoname"
|
placeholder="请输入信息员"
|
border="none"
|
/>
|
</view>
|
|
<view class="form-item">
|
<text class="item-label">联系电话</text>
|
<u-input
|
v-model="form.infophone"
|
placeholder="请输入联系电话"
|
type="number"
|
border="none"
|
/>
|
</view>
|
|
<!-- <view class="form-item">
|
<text class="item-label">报告人</text>
|
<u-input
|
v-model="form.reporterno"
|
placeholder="请选择报告人"
|
readonly
|
border="none"
|
@click="showReporterPicker = true"
|
>
|
<template #suffix>
|
<u-icon name="arrow-down" color="#86868b"></u-icon>
|
</template>
|
</u-input>
|
</view> -->
|
|
<view class="form-item">
|
<text class="item-label">报告时间</text>
|
<u-input
|
v-model="currentTime"
|
disabled
|
:disabledColor="disabledColor"
|
border="none"
|
/>
|
</view>
|
</view>
|
</view>
|
|
<!-- 操作按钮 -->
|
<view class="action-buttons">
|
<u-button class="btn secondary" @click="handleCancel">取消</u-button>
|
<u-button class="btn secondary" @click="resetForm">重置表单</u-button>
|
<u-button
|
class="btn primary"
|
:disabled="!isFormValid || loading"
|
@click="handleSubmit"
|
>
|
{{ loading ? "提交中..." : isEditMode ? "保存修改" : "提交上报" }}
|
</u-button>
|
</view>
|
<attachment-upload
|
ref="attachment"
|
:files="attachments"
|
:readonly="isReadonly"
|
:maxCount="5"
|
@update:files="handleFilesUpdate"
|
@upload-base="handleBaseUpload"
|
@preview="handlePreview"
|
/>
|
</view>
|
</scroll-view>
|
|
<!-- 科室选择器 -->
|
<u-picker
|
:show="selectShow"
|
:columns="pickerColumns"
|
keyName="label"
|
@confirm="onConfirm"
|
@cancel="selectShow = false"
|
title="请选择科室"
|
ref="uPicker"
|
></u-picker>
|
|
<!-- 医疗机构选择器 -->
|
<u-picker
|
:show="showHospitalPicker"
|
:columns="[hospitalOptions]"
|
keyName="label"
|
@confirm="onHospitalConfirm"
|
@cancel="showHospitalPicker = false"
|
title="请选择医疗机构"
|
></u-picker>
|
|
<!-- 民族选择器 -->
|
<u-picker
|
:show="showNationPicker"
|
:columns="[nationOptions]"
|
keyName="label"
|
@confirm="onNationConfirm"
|
@cancel="showNationPicker = false"
|
title="请选择民族"
|
></u-picker>
|
|
<!-- 证件类型选择器 -->
|
<!-- <u-picker
|
:show="showIdCardTypePicker"
|
:columns="[idCardTypeOptions]"
|
keyName="label"
|
@confirm="onIdCardTypeConfirm"
|
@cancel="showIdCardTypePicker = false"
|
title="请选择证件类型"
|
></u-picker> -->
|
|
<!-- 日期选择器 -->
|
<u-datetime-picker
|
:show="showDatePicker"
|
v-model="birthdayValue"
|
mode="date"
|
@confirm="onDateConfirm"
|
@cancel="showDatePicker = false"
|
title="选择出生日期"
|
></u-datetime-picker>
|
|
<!-- 报告人选择器 -->
|
<u-picker
|
:show="showReporterPicker"
|
:columns="[reporterOptions]"
|
keyName="label"
|
@confirm="onReporterConfirm"
|
@cancel="showReporterPicker = false"
|
title="请选择报告人"
|
></u-picker>
|
|
<!-- 加载状态 -->
|
<u-loading-icon :show="loading" text="提交中..."></u-loading-icon>
|
</view>
|
</template>
|
|
<script setup>
|
import { ref, computed, onMounted } from "vue";
|
import { onLoad } from "@dcloudio/uni-app";
|
import attachmentUpload from "@/components/attachment";
|
import { useUserStore } from "@/stores/user";
|
import { useDict } from "@/utils/dict";
|
|
const dict = ref({});
|
const userStore = useUserStore();
|
const isEditMode = ref(false);
|
const currentId = ref(null);
|
// 表单数据
|
const form = ref({
|
caseNo: "",
|
treatmenthospitalname: "",
|
treatmentdeptname: "",
|
name: "",
|
nation: "",
|
nationality: "中国",
|
idcardtype: "",
|
idcardno: "",
|
sex: "",
|
birthday: "",
|
age: "",
|
ageunit: "", // 新增:年龄单位
|
inpatientno: "",
|
diagnosisname: "",
|
bloodType: "",
|
rhYin: "",
|
infoname: "",
|
infophone: "",
|
reportername: userStore.name || "",
|
reporterno: userStore.userId || "",
|
reporterphone: "", // 报告者联系电话
|
reporttime: "",
|
contactperson: "", // 新增:联系人(协调员)
|
education: "", // 新增:学历
|
illnessoverview: "", // 新增:病情概况
|
infectious: "", // 传染病情况
|
infectiousOther: "", // 传染病其他
|
isTransport: "1", // 新增:是否需要转运,默认1不需要
|
nativeplace: "", // 新增:籍贯
|
occupation: "", // 新增:职业
|
patientstate: "", // 新增:病人状况
|
phone: "", // 新增:联系电话
|
registeraddress: "", // 新增:户籍地址
|
registerprovince: "", // 新增:户籍地址省编号
|
registerprovincename: "", // 新增:户籍地址省名称
|
registercityname: "", // 新增:市名称
|
registertownname: "", // 新增:所属街道(镇)名称
|
registercommunityname: "", // 新增:社区(村)名称
|
residenceaddress: "", // 新增:现住地址
|
residenceprovince: "", // 新增:现住地址省代码
|
residenceprovincename: "", // 新增:现住地址省名称
|
residencecountycode: "", // 新增:所属区域编号
|
residencecountyname: "", // 新增:所属区域名称
|
residencetownname: "", // 新增:所属街道(镇)名称
|
residencecommunity: "", // 新增:社区(村)编号
|
residencecommunityname: "", // 新增:社区(村)名称
|
remark: "", // 新增:备注
|
reportStatus: "1", // 新增:上报状态,默认1已上报
|
terminationCase: 0, // 新增:是否终止案例,默认0开启
|
annexfilesList: [], // 附件文件地址集合
|
});
|
|
// 选择器状态
|
const attachments = ref([]);
|
const infectiousDiseaselist = ref([]);
|
const nationLabel = ref([]);
|
|
const isReadonly = ref(false);
|
const id = ref(null);
|
const selectShow = ref(false);
|
const showHospitalPicker = ref(false);
|
const showNationPicker = ref(false);
|
const showIdCardTypePicker = ref(false);
|
const showDatePicker = ref(false);
|
const showReporterPicker = ref(false);
|
const birthdayValue = ref(0);
|
|
// 字典数据选项
|
const hospitalOptions = ref([
|
{ label: "青岛镜湖医院", value: "qdhospital1" },
|
{ label: "青岛科大医院", value: "qdhospital2" },
|
{ label: "青岛大学附属医院", value: "qdhospital3" },
|
{ label: "青岛市立医院", value: "qdhospital4" },
|
]);
|
|
const pickerColumns = ref([
|
[
|
{ label: "神经外科", value: "neurosurgery" },
|
{ label: "心血管内科", value: "cardiology" },
|
{ label: "重症医学科", value: "icu" },
|
{ label: "急诊科", value: "emergency" },
|
{ label: "神经内科", value: "neurology" },
|
{ label: "呼吸内科", value: "respiratory" },
|
{ label: "消化内科", value: "gastroenterology" },
|
{ label: "肾内科", value: "nephrology" },
|
],
|
]);
|
|
const nationOptions = ref([
|
{ label: "汉族", value: "han" },
|
{ label: "回族", value: "hui" },
|
{ label: "满族", value: "man" },
|
{ label: "蒙古族", value: "menggu" },
|
]);
|
|
const idCardTypeOptions = ref([
|
{ label: "居民身份证", value: "idcard" },
|
{ label: "护照", value: "passport" },
|
{ label: "军官证", value: "officer" },
|
]);
|
|
const genderOptions = ref([
|
{ label: "男", value: "1" },
|
{ label: "女", value: "2" },
|
]);
|
|
const bloodTypeOptions = ref([
|
{ label: "A型", value: "A" },
|
{ label: "B型", value: "B" },
|
{ label: "O型", value: "O" },
|
{ label: "AB型", value: "AB" },
|
]);
|
|
const rhOptions = ref([
|
{ label: "阳性", value: "positive" },
|
{ label: "阴性", value: "negative" },
|
]);
|
|
const reporterOptions = ref([
|
{ label: "张医生", value: "doctor1" },
|
{ label: "李医生", value: "doctor2" },
|
]);
|
|
// 状态管理
|
const loading = ref(false);
|
const currentTime = ref("");
|
const disabledColor = ref("#f5f5f7");
|
|
// 计算属性
|
const isFormValid = computed(() => {
|
return (
|
form.value.name &&
|
form.value.idcardno &&
|
form.value.diagnosisname &&
|
form.value.toHospital
|
);
|
});
|
// 选择器索引
|
const hospitalIndex = ref(-1);
|
const deptIndex = ref(-1);
|
const nationIndex = ref(-1);
|
const idCardTypeIndex = ref(-1);
|
|
// 计算属性 - 标签数组
|
const hospitalLabels = computed(() =>
|
hospitalOptions.value.map((item) => item.label),
|
);
|
const ageDisplay = computed(() => {
|
if (!form.value.age || !form.value.ageunit) {
|
return "自动计算";
|
}
|
return `${form.value.age}${form.value.ageunit}`;
|
});
|
const deptLabels = computed(() => {
|
return pickerColumns.value[0].map((item) => item.label);
|
});
|
const nationLabels = computed(() =>
|
nationLabel.value.map((item) => item.label),
|
);
|
const idCardTypeLabels = computed(() =>
|
idCardTypeOptions.value.map((item) => item.label),
|
);
|
|
// 计算属性 - 当前选中显示文本
|
const currentHospital = computed(() => {
|
return hospitalIndex.value >= 0
|
? hospitalLabels.value[hospitalIndex.value]
|
: "请选择医疗机构";
|
});
|
|
const currentDept = computed(() => {
|
return deptIndex.value >= 0
|
? deptLabels.value[deptIndex.value]
|
: "请选择科室";
|
});
|
|
const currentNation = computed(() => {
|
return nationIndex.value >= 0
|
? nationLabels.value[nationIndex.value]
|
: "请选择民族";
|
});
|
|
const currentIdCardType = computed(() => {
|
return idCardTypeIndex.value >= 0
|
? idCardTypeLabels.value[idCardTypeIndex.value]
|
: "请选择证件类型";
|
});
|
|
|
const onNationChange = (e) => {
|
const index = parseInt(e.detail.value);
|
nationIndex.value = nationOptions.value[index].label;
|
form.value.nation = nationOptions.value[index].label;
|
};
|
|
const onIdCardTypeChange = (e) => {
|
const index = parseInt(e.detail.value);
|
idCardTypeIndex.value = index;
|
form.value.idcardtype = idCardTypeOptions.value[index].value;
|
};
|
|
const onBirthdayChange = (e) => {
|
form.value.birthday = e.detail.value;
|
calculateAge();
|
};
|
const onDateConfirm = (e) => {
|
const date = new Date(e.value);
|
|
// 格式化日期为 YYYY-MM-DD
|
form.value.birthday = `${date.getFullYear()}-${(date.getMonth() + 1)
|
.toString()
|
.padStart(2, "0")}-${date.getDate().toString().padStart(2, "0")}`;
|
|
calculateAge();
|
showDatePicker.value = false;
|
};
|
|
// 身份证验证
|
const idCardError = ref("");
|
const validateIdCard = () => {
|
if (!form.value.idcardno) {
|
idCardError.value = "请输入证件号码";
|
return false;
|
}
|
|
if (form.value.idcardno.length !== 18) {
|
idCardError.value = "请输入18位身份证号码";
|
return false;
|
}
|
|
idCardError.value = "";
|
return true;
|
};
|
// 样式方法
|
const inputStyle = (isError) => {
|
return isError
|
? "border: 2rpx solid #ff4757; border-radius: 12rpx;"
|
: "border: 2rpx solid #e5e5e7; border-radius: 12rpx;";
|
};
|
|
const textareaStyle = (isError) => {
|
return isError
|
? "border: 2rpx solid #ff4757; border-radius: 12rpx; min-height: 120rpx; padding: 20rpx 24rpx;"
|
: "border: 2rpx solid #e5e5e7; border-radius: 12rpx; min-height: 120rpx; padding: 20rpx 24rpx;";
|
};
|
|
// 生命周期
|
onMounted(() => {
|
// updateCurrentTime();
|
// generateDonorNo();
|
setInterval(updateCurrentTime, 1000);
|
});
|
|
onLoad(async (options) => {
|
id.value = options.id;
|
if (options.id) {
|
currentId.value = options.id;
|
isEditMode.value = true;
|
await loadCaseData(options.id);
|
} else {
|
isEditMode.value = false;
|
generateDonorNo();
|
}
|
// 获取字典数据
|
dict.value = await useDict(
|
"sys_IDType",
|
"sys_user_sex",
|
"sys_Nation",
|
"sys_BloodType",
|
"sys_Infectious",
|
"sys_AgeUnit", // 新增年龄单位
|
"sys_education", // 新增学历
|
"sys_occupation", // 新增职业
|
);
|
initOptions();
|
updateCurrentTime();
|
});
|
// 初始化选项数据的方法
|
const initOptions = () => {
|
infectiousDiseaselist.value = dict.value.sys_Infectious || [];
|
idCardTypeOptions.value = dict.value.sys_IDType || [];
|
nationLabel.value = dict.value.sys_Nation || [];
|
};
|
// 方法定义
|
const updateCurrentTime = () => {
|
const now = new Date();
|
// 先获取格式化的字符串,然后替换分隔符和调整顺序
|
const localString = now.toLocaleString("zh-CN", {
|
year: "numeric",
|
month: "2-digit",
|
day: "2-digit",
|
hour: "2-digit",
|
minute: "2-digit",
|
second: "2-digit",
|
hour12: false,
|
});
|
// 将 "yyyy/mm/dd hh:mm:ss" 转换为 "yyyy-mm-dd hh:mm:ss"
|
currentTime.value = localString.replace(/\//g, "-");
|
form.value.reporttime = currentTime.value;
|
};
|
|
const generateDonorNo = () => {
|
const date = new Date();
|
const timestamp = date.getTime().toString().slice(-6);
|
// form.value.caseNo = `DON${date.getFullYear()}${(date.getMonth() + 1)
|
// .toString()
|
// .padStart(2, "0")}${timestamp}`;
|
};
|
|
const calculateAge = () => {
|
if (!form.value.birthday) {
|
form.value.age = "";
|
form.value.ageunit = "";
|
return;
|
}
|
|
const birthDate = new Date(form.value.birthday);
|
const today = new Date();
|
|
// 检查日期有效性
|
if (isNaN(birthDate.getTime())) {
|
form.value.age = "";
|
form.value.ageunit = "";
|
return;
|
}
|
|
// 计算总天数差
|
const timeDiff = today.getTime() - birthDate.getTime();
|
const daysDiff = Math.floor(timeDiff / (1000 * 60 * 60 * 24));
|
|
if (daysDiff < 0) {
|
// 未来日期处理
|
form.value.age = "";
|
form.value.ageunit = "";
|
return;
|
}
|
|
// 计算年、月、日
|
const years = today.getFullYear() - birthDate.getFullYear();
|
const months = today.getMonth() - birthDate.getMonth();
|
const days = today.getDate() - birthDate.getDate();
|
|
let ageValue, ageUnit;
|
|
if (years >= 1) {
|
// 大于等于1年:显示年
|
let actualYears = years;
|
|
// 处理月份和日期的边界情况
|
if (months < 0 || (months === 0 && days < 0)) {
|
actualYears = years - 1;
|
}
|
|
ageValue = actualYears.toString();
|
ageUnit = "岁";
|
} else if (daysDiff >= 30) {
|
// 大于等于30天:显示月
|
let totalMonths = years * 12 + months;
|
if (days < 0) {
|
totalMonths--;
|
}
|
ageValue = Math.max(1, totalMonths).toString(); // 确保至少1个月
|
ageUnit = "个月";
|
} else {
|
// 小于30天:显示天
|
ageValue = Math.max(1, daysDiff).toString(); // 确保至少1天
|
ageUnit = "天";
|
}
|
|
form.value.age = ageValue;
|
form.value.ageunit = ageUnit;
|
};
|
|
// 处理基础附件上传
|
const handleBaseUpload = (file) => {
|
console.log("基础附件上传成功:", file);
|
};
|
|
// 处理其他附件上传
|
const handleFilesUpdate = (files) => {
|
formData.attachments = files.map((file) => ({
|
...file,
|
// 确保只存储半路径
|
url: file.url.startsWith("http")
|
? file.url.replace(baseUrlHt, "")
|
: file.url,
|
}));
|
};
|
|
// 预览文件 - 修改为使用完整URL
|
const handlePreview = (file) => {
|
const fullUrl = file.url.startsWith("http")
|
? file.url
|
: baseUrlHt + (file.url.startsWith("/") ? "" : "/") + file.url;
|
|
if (file.type.includes("image")) {
|
uni.previewImage({
|
urls: formData.attachments
|
.filter((f) => f.type.includes("image"))
|
.map((f) =>
|
f.url.startsWith("http")
|
? f.url
|
: baseUrlHt + (f.url.startsWith("/") ? "" : "/") + f.url,
|
),
|
current: fullUrl,
|
});
|
} else if (file.type.includes("pdf")) {
|
uni.downloadFile({
|
url: fullUrl,
|
success: (res) => {
|
uni.openDocument({
|
filePath: res.tempFilePath,
|
fileType: "pdf",
|
showMenu: true,
|
});
|
},
|
fail: (err) => {
|
console.error("打开文档失败:", err);
|
uni.showToast({ title: "打开文件失败", icon: "none" });
|
},
|
});
|
} else {
|
uni.showToast({ title: "暂不支持此文件类型预览", icon: "none" });
|
}
|
};
|
// 选择器确认事件
|
const onConfirm = (e) => {
|
if (e.value && e.value[0]) {
|
form.value.treatmentdeptname = e.value[0].label;
|
}
|
selectShow.value = false;
|
};
|
|
const onHospitalConfirm = (e) => {
|
if (e.value && e.value[0]) {
|
form.value.treatmenthospitalname = e.value[0].label;
|
}
|
showHospitalPicker.value = false;
|
};
|
|
const onNationConfirm = (e) => {
|
if (e.value && e.value[0]) {
|
form.value.nation = e.value[0].label;
|
}
|
showNationPicker.value = false;
|
};
|
|
const onIdCardTypeConfirm = (e) => {
|
if (e.value && e.value[0]) {
|
form.value.idcardtype = e.value[0].value;
|
}
|
showIdCardTypePicker.value = false;
|
};
|
|
// const onDateConfirm = (e) => {
|
// const date = new Date(e.value);
|
// form.value.birthday = `${date.getFullYear()}-${(date.getMonth() + 1)
|
// .toString()
|
// .padStart(2, "0")}-${date.getDate().toString().padStart(2, "0")}`;
|
// calculateAge();
|
// showDatePicker.value = false;
|
// };
|
|
const onReporterConfirm = (e) => {
|
if (e.value && e.value[0]) {
|
form.value.reporterno = e.value[0].label;
|
}
|
showReporterPicker.value = false;
|
};
|
|
const goBack = () => {
|
uni.navigateBack();
|
};
|
|
const resetForm = () => {
|
uni.showModal({
|
title: "确认重置",
|
content: "确定要清空所有已填写的内容吗?",
|
success: (res) => {
|
if (res.confirm) {
|
Object.keys(form.value).forEach((key) => {
|
if (!["id", "caseNo"].includes(key)) {
|
form.value[key] = "";
|
}
|
});
|
|
// 重置选择器索引
|
hospitalIndex.value = -1;
|
deptIndex.value = -1;
|
nationIndex.value = -1;
|
idCardTypeIndex.value = -1;
|
attachments.value = [];
|
form.value.nationality = "中国";
|
form.value.isTransport = "1";
|
form.value.terminationCase = 0;
|
form.value.reportStatus = "1";
|
|
if (!isEditMode.value) {
|
generateDonorNo();
|
}
|
|
uni.showToast({ title: "表单已重置", icon: "success" });
|
}
|
},
|
});
|
};
|
|
const handleSubmit = async () => {
|
if (!isFormValid.value) {
|
uni.showToast({
|
title: "请填写姓名、证件号码和疾病诊断",
|
icon: "none",
|
});
|
return;
|
}
|
|
try {
|
uni.showLoading({ title: isEditMode.value ? "修改中..." : "提交中..." });
|
|
// 准备提交数据
|
const submitData = {
|
...form.value,
|
age: parseInt(form.value.age) || 0,
|
annexfilesList: attachments.value.map((file) => ({
|
url: file.url,
|
name: file.name,
|
type: file.type,
|
})),
|
phone: form.value.infophone,
|
isTransport: form.value.isTransport || "1",
|
terminationCase: form.value.terminationCase || 0,
|
reportStatus: form.value.reportStatus || "1",
|
};
|
|
let res;
|
if (isEditMode.value) {
|
// 修改接口
|
res = await uni.$uapi.post(
|
"/project/donatebaseinforeport/edit",
|
submitData,
|
);
|
} else {
|
// 新增接口
|
res = await uni.$uapi.post(
|
"/project/donatebaseinforeport/add",
|
submitData,
|
);
|
}
|
|
uni.hideLoading();
|
|
if (res.code === 200) {
|
uni.showToast({
|
title: isEditMode.value ? "修改成功" : "上报成功",
|
icon: "success",
|
});
|
|
// 清空本地存储的草稿
|
removeDraft();
|
|
setTimeout(() => {
|
uni.navigateBack();
|
}, 1500);
|
} else {
|
throw new Error(res.msg || "操作失败");
|
}
|
} catch (error) {
|
console.error("操作失败:", error);
|
uni.showToast({
|
title: error.message || (isEditMode.value ? "修改失败" : "上报失败"),
|
icon: "none",
|
});
|
} finally {
|
loading.value = false;
|
}
|
};
|
const removeDraft = () => {
|
localStorage.removeItem("caseReportDraft");
|
};
|
// 取消处理
|
const handleCancel = () => {
|
uni.navigateBack();
|
};
|
|
const loadCaseData = async (id) => {
|
// 模拟加载编辑数据
|
// form.value = {
|
// caseNo: "DON20241216001",
|
// treatmenthospitalname: "青岛镜湖医院",
|
// treatmentdeptname: "神经外科",
|
// name: "张三",
|
// nation: "汉族",
|
// nationality: "中国",
|
// idcardtype: "居民身份证",
|
// idcardno: "370203198510123456",
|
// sex: "1",
|
// birthday: "1985-10-12",
|
// age: "38",
|
// inpatientno: "ZY20241216001",
|
// diagnosisname: "脑外伤导致脑死亡",
|
// bloodType: "A",
|
// rhYin: "positive",
|
// infoname: "李医生",
|
// infophone: "13800138000",
|
// reporterno: "张医生",
|
// reporttime: currentTime.value,
|
// };
|
try {
|
loading.value = true;
|
const res = await uni.$uapi.get(
|
`/project/donatebaseinforeport/getInfo/${id}`,
|
);
|
|
if (res) {
|
console.log(res, "res");
|
|
form.value = res;
|
console.log(1, "res");
|
|
// 处理选择器索引
|
// updatePickerIndexes();
|
|
console.log(2, "res");
|
// 处理附件
|
if (res.annexfilesList) {
|
attachments.value = res.annexfilesList;
|
}
|
console.log(3, "res");
|
|
uni.showToast({
|
title: "数据加载成功",
|
icon: "success",
|
});
|
} else {
|
throw new Error(res.msg || "数据加载失败");
|
}
|
} catch (error) {
|
console.error("加载案例数据失败:", error);
|
uni.showToast({
|
title: "数据加载失败,请重试",
|
icon: "none",
|
});
|
} finally {
|
loading.value = false;
|
}
|
};
|
// 更新选择器索引
|
const updatePickerIndexes = () => {
|
// 医疗机构索引
|
const hospitalIndex = hospitalOptions.value.findIndex(
|
(item) => item.label === form.value.treatmenthospitalname,
|
);
|
if (hospitalIndex !== -1) hospitalIndex.value = hospitalIndex;
|
|
// 科室索引
|
const deptIndex = pickerColumns.value[0].findIndex(
|
(item) => item.label === form.value.treatmentdeptname,
|
);
|
if (deptIndex !== -1) deptIndex.value = deptIndex;
|
|
// 民族索引
|
const nationIndex = nationOptions.value.findIndex(
|
(item) => item.label === form.value.nation,
|
);
|
if (nationIndex !== -1) nationIndex.value = nationIndex;
|
|
// 证件类型索引
|
const idCardTypeIndex = idCardTypeOptions.value.findIndex(
|
(item) => item.value === form.value.idcardtype,
|
);
|
if (idCardTypeIndex !== -1) idCardTypeIndex.value = idCardTypeIndex;
|
};
|
</script>
|
<style lang="scss" scoped>
|
.case-report-container {
|
min-height: 100vh;
|
background: linear-gradient(135deg, #f8fdff 0%, #e8f7f6 100%);
|
}
|
|
.form-scroll {
|
height: 100vh;
|
}
|
|
.form-content {
|
padding: 30rpx;
|
}
|
|
.form-section {
|
background: #fff;
|
border-radius: 20rpx;
|
padding: 30rpx;
|
margin-bottom: 30rpx;
|
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.06);
|
}
|
|
.section-header {
|
display: flex;
|
// align-items: center;
|
margin-bottom: 30rpx;
|
padding-bottom: 20rpx;
|
border-bottom: 2rpx solid #f0f0f0;
|
}
|
|
.section-icon {
|
font-size: 32rpx;
|
margin-right: 16rpx;
|
}
|
|
.section-title {
|
font-size: 32rpx;
|
font-weight: 600;
|
color: #1d1d1f;
|
}
|
|
.form-grid {
|
display: flex;
|
flex-direction: column;
|
gap: 24rpx;
|
}
|
|
.form-item {
|
display: flex;
|
flex-direction: column;
|
|
&.full-width {
|
grid-column: 1 / -1;
|
}
|
}
|
|
.item-label {
|
font-size: 28rpx;
|
color: #1d1d1f;
|
font-weight: 500;
|
margin-bottom: 12rpx;
|
|
&.required::after {
|
content: "*";
|
color: #ff4757;
|
margin-left: 4rpx;
|
}
|
}
|
|
// 自定义u-input样式
|
:deep(.u-input) {
|
border: 2rpx solid #e5e5e7 !important;
|
border-radius: 12rpx !important;
|
padding: 20rpx 24rpx !important;
|
background: #fff !important;
|
}
|
|
:deep(.u-textarea) {
|
border: 2rpx solid #e5e5e7 !important;
|
border-radius: 12rpx !important;
|
padding: 20rpx 24rpx !important;
|
background: #fff !important;
|
}
|
|
.radio-group {
|
display: flex;
|
gap: 40rpx;
|
|
&.horizontal {
|
flex-wrap: wrap;
|
gap: 20rpx;
|
}
|
}
|
|
.radio-item {
|
display: flex;
|
align-items: center;
|
gap: 16rpx;
|
}
|
|
.radio-dot {
|
width: 32rpx;
|
height: 32rpx;
|
border: 2rpx solid #e5e5e7;
|
border-radius: 50%;
|
position: relative;
|
|
&.active {
|
border-color: #0f95b0;
|
|
&::after {
|
content: "";
|
position: absolute;
|
top: 50%;
|
left: 50%;
|
transform: translate(-50%, -50%);
|
width: 16rpx;
|
height: 16rpx;
|
background: #0f95b0;
|
border-radius: 50%;
|
}
|
}
|
}
|
|
.radio-label {
|
font-size: 28rpx;
|
color: #1d1d1f;
|
}
|
|
.action-buttons {
|
display: flex;
|
gap: 20rpx;
|
margin-top: 40rpx;
|
}
|
|
.btn {
|
flex: 1;
|
height: 80rpx;
|
border-radius: 16rpx;
|
font-size: 32rpx;
|
font-weight: 500;
|
|
&.secondary {
|
background: #f5f5f7 !important;
|
color: #1d1d1f !important;
|
}
|
|
&.primary {
|
background: linear-gradient(135deg, #0f95b0, #89c4c1) !important;
|
color: #fff !important;
|
|
&:disabled {
|
background: #c0c0c0 !important;
|
opacity: 0.6;
|
}
|
}
|
}
|
.case-report-container {
|
min-height: 100vh;
|
background: linear-gradient(135deg, #f8fdff 0%, #e8f7f6 100%);
|
}
|
|
.form-scroll {
|
height: 100vh;
|
}
|
|
.form-content {
|
padding: 30rpx;
|
}
|
|
.form-section {
|
background: #fff;
|
border-radius: 20rpx;
|
padding: 30rpx;
|
margin-bottom: 30rpx;
|
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.06);
|
}
|
|
.section-header {
|
display: flex;
|
align-items: center;
|
margin-bottom: 30rpx;
|
padding-bottom: 20rpx;
|
border-bottom: 2rpx solid #f0f0f0;
|
}
|
|
.section-icon {
|
font-size: 32rpx;
|
margin-right: 16rpx;
|
}
|
|
.section-title {
|
font-size: 32rpx;
|
font-weight: 600;
|
color: #1d1d1f;
|
}
|
|
.form-grid {
|
display: flex;
|
flex-direction: column;
|
gap: 24rpx;
|
}
|
|
.form-item {
|
display: flex;
|
flex-direction: column;
|
}
|
|
.item-label {
|
font-size: 28rpx;
|
color: #1d1d1f;
|
font-weight: 500;
|
margin-bottom: 12rpx;
|
|
&.required::after {
|
content: "*";
|
color: #ff4757;
|
margin-left: 4rpx;
|
}
|
}
|
|
/* 改造后的选择器样式 */
|
.picker {
|
height: 88rpx;
|
background: #f5f5f7;
|
border-radius: 12rpx;
|
padding: 0 24rpx;
|
display: flex;
|
align-items: center;
|
justify-content: space-between;
|
border: 2rpx solid #e5e5e7;
|
|
text {
|
font-size: 28rpx;
|
color: #1d1d1f;
|
|
&.icon-arrow {
|
font-size: 32rpx;
|
color: #86868b;
|
transform: rotate(90deg);
|
}
|
}
|
}
|
|
.page-header {
|
padding: 30rpx 0;
|
text-align: center;
|
margin-bottom: 20rpx;
|
}
|
|
.page-title {
|
font-size: 36rpx;
|
font-weight: 600;
|
color: #1d1d1f;
|
}
|
|
/* 在原有样式基础上添加 */
|
.form-section {
|
position: relative;
|
}
|
|
.edit-badge {
|
position: absolute;
|
top: 30rpx;
|
right: 30rpx;
|
background: #ff6b35;
|
color: white;
|
padding: 8rpx 16rpx;
|
border-radius: 20rpx;
|
font-size: 24rpx;
|
}
|
|
/* 加载状态样式 */
|
.loading-overlay {
|
position: fixed;
|
top: 0;
|
left: 0;
|
right: 0;
|
bottom: 0;
|
background: rgba(0, 0, 0, 0.5);
|
display: flex;
|
justify-content: center;
|
align-items: center;
|
z-index: 9999;
|
}
|
|
/* 响应式调整 */
|
@media (max-width: 768px) {
|
.form-content {
|
padding: 20rpx;
|
}
|
|
.form-section {
|
padding: 20rpx;
|
}
|
}
|
|
/* 改造后的单选按钮样式 */
|
.radio-options {
|
display: flex;
|
gap: 40rpx;
|
}
|
|
.option-item {
|
display: flex;
|
align-items: center;
|
gap: 16rpx;
|
|
.radio-dot {
|
width: 32rpx;
|
height: 32rpx;
|
border: 2rpx solid #e5e5e7;
|
border-radius: 50%;
|
position: relative;
|
}
|
|
.option-label {
|
font-size: 28rpx;
|
color: #1d1d1f;
|
}
|
|
&.active {
|
.radio-dot {
|
border-color: #0f95b0;
|
|
&::after {
|
content: "";
|
position: absolute;
|
top: 50%;
|
left: 50%;
|
transform: translate(-50%, -50%);
|
width: 16rpx;
|
height: 16rpx;
|
background: #0f95b0;
|
border-radius: 50%;
|
}
|
}
|
|
.option-label {
|
color: #0f95b0;
|
}
|
}
|
}
|
|
.error-text {
|
font-size: 24rpx;
|
color: #ff4757;
|
margin-top: 8rpx;
|
}
|
|
/* 原有样式调整 */
|
:deep(.u-input) {
|
border: 2rpx solid #e5e5e7 !important;
|
border-radius: 12rpx !important;
|
padding: 20rpx 24rpx !important;
|
background: #fff !important;
|
}
|
|
.action-buttons {
|
display: flex;
|
gap: 20rpx;
|
margin-top: 40rpx;
|
}
|
|
.btn {
|
flex: 1;
|
height: 80rpx;
|
border-radius: 16rpx;
|
font-size: 32rpx;
|
font-weight: 500;
|
|
&.secondary {
|
background: #f5f5f7 !important;
|
color: #1d1d1f !important;
|
}
|
|
&.primary {
|
background: linear-gradient(135deg, #0f95b0, #89c4c1) !important;
|
color: #fff !important;
|
|
&:disabled {
|
background: #c0c0c0 !important;
|
opacity: 0.6;
|
}
|
}
|
}
|
</style>
|