WXL
2 天以前 9bce51f651aad297ef9eb6df832bfdaf1de05d84
pages/case/transferinfo.vue
@@ -3,217 +3,310 @@
    <!-- 表单内容 -->
    <scroll-view scroll-y class="form-scroll" :show-scrollbar="false">
      <view class="form-content">
        <!-- 案例信息卡片 -->
        <view class="form-section" v-if="transportData.caseNo">
          <view class="section-header">
            <view class="section-icon">📋</view>
            <text class="section-title">关联案例信息</text>
          </view>
          <view class="case-info">
            <view class="info-row">
              <text class="info-label">案例编号:</text>
              <text class="info-value">{{ transportData.caseNo }}</text>
            </view>
            <view class="info-row">
              <text class="info-label">患者姓名:</text>
              <text class="info-value">{{ transportData.patName }}</text>
            </view>
            <view class="info-row">
              <text class="info-label">性别/年龄:</text>
              <text class="info-value"
                >{{ getGenderText(transportData.sex) }} /
                {{ transportData.age }}岁</text
              >
            </view>
            <view class="info-row">
              <text class="info-label">疾病诊断:</text>
              <text class="info-value">{{ transportData.diagnosisname }}</text>
            </view>
            <view class="info-row">
              <text class="info-label">治疗医院:</text>
              <text class="info-value">{{
                transportData.treatmentHospitalName
              }}</text>
            </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 required">案例选择</text>
              <u-input
                v-model="form.caseInfo.donorName"
                placeholder="选择案例"
                readonly
                border="none"
                @click="showCasePicker = true"
                :customStyle="inputStyle(!form.caseInfo.caseId)"
              >
                <template #suffix>
                  <u-icon name="arrow-down" color="#86868b"></u-icon>
                </template>
              </u-input>
            </view>
            <view class="form-item">
              <text class="item-label required">捐献医院</text>
              <u-input
                v-model="form.hospital"
                placeholder="请输入捐献医院"
                border="none"
                :customStyle="inputStyle(!form.hospital)"
              />
            </view>
            <view class="form-item">
              <text class="item-label">科室</text>
              <u-input
                v-model="form.department"
                placeholder="请输入科室"
                border="none"
              />
            <view class="section-icon">📄</view>
            <text class="section-title">转运单信息</text>
            <!-- 状态标签 -->
            <view
              class="status-tag"
              :class="getTransportStatusClass(transportData.transitStatus)"
            >
              {{ getTransportStatusText(transportData.transitStatus) }}
            </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="transportData.reportId"
                placeholder="自动生成"
                disabled
                :disabledColor="disabledColor"
                border="none"
              />
            </view>
            <view class="form-item">
              <text class="item-label required">出发地点</text>
              <u-input
                v-model="transportData.transportStartPlace"
                placeholder="请输入出发地点"
                border="none"
                :readonly="!isEdit"
                :customStyle="inputStyle(!transportData.transportStartPlace)"
              />
            </view>
            <view class="form-item">
              <text class="item-label required">出发时间</text>
              <u-input
                v-model="form.departureTime"
                v-model="transportData.transportStartTime"
                placeholder="请选择出发时间"
                readonly
                border="none"
                @click="showTimePicker = true"
                :customStyle="inputStyle(!form.departureTime)"
                :disabled="!isEdit"
                @click="isEdit && (showTimePicker = true)"
                :customStyle="inputStyle(!transportData.transportStartTime)"
              >
                <template #suffix>
                <template #suffix v-if="isEdit">
                  <u-icon name="arrow-down" color="#86868b"></u-icon>
                </template>
              </u-input>
            </view>
            <view class="form-item full-width">
              <text class="item-label">出发地点</text>
              <u-textarea
                v-model="form.departureLocation"
                placeholder="请输入出发地点详细地址"
                count
                maxlength="200"
                height="120"
            <view class="form-item">
              <text class="item-label">转运状态</text>
              <u-select
                v-model="statusSelectVisible"
                :list="statusOptions"
                :default-value="[statusIndex]"
                :confirm-text="'确定'"
                :cancel-text="'取消'"
                @confirm="onStatusConfirm"
                :disabled="!isEdit"
              >
                <template #default>
                  <view class="picker-trigger">
                    <text>{{
                      getTransportStatusText(transportData.transitStatus)
                    }}</text>
                    <u-icon
                      v-if="isEdit"
                      name="arrow-down"
                      size="16"
                      color="#999"
                    ></u-icon>
                  </view>
                </template>
              </u-select>
            </view>
            <view class="form-item">
              <text class="item-label required">负责协调员</text>
              <u-input
                v-model="transportData.contactPerson"
                placeholder="请输入协调员姓名"
                border="none"
                :readonly="!isEdit"
                :customStyle="inputStyle(!transportData.contactPerson)"
              />
            </view>
            <view class="form-item">
              <text class="item-label">抵达医院</text>
            <view class="form-item" v-if="transportData.createTime">
              <text class="item-label">创建时间</text>
              <u-input
                v-model="form.destinationHospital"
                placeholder="请输入抵达医院"
                v-model="transportData.createTime"
                placeholder="自动生成"
                disabled
                :disabledColor="disabledColor"
                border="none"
              />
            </view>
            <view class="form-item" v-if="transportData.createBy">
              <text class="item-label">创建人</text>
              <u-input
                v-model="transportData.createBy"
                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>
            <text class="section-title">医护人员信息</text>
          </view>
          <view class="form-grid">
            <view class="form-item">
              <text class="item-label">协调员</text>
              <u-input
                v-model="form.coordinator.name"
                placeholder="选择协调员"
                readonly
                border="none"
                @click="showCoordinatorPicker = 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="form.emergencyDoctor.name"
                placeholder="选择急诊科医生"
                readonly
                v-model="transportData.doctor"
                placeholder="请输入急诊科医生"
                border="none"
                @click="showDoctorPicker = true"
              >
                <template #suffix>
                  <u-icon name="arrow-down" color="#86868b"></u-icon>
                </template>
              </u-input>
                :readonly="!isEdit"
              />
            </view>
            <view class="form-item">
              <text class="item-label">医生电话</text>
              <u-input
                v-model="transportData.doctorPhone"
                placeholder="请输入医生手机号"
                type="number"
                border="none"
                :readonly="!isEdit"
              />
            </view>
            <view class="form-item">
              <text class="item-label">护士</text>
              <u-input
                v-model="form.nurse.name"
                placeholder="选择护士"
                readonly
                v-model="transportData.nurse"
                placeholder="请输入护士姓名"
                border="none"
                @click="showNursePicker = true"
              >
                <template #suffix>
                  <u-icon name="arrow-down" color="#86868b"></u-icon>
                </template>
              </u-input>
                :readonly="!isEdit"
              />
            </view>
            <view class="form-item">
              <text class="item-label">司机</text>
              <text class="item-label">护士电话</text>
              <u-input
                v-model="form.driver.name"
                placeholder="选择司机"
                readonly
                v-model="transportData.nursePhone"
                placeholder="请输入护士手机号"
                type="number"
                border="none"
                @click="showDriverPicker = true"
              >
                <template #suffix>
                  <u-icon name="arrow-down" color="#86868b"></u-icon>
                </template>
              </u-input>
                :readonly="!isEdit"
              />
            </view>
            <view class="form-item">
              <text class="item-label">驾驶员</text>
              <u-input
                v-model="transportData.driver"
                placeholder="请输入驾驶员姓名"
                border="none"
                :readonly="!isEdit"
              />
            </view>
            <view class="form-item">
              <text class="item-label">驾驶员电话</text>
              <u-input
                v-model="transportData.driverPhone"
                placeholder="请输入驾驶员手机号"
                type="number"
                border="none"
                :readonly="!isEdit"
              />
            </view>
            <view class="form-item">
              <text class="item-label">ICU评估医生</text>
              <u-input
                v-model="form.icuDoctor.name"
                placeholder="选择ICU评估医生"
                readonly
                v-model="transportData.icuDoctor"
                placeholder="请输入ICU评估医生"
                border="none"
                @click="showIcuDoctorPicker = true"
              >
                <template #suffix>
                  <u-icon name="arrow-down" color="#86868b"></u-icon>
                </template>
              </u-input>
                :readonly="!isEdit"
              />
            </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" v-for="(contact, index) in form.contacts" :key="index">
              <text class="item-label">{{ contact.role }}</text>
            <view class="form-item">
              <text class="item-label">ICU医生电话</text>
              <u-input
                v-model="contact.phone"
                placeholder="请输入联系电话"
                border="none"
                v-model="transportData.icuDoctorPhone"
                placeholder="请输入ICU医生手机号"
                type="number"
                border="none"
                :readonly="!isEdit"
              />
            </view>
          </view>
        </view>
        <!-- 备注信息卡片 -->
        <!-- 附件信息 -->
        <view
          class="form-section"
          v-if="
            transportData.annexfilesList &&
            transportData.annexfilesList.length > 0
          "
        >
          <view class="section-header">
            <view class="section-icon">📎</view>
            <text class="section-title"
              >附件信息 ({{ transportData.annexfilesList.length }})</text
            >
          </view>
          <view class="attachment-list">
            <view
              v-for="(file, index) in transportData.annexfilesList"
              :key="index"
              class="attachment-item"
              @click="previewFile(file)"
            >
              <view class="file-info">
                <u-icon
                  name="file-text"
                  color="#409EFF"
                  size="20"
                  class="file-icon"
                ></u-icon>
                <view class="file-details">
                  <text class="file-name">{{ file.fileName }}</text>
                  <text class="file-time">{{
                    formatTime(file.createTime)
                  }}</text>
                </view>
              </view>
              <u-icon name="arrow-right" color="#999" size="16"></u-icon>
            </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 full-width">
              <u-textarea
                v-model="form.remarks"
                placeholder="请输入特殊要求或备注信息"
                count
                v-model="transportData.remark"
                placeholder="请输入备注信息"
                border="none"
                :readonly="!isEdit"
                :count="isEdit"
                maxlength="500"
                height="200"
                height="150"
              />
            </view>
          </view>
@@ -221,23 +314,48 @@
        <!-- 操作按钮 -->
        <view class="action-buttons">
          <u-button class="btn secondary" @click="handleCancel">取消</u-button>
          <u-button class="btn primary" @click="handleSaveDraft">保存草稿</u-button>
          <u-button class="btn success" @click="handleSubmit" :disabled="!isFormValid">提交申请</u-button>
          <!-- 查看模式 -->
          <template v-if="!isEdit">
            <u-button class="btn secondary" @click="goBack">返回</u-button>
            <u-button v-if="canEdit" class="btn primary" @click="handleEdit">
              编辑
            </u-button>
            <u-button
              v-if="canStartTransport"
              class="btn warning"
              @click="handleStartTransport"
            >
              开始转运
            </u-button>
            <u-button
              v-if="canCompleteTransport"
              class="btn success"
              @click="handleCompleteTransport"
            >
              完成转运
            </u-button>
            <u-button v-if="canDelete" class="btn error" @click="handleDelete">
              删除
            </u-button>
          </template>
          <!-- 编辑模式 -->
          <template v-else>
            <u-button class="btn secondary" @click="cancelEdit">取消</u-button>
            <u-button
              class="btn success"
              @click="handleSave"
              :disabled="!isFormValid"
              :loading="saving"
            >
              保存
            </u-button>
          </template>
        </view>
      </view>
    </scroll-view>
    <!-- 选择器组件 -->
    <u-picker
      :show="showCasePicker"
      :columns="[caseOptions]"
      keyName="label"
      @confirm="onCaseConfirm"
      @cancel="showCasePicker = false"
      title="选择案例"
    ></u-picker>
    <!-- 时间选择器 -->
    <u-datetime-picker
      :show="showTimePicker"
      v-model="departureTimeValue"
@@ -247,385 +365,428 @@
      title="选择出发时间"
    ></u-datetime-picker>
    <u-picker
      :show="showCoordinatorPicker"
      :columns="[coordinatorOptions]"
      keyName="label"
      @confirm="onCoordinatorConfirm"
      @cancel="showCoordinatorPicker = false"
      title="选择协调员"
    ></u-picker>
    <u-picker
      :show="showDoctorPicker"
      :columns="[doctorOptions]"
      keyName="label"
      @confirm="onDoctorConfirm"
      @cancel="showDoctorPicker = false"
      title="选择急诊科医生"
    ></u-picker>
    <u-picker
      :show="showNursePicker"
      :columns="[nurseOptions]"
      keyName="label"
      @confirm="onNurseConfirm"
      @cancel="showNursePicker = false"
      title="选择护士"
    ></u-picker>
    <u-picker
      :show="showDriverPicker"
      :columns="[driverOptions]"
      keyName="label"
      @confirm="onDriverConfirm"
      @cancel="showDriverPicker = false"
      title="选择司机"
    ></u-picker>
    <u-picker
      :show="showIcuDoctorPicker"
      :columns="[icuDoctorOptions]"
      keyName="label"
      @confirm="onIcuDoctorConfirm"
      @cancel="showIcuDoctorPicker = false"
      title="选择ICU评估医生"
    ></u-picker>
    <!-- 加载状态 -->
    <u-loading-icon :show="loading" text="提交中..."></u-loading-icon>
    <u-loading-icon :show="loading" :text="loadingText"></u-loading-icon>
  </view>
</template>
<script setup>
import { ref, reactive, computed, onMounted } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import { ref, computed, onMounted } from "vue";
import { onLoad } from "@dcloudio/uni-app";
// 表单数据
const form = reactive({
  caseInfo: {
    caseId: '',
    donorName: '',
    gender: '',
    age: '',
    diagnosis: ''
  },
  hospital: '',
  department: '',
  departureTime: '',
  departureLocation: '',
  destinationHospital: '',
  coordinator: { id: '', name: '' },
  emergencyDoctor: { id: '', name: '' },
  nurse: { id: '', name: '' },
  driver: { id: '', name: '' },
  icuDoctor: { id: '', name: '' },
  contacts: [
    { role: '协调员电话', phone: '' },
    { role: '急诊医生电话', phone: '' },
    { role: '护士电话', phone: '' },
    { role: '司机电话', phone: '' },
    { role: 'ICU医生电话', phone: '' }
  ],
  remarks: ''
})
// 字典数据
const dict = ref({});
// 选择器状态
const showCasePicker = ref(false)
const showTimePicker = ref(false)
const showCoordinatorPicker = ref(false)
const showDoctorPicker = ref(false)
const showNursePicker = ref(false)
const showDriverPicker = ref(false)
const showIcuDoctorPicker = ref(false)
const departureTimeValue = ref(0)
// 数据
const transportData = ref({});
const loading = ref(false);
const saving = ref(false);
const isEdit = ref(false);
const transportId = ref(null);
const showTimePicker = ref(false);
const departureTimeValue = ref(0);
const statusSelectVisible = ref(false);
// 选项数据
const caseOptions = ref([
  {
    label: '张三 - 脑外伤导致脑死亡 - 青岛镜湖医院',
    value: 'DON20241216001',
    data: {
      donorName: '张三',
      gender: '男',
      age: '38',
      diagnosis: '脑外伤导致脑死亡',
      hospital: '青岛镜湖医院'
    }
  },
  {
    label: '李四 - 脑梗死 - 青岛大学附属医院',
    value: 'DON20241216002',
    data: {
      donorName: '李四',
      gender: '女',
      age: '45',
      diagnosis: '脑梗死',
      hospital: '青岛大学附属医院'
    }
  }
])
// 字典选项
const statusOptions = ref([
  { label: "待转运", value: 1 },
  { label: "转运中", value: 2 },
  { label: "转运完成", value: 3 },
  { label: "转运取消", value: 4 },
  { label: "暂存", value: 5 },
]);
const coordinatorOptions = ref([
  { label: '张医生', value: '1' },
  { label: '李医生', value: '2' },
  { label: '王医生', value: '3' }
])
const doctorOptions = ref([
  { label: '赵医生', value: '1' },
  { label: '钱医生', value: '2' },
  { label: '孙医生', value: '3' }
])
const nurseOptions = ref([
  { label: '周护士', value: '1' },
  { label: '吴护士', value: '2' },
  { label: '郑护士', value: '3' }
])
const driverOptions = ref([
  { label: '刘师傅', value: '1' },
  { label: '陈师傅', value: '2' },
  { label: '杨师傅', value: '3' }
])
const icuDoctorOptions = ref([
  { label: '朱医生', value: '1' },
  { label: '秦医生', value: '2' },
  { label: '尤医生', value: '3' }
])
// 状态管理
const loading = ref(false)
const isEdit = ref(false)
const transportId = ref('')
const disabledColor = ref('#f5f5f7')
// 样式
const disabledColor = ref("#f5f5f7");
// 计算属性
const loadingText = computed(() => {
  return loading.value ? "加载中..." : saving.value ? "保存中..." : "";
});
const isFormValid = computed(() => {
  return form.caseInfo.caseId && form.hospital && form.departureTime
})
  return (
    transportData.value.transportStartPlace &&
    transportData.value.transportStartTime &&
    transportData.value.contactPerson
  );
});
// 样式方法
const inputStyle = (isError) => {
  return isError ?
    'border: 2rpx solid #ff4757 !important; border-radius: 12rpx !important;' :
    'border: 2rpx solid #e5e5e7 !important; border-radius: 12rpx !important;'
}
// 权限判断
const canEdit = computed(() => {
  if (loading.value) return false;
  return (
    transportData.value.transitStatus === 1 || // 待转运
    transportData.value.transitStatus === 5
  ); // 暂存
});
// 方法定义
const onCaseConfirm = (e) => {
  if (e.value && e.value[0]) {
    const selectedCase = e.value[0]
    form.caseInfo.caseId = selectedCase.value
    form.caseInfo.donorName = selectedCase.data.donorName
    form.caseInfo.gender = selectedCase.data.gender
    form.caseInfo.age = selectedCase.data.age
    form.caseInfo.diagnosis = selectedCase.data.diagnosis
    form.hospital = selectedCase.data.hospital
const canStartTransport = computed(() => {
  if (loading.value) return false;
  return transportData.value.transitStatus === 1; // 待转运
});
const canCompleteTransport = computed(() => {
  if (loading.value) return false;
  return transportData.value.transitStatus === 2; // 转运中
});
const canDelete = computed(() => {
  if (loading.value) return false;
  return true; // 根据实际权限控制
});
// 计算索引
const statusIndex = computed(() => {
  if (!transportData.value.transitStatus) return 0;
  return statusOptions.value.findIndex(
    (item) => item.value === transportData.value.transitStatus,
  );
});
onLoad(async (options) => {
  if (options.id) {
    transportId.value = options.id;
    await loadTransportData(options.id);
  } else if (options.caseId) {
    // 新增模式
    isEdit.value = true;
    await initNewTransport(options.caseId, options.caseNo);
  }
  showCasePicker.value = false
}
});
const onTimeConfirm = (e) => {
  const date = new Date(e.value)
  form.departureTime = `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')} ${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`
  showTimePicker.value = false
}
const onCoordinatorConfirm = (e) => {
  if (e.value && e.value[0]) {
    form.coordinator.name = e.value[0].label
    form.coordinator.id = e.value[0].value
    // 自动填充协调员电话
    const contact = form.contacts.find(item => item.role === '协调员电话')
    if (contact) {
      contact.phone = '13800138000' // 模拟数据
    }
  }
  showCoordinatorPicker.value = false
}
const onDoctorConfirm = (e) => {
  if (e.value && e.value[0]) {
    form.emergencyDoctor.name = e.value[0].label
    form.emergencyDoctor.id = e.value[0].value
    // 自动填充急诊医生电话
    const contact = form.contacts.find(item => item.role === '急诊医生电话')
    if (contact) {
      contact.phone = '13800138001' // 模拟数据
    }
  }
  showDoctorPicker.value = false
}
const onNurseConfirm = (e) => {
  if (e.value && e.value[0]) {
    form.nurse.name = e.value[0].label
    form.nurse.id = e.value[0].value
    // 自动填充护士电话
    const contact = form.contacts.find(item => item.role === '护士电话')
    if (contact) {
      contact.phone = '13800138002' // 模拟数据
    }
  }
  showNursePicker.value = false
}
const onDriverConfirm = (e) => {
  if (e.value && e.value[0]) {
    form.driver.name = e.value[0].label
    form.driver.id = e.value[0].value
    // 自动填充司机电话
    const contact = form.contacts.find(item => item.role === '司机电话')
    if (contact) {
      contact.phone = '13800138003' // 模拟数据
    }
  }
  showDriverPicker.value = false
}
const onIcuDoctorConfirm = (e) => {
  if (e.value && e.value[0]) {
    form.icuDoctor.name = e.value[0].label
    form.icuDoctor.id = e.value[0].value
    // 自动填充ICU医生电话
    const contact = form.contacts.find(item => item.role === 'ICU医生电话')
    if (contact) {
      contact.phone = '13800138004' // 模拟数据
    }
  }
  showIcuDoctorPicker.value = false
}
const handleCancel = () => {
  uni.navigateBack()
}
const validateForm = () => {
  if (!form.caseInfo.caseId) {
    uni.showToast({ title: '请选择案例', icon: 'none' })
    return false
  }
  if (!form.hospital) {
    uni.showToast({ title: '请输入捐献医院', icon: 'none' })
    return false
  }
  if (!form.departureTime) {
    uni.showToast({ title: '请选择出发时间', icon: 'none' })
    return false
  }
  return true
}
const handleSaveDraft = async () => {
  if (!validateForm()) return
  loading.value = true
// 加载转运单数据
const loadTransportData = async (id) => {
  loading.value = true;
  try {
    await new Promise(resolve => setTimeout(resolve, 1000))
    await saveTransport('draft')
    uni.showToast({ title: '保存草稿成功', icon: 'success' })
  } catch (error) {
    console.error('保存草稿失败:', error)
    uni.showToast({ title: '保存失败,请重试', icon: 'none' })
  } finally {
    loading.value = false
  }
}
    const res = await uni.$uapi.post(`/project/transport/list`, { id: id });
const handleSubmit = async () => {
  if (!validateForm()) return
    if (res) {
      transportData.value = res[0];
    } else {
      throw new Error(res.msg || "数据加载失败");
    }
  } catch (error) {
    console.error("加载转运单失败:", error);
    uni.showToast({
      title: "数据加载失败,请重试",
      icon: "none",
    });
  } finally {
    loading.value = false;
  }
};
// 初始化新的转运单
const initNewTransport = async (caseId, caseNo) => {
  try {
    // 如果有案例ID,加载案例信息
    if (caseId) {
      const res = await uni.$uapi.post(
        `/project/transport/list`,
        { id: caseId },
      );
      if (res) {
        const caseData = res[0];
        transportData.value = {
          ...transportData.value,
          caseNo: caseNo || caseData.caseNo,
          patName: caseData.patName,
          sex: caseData.sex,
          age: caseData.age,
          diagnosisname: caseData.diagnosisname,
          treatmentHospitalName: caseData.treatmenthospitalname,
          transitStatus: 1, // 待转运
          createTime: new Date()
            .toISOString()
            .replace("T", " ")
            .substring(0, 19),
        };
      }
    } else {
      transportData.value = {
        transitStatus: 1,
        createTime: new Date().toISOString().replace("T", " ").substring(0, 19),
      };
    }
  } catch (error) {
    console.error("初始化转运单失败:", error);
  }
};
// 获取转运状态文本
const getTransportStatusText = (status) => {
  const map = {
    1: "待转运",
    2: "转运中",
    3: "转运完成",
    4: "转运取消",
    5: "暂存",
  };
  return map[status] || "未知";
};
// 获取转运状态样式
const getTransportStatusClass = (status) => {
  const map = {
    1: "pending",
    2: "transporting",
    3: "completed",
    4: "cancelled",
    5: "draft",
  };
  return map[status] || "draft";
};
// 获取性别文本
const getGenderText = (gender) => {
  if (!gender) return "未知";
  return gender === "1" ? "男" : "女";
};
// 格式化时间
const formatTime = (timeStr) => {
  if (!timeStr) return "";
  return timeStr.replace("T", " ").substring(0, 16);
};
// 输入框样式
const inputStyle = (isError) => {
  return isError
    ? "border: 2rpx solid #f56c6c !important; border-radius: 12rpx !important;"
    : "border: 2rpx solid #e5e5e7 !important; border-radius: 12rpx !important;";
};
// 时间确认
const onTimeConfirm = (e) => {
  const date = new Date(e.value);
  transportData.value.transportStartTime = `${date.getFullYear()}-${(
    date.getMonth() + 1
  )
    .toString()
    .padStart(2, "0")}-${date.getDate().toString().padStart(2, "0")} ${date
    .getHours()
    .toString()
    .padStart(2, "0")}:${date.getMinutes().toString().padStart(2, "0")}`;
  showTimePicker.value = false;
};
// 状态确认
const onStatusConfirm = (e) => {
  if (e[0]) {
    transportData.value.transitStatus = e[0].value;
  }
  statusSelectVisible.value = false;
};
// 预览文件
const previewFile = (file) => {
  const fullUrl = file.path || file.fileUrl;
  if (!fullUrl) {
    uni.showToast({ title: "文件路径不存在", icon: "none" });
    return;
  }
  if (file.fileName && file.fileName.match(/\.(jpg|jpeg|png|gif|bmp|webp)$/i)) {
    uni.previewImage({
      urls: [fullUrl],
      current: 0,
    });
  } else if (file.fileName && file.fileName.match(/\.pdf$/i)) {
    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 goBack = () => {
  uni.navigateBack();
};
// 编辑
const handleEdit = () => {
  isEdit.value = true;
};
// 取消编辑
const cancelEdit = () => {
  if (transportId.value) {
    // 重新加载数据
    isEdit.value = false;
    loadTransportData(transportId.value);
  } else {
    // 新增模式,直接返回
    uni.navigateBack();
  }
};
// 保存
const handleSave = async () => {
  if (!validateForm()) return;
  saving.value = true;
  try {
    const submitData = {
      ...transportData.value,
    };
    let res;
    if (transportId.value) {
      // 修改
      res = await uni.$uapi.post("/project/transport/edit", submitData);
    } else {
      // 新增
      submitData.createBy = "移动端用户";
      res = await uni.$uapi.post("/project/transport/add", submitData);
    }
    if (res.code === 200) {
      uni.showToast({
        title: transportId.value ? "修改成功" : "新增成功",
        icon: "success",
      });
      if (transportId.value) {
        // 重新加载数据
        isEdit.value = false;
        await loadTransportData(transportId.value);
      } else {
        // 新增成功后返回列表
        setTimeout(() => {
          uni.navigateBack();
        }, 1500);
      }
    } else {
      throw new Error(res.msg || "操作失败");
    }
  } catch (error) {
    console.error("保存失败:", error);
    uni.showToast({
      title: error.message || (transportId.value ? "修改失败" : "新增失败"),
      icon: "none",
    });
  } finally {
    saving.value = false;
  }
};
// 表单验证
const validateForm = () => {
  if (!transportData.value.transportStartPlace) {
    uni.showToast({ title: "请输入出发地点", icon: "none" });
    return false;
  }
  if (!transportData.value.transportStartTime) {
    uni.showToast({ title: "请选择出发时间", icon: "none" });
    return false;
  }
  if (!transportData.value.contactPerson) {
    uni.showToast({ title: "请输入负责协调员", icon: "none" });
    return false;
  }
  return true;
};
// 开始转运
const handleStartTransport = () => {
  uni.showModal({
    title: '确认提交',
    content: '确定要提交转运单申请吗?',
    title: "开始转运",
    content: "确定要开始转运吗?",
    success: async (res) => {
      if (res.confirm) {
        loading.value = true
        await updateTransportStatus(2, "开始转运");
      }
    },
  });
};
// 完成转运
const handleCompleteTransport = () => {
  uni.showModal({
    title: "完成转运",
    content: "确定要完成转运吗?",
    success: async (res) => {
      if (res.confirm) {
        await updateTransportStatus(3, "完成转运");
      }
    },
  });
};
// 更新转运状态
const updateTransportStatus = async (newStatus, actionName) => {
  try {
    const updateData = {
      id: transportId.value,
      transitStatus: newStatus,
    };
    const res = await uni.$uapi.post("/system/transport/edit", updateData);
    if (res.code === 200) {
      uni.showToast({ title: `${actionName}成功`, icon: "success" });
      await loadTransportData(transportId.value);
    } else {
      throw new Error(res.msg || `${actionName}失败`);
    }
  } catch (error) {
    console.error(`${actionName}失败:`, error);
    uni.showToast({ title: `${actionName}失败`, icon: "none" });
  }
};
// 删除转运单
const handleDelete = () => {
  uni.showModal({
    title: "确认删除",
    content: `确定要删除转运单 ${transportData.value.reportId} 吗?`,
    success: async (res) => {
      if (res.confirm) {
        try {
          await new Promise(resolve => setTimeout(resolve, 1500))
          await saveTransport('pending')
          uni.showToast({ title: '提交成功', icon: 'success' })
          setTimeout(() => {
            uni.navigateBack()
          }, 1500)
          const result = await uni.$uapi.delete(
            `/system/transport/${transportId.value}`,
          );
          if (result.code === 200) {
            uni.showToast({ title: "删除成功", icon: "success" });
            setTimeout(() => {
              uni.navigateBack();
            }, 1500);
          } else {
            uni.showToast({ title: result.msg || "删除失败", icon: "none" });
          }
        } catch (error) {
          console.error('提交失败:', error)
          uni.showToast({ title: '提交失败,请重试', icon: 'none' })
        } finally {
          loading.value = false
          console.error("删除失败:", error);
          uni.showToast({ title: "删除失败", icon: "none" });
        }
      }
    }
  })
}
const saveTransport = async (status) => {
  const submitData = {
    ...form,
    status: status,
    id: isEdit.value ? transportId.value : generateTransportId(),
    createTime: new Date().toISOString()
  }
  console.log('保存转运单:', submitData)
  // 实际项目中调用API接口
}
const generateTransportId = () => {
  const date = new Date()
  return `T${date.getFullYear()}${(date.getMonth() + 1).toString().padStart(2, '0')}${date.getDate().toString().padStart(2, '0')}${Math.random().toString().slice(-3)}`
}
const loadTransportData = (id) => {
  // 模拟加载编辑数据
  const mockData = {
    caseInfo: {
      caseId: 'DON20241216001',
      donorName: '张三',
      gender: '男',
      age: '38',
      diagnosis: '脑外伤导致脑死亡'
    },
    hospital: '青岛镜湖医院',
    department: '神经外科',
    departureTime: '2024-12-17 14:30:00',
    departureLocation: '青岛市立医院急诊科',
    destinationHospital: '青岛镜湖医院',
    coordinator: { id: '1', name: '张医生' },
    emergencyDoctor: { id: '2', name: '王医生' },
    nurse: { id: '3', name: '李护士' },
    driver: { id: '4', name: '刘师傅' },
    icuDoctor: { id: '5', name: '赵医生' },
    contacts: [
      { role: '协调员电话', phone: '13800138000' },
      { role: '急诊医生电话', phone: '13800138001' },
      { role: '护士电话', phone: '13800138002' },
      { role: '司机电话', phone: '13800138003' },
      { role: 'ICU医生电话', phone: '13800138004' }
    ],
    remarks: '需要准备呼吸机等急救设备'
  }
  Object.assign(form, mockData)
}
// 生命周期
onLoad((options) => {
  if (options.id) {
    isEdit.value = true
    transportId.value = options.id
    loadTransportData(options.id)
  }
})
  });
};
</script>
<style lang="scss" scoped>
.transport-edit-container {
  min-height: 100vh;
  background: linear-gradient(135deg, #f8fdff 0%, #e8f7f6 100%);
  padding-bottom: 120rpx; /* 为操作栏留出空间 */
}
.form-scroll {
@@ -642,25 +803,84 @@
  padding: 30rpx;
  margin-bottom: 30rpx;
  box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.06);
  .section-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    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;
    flex: 1;
  }
  .status-tag {
    padding: 6rpx 16rpx;
    border-radius: 8rpx;
    font-size: 24rpx;
    font-weight: 500;
    &.pending {
      background: rgba(240, 173, 78, 0.1);
      color: #f0ad4e;
    }
    &.transporting {
      background: rgba(0, 122, 255, 0.1);
      color: #007aff;
    }
    &.completed {
      background: rgba(76, 217, 100, 0.1);
      color: #4cd964;
    }
    &.cancelled {
      background: rgba(220, 223, 230, 0.1);
      color: #dcdfe6;
    }
    &.draft {
      background: rgba(144, 147, 153, 0.1);
      color: #909399;
    }
  }
}
.section-header {
  display: flex;
//   align-items: center;
  margin-bottom: 30rpx;
  padding-bottom: 20rpx;
  border-bottom: 2rpx solid #f0f0f0;
}
.case-info {
  .info-row {
    display: flex;
    margin-bottom: 16rpx;
.section-icon {
  font-size: 32rpx;
  margin-right: 16rpx;
}
    &:last-child {
      margin-bottom: 0;
    }
.section-title {
  font-size: 32rpx;
  font-weight: 600;
  color: #1d1d1f;
    .info-label {
      font-size: 28rpx;
      color: #606266;
      min-width: 140rpx;
      margin-right: 10rpx;
    }
    .info-value {
      font-size: 28rpx;
      color: #303133;
      flex: 1;
      font-weight: 500;
    }
  }
}
.form-grid {
@@ -672,22 +892,38 @@
.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;
  .item-label {
    font-size: 28rpx;
    color: #1d1d1f;
    font-weight: 500;
    margin-bottom: 12rpx;
    &.required::after {
      content: "*";
      color: #f56c6c;
      margin-left: 4rpx;
    }
  }
  .picker-trigger {
    display: flex;
    justify-content: space-between;
    align-items: center;
    height: 88rpx;
    padding: 0 20rpx;
    background: #f5f5f5;
    border-radius: 8rpx;
    border: 1rpx solid #dcdfe6;
    text {
      font-size: 28rpx;
      color: #303133;
    }
  }
}
@@ -704,39 +940,132 @@
  border-radius: 12rpx !important;
  padding: 20rpx 24rpx !important;
  background: #fff !important;
  min-height: 150rpx;
}
// 附件列表
.attachment-list {
  .attachment-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 20rpx 0;
    border-bottom: 1rpx solid #f0f0f0;
    &:last-child {
      border-bottom: none;
    }
    &:active {
      background: #f5f5f5;
    }
    .file-info {
      display: flex;
      align-items: center;
      flex: 1;
      .file-icon {
        margin-right: 16rpx;
      }
      .file-details {
        display: flex;
        flex-direction: column;
        flex: 1;
        .file-name {
          font-size: 28rpx;
          color: #303133;
          margin-bottom: 4rpx;
          overflow: hidden;
          text-overflow: ellipsis;
          white-space: nowrap;
          max-width: 500rpx;
        }
        .file-time {
          font-size: 24rpx;
          color: #909399;
        }
      }
    }
  }
}
.action-buttons {
  display: flex;
  gap: 20rpx;
  margin-top: 40rpx;
  background: #fff;
  padding: 20rpx 0;
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  padding: 20rpx 30rpx;
  padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
  box-shadow: 0 -2rpx 20rpx rgba(0, 0, 0, 0.08);
  z-index: 100;
}
.btn {
  flex: 1;
  height: 80rpx;
  border-radius: 16rpx;
  font-size: 32rpx;
  font-weight: 500;
  border-radius: 20rpx;
  font-size: 28rpx;
  font-weight: 600;
  border: none;
  transition: all 0.3s ease;
  &.secondary {
    background: #f5f5f7 !important;
    color: #1d1d1f !important;
    background: #f5f5f7;
    color: #1d1d1f;
    &:active {
      background: #e5e5e7;
    }
  }
  &.primary {
    background: #2979ff !important;
    color: #fff !important;
    background: linear-gradient(90deg, #0071e3 0%, #2997ff 100%);
    color: #fff;
    &:active {
      transform: scale(0.98);
    }
  }
  &.warning {
    background: linear-gradient(90deg, #f0ad4e 0%, #f8b62d 100%);
    color: #fff;
    &:active {
      transform: scale(0.98);
    }
  }
  &.success {
    background: linear-gradient(135deg, #0f95b0, #89C4C1) !important;
    color: #fff !important;
    background: linear-gradient(90deg, #34c759 0%, #4cd964 100%);
    color: #fff;
    &:disabled {
      background: #c0c0c0 !important;
      background: #c0c4cc;
      opacity: 0.6;
    }
    &:active:not(:disabled) {
      transform: scale(0.98);
    }
  }
  &.error {
    background: linear-gradient(90deg, #ff3b30 0%, #ff5a5a 100%);
    color: #fff;
    &:active {
      transform: scale(0.98);
    }
  }
}
</style>
</style>