WXL
3 天以前 4ddfa807643c73ff90840b0b65a5118741e12b48
移动端维护
已修改8个文件
562 ■■■■ 文件已修改
components/attachment/index.vue 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/case/CaseDetails.vue 413 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/case/index.vue 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/case/transfer.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/case/transferinfo.vue 128 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/login/Login.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/my/index.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/my/profile.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
components/attachment/index.vue
@@ -120,14 +120,14 @@
          <!-- 空状态 -->
          <view class="empty" v-if="currentFileList.length === 0">
            <uni-icons type="info" size="24" color="#999" />
            <text v-if="currentTab === 'base' || !showGradeSlip">暂无基础附件</text>
            <text v-if="currentTab === 'base' || !showGradeSlip">暂无附件</text>
            <text v-else-if="currentTab === 'grade'">暂无成绩单附件</text>
          </view>
        </scroll-view>
        <!-- 操作按钮 -->
        <view class="popup-footer" v-if="!readonly">
          <button class="btn" @click="chooseFile">添加{{ currentTab === 'grade' ? '成绩单' : '基础' }}附件</button>
          <button class="btn" @click="chooseFile">添加</button>
          <button class="btn primary" @click="confirmUpload">确认上传</button>
        </view>
      </view>
@@ -520,7 +520,7 @@
        });
        emit("upload-base", file);
      } catch (error) {
        console.error('基础附件上传失败:', error);
        console.error('上传失败:', error);
        file.status = 'error';
        uni.showToast({
          title: `文件 ${file.name} 上传失败`,
pages/case/CaseDetails.vue
@@ -17,7 +17,7 @@
          <view class="form-grid">
            <!-- 修改后:治疗医院输入框 -->
            <view class="form-item">
            <!-- <view class="form-item">
              <text class="item-label required">治疗医院</text>
              <u-input
                v-model="form.treatmenthospitalname"
@@ -25,7 +25,7 @@
                maxlength="100"
                class="custom-input"
              />
            </view>
            </view> -->
            <!-- 新增:上报医院 -->
            <view class="form-item">
@@ -40,10 +40,10 @@
            <!-- 新增:部门名称 -->
            <view class="form-item">
              <text class="item-label">部门名称</text>
              <text class="item-label">科室名称</text>
              <u-input
                v-model="form.deptName"
                placeholder="请输入部门名称"
                placeholder="请输入上报科室"
                maxlength="50"
                class="custom-input"
              />
@@ -120,7 +120,7 @@
                placeholder="请输入证件号码"
                maxlength="18"
                class="custom-input"
                @blur="validateIdCard"
                @blur="onIdCardChange"
              />
              <text class="error-text" v-if="idCardError">{{
                idCardError
@@ -241,24 +241,30 @@
                </view>
              </view>
            </view>
            <view class="form-item">
            <view class="form-item full-width">
              <text class="item-label">传染病</text>
              <view class="radio-group horizontal">
              <view class="checkbox-group single-line">
                <view
                  v-for="bloodType in infectiousDiseaselist"
                  :key="bloodType.value"
                  class="radio-item"
                  @click="form.infectious = bloodType.value"
                  v-for="disease in infectiousDiseaselist"
                  :key="disease.value"
                  class="checkbox-item"
                  @click="toggleInfectious(disease.value)"
                >
                  <view
                    class="radio-dot"
                    :class="{ active: form.infectious == bloodType.value }"
                  ></view>
                  <text class="radio-label">{{ bloodType.label }}</text>
                    class="checkbox-box"
                    :class="{ active: isInfectiousSelected(disease.value) }"
                  >
                    <text
                      v-if="isInfectiousSelected(disease.value)"
                      class="checkbox-check"
                      >✓</text
                    >
                  </view>
                  <text class="checkbox-label">{{ disease.label }}</text>
                </view>
              </view>
            </view>
            <view class="form-item">
            <view class="form-item full-width"">
              <text class="item-label">其他</text>
              <u-input
                v-model="form.infectiousOther"
@@ -296,9 +302,9 @@
          <view class="form-grid">
            <view class="form-item">
              <text class="item-label">信息员</text>
              <text class="item-label">上报信息员</text>
              <u-input
                v-model="form.infoname"
                v-model="form.infoName"
                placeholder="请输入信息员"
                border="none"
              />
@@ -307,7 +313,7 @@
            <view class="form-item">
              <text class="item-label">联系电话</text>
              <u-input
                v-model="form.infophone"
                v-model="form.phone"
                placeholder="请输入联系电话"
                type="number"
                border="none"
@@ -432,7 +438,7 @@
</template>
<script setup>
import { ref, computed, onMounted } from "vue";
import { ref, computed, onMounted, watch } from "vue";
import { onLoad } from "@dcloudio/uni-app";
import attachmentUpload from "@/components/attachment";
import { useUserStore } from "@/stores/user";
@@ -442,10 +448,15 @@
const userStore = useUserStore();
const isEditMode = ref(false);
const currentId = ref(null);
const selectedInfectious = ref([]); // 存储选中的传染病值数组
// 表单数据
const form = ref({
  caseNo: "",
  treatmenthospitalname: "",
  treatmenthospitalname: userStore.userInfo.user.orgName,
  toHospital: userStore.userInfo.user.orgName,
  coordinatorName: userStore.userInfo.user.coordinatorName,
  coordinatorNo: userStore.userInfo.user.coordinatorNo,
  treatmentdeptname: "",
  name: "",
  nation: "",
@@ -460,8 +471,8 @@
  diagnosisname: "",
  bloodType: "",
  rhYin: "",
  infoname: "",
  infophone: "",
  infoName: userStore.userInfo.user.nickName,
  phone: userStore.userInfo.user.phonenumber,
  reportername: userStore.name || "",
  reporterno: userStore.userId || "",
  reporterphone: "", // 报告者联系电话
@@ -475,7 +486,6 @@
  nativeplace: "", // 新增:籍贯
  occupation: "", // 新增:职业
  patientstate: "", // 新增:病人状况
  phone: "", // 新增:联系电话
  registeraddress: "", // 新增:户籍地址
  registerprovince: "", // 新增:户籍地址省编号
  registerprovincename: "", // 新增:户籍地址省名称
@@ -626,7 +636,7 @@
const currentNation = computed(() => {
  return nationIndex.value >= 0
    ? nationLabels.value[nationIndex.value]
    : "请选择民族";
    : (form.value.nation?form.value.nation:"请选择证件类型");
});
const currentIdCardType = computed(() => {
@@ -668,24 +678,153 @@
// 身份证验证
const idCardError = ref("");
const validateIdCard = () => {
  if (!form.value.idcardno) {
  const idCard = form.value.idcardno;
  console.log(idCard, "当前输入");
  if (!idCard) {
    idCardError.value = "请输入证件号码";
    return false;
  }
  if (form.value.idcardno.length !== 18) {
    idCardError.value = "请输入18位身份证号码";
  if (idCard.length !== 18) {
    idCardError.value = "身份证号码必须是18位";
    return false;
  }
  console.log(1);
  // 验证前17位必须是数字
  const reg = /^\d{17}(\d|X|x)$/;
  if (!reg.test(idCard)) {
    idCardError.value = "身份证号码格式不正确";
    return false;
  }
  console.log(2);
  // 验证出生日期
  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 inputStyle = (isError) => {
  return isError
    ? "border: 2rpx solid #ff4757; border-radius: 12rpx;"
    : "border: 2rpx solid #e5e5e7; border-radius: 12rpx;";
// 身份证号变化处理
const onIdCardChange = (value) => {
  // 验证身份证格式
  if (validateIdCard()) {
    // 尝试提取出生日期
    extractBirthdayFromIdCard();
  }
};
// 身份证校验码验证函数
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) => {
@@ -730,7 +869,35 @@
  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();
@@ -769,6 +936,17 @@
  // 检查日期有效性
  if (isNaN(birthDate.getTime())) {
    form.value.age = "";
    form.value.ageunit = "";
    return;
  }
  // 检查是否为未来日期
  if (birthDate > today) {
    uni.showToast({
      title: "出生日期不能是未来日期",
      icon: "none",
    });
    form.value.age = "";
    form.value.ageunit = "";
    return;
@@ -944,6 +1122,10 @@
        deptIndex.value = -1;
        nationIndex.value = -1;
        idCardTypeIndex.value = -1;
        // 重置传染病选择
        selectedInfectious.value = [];
        // 重置附件
        attachments.value = [];
        form.value.nationality = "中国";
        form.value.isTransport = "1";
@@ -980,7 +1162,6 @@
        fileName: file.name,
        type: file.type,
      })),
      phone: form.value.infophone,
      isTransport: form.value.isTransport || "1",
      terminationCase: form.value.terminationCase || 0,
      reportStatus: form.value.reportStatus || "1",
@@ -1045,11 +1226,15 @@
    if (res.code) {
      form.value = res.data;
      if (res.data.infectious) {
        selectedInfectious.value = res.data.infectious
          .split(",")
          .filter((item) => item.trim() !== "");
      }
      currentNation.value=form.value.nation;
      idCardTypeIndex.value=form.value.idcardtype;
      // 处理选择器索引
      // updatePickerIndexes();
      console.log(2, "res");
      // 处理附件
      if (res.data.annexfilesList) {
        attachments.value = res.data.annexfilesList;
@@ -1077,7 +1262,6 @@
    loading.value = false;
  }
};
</script>
<style lang="scss" scoped>
.case-report-container {
@@ -1446,7 +1630,30 @@
  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;
@@ -1469,4 +1676,134 @@
    }
  }
}
.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;
    display: flex;
    align-items: center;
    gap: 8rpx;
    padding: 8rpx 16rpx;
    border-radius: 20rpx;
  }
  .radio-item .radio-dot.active {
    border-color: #0f95b0;
    &::after {
      background: #0f95b0;
    }
  }
}
/* 如果需要固定高度,可以这样设置 */
.checkbox-group.single-line {
  min-height: 60rpx;
  align-items: center;
}
/* 在移动端优化触摸区域 */
.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;
  }
}
</style>
pages/case/index.vue
@@ -222,13 +222,13 @@
            <text class="case-status">{{ caseItem.statusText }}</text>
          </view>
          <view class="actions">
            <button
            <!-- <button
              class="action-btn"
              v-if="caseItem.reportStatus == '1' || caseItem.reportStatus == '2'"
              @tap.stop="withdrawCase(caseItem)"
            >
              撤回
            </button>
            </button> -->
            <button class="action-btn" @tap.stop="viewDetails(caseItem)">
              查看详情
            </button>
@@ -327,6 +327,7 @@
  return {
    id: apiData.id || apiData.donatebaseinfoReportId,
    donorNo: apiData.caseNo,
    reportStatus: apiData.reportStatus,
    hospitalName: apiData.treatmenthospitalname,
    hospitalLogo: "/static/hospital/default.jpg",
    caseType: "器官捐献案例",
@@ -644,6 +645,7 @@
// 计算属性:筛选记录 - 现在只做前端状态筛选
const filteredCases = computed(() => {
  let result = cases.value;
  console.log(result,'result');
  
  // 只做前端状态筛选,时间筛选已经通过接口实现
  // if (currentType.value !== "all") {
pages/case/transfer.vue
@@ -316,12 +316,12 @@
    4: "已取消",
    5: "暂存",
  };
  return map[status] || "未知";
  return map[status] || "待转运";
};
// 获取性别文本
const getGenderText = (gender) => {
  if (!gender) return "未知";
  if (!gender) return "待转运";
  if (!dict.value.sys_user_sex) return gender;
  const genderItem = dict.value.sys_user_sex.find(
    (item) => item.dictValue === gender,
pages/case/transferinfo.vue
@@ -95,17 +95,11 @@
            <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"
              <view
                class="picker-trigger"
                @click="isEdit && handleStatusClick()"
                :class="{ disabled: !isEdit }"
              >
                <template #default>
                  <view class="picker-trigger">
                    <text>{{
                      getTransportStatusText(transportData.transitStatus)
                    }}</text>
@@ -116,8 +110,6 @@
                      color="#999"
                    ></u-icon>
                  </view>
                </template>
              </u-select>
            </view>
            <view class="form-item">
@@ -331,14 +323,23 @@
      @cancel="showTimePicker = false"
      title="选择出发时间"
    ></u-datetime-picker>
    <!-- 状态选择器 -->
    <u-picker
      :show="statusPickerVisible"
      :columns="[statusLabels]"
      :defaultIndex="[statusCurrentIndex]"
      keyName="label"
      @confirm="onStatusPickerConfirm"
      @cancel="statusPickerVisible = false"
      title="请选择转运状态"
    ></u-picker>
    <!-- 加载状态 -->
    <u-loading-icon :show="loading" :text="loadingText"></u-loading-icon>
  </view>
</template>
<script setup>
import { ref, computed, onMounted } from "vue";
import { ref, computed, onMounted,watch } from "vue";
import attachmentUpload from "@/components/attachment";
import { useUserStore } from "@/stores/user";
@@ -354,13 +355,14 @@
const loading = ref(false);
const saving = ref(false);
const isEdit = ref(false);
const statusPickerVisible = ref(false);
const statusCurrentIndex = ref(0);
const transportId = ref(null);
const showTimePicker = ref(false);
const departureTimeValue = ref(0);
const statusSelectVisible = ref(false);
const isReadonly = ref(false);
const attachments = ref([]);
// 字典选项
const statusOptions = ref([
@@ -411,14 +413,35 @@
  return true; // 根据实际权限控制
});
// 计算索引
const statusIndex = computed(() => {
  if (!transportData.value.transitStatus) return 0;
  return statusOptions.value.findIndex(
    (item) => item.value === transportData.value.transitStatus,
  );
// 修改或添加计算属性
const statusLabels = computed(() => {
  return statusOptions.value.map((item) => item.label);
});
// 修改 statusIndex 计算属性
const statusIndex = computed(() => {
  if (!transportData.value.transitStatus) return 0;
  const index = statusOptions.value.findIndex(
    (item) => item.value == transportData.value.transitStatus,
  );
  return index >= 0 ? index : 0;
});
// 添加监听,当转运状态变化时更新当前索引
watch(
  () => transportData.value.transitStatus,
  (newVal) => {
    if (newVal !== undefined && newVal !== null) {
      const index = statusOptions.value.findIndex(
        (item) => item.value == newVal,
      );
      if (index >= 0) {
        statusCurrentIndex.value = index;
      }
    }
  },
  { immediate: true },
);
onLoad(async (options) => {
  if (options.id) {
    transportId.value = options.id;
@@ -427,6 +450,14 @@
    // 新增模式
    isEdit.value = true;
    await initNewTransport(options.caseId, options.caseNo);
  }
  // 确保状态索引正确初始化
  if (transportData.value.transitStatus !== undefined) {
    const index = statusOptions.value.findIndex(
      (item) => item.value == transportData.value.transitStatus,
    );
    statusCurrentIndex.value = index >= 0 ? index : 0;
  }
});
@@ -441,10 +472,17 @@
      
        if (res.data.annexfilesList) {
           attachments.value = res.data.annexfilesList;
        attachments.value.forEach(item=>{
          item.url=item.opath,
          item.name=item.fileName
        })
        attachments.value.forEach((item) => {
          (item.url = item.opath), (item.name = item.fileName);
        });
      }
      // 更新状态索引
      if (transportData.value.transitStatus !== undefined) {
        const index = statusOptions.value.findIndex(
          (item) => item.value == transportData.value.transitStatus,
        );
        statusCurrentIndex.value = index >= 0 ? index : 0;
        }
    } else {
      throw new Error(res.msg || "数据加载失败");
@@ -561,12 +599,18 @@
  showTimePicker.value = false;
};
// 状态确认
const onStatusConfirm = (e) => {
  if (e[0]) {
    transportData.value.transitStatus = e[0].value;
// 删除原来的 onStatusConfirm 函数,添加新的函数
const handleStatusClick = () => {
  if (!isEdit.value) return;
  statusPickerVisible.value = true;
};
const onStatusPickerConfirm = (e) => {
  const index = e.indexs[0];
  if (statusOptions.value[index]) {
    transportData.value.transitStatus = statusOptions.value[index].value;
  }
  statusSelectVisible.value = false;
  statusPickerVisible.value = false;
};
// 预览文件
@@ -761,12 +805,11 @@
const handleBaseUpload = (file) => {
  console.log("基础附件上传成功:", file);
  attachments.value.push(file);
};
// 处理其他附件上传
const handleFilesUpdate = (files) => {
  console.log(files,'files');
  console.log(files, "files");
  
  attachments.value = files.map((file) => ({
    ...file,
@@ -776,7 +819,6 @@
    //   : file.url,
  }));
  console.log(attachments.value);
};
// 预览文件 - 修改为使用完整URL
@@ -831,7 +873,27 @@
.form-content {
  padding: 30rpx;
}
.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;
  font-size: 28rpx;
  color: #303133;
  &.disabled {
    background: #f8f9fa;
    color: #909399;
  }
  text {
    font-size: 28rpx;
  }
}
.form-section {
  background: #fff;
  border-radius: 20rpx;
pages/login/Login.vue
@@ -121,6 +121,7 @@
    // 6. 存储用户信息
    userStore.setUserInfo(userInfo);
    console.log(userInfo,'userInfo');
    // 7. 跳转到目标页面
    const redirects = redirect.value || "/pages/index/index";
pages/my/index.vue
@@ -188,7 +188,7 @@
        uni.clearStorageSync();
        // 跳转到登录页
        uni.reLaunch({
          url: "/pages/login/index",
          url: "/pages/login/Login",
        });
      }
    },
pages/my/profile.vue
@@ -229,7 +229,7 @@
      if (res.confirm) {
        // 这里处理退出登录逻辑
        uni.reLaunch({
          url: '/pages/login/index'
          url: '/pages/login/Login'
        })
      }
    }