WXL
2 天以前 c80bc467a41daa6cbae4e5515a300a8ca98cfeaa
pagesSub/case/CaseDetails.vue
@@ -1,54 +1,44 @@
<template>
  <view class="case-report-container">
    <!-- 表单内容 -->
    <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>
          <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.caseNo"
              placeholder="系统自动生成"
              disabled
              :disabledColor="disabledColor"
            />
          </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
@@ -56,76 +46,65 @@
              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>
          <text class="section-title">个人信息</text>
        </view>
        <view class="form-grid">
          <!-- 改造后的民族选择 -->
          <view class="form-item">
            <text class="item-label">民族</text>
            <picker
              mode="selector"
              :range="nationLabels"
              :range="nationList"
              :value="nationIndex"
              @change="onNationChange"
            >
              <view class="picker">
                <text>{{ currentNation }}</text>
                <text>{{ currentNationText || "请选择民族" }}</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"
              :range="idCardTypeList"
              :value="idCardTypeIndex"
              @change="onIdCardTypeChange"
            >
              <view class="picker">
                <text>{{ currentIdCardType }}</text>
                <text>{{ currentIdCardTypeText || "请选择证件类型" }}</text>
                <text class="icon-arrow">›</text>
              </view>
            </picker>
          </view>
          <view class="form-item">
            <text class="item-label required">证件号码</text>
            <text class="item-label">证件号码</text>
            <u-input
              type="idcard"
              v-model="form.idcardno"
              placeholder="请输入证件号码"
              maxlength="18"
              class="custom-input"
              @blur="onIdCardChange"
            />
            <text class="error-text" v-if="idCardError">{{ idCardError }}</text>
          </view>
          <!-- 改造后的性别选择 -->
          <view class="form-item">
            <text class="item-label">性别</text>
            <view class="radio-options">
@@ -133,7 +112,7 @@
                v-for="gender in genderOptions"
                :key="gender.value"
                class="option-item"
                :class="{ active: form.sex === gender.value }"
                :class="{ active: form.sex == gender.value }"
                @click="form.sex = gender.value"
              >
                <text class="radio-dot"></text>
@@ -141,8 +120,6 @@
              </view>
            </view>
          </view>
          <!-- 改造后的出生日期选择 -->
          <view class="form-item">
            <text class="item-label">出生日期</text>
            <picker
@@ -156,17 +133,113 @@
              </view>
            </picker>
          </view>
          <!-- ===== 修改:年龄改为可手动输入 + 单位选择 ===== -->
          <view class="form-item">
            <text class="item-label">年龄</text>
            <view style="display: flex; gap: 10rpx; align-items: center">
              <u-input
                v-model="form.age"
                placeholder="输入或自动计算"
                type="number"
                style="flex: 1"
              />
              <picker
                mode="selector"
                :range="ageUnitList"
                :value="ageUnitIndex"
                @change="onAgeUnitChange"
                style="flex: 0 0 160rpx"
              >
                <view
                  class="picker"
                  style="
                    height: 86rpx;
                    background: #fafafa;
                    border-radius: 12rpx;
                    padding: 0 16rpx;
                    display: flex;
                    align-items: center;
                    justify-content: space-between;
                    border: 2rpx solid #e5e5e7;
                  "
                >
                  <text>{{ currentAgeUnitText || "单位" }}</text>
                  <text class="icon-arrow">›</text>
                </view>
              </picker>
            </view>
          </view>
          <!-- ===== 修改结束 ===== -->
          <view class="form-item">
            <text class="item-label">联系电话</text>
            <u-input
              v-model="ageDisplay"
              placeholder="自动计算"
              disabled
              :disabledColor="disabledColor"
              border="none"
              v-model="form.phone"
              placeholder="请输入联系电话"
              type="number"
            />
          </view>
          <view class="form-item">
            <text class="item-label">学历</text>
            <picker
              mode="selector"
              :range="educationList"
              :value="educationIndex"
              @change="onEducationChange"
            >
              <view class="picker">
                <text>{{ currentEducationText || "请选择学历" }}</text>
                <text class="icon-arrow">›</text>
              </view>
            </picker>
          </view>
          <view class="form-item">
            <text class="item-label">职业</text>
            <picker
              mode="selector"
              :range="occupationList"
              :value="occupationIndex"
              @change="onOccupationChange"
            >
              <view class="picker">
                <text>{{ currentOccupationText || "请选择职业" }}</text>
                <text class="icon-arrow">›</text>
              </view>
            </picker>
          </view>
          <view class="form-item">
            <text class="item-label">籍贯</text>
            <u-input v-model="form.nativeplace" placeholder="请输入籍贯" />
          </view>
        </view>
      </view>
      <!-- 地址信息卡片 -->
      <view class="form-section">
        <view class="section-header">
          <view class="section-icon">📍</view>
          <text class="section-title">地址信息</text>
        </view>
        <view class="address-block">
          <text class="address-label">现住地址</text>
          <area-select v-model="residenceAddress" @change="onResidenceChange" />
          <u-input
            class="address-detail-input"
            v-model="form.residenceaddress"
            placeholder="请输入详细地址"
            border="none"
          />
        </view>
        <view class="address-block">
          <text class="address-label">户籍地址</text>
          <area-select v-model="registerAddress" @change="onRegisterChange" />
          <u-input
            class="address-detail-input"
            v-model="form.registeraddress"
            placeholder="请输入详细地址"
            border="none"
          />
        </view>
      </view>
@@ -176,15 +249,10 @@
          <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"
            />
            <u-input v-model="form.inpatientno" placeholder="请输入住院号" />
          </view>
          <view class="form-item">
            <text class="item-label">GCS评分</text>
@@ -193,11 +261,9 @@
              type="number"
              maxlength="1"
              placeholder="≤7"
              border="none"
              @blur="handleGcsBlur"
            />
          </view>
          <view class="form-item full-width">
            <text class="item-label required">疾病诊断</text>
            <u-textarea
@@ -205,26 +271,8 @@
              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 isTransportOptions"
                  :key="bloodType.value"
                  class="radio-item"
                  @click="form.isTransport = bloodType.value"
                >
                  <view
                    class="radio-dot"
                    :class="{ active: form.isTransport === 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">
@@ -236,7 +284,7 @@
              >
                <view
                  class="radio-dot"
                  :class="{ active: form.bloodType === bloodType.value }"
                  :class="{ active: form.bloodType == bloodType.value }"
                ></view>
                <text class="radio-label">{{ bloodType.label }}</text>
              </view>
@@ -253,7 +301,7 @@
              >
                <view
                  class="radio-dot"
                  :class="{ active: form.rhYin === rh.value }"
                  :class="{ active: form.rhYin == rh.value }"
                ></view>
                <text class="radio-label">{{ rh.label }}</text>
              </view>
@@ -263,9 +311,10 @@
            <text class="item-label">传染病</text>
            <view class="checkbox-group single-line">
              <view
                v-for="disease in infectiousDiseaselist"
                v-for="disease in infectiousList"
                :key="disease.value"
                class="checkbox-item"
                :class="{ active: isInfectiousSelected(disease.value) }"
                @click="toggleInfectious(disease.value)"
              >
                <view
@@ -287,7 +336,6 @@
            <u-input
              v-model="form.infectiousOther"
              placeholder="请输入其他传染病"
              border="none"
            />
          </view>
        </view>
@@ -299,71 +347,62 @@
          <view class="section-icon">📞</view>
          <text class="section-title">联系信息</text>
        </view>
        <view class="form-grid">
          <view class="form-item">
          <!-- <view class="form-item">
            <text class="item-label">ICU评估医生</text>
            <u-input
              v-model="form.icuDoctor"
              placeholder="请输入ICU评估医生"
              border="none"
            />
            <u-input v-model="form.icuDoctor" placeholder="请输入ICU评估医生" />
          </view>
          <view class="form-item">
            <text class="item-label">ICU医生电话</text>
            <u-input
              v-model="form.icuDoctorPhone"
              placeholder="请输入ICU医生电话"
              type="number"
              border="none"
            />
          </view>
            <u-input v-model="form.icuDoctorPhone" placeholder="请输入ICU医生电话" type="number" />
          </view> -->
          <view class="form-item">
            <text class="item-label">上报信息员</text>
            <u-input
              v-model="form.infoName"
              placeholder="请输入信息员"
              border="none"
            />
            <u-input v-model="form.infoName" placeholder="请输入信息员" />
          </view>
          <view class="form-item">
            <text class="item-label">联系电话</text>
            <u-input
              v-model="form.phone"
              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
              class="picker"
              @click="showReportTimePicker = true"
              style="
                height: 86rpx;
                background: #fafafa;
                border-radius: 12rpx;
                padding: 0 24rpx;
                display: flex;
                align-items: center;
                justify-content: space-between;
                border: 2rpx solid #e5e5e7;
              "
            >
              <text>{{ form.reporttime || "选择报告时间" }}</text>
              <text class="icon-arrow">›</text>
            </view>
            <u-datetime-picker
              :show="showReportTimePicker"
              v-model="reportTimeValue"
              mode="datetime"
              @confirm="onReportTimeConfirm"
              @cancel="showReportTimePicker = false"
              title="选择报告时间"
            />
          </view>
          <!-- ===== 修改结束 ===== -->
        </view>
      </view>
      <!-- 附件上传组件(假设已实现) -->
      <attachment-upload
        ref="attachment"
        :files="attachments"
        :readonly="isReadonly"
        :maxCount="5"
        @update:files="handleFilesUpdate"
        @upload-base="handleBaseUpload"
        @preview="handlePreview"
      />
      <!-- 操作按钮 -->
      <view class="action-buttons">
@@ -377,97 +416,81 @@
          {{ loading ? "提交中..." : isEditMode ? "保存修改" : "提交上报" }}
        </u-button>
      </view>
      <attachment-upload
        ref="attachment"
        :files="attachments"
        :readonly="isReadonly"
        :maxCount="5"
        @update:files="handleFilesUpdate"
        @upload-base="handleBaseUpload"
        @preview="handlePreview"
      />
    </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, watch } from "vue";
import { onLoad } from "@dcloudio/uni-app";
import attachmentUpload from "@/components/attachment";
import attachmentUpload from "@/components/attachment"; // 根据实际路径调整
import AreaSelect from "@/components/AreaSelect"; // 引入省市区组件
import { useUserStore } from "@/stores/user";
import { useDict } from "@/utils/dict";
import { useDictMapper } from "@/utils/useDictMapper";
const dict = ref({});
// ==================== 字典数据 ====================
const requiredDictTypes = [
  "sys_IDType",
  "sys_user_sex",
  "sys_Nation",
  "sys_BloodType",
  "sys_Infectious",
  "sys_AgeUnit", // 年龄单位(已存在)
  "sys_education",
  "sys_occupation",
];
const { dictData, loading: dictLoading } = useDictMapper(requiredDictTypes);
const getDictList = (dictType) => dictData.value[dictType] || [];
const nationList = computed(() =>
  getDictList("sys_Nation").map((item) => item.label),
);
const idCardTypeList = computed(() =>
  getDictList("sys_IDType").map((item) => item.label),
);
const infectiousList = computed(() => getDictList("sys_Infectious"));
const educationList = computed(() =>
  getDictList("sys_education").map((item) => item.label),
);
const occupationList = computed(() =>
  getDictList("sys_occupation").map((item) => item.label),
);
// 年龄单位列表
const ageUnitList = computed(() =>
  getDictList("sys_AgeUnit").map((item) => item.label),
);
// ==================== 状态管理 ====================
const userStore = useUserStore();
const isEditMode = ref(false);
const currentId = ref(null);
const selectedInfectious = ref([]); // 存储选中的传染病值数组
const selectedInfectious = ref([]);
const loading = ref(false);
const currentTime = ref("");
const disabledColor = ref("#f5f5f7");
const isReadonly = ref(false);
const showDatePicker = ref(false);
const birthdayValue = ref(0);
const nationIndex = ref(-1);
const idCardTypeIndex = ref(-1);
const educationIndex = ref(-1);
const occupationIndex = ref(-1);
const idCardError = ref("");
const attachments = ref([]);
// 表单数据
// 年龄单位索引
const ageUnitIndex = ref(-1);
// 报告时间选择器
const showReportTimePicker = ref(false);
const reportTimeValue = ref(Date.now());
// 地址数据
const residenceAddress = ref({ sheng: "", shi: "", qu: "" });
const registerAddress = ref({ sheng: "", shi: "", qu: "" });
// ==================== 表单数据 ====================
const form = ref({
  caseNo: "",
  treatmenthospitalname: "",
@@ -475,604 +498,415 @@
  coordinatorName: "",
  coordinatorNo: "",
  treatmentdeptname: "",
  deptName: "",
  name: "",
  nation: "",
  nationality: "中国",
  idcardtype: "",
  idcardno: "",
  rhYin: "1",
  sex: "",
  birthday: "",
  age: "",
  ageunit: "", // 新增:年龄单位
  ageunit: "",
  inpatientno: "",
  gcsScore: "",
  diagnosisname: "",
  bloodType: "",
  rhYin: "",
  infoName: "",
  phone: "",
  icuDoctor: "",
  icuDoctorPhone: "",
  reportername: "",
  reporterno: "",
  reporterphone: "", // 报告者联系电话
  reporterphone: "",
  reporttime: "",
  contactperson: "", // 新增:联系人(协调员)
  education: "", // 新增:学历
  illnessoverview: "", // 新增:病情概况
  infectious: "", // 传染病情况
  infectiousOther: "", // 传染病其他
  isTransport: "", // 新增:是否需要转运,默认1不需要
  nativeplace: "", // 新增:籍贯
  occupation: "", // 新增:职业
  patientstate: "", // 新增:病人状况
  registeraddress: "", // 新增:户籍地址
  registerprovince: "", // 新增:户籍地址省编号
  registerprovincename: "", // 新增:户籍地址省名称
  registercityname: "", // 新增:市名称
  registertownname: "", // 新增:所属街道(镇)名称
  registercommunityname: "", // 新增:社区(村)名称
  residenceaddress: "", // 新增:现住地址
  residenceprovince: "", // 新增:现住地址省代码
  residenceprovincename: "", // 新增:现住地址省名称
  residencecountycode: "", // 新增:所属区域编号
  residencecountyname: "", // 新增:所属区域名称
  residencetownname: "", // 新增:所属街道(镇)名称
  residencecommunity: "", // 新增:社区(村)编号
  residencecommunityname: "", // 新增:社区(村)名称
  remark: "", // 新增:备注
  reportStatus: "1", // 新增:上报状态,默认1已上报
  terminationCase: 0, // 新增:是否终止案例,默认0开启
  annexfilesList: [], // 附件文件地址集合
  contactperson: "",
  education: "",
  illnessoverview: "",
  infectious: "",
  infectiousOther: "",
  isTransport: "",
  nativeplace: "",
  occupation: "",
  patientstate: "",
  registeraddress: "",
  registerprovince: "",
  registerprovincename: "",
  registercityname: "",
  registertownname: "",
  registercommunityname: "",
  residenceaddress: "",
  residenceprovince: "",
  residenceprovincename: "",
  residencecountycode: "",
  residencecountyname: "",
  residencetownname: "",
  residencecommunity: "",
  residencecommunityname: "",
  remark: "",
  reportStatus: "1",
  terminationCase: 0,
  annexfilesList: [],
});
// 选择器状态
const attachments = ref([]);
const infectiousDiseaselist = ref([]);
const nationLabel = ref([]);
// ==================== 选项数据 ====================
const genderOptions = computed(() => {
  const sexDict = getDictList("sys_user_sex");
  if (sexDict.length)
    return sexDict.map((item) => ({ label: item.label, value: item.value }));
  return [
    { label: "男", value: "1" },
    { label: "女", value: "2" },
  ];
});
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([
const bloodTypeOptions = [
  { label: "A型", value: "A型" },
  { label: "B型", value: "B型" },
  { label: "O型", value: "O型" },
  { label: "AB型", value: "AB型" },
]);
const isTransportOptions = ref([
  { label: "需要", value: "2" },
  { label: "不需要", value: "1" },
]);
const rhOptions = ref([
];
const rhOptions = [
  { label: "阳性", value: "1" },
  { label: "阴性", value: "0" },
]);
];
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 isFormValid = computed(
  () => form.value.name && form.value.diagnosisname && form.value.toHospital,
);
// 计算属性 - 当前选中显示文本
const currentHospital = computed(() => {
  return hospitalIndex.value >= 0
    ? hospitalLabels.value[hospitalIndex.value]
    : "请选择医疗机构";
// 年龄显示(用于回显单位文本)
const currentAgeUnitText = computed(() => {
  if (ageUnitIndex.value >= 0 && ageUnitList.value[ageUnitIndex.value]) {
    return ageUnitList.value[ageUnitIndex.value];
  }
  if (form.value.ageunit) {
    const found = getDictList("sys_AgeUnit").find(
      (item) => item.value === form.value.ageunit,
    );
    return found ? found.label : form.value.ageunit;
  }
  return "";
});
const currentDept = computed(() => {
  return deptIndex.value >= 0
    ? deptLabels.value[deptIndex.value]
    : "请选择科室";
const currentNationText = computed(() => {
  if (nationIndex.value >= 0 && nationList.value[nationIndex.value])
    return nationList.value[nationIndex.value];
  return form.value.nation || "";
});
const currentNation = computed(() => {
  return nationIndex.value >= 0
    ? nationLabels.value[nationIndex.value]
    : form.value.nation
    ? form.value.nation
    : "请选择民族";
const currentIdCardTypeText = computed(() => {
  if (idCardTypeIndex.value >= 0 && idCardTypeList.value[idCardTypeIndex.value])
    return idCardTypeList.value[idCardTypeIndex.value];
  if (form.value.idcardtype) {
    const found = getDictList("sys_IDType").find(
      (item) => item.value == form.value.idcardtype,
    );
    return found ? found.label : form.value.idcardtype;
  }
  return "";
});
const currentIdCardType = computed(() => {
  return idCardTypeIndex.value >= 0
    ? idCardTypeLabels.value[idCardTypeIndex.value]
    : "请选择证件类型";
});
const onNationChange = (e) => {
  const index = parseInt(e.detail.value);
  nationIndex.value = index;
  form.value.nation = nationOptions.value[index].label;
  console.log(form.value.nation, "form.value.nation");
};
const onIdCardTypeChange = (e) => {
  const index = parseInt(e.detail.value);
  idCardTypeIndex.value = index;
  form.value.idcardtype = idCardTypeOptions.value[index].value;
  console.log(form.value.idcardtype, "form.value.idcardtype");
};
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 = () => {
  const idCard = form.value.idcardno;
  console.log(idCard, "当前输入");
  // if (!idCard) {
  //   idCardError.value = "请输入证件号码";
  //   return false;
  // }
  if (idCard.length !== 18) {
    idCardError.value = "身份证号码必须是18位";
    return false;
const currentEducationText = computed(() => {
  if (educationIndex.value >= 0 && educationList.value[educationIndex.value])
    return educationList.value[educationIndex.value];
  if (form.value.education) {
    const found = getDictList("sys_education").find(
      (item) => item.value == form.value.education,
    );
    return found ? found.label : form.value.education;
  }
  // 验证前17位必须是数字
  const reg = /^\d{17}(\d|X|x)$/;
  if (!reg.test(idCard)) {
    idCardError.value = "身份证号码格式不正确";
    return false;
  }
  // 验证出生日期
  const birthStr = idCard.substring(6, 14);
  const year = birthStr.substring(0, 4);
  const month = birthStr.substring(4, 6);
  const day = birthStr.substring(6, 8);
  const birthDate = new Date(`${year}-${month}-${day}`);
  if (isNaN(birthDate.getTime())) {
    idCardError.value = "身份证号码中的出生日期无效";
    return false;
  }
  console.log(3);
  // 验证日期范围(1900年至今)
  const currentYear = new Date().getFullYear();
  const birthYear = parseInt(year, 10);
  if (birthYear < 1900 || birthYear > currentYear) {
    idCardError.value = "出生年份不在有效范围内";
    return false;
  }
  console.log(4);
  // 验证校验码(第18位)
  if (!validateIdCardCheckCode(idCard)) {
    idCardError.value = "身份证号码校验失败";
    return false;
  }
  console.log(5);
  idCardError.value = "";
  return true;
};
// 身份证号变化处理
const onIdCardChange = (value) => {
  // 验证身份证格式
  if (validateIdCard()) {
    // 尝试提取出生日期
    extractBirthdayFromIdCard();
  }
};
const handleGcsBlur = () => {
  const val = Number(form.value.gcsScore);
  if (!val && val !== 0) return;
  console.log(val);
  if (val > 7) {
    uni.showToast({
      title: "GCS评分不能大于7",
      icon: "none",
    });
    form.value.gcsScore = "";
  }
  if (val < 3) {
    uni.showToast({
      title: "GCS评分不能小于3",
      icon: "none",
    });
    form.value.gcsScore = "";
  }
};
// 身份证校验码验证函数
const validateIdCardCheckCode = (idCard) => {
  // 系数数组
  const coefficientArray = [
    7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2,
  ];
  // 校验码对应值
  const checkCodeMap = ["1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2"];
  let sum = 0;
  for (let i = 0; i < 17; i++) {
    sum += parseInt(idCard.charAt(i), 10) * coefficientArray[i];
  }
  const checkCode = checkCodeMap[sum % 11];
  return checkCode === idCard.charAt(17).toUpperCase();
};
// 从身份证号提取出生日期
const extractBirthdayFromIdCard = () => {
  const idCard = form.value.idcardno;
  if (!idCard || idCard.length !== 18) {
    return;
  }
  try {
    // 提取出生日期部分(第7-14位:YYYYMMDD)
    const birthStr = idCard.substring(6, 14);
    const year = birthStr.substring(0, 4);
    const month = birthStr.substring(4, 6);
    const day = birthStr.substring(6, 8);
    // 验证日期是否有效
    const birthDate = new Date(`${year}-${month}-${day}`);
    if (isNaN(birthDate.getTime())) {
      console.log("身份证号码中的出生日期无效");
      return;
    }
    // 验证日期范围(不能是未来日期)
    const today = new Date();
    if (birthDate > today) {
      console.log("出生日期不能是未来日期");
      return;
    }
    // 验证月份和日期是否合理
    const monthNum = parseInt(month, 10);
    const dayNum = parseInt(day, 10);
    if (monthNum < 1 || monthNum > 12) {
      console.log("月份无效");
      return;
    }
    // 检查日期是否有效(简单验证)
    const daysInMonth = new Date(year, monthNum, 0).getDate();
    if (dayNum < 1 || dayNum > daysInMonth) {
      console.log("日期无效");
      return;
    }
    // 设置出生日期
    form.value.birthday = `${year}-${month.padStart(2, "0")}-${day.padStart(
      2,
      "0",
    )}`;
    // 计算年龄
    calculateAge();
    // 从身份证提取性别(第17位,奇数为男,偶数为女)
    const genderCode = parseInt(idCard.charAt(16), 10);
    if (!isNaN(genderCode)) {
      form.value.sex = genderCode % 2 === 1 ? "1" : "2";
    }
    uni.showToast({
      title: "已自动提取出生日期和性别",
      icon: "success",
      duration: 1500,
    });
  } catch (error) {
    console.error("解析身份证出生日期失败:", error);
  }
};
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);
  return "";
});
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();
const currentOccupationText = computed(() => {
  if (occupationIndex.value >= 0 && occupationList.value[occupationIndex.value])
    return occupationList.value[occupationIndex.value];
  if (form.value.occupation) {
    const found = getDictList("sys_occupation").find(
      (item) => item.value == form.value.occupation,
    );
    return found ? found.label : form.value.occupation;
  }
  console.log(userStore.userInfo, "userStoreuserInfo");
  if (!userStore.userInfo) {
    await userStore.refreshUserInfo();
  }
  form.value.treatmenthospitalname = userStore.userInfo.orgName;
  form.value.toHospital = userStore.userInfo.orgName;
  form.value.coordinatorName = userStore.userInfo.coordinatorName;
  form.value.coordinatorNo = userStore.userInfo.coordinatorNo;
  form.value.infoName = userStore.userInfo.nickName;
  form.value.phone = userStore.userInfo.phonenumber;
  form.value.reportername = userStore.userInfo.name;
  form.value.reporterno = userStore.userInfo.userId;
  // 获取字典数据
  dict.value = await useDict(
    "sys_IDType",
    "sys_user_sex",
    "sys_Nation",
    "sys_BloodType",
    "sys_Infectious",
    "sys_AgeUnit", // 新增年龄单位
    "sys_education", // 新增学历
    "sys_occupation", // 新增职业
  );
  initOptions();
  updateCurrentTime();
  return "";
});
// 初始化选项数据的方法
const initOptions = () => {
  infectiousDiseaselist.value = dict.value.sys_Infectious || [];
  idCardTypeOptions.value = dict.value.sys_IDType || [];
  nationLabel.value = dict.value.sys_Nation || [];
  // 初始化传染病选择状态
  if (form.value.infectious) {
    // 将逗号分隔的字符串转换为数组
    selectedInfectious.value = form.value.infectious
      .split(",")
      .filter((item) => item.trim() !== "");
  }
};
// 切换传染病选择
const toggleInfectious = (value) => {
  const index = selectedInfectious.value.indexOf(value);
  if (index === -1) {
    // 添加选中
    selectedInfectious.value.push(value);
  } else {
    // 移除选中
    selectedInfectious.value.splice(index, 1);
  }
  // 更新表单的 infectious 字段(逗号分隔的字符串)
  form.value.infectious = selectedInfectious.value.join(",");
};
// 检查传染病是否被选中
const isInfectiousSelected = (value) => {
  return selectedInfectious.value.includes(value);
};
// 方法定义
// ==================== 方法 ====================
const updateCurrentTime = () => {
  const now = new Date();
  // 手动格式化日期和时间
  const year = now.getFullYear();
  const month = String(now.getMonth() + 1).padStart(2, "0");
  const day = String(now.getDate()).padStart(2, "0");
  const hours = String(now.getHours()).padStart(2, "0");
  const minutes = String(now.getMinutes()).padStart(2, "0");
  const seconds = String(now.getSeconds()).padStart(2, "0");
  currentTime.value = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
  form.value.reporttime = currentTime.value;
  const timeStr = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
  currentTime.value = timeStr;
  // 如果报告时间尚未手动设置(或为空),则自动填入当前时间
  if (!form.value.reporttime) {
    form.value.reporttime = timeStr;
  }
};
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 generateCaseNo = () => {
  // 优先使用上报时间,如果没有则使用当前时间
  const timeStr = form.value.reporttime || currentTime.value;
  // 解析时间字符串
  let year, month, day, hours, minutes;
  if (timeStr) {
    // 格式:2026-07-15 14:30:00
    const parts = timeStr.split(" ");
    if (parts.length >= 2) {
      const dateParts = parts[0].split("-");
      const timeParts = parts[1].split(":");
      year = dateParts[0];
      month = dateParts[1];
      day = dateParts[2];
      hours = timeParts[0];
      minutes = timeParts[1];
    } else {
      // 只有日期没有时间
      const dateParts = timeStr.split("-");
      year = dateParts[0];
      month = dateParts[1];
      day = dateParts[2];
      hours = "00";
      minutes = "00";
    }
  } else {
    // 没有上报时间,使用当前时间
    const now = new Date();
    year = now.getFullYear().toString();
    month = String(now.getMonth() + 1).padStart(2, "0");
    day = String(now.getDate()).padStart(2, "0");
    hours = String(now.getHours()).padStart(2, "0");
    minutes = String(now.getMinutes()).padStart(2, "0");
  }
  // 格式:opo202607151430
  form.value.caseNo = `${year}${month}${day}${hours}${minutes}`;
};
// 民族选择
const onNationChange = (e) => {
  const index = parseInt(e.detail.value);
  nationIndex.value = index;
  form.value.nation = nationList.value[index];
};
// 证件类型选择
const onIdCardTypeChange = (e) => {
  const index = parseInt(e.detail.value);
  idCardTypeIndex.value = index;
  const selectedLabel = idCardTypeList.value[index];
  const dictItem = getDictList("sys_IDType").find(
    (item) => item.label == selectedLabel,
  );
  form.value.idcardtype = dictItem ? dictItem.value : selectedLabel;
};
// 学历选择
const onEducationChange = (e) => {
  const index = parseInt(e.detail.value);
  educationIndex.value = index;
  const selectedLabel = educationList.value[index];
  const dictItem = getDictList("sys_education").find(
    (item) => item.label == selectedLabel,
  );
  form.value.education = dictItem ? dictItem.value : selectedLabel;
};
// 职业选择
const onOccupationChange = (e) => {
  const index = parseInt(e.detail.value);
  occupationIndex.value = index;
  const selectedLabel = occupationList.value[index];
  const dictItem = getDictList("sys_occupation").find(
    (item) => item.label == selectedLabel,
  );
  form.value.occupation = dictItem ? dictItem.value : selectedLabel;
};
// 年龄单位选择
const onAgeUnitChange = (e) => {
  const index = parseInt(e.detail.value);
  ageUnitIndex.value = index;
  const selectedLabel = ageUnitList.value[index];
  const dictItem = getDictList("sys_AgeUnit").find(
    (item) => item.label === selectedLabel,
  );
  form.value.ageunit = dictItem ? dictItem.value : selectedLabel;
};
// 出生日期
const onBirthdayChange = (e) => {
  form.value.birthday = e.detail.value;
  calculateAge();
};
const onDateConfirm = (e) => {
  const date = new Date(e.value);
  form.value.birthday = `${date.getFullYear()}-${String(
    date.getMonth() + 1,
  ).padStart(2, "0")}-${String(date.getDate()).padStart(2, "0")}`;
  calculateAge();
  showDatePicker.value = false;
};
const calculateAge = () => {
  if (!form.value.birthday) {
    form.value.age = "";
    form.value.ageunit = "";
    ageUnitIndex.value = -1;
    return;
  }
  const birthDate = new Date(form.value.birthday);
  const today = new Date();
  // 检查日期有效性
  if (isNaN(birthDate.getTime())) {
    form.value.age = "";
    form.value.ageunit = "";
    return;
  }
  // 检查是否为未来日期
  if (isNaN(birthDate.getTime())) return;
  if (birthDate > today) {
    uni.showToast({
      title: "出生日期不能是未来日期",
      icon: "none",
    });
    uni.showToast({ title: "出生日期不能是未来日期", icon: "none" });
    form.value.age = "";
    form.value.ageunit = "";
    ageUnitIndex.value = -1;
    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();
  const daysDiff = Math.floor((today - birthDate) / (1000 * 60 * 60 * 24));
  if (daysDiff < 0) return;
  let years = today.getFullYear() - birthDate.getFullYear();
  let months = today.getMonth() - birthDate.getMonth();
  let 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();
    if (months < 0 || (months === 0 && days < 0)) years--;
    ageValue = years.toString();
    ageUnit = "岁";
  } else if (daysDiff >= 30) {
    // 大于等于30天:显示月
    let totalMonths = years * 12 + months;
    if (days < 0) {
      totalMonths--;
    }
    ageValue = Math.max(1, totalMonths).toString(); // 确保至少1个月
    if (days < 0) totalMonths--;
    ageValue = Math.max(1, totalMonths).toString();
    ageUnit = "个月";
  } else {
    // 小于30天:显示天
    ageValue = Math.max(1, daysDiff).toString(); // 确保至少1天
    ageValue = Math.max(1, daysDiff).toString();
    ageUnit = "天";
  }
  form.value.age = ageValue;
  form.value.ageunit = ageUnit;
  // 同步单位索引
  const unitList = ageUnitList.value;
  const idx = unitList.findIndex((item) => item === ageUnit);
  ageUnitIndex.value = idx >= 0 ? idx : -1;
};
// 处理基础附件上传
const handleBaseUpload = (file) => {
  console.log("基础附件上传成功:", file);
  attachments.value.push(file);
// 身份证处理
const validateIdCard = () => {
  const idCard = form.value.idcardno;
  if (!idCard) {
    idCardError.value = "";
    return true;
  }
  if (idCard.length !== 18) {
    idCardError.value = "身份证号码必须是18位";
    return false;
  }
  const reg = /^\d{17}(\d|X|x)$/;
  if (!reg.test(idCard)) {
    idCardError.value = "身份证号码格式不正确";
    return false;
  }
  const coefficientArray = [
    7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2,
  ];
  const checkCodeMap = ["1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2"];
  let sum = 0;
  for (let i = 0; i < 17; i++)
    sum += parseInt(idCard.charAt(i), 10) * coefficientArray[i];
  const checkCode = checkCodeMap[sum % 11];
  if (checkCode != idCard.charAt(17).toUpperCase()) {
    idCardError.value = "身份证号码校验失败";
    return false;
  }
  idCardError.value = "";
  return true;
};
// 处理其他附件上传
const onIdCardChange = () => {
  if (validateIdCard()) extractBirthdayFromIdCard();
};
const extractBirthdayFromIdCard = () => {
  const idCard = form.value.idcardno;
  if (!idCard || idCard.length !== 18) return;
  const year = idCard.substring(6, 10);
  const month = idCard.substring(10, 12);
  const day = idCard.substring(12, 14);
  const birthDate = new Date(`${year}-${month}-${day}`);
  if (isNaN(birthDate.getTime())) return;
  form.value.birthday = `${year}-${month}-${day}`;
  calculateAge();
  const genderCode = parseInt(idCard.charAt(16), 10);
  if (!isNaN(genderCode)) form.value.sex = genderCode % 2 === 1 ? "1" : "2";
  uni.showToast({
    title: "已自动提取出生日期和性别",
    icon: "success",
    duration: 1500,
  });
};
const handleGcsBlur = () => {
  const val = Number(form.value.gcsScore);
  if (!val && val !== 0) return;
  if (val > 7) {
    uni.showToast({ title: "GCS评分不能大于7", icon: "none" });
    form.value.gcsScore = "";
  }
  if (val < 3) {
    uni.showToast({ title: "GCS评分不能小于3", icon: "none" });
    form.value.gcsScore = "";
  }
};
// 传染病
const toggleInfectious = (value) => {
  const index = selectedInfectious.value.indexOf(value);
  if (index === -1) selectedInfectious.value.push(value);
  else selectedInfectious.value.splice(index, 1);
  form.value.infectious = selectedInfectious.value.join(",");
};
const isInfectiousSelected = (value) =>
  selectedInfectious.value.includes(value);
// 报告时间手动选择
const onReportTimeConfirm = (e) => {
  const date = new Date(e.value);
  const year = date.getFullYear();
  const month = String(date.getMonth() + 1).padStart(2, "0");
  const day = String(date.getDate()).padStart(2, "0");
  const hours = String(date.getHours()).padStart(2, "0");
  const minutes = String(date.getMinutes()).padStart(2, "0");
  const seconds = String(date.getSeconds()).padStart(2, "0");
  form.value.reporttime = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
  showReportTimePicker.value = false;
  // 如果是新增模式,重新生成案例编号
  if (!isEditMode.value) {
    generateCaseNo();
  }
};
// 附件处理(示例,需根据实际附件组件调整)
const handleBaseUpload = (file) => attachments.value.push(file);
const handleFilesUpdate = (files) => {
  console.log(files, "files");
  attachments.value = files.map((file) => ({
    ...file,
    // 确保只存储半路径
    // url: file.url.startsWith("http")
    //   ? file.url.replace(baseUrlHt, "")
    //   : file.url,
  }));
  attachments.value = files.map((file) => ({ ...file }));
};
// 预览文件 - 修改为使用完整URL
const handlePreview = (file) => {
  const fullUrl = file.url.startsWith("http")
    ? file.url
    : baseUrlHt + (file.url.startsWith("/") ? "" : "/") + file.url;
    : (file.url.startsWith("/") ? "" : "/") + file.url;
  if (file.type.includes("image")) {
    uni.previewImage({
      urls: attachments.value
@@ -1080,79 +914,42 @@
        .map((f) =>
          f.url.startsWith("http")
            ? f.url
            : baseUrlHt + (f.url.startsWith("/") ? "" : "/") + f.url,
            : (f.url.startsWith("/") ? "" : "/") + f.url,
        ),
      current: fullUrl,
    });
  } else if (file.type.includes("pdf")) {
    uni.downloadFile({
      url: fullUrl,
      success: (res) => {
      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 onResidenceChange = (val) => {
  form.value.residenceprovincename = val.sheng;
  form.value.residenceprovince = val.provinceCode || "";
  form.value.residencecountyname = val.shi;
  form.value.residencetownname = val.qu;
  // 可根据需要补充区县code
};
const onRegisterChange = (val) => {
  form.value.registerprovincename = val.sheng;
  form.value.registerprovince = val.provinceCode || "";
  form.value.registercityname = val.shi;
  form.value.registertownname = val.qu;
};
const onHospitalConfirm = (e) => {
  console.log(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 handleCancel = () => uni.navigateBack();
const resetForm = () => {
  uni.showModal({
@@ -1161,30 +958,26 @@
    success: (res) => {
      if (res.confirm) {
        Object.keys(form.value).forEach((key) => {
          if (!["id", "caseNo"].includes(key)) {
            form.value[key] = "";
          }
          if (!["id", "caseNo"].includes(key)) form.value[key] = "";
        });
        // 重置选择器索引
        hospitalIndex.value = -1;
        deptIndex.value = -1;
        form.value.nationality = "中国";
        form.value.reportStatus = "1";
        form.value.terminationCase = 0;
        nationIndex.value = -1;
        idCardTypeIndex.value = -1;
        // 重置传染病选择
        educationIndex.value = -1;
        occupationIndex.value = -1;
        ageUnitIndex.value = -1;
        selectedInfectious.value = [];
        // 重置附件
        attachments.value = [];
        form.value.nationality = "中国";
        form.value.isTransport = "";
        form.value.terminationCase = 0;
        form.value.reportStatus = "1";
        residenceAddress.value = { sheng: "", shi: "", qu: "" };
        registerAddress.value = { sheng: "", shi: "", qu: "" };
        if (!isEditMode.value) {
          generateDonorNo();
          // 重置报告时间为当前时间
          updateCurrentTime();
          // 根据新的上报时间生成案例编号
          generateCaseNo();
        }
        uni.showToast({ title: "表单已重置", icon: "success" });
      }
    },
@@ -1193,18 +986,15 @@
const handleSubmit = async () => {
  if (!isFormValid.value) {
    uni.showToast({
      title: "请填写姓名、证件号码和疾病诊断",
      icon: "none",
    });
    uni.showToast({ title: "请填写姓名、疾病诊断和上报医院", icon: "none" });
    return;
  }
  try {
    loading.value = true;
    uni.showLoading({ title: isEditMode.value ? "修改中..." : "提交中..." });
    // 准备提交数据
    const submitData = {
      ...form.value,
      treatmenthospitalname: form.value.toHospital,
      age: parseInt(form.value.age) || 0,
      annexfilesList: attachments.value.map((file) => ({
        path: file.url,
@@ -1215,41 +1005,29 @@
      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) {
    if (res.code == 200) {
      uni.showToast({
        title: isEditMode.value ? "修改成功" : "上报成功",
        icon: "success",
      });
      // 清空本地存储的草稿
      removeDraft();
      setTimeout(() => {
        uni.navigateBack();
      }, 1500);
      setTimeout(() => uni.navigateBack(), 1500);
    } else {
      throw new Error(res.msg || "操作失败");
    }
  } catch (error) {
    console.error("操作失败:", error);
    uni.showToast({
      title: error.message || (isEditMode.value ? "修改失败" : "上报失败"),
      icon: "none",
@@ -1258,65 +1036,135 @@
    loading.value = false;
  }
};
const removeDraft = () => {
  try {
    uni.removeStorageSync('caseReportDraft');
  } catch (e) {
    console.error('移除草稿失败', e);
  }
};
// 取消处理
const handleCancel = () => {
  uni.navigateBack();
};
// 加载案例数据
const loadCaseData = async (id) => {
  try {
    loading.value = true;
    const res = await uni.$uapi.get(
      `/project/donatebaseinforeport/getInfo/${id}`,
    );
    if (res.code) {
      form.value = res.data;
      if (res.data.infectious) {
      if (res.data.infectious)
        selectedInfectious.value = res.data.infectious
          .split(",")
          .filter((item) => item.trim() !== "");
      if (form.value.nation) {
        const idx = nationList.value.findIndex(
          (item) => item == form.value.nation,
        );
        nationIndex.value = idx >= 0 ? idx : -1;
      }
      currentNation.value = form.value.nation;
      idCardTypeIndex.value = form.value.idcardtype;
      // 处理选择器索引
      // updatePickerIndexes();
      // 处理附件
      if (form.value.idcardtype) {
        const dictList = getDictList("sys_IDType");
        const idx = dictList.findIndex(
          (item) => item.value == form.value.idcardtype,
        );
        idCardTypeIndex.value = idx >= 0 ? idx : -1;
      }
      if (form.value.education) {
        const dictList = getDictList("sys_education");
        const idx = dictList.findIndex(
          (item) => item.value == form.value.education,
        );
        educationIndex.value = idx >= 0 ? idx : -1;
      }
      if (form.value.occupation) {
        const dictList = getDictList("sys_occupation");
        const idx = dictList.findIndex(
          (item) => item.value == form.value.occupation,
        );
        occupationIndex.value = idx >= 0 ? idx : -1;
      }
      // 年龄单位回显
      if (form.value.ageunit) {
        const unitList = ageUnitList.value;
        const idx = unitList.findIndex((item) => item === form.value.ageunit);
        ageUnitIndex.value = idx >= 0 ? idx : -1;
      }
      // 地址回显
      if (res.data.residenceprovincename) {
        residenceAddress.value = {
          sheng: res.data.residenceprovincename,
          shi: res.data.residencecountyname,
          qu: res.data.residencetownname,
        };
      }
      if (res.data.registerprovincename) {
        registerAddress.value = {
          sheng: res.data.registerprovincename,
          shi: res.data.registercityname,
          qu: res.data.registertownname,
        };
      }
      if (res.data.annexfilesList) {
        attachments.value = res.data.annexfilesList;
        attachments.value.forEach((item) => {
          item.url = item.path;
          item.name = item.fileName;
        });
        attachments.value = res.data.annexfilesList.map((item) => ({
          url: item.path,
          name: item.fileName,
          type: item.type || "",
        }));
      }
      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",
    });
    uni.showToast({ title: "数据加载失败,请重试", icon: "none" });
  } finally {
    loading.value = false;
  }
};
// ==================== 生命周期 ====================
onMounted(() => {
  updateCurrentTime();
  setInterval(updateCurrentTime, 1000);
});
onLoad(async (options) => {
  if (options.id) {
    currentId.value = options.id;
    isEditMode.value = true;
    await new Promise((resolve) => {
      if (!dictLoading.value) resolve();
      else {
        const stopWatch = watch(dictLoading, (val) => {
          if (!val) {
            stopWatch();
            resolve();
          }
        });
      }
    });
    await loadCaseData(options.id);
  } else {
    isEditMode.value = false;
    generateCaseNo();
    // 新增时默认填入报告时间
    updateCurrentTime();
  }
  if (!userStore.userInfo) await userStore.refreshUserInfo();
  const user = userStore.userInfo;
  if (user) {
    if (!form.value.treatmenthospitalname)
      form.value.treatmenthospitalname = user.orgName;
    if (!form.value.toHospital) form.value.toHospital = user.orgName;
    if (!form.value.coordinatorName)
      form.value.coordinatorName = user.coordinatorName;
    if (!form.value.coordinatorNo)
      form.value.coordinatorNo = user.coordinatorNo;
    if (!form.value.infoName) form.value.infoName = user.nickName;
    if (!form.value.phone) form.value.phone = user.phonenumber;
    if (!form.value.reportername) form.value.reportername = user.name;
    if (!form.value.reporterno) form.value.reporterno = user.userId;
  }
  updateCurrentTime();
});
</script>
<style lang="scss" scoped>
// 样式与原来保持一致,新增地址块样式
.case-report-container {
  min-height: 100vh;
  background: linear-gradient(135deg, #f8fdff 0%, #e8f7f6 100%);
@@ -1324,40 +1172,53 @@
.form-content {
  padding: 30rpx;
  padding-bottom: 180rpx; // 给按钮留出空间
  padding-bottom: 220rpx;
}
.page-header {
  padding: 30rpx 0;
  text-align: center;
  margin-bottom: 20rpx;
}
.page-title {
  font-size: 38rpx;
  font-weight: 700;
  color: #1d1d1f;
  letter-spacing: 2rpx;
}
.form-section {
  background: #fff;
  border-radius: 20rpx;
  padding: 30rpx;
  margin-bottom: 30rpx;
  box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.06);
  margin-bottom: 26rpx;
  box-shadow: 0 4rpx 24rpx rgba(0, 0, 0, 0.05);
}
.section-header {
  display: flex;
  // align-items: center;
  margin-bottom: 30rpx;
  align-items: center;
  margin-bottom: 28rpx;
  padding-bottom: 20rpx;
  border-bottom: 2rpx solid #f0f0f0;
}
.section-icon {
  font-size: 32rpx;
  margin-right: 16rpx;
  font-size: 34rpx;
  margin-right: 14rpx;
}
.section-title {
  font-size: 32rpx;
  font-weight: 600;
  font-weight: 650;
  color: #1d1d1f;
}
.form-grid {
  display: flex;
  flex-direction: column;
  gap: 24rpx;
  gap: 28rpx;
}
.form-item {
@@ -1372,7 +1233,7 @@
.item-label {
  font-size: 28rpx;
  color: #1d1d1f;
  font-weight: 500;
  font-weight: 520;
  margin-bottom: 12rpx;
  &.required::after {
@@ -1382,19 +1243,82 @@
  }
}
// 自定义u-input样式
:deep(.u-input) {
  border: 2rpx solid #e5e5e7 !important;
  border-radius: 12rpx !important;
  padding: 20rpx 24rpx !important;
  background: #fff !important;
}
:deep(.u-input),
:deep(.u-textarea) {
  border: 2rpx solid #e5e5e7 !important;
  border-radius: 12rpx !important;
  padding: 20rpx 24rpx !important;
  background: #fff !important;
  &:focus-within {
    border-color: #0f95b0 !important;
  }
}
.picker {
  height: 86rpx;
  background: #fafafa;
  border-radius: 12rpx;
  padding: 0 24rpx;
  display: flex;
  align-items: center;
  justify-content: space-between;
  border: 2rpx solid #e5e5e7;
  &:active {
    border-color: #0f95b0;
  }
  .icon-arrow {
    font-size: 34rpx;
    color: #86868b;
    transform: rotate(90deg);
  }
}
.radio-options {
  display: flex;
  gap: 44rpx;
  .option-item {
    display: flex;
    align-items: center;
    gap: 14rpx;
    .radio-dot {
      width: 34rpx;
      height: 34rpx;
      border: 3rpx solid #d1d1d6;
      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: 18rpx;
        height: 18rpx;
        background: #0f95b0;
        border-radius: 50%;
      }
    }
    &.active .option-label {
      color: #0f95b0;
      font-weight: 550;
    }
  }
}
.radio-group {
@@ -1407,39 +1331,131 @@
  }
}
.radio-item {
// 替换原有的 .radio-group.horizontal 相关样式
.radio-group.horizontal {
  display: flex;
  align-items: center;
  gap: 16rpx;
}
  flex-wrap: nowrap;
  overflow-x: auto;
  gap: 18rpx;
.radio-dot {
  width: 32rpx;
  height: 32rpx;
  border: 2rpx solid #e5e5e7;
  border-radius: 50%;
  position: relative;
  .radio-item {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    gap: 8rpx;
    padding: 10rpx 20rpx;
    border-radius: 20rpx;
    background: #f5f5f7;
    transition: all 0.2s;
  &.active {
    border-color: #0f95b0;
    &::after {
      content: "";
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      width: 16rpx;
      height: 16rpx;
      background: #0f95b0;
    .radio-dot {
      width: 36rpx;
      height: 36rpx;
      border: 2rpx solid #d1d1d6;
      border-radius: 50%;
      background-color: #fff;
      display: flex;
      align-items: center;
      justify-content: center;
      transition: all 0.2s;
      &.active {
        border-color: #0f95b0;
        background-color: #0f95b0;
        // 可选:如果希望有白色对勾,取消注释下面
        // &::after {
        //   content: "✓";
        //   font-size: 20rpx;
        //   color: white;
        //   line-height: 1;
        // }
      }
    }
    .radio-label {
      font-size: 26rpx;
      color: #1d1d1f;
      white-space: nowrap;
    }
    // 选中时整体背景微微变色(可选)
    &.active {
      background: rgba(15, 149, 176, 0.1);
    }
  }
}
.radio-label {
  font-size: 28rpx;
  color: #1d1d1f;
.checkbox-group.single-line {
  display: flex;
  flex-wrap: nowrap;
  overflow-x: auto;
  gap: 16rpx;
  .checkbox-item {
    display: flex;
    align-items: center;
    gap: 8rpx;
    flex-shrink: 0;
    padding: 10rpx 20rpx;
    border-radius: 22rpx;
    background: #f5f5f7;
    &.active {
      border-color: #0f95b0;
      background: rgba(15, 149, 176, 0.09);
    }
    .checkbox-box {
      width: 30rpx;
      height: 30rpx;
      border: 2rpx solid #d1d1d6;
      border-radius: 6rpx;
      display: flex;
      align-items: center;
      justify-content: center;
      background: #fff;
      &.active {
        border-color: #0f95b0;
        background: #0f95b0;
      }
      .checkbox-check {
        font-size: 20rpx;
        color: white;
        font-weight: bold;
      }
    }
    .checkbox-label {
      font-size: 25rpx;
      color: #1d1d1f;
      white-space: nowrap;
    }
  }
}
.error-text {
  font-size: 23rpx;
  color: #ff4757;
  margin-top: 8rpx;
}
.address-block {
  margin-bottom: 32rpx;
  .address-label {
    font-size: 27rpx;
    color: #1d1d1f;
    font-weight: 520;
    margin-bottom: 12rpx;
    display: block;
  }
  .address-detail-input {
    margin-top: 16rpx;
  }
}
.action-buttons {
@@ -1449,407 +1465,35 @@
  right: 0;
  background: #fff;
  padding: 20rpx 30rpx calc(20rpx + env(safe-area-inset-bottom));
  box-shadow: 0 -2rpx 20rpx rgba(0, 0, 0, 0.08);
  z-index: 99;
  box-shadow: 0 -4rpx 24rpx rgba(0, 0, 0, 0.07);
  z-index: 9;
  display: flex;
  gap: 20rpx;
}
.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-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;
    padding-bottom: 180rpx;
  }
  .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;
}
.idcard-hint {
  margin-top: 8rpx;
  padding: 12rpx 16rpx;
  background: #f0f9ff;
  border-radius: 8rpx;
  border-left: 4rpx solid #0f95b0;
}
.hint-text {
  display: block;
  font-size: 24rpx;
  color: #0f95b0;
  margin-bottom: 4rpx;
  &:last-child {
    margin-bottom: 0;
  }
}
.error-text {
  font-size: 24rpx;
  color: #ff4757;
  margin-top: 8rpx;
}
.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;
    }
  }
}
.checkbox-group {
  display: flex;
  flex-wrap: nowrap; /* 禁止换行 */
  gap: 20rpx;
  overflow-x: auto; /* 水平滚动 */
  padding-bottom: 10rpx; /* 给滚动条留出空间 */
  -webkit-overflow-scrolling: touch; /* iOS平滑滚动 */
  &.single-line {
    display: flex;
    flex-wrap: nowrap;
    overflow-x: auto;
    width: 100%;
    /* 隐藏滚动条,但保持滚动功能 */
    &::-webkit-scrollbar {
      display: none;
    }
  }
}
.checkbox-item {
  display: flex;
  align-items: center;
  gap: 8rpx;
  flex-shrink: 0; /* 防止选项被压缩 */
  padding: 8rpx 16rpx;
  border-radius: 20rpx;
  background: #f5f5f7;
  transition: all 0.3s ease;
  &.active {
    background: rgba(15, 149, 176, 0.1);
  }
}
.checkbox-box {
  width: 28rpx;
  height: 28rpx;
  border: 2rpx solid #e5e5e7;
  border-radius: 6rpx;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #fff;
  transition: all 0.3s ease;
  flex-shrink: 0;
  &.active {
    border-color: #0f95b0;
    background: #0f95b0;
  }
}
.checkbox-check {
  font-size: 20rpx;
  color: white;
  font-weight: bold;
}
.checkbox-label {
  font-size: 24rpx;
  color: #1d1d1f;
  white-space: nowrap;
}
/* 优化单选按钮组的样式,保持一致性 */
.radio-group.horizontal {
  display: flex;
  flex-wrap: nowrap;
  overflow-x: auto;
  gap: 20rpx;
  padding-bottom: 10rpx;
  -webkit-overflow-scrolling: touch;
  &::-webkit-scrollbar {
    display: none;
  }
  .radio-item {
    flex-shrink: 0;
  .btn {
    flex: 1;
    height: 84rpx;
    border-radius: 16rpx;
    font-size: 31rpx;
    font-weight: 530;
    display: flex;
    align-items: center;
    gap: 8rpx;
    padding: 8rpx 16rpx;
    border-radius: 20rpx;
  }
    justify-content: center;
  .radio-item .radio-dot.active {
    border-color: #0f95b0;
    &::after {
      background: #0f95b0;
    &.secondary {
      background: #f5f5f7 !important;
      color: #1d1d1f !important;
    }
  }
}
/* 如果需要固定高度,可以这样设置 */
.checkbox-group.single-line {
  min-height: 60rpx;
  align-items: center;
}
    &.primary {
      background: linear-gradient(135deg, #0f95b0, #66b8b5) !important;
      color: #fff !important;
/* 在移动端优化触摸区域 */
.checkbox-item {
  min-height: 60rpx;
  padding: 8rpx 20rpx;
  cursor: pointer;
}
/* 添加选中状态的视觉反馈 */
.checkbox-item.active {
  border: 1rpx solid #0f95b0;
  background: rgba(15, 149, 176, 0.08);
}
/* 响应式调整 */
@media (max-width: 768px) {
  .checkbox-group.single-line {
    gap: 12rpx;
  }
  .checkbox-item {
    padding: 6rpx 14rpx;
  }
  .checkbox-label {
    font-size: 22rpx;
      &:disabled {
        background: #c8c8cc !important;
        opacity: 0.55;
      }
    }
  }
}
</style>