3bd962a6d7f61239c020e2dbbeb7341e5b842dd1..2cc85c64f1c64a2dbaeae276a3e2ca8420de76b7
2026-04-22 WXL
上报转运调试
2cc85c 对比 | 目录
2026-04-22 WXL
青岛推送
9bce51 对比 | 目录
已删除86个文件
已修改13个文件
226289 ■■■■■ 文件已修改
components/attachment/index.vue 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/.bin/esbuild 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/.bin/esbuild.cmd 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/.bin/esbuild.ps1 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/.bin/rollup 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/.bin/rollup.cmd 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/.bin/rollup.ps1 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/.bin/vite 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/.bin/vite.cmd 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/.bin/vite.ps1 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/.package-lock.json 116 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/@vitejs/plugin-vue/CHANGELOG.md 362 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/@vitejs/plugin-vue/LICENSE 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/@vitejs/plugin-vue/README.md 126 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/@vitejs/plugin-vue/dist/index.d.ts 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/@vitejs/plugin-vue/dist/index.js 4842 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/@vitejs/plugin-vue/package.json 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/esbuild-windows-64/README.md 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/esbuild-windows-64/bin/esbuild 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/esbuild-windows-64/esbuild.exe 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/esbuild-windows-64/package.json 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/esbuild/LICENSE.md 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/esbuild/README.md 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/esbuild/bin/esbuild 178 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/esbuild/install.js 244 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/esbuild/lib/main.d.ts 602 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/esbuild/lib/main.js 2332 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/esbuild/package.json 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/rollup/CHANGELOG.md 6710 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/rollup/LICENSE.md 703 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/rollup/README.md 125 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/rollup/dist/bin/rollup 1721 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/rollup/dist/es/package.json 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/rollup/dist/es/rollup.browser.js 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/rollup/dist/es/rollup.js 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/rollup/dist/es/shared/rollup.js 23874 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/rollup/dist/es/shared/watch.js 5003 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/rollup/dist/loadConfigFile.js 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/rollup/dist/rollup.browser.js 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/rollup/dist/rollup.browser.js.map 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/rollup/dist/rollup.d.ts 954 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/rollup/dist/rollup.js 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/rollup/dist/shared/index.js 4568 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/rollup/dist/shared/loadConfigFile.js 670 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/rollup/dist/shared/mergeOptions.js 180 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/rollup/dist/shared/rollup.js 23912 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/rollup/dist/shared/watch-cli.js 511 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/rollup/dist/shared/watch.js 307 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/rollup/package.json 143 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/vite/LICENSE.md 3819 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/vite/README.md 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/vite/bin/openChrome.applescript 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/vite/bin/vite.js 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/vite/client.d.ts 208 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/vite/dist/client/client.mjs 583 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/vite/dist/client/client.mjs.map 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/vite/dist/client/env.mjs 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/vite/dist/client/env.mjs.map 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/vite/dist/node/chunks/dep-0a035c79.js 62110 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/vite/dist/node/chunks/dep-11455e2b.js 7507 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/vite/dist/node/chunks/dep-1e6e3914.js 8757 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/vite/dist/node/chunks/dep-2056ae8a.js 547 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/vite/dist/node/chunks/dep-a9015192.js 823 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/vite/dist/node/chunks/dep-b120d181.js 19600 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/vite/dist/node/cli.js 806 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/vite/dist/node/index.d.ts 2921 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/vite/dist/node/index.js 157 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/vite/dist/node/terser.js 32876 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/vite/package.json 138 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/vite/src/client/client.ts 510 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/vite/src/client/env.ts 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/vite/src/client/overlay.ts 189 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/vite/src/client/tsconfig.json 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/vite/types/alias.d.ts 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/vite/types/anymatch.d.ts 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/vite/types/chokidar.d.ts 227 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/vite/types/commonjs.d.ts 182 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/vite/types/connect.d.ts 111 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/vite/types/customEvent.d.ts 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/vite/types/dynamicImportVars.d.ts 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/vite/types/hmrPayload.d.ts 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/vite/types/hot.d.ts 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/vite/types/http-proxy.d.ts 242 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/vite/types/importMeta.d.ts 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/vite/types/package.json 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/vite/types/shims.d.ts 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/vite/types/terser.d.ts 209 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
node_modules/vite/types/ws.d.ts 553 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package-lock.json 664 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package.json 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages.json 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/case/CaseDetails.vue 95 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/case/CaseInfo.vue 731 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/case/index.vue 298 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/case/transfer.vue 544 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/case/transferinfo.vue 1454 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
unpackage/dist/cache/.vite/deps/_metadata.json 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
utils/dict.js 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
utils/request.js 156 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
components/attachment/index.vue
@@ -451,6 +451,8 @@
      success: (res) => {
        if (res.statusCode === 200) {
          const data = JSON.parse(res.data);
          console.log(data,'文件');
          if (data.code === 200) {
            resolve({
              ...data,
@@ -509,11 +511,12 @@
        file.status = 'uploading';
        const res = await uploadFile(file.file, 'base');
        Object.assign(file, {
          url: res.fileName,
          fileName: res.fileName,
          url: res.url,
          fileName: res.name,
          newFileName: res.newFileName,
          originalFilename: res.originalFilename,
          status: 'success'
          status: 'success',
          size:res.size
        });
        emit("upload-base", file);
      } catch (error) {
node_modules/.bin/esbuild
ÎļþÒÑɾ³ý
node_modules/.bin/esbuild.cmd
ÎļþÒÑɾ³ý
node_modules/.bin/esbuild.ps1
ÎļþÒÑɾ³ý
node_modules/.bin/rollup
ÎļþÒÑɾ³ý
node_modules/.bin/rollup.cmd
ÎļþÒÑɾ³ý
node_modules/.bin/rollup.ps1
ÎļþÒÑɾ³ý
node_modules/.bin/vite
ÎļþÒÑɾ³ý
node_modules/.bin/vite.cmd
ÎļþÒÑɾ³ý
node_modules/.bin/vite.ps1
ÎļþÒÑɾ³ý
node_modules/.package-lock.json
@@ -185,18 +185,6 @@
        "undici-types": "~7.19.0"
      }
    },
    "node_modules/@vitejs/plugin-vue": {
      "version": "1.10.2",
      "resolved": "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-1.10.2.tgz",
      "integrity": "sha512-/QJ0Z9qfhAFtKRY+r57ziY4BSbGUTGsPRMpB/Ron3QPwBZM4OZAZHdTa4a8PafCwU5DTatXG8TMDoP8z+oDqJw==",
      "dev": true,
      "engines": {
        "node": ">=12.0.0"
      },
      "peerDependencies": {
        "vite": "^2.5.10"
      }
    },
    "node_modules/@vue/compiler-core": {
      "version": "3.5.32",
      "resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.5.32.tgz",
@@ -900,58 +888,6 @@
      "resolved": "https://registry.npmmirror.com/es-module-lexer/-/es-module-lexer-2.0.0.tgz",
      "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==",
      "dev": true
    },
    "node_modules/esbuild": {
      "version": "0.14.54",
      "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.14.54.tgz",
      "integrity": "sha512-Cy9llcy8DvET5uznocPyqL3BFRrFXSVqbgpMJ9Wz8oVjZlh/zUSNbPRbov0VX7VxN2JH1Oa0uNxZ7eLRb62pJA==",
      "dev": true,
      "hasInstallScript": true,
      "bin": {
        "esbuild": "bin/esbuild"
      },
      "engines": {
        "node": ">=12"
      },
      "optionalDependencies": {
        "@esbuild/linux-loong64": "0.14.54",
        "esbuild-android-64": "0.14.54",
        "esbuild-android-arm64": "0.14.54",
        "esbuild-darwin-64": "0.14.54",
        "esbuild-darwin-arm64": "0.14.54",
        "esbuild-freebsd-64": "0.14.54",
        "esbuild-freebsd-arm64": "0.14.54",
        "esbuild-linux-32": "0.14.54",
        "esbuild-linux-64": "0.14.54",
        "esbuild-linux-arm": "0.14.54",
        "esbuild-linux-arm64": "0.14.54",
        "esbuild-linux-mips64le": "0.14.54",
        "esbuild-linux-ppc64le": "0.14.54",
        "esbuild-linux-riscv64": "0.14.54",
        "esbuild-linux-s390x": "0.14.54",
        "esbuild-netbsd-64": "0.14.54",
        "esbuild-openbsd-64": "0.14.54",
        "esbuild-sunos-64": "0.14.54",
        "esbuild-windows-32": "0.14.54",
        "esbuild-windows-64": "0.14.54",
        "esbuild-windows-arm64": "0.14.54"
      }
    },
    "node_modules/esbuild-windows-64": {
      "version": "0.14.54",
      "resolved": "https://registry.npmmirror.com/esbuild-windows-64/-/esbuild-windows-64-0.14.54.tgz",
      "integrity": "sha512-AoHTRBUuYwXtZhjXZbA1pGfTo8cJo3vZIcWGLiUcTNgHpJJMC1rVA44ZereBHMJtotyN71S8Qw0npiCIkW96cQ==",
      "cpu": [
        "x64"
      ],
      "dev": true,
      "optional": true,
      "os": [
        "win32"
      ],
      "engines": {
        "node": ">=12"
      }
    },
    "node_modules/escalade": {
      "version": "3.2.0",
@@ -1680,21 +1616,6 @@
        "url": "https://github.com/sponsors/isaacs"
      }
    },
    "node_modules/rollup": {
      "version": "2.77.3",
      "resolved": "https://registry.npmmirror.com/rollup/-/rollup-2.77.3.tgz",
      "integrity": "sha512-/qxNTG7FbmefJWoeeYJFbHehJ2HNWnjkAFRKzWN/45eNBBF/r8lo992CwcJXEzyVxs5FmfId+vTSTQDb+bxA+g==",
      "dev": true,
      "bin": {
        "rollup": "dist/bin/rollup"
      },
      "engines": {
        "node": ">=10.0.0"
      },
      "optionalDependencies": {
        "fsevents": "~2.3.2"
      }
    },
    "node_modules/schema-utils": {
      "version": "4.3.3",
      "resolved": "https://registry.npmmirror.com/schema-utils/-/schema-utils-4.3.3.tgz",
@@ -1963,43 +1884,6 @@
        "HBuilderX": "^3.1.0",
        "uni-app": "^4.66",
        "uni-app-x": ""
      }
    },
    "node_modules/vite": {
      "version": "2.9.18",
      "resolved": "https://registry.npmmirror.com/vite/-/vite-2.9.18.tgz",
      "integrity": "sha512-sAOqI5wNM9QvSEE70W3UGMdT8cyEn0+PmJMTFvTB8wB0YbYUWw3gUbY62AOyrXosGieF2htmeLATvNxpv/zNyQ==",
      "dev": true,
      "dependencies": {
        "esbuild": "^0.14.27",
        "postcss": "^8.4.13",
        "resolve": "^1.22.0",
        "rollup": ">=2.59.0 <2.78.0"
      },
      "bin": {
        "vite": "bin/vite.js"
      },
      "engines": {
        "node": ">=12.2.0"
      },
      "optionalDependencies": {
        "fsevents": "~2.3.2"
      },
      "peerDependencies": {
        "less": "*",
        "sass": "*",
        "stylus": "*"
      },
      "peerDependenciesMeta": {
        "less": {
          "optional": true
        },
        "sass": {
          "optional": true
        },
        "stylus": {
          "optional": true
        }
      }
    },
    "node_modules/vue": {
node_modules/@vitejs/plugin-vue/CHANGELOG.md
ÎļþÒÑɾ³ý
node_modules/@vitejs/plugin-vue/LICENSE
ÎļþÒÑɾ³ý
node_modules/@vitejs/plugin-vue/README.md
ÎļþÒÑɾ³ý
node_modules/@vitejs/plugin-vue/dist/index.d.ts
ÎļþÒÑɾ³ý
node_modules/@vitejs/plugin-vue/dist/index.js
ÎļþÒÑɾ³ý
node_modules/@vitejs/plugin-vue/package.json
ÎļþÒÑɾ³ý
node_modules/esbuild-windows-64/README.md
ÎļþÒÑɾ³ý
node_modules/esbuild-windows-64/bin/esbuild
ÎļþÒÑɾ³ý
node_modules/esbuild-windows-64/esbuild.exe
Binary files differ
node_modules/esbuild-windows-64/package.json
ÎļþÒÑɾ³ý
node_modules/esbuild/LICENSE.md
ÎļþÒÑɾ³ý
node_modules/esbuild/README.md
ÎļþÒÑɾ³ý
node_modules/esbuild/bin/esbuild
ÎļþÒÑɾ³ý
node_modules/esbuild/install.js
ÎļþÒÑɾ³ý
node_modules/esbuild/lib/main.d.ts
ÎļþÒÑɾ³ý
node_modules/esbuild/lib/main.js
ÎļþÒÑɾ³ý
node_modules/esbuild/package.json
ÎļþÒÑɾ³ý
node_modules/rollup/CHANGELOG.md
ÎļþÒÑɾ³ý
node_modules/rollup/LICENSE.md
ÎļþÒÑɾ³ý
node_modules/rollup/README.md
ÎļþÒÑɾ³ý
node_modules/rollup/dist/bin/rollup
ÎļþÒÑɾ³ý
node_modules/rollup/dist/es/package.json
ÎļþÒÑɾ³ý
node_modules/rollup/dist/es/rollup.browser.js
ÎļþÒÑɾ³ý
node_modules/rollup/dist/es/rollup.js
ÎļþÒÑɾ³ý
node_modules/rollup/dist/es/shared/rollup.js
ÎļþÒÑɾ³ý
node_modules/rollup/dist/es/shared/watch.js
ÎļþÒÑɾ³ý
node_modules/rollup/dist/loadConfigFile.js
ÎļþÒÑɾ³ý
node_modules/rollup/dist/rollup.browser.js
ÎļþÒÑɾ³ý
node_modules/rollup/dist/rollup.browser.js.map
ÎļþÒÑɾ³ý
node_modules/rollup/dist/rollup.d.ts
ÎļþÒÑɾ³ý
node_modules/rollup/dist/rollup.js
ÎļþÒÑɾ³ý
node_modules/rollup/dist/shared/index.js
ÎļþÒÑɾ³ý
node_modules/rollup/dist/shared/loadConfigFile.js
ÎļþÒÑɾ³ý
node_modules/rollup/dist/shared/mergeOptions.js
ÎļþÒÑɾ³ý
node_modules/rollup/dist/shared/rollup.js
ÎļþÒÑɾ³ý
node_modules/rollup/dist/shared/watch-cli.js
ÎļþÒÑɾ³ý
node_modules/rollup/dist/shared/watch.js
ÎļþÒÑɾ³ý
node_modules/rollup/package.json
ÎļþÒÑɾ³ý
node_modules/vite/LICENSE.md
ÎļþÒÑɾ³ý
node_modules/vite/README.md
ÎļþÒÑɾ³ý
node_modules/vite/bin/openChrome.applescript
ÎļþÒÑɾ³ý
node_modules/vite/bin/vite.js
ÎļþÒÑɾ³ý
node_modules/vite/client.d.ts
ÎļþÒÑɾ³ý
node_modules/vite/dist/client/client.mjs
ÎļþÒÑɾ³ý
node_modules/vite/dist/client/client.mjs.map
ÎļþÒÑɾ³ý
node_modules/vite/dist/client/env.mjs
ÎļþÒÑɾ³ý
node_modules/vite/dist/client/env.mjs.map
ÎļþÒÑɾ³ý
node_modules/vite/dist/node/chunks/dep-0a035c79.js
ÎļþÒÑɾ³ý
node_modules/vite/dist/node/chunks/dep-11455e2b.js
ÎļþÒÑɾ³ý
node_modules/vite/dist/node/chunks/dep-1e6e3914.js
ÎļþÒÑɾ³ý
node_modules/vite/dist/node/chunks/dep-2056ae8a.js
ÎļþÒÑɾ³ý
node_modules/vite/dist/node/chunks/dep-a9015192.js
ÎļþÒÑɾ³ý
node_modules/vite/dist/node/chunks/dep-b120d181.js
ÎļþÒÑɾ³ý
node_modules/vite/dist/node/cli.js
ÎļþÒÑɾ³ý
node_modules/vite/dist/node/index.d.ts
ÎļþÒÑɾ³ý
node_modules/vite/dist/node/index.js
ÎļþÒÑɾ³ý
node_modules/vite/dist/node/terser.js
ÎļþÒÑɾ³ý
node_modules/vite/package.json
ÎļþÒÑɾ³ý
node_modules/vite/src/client/client.ts
ÎļþÒÑɾ³ý
node_modules/vite/src/client/env.ts
ÎļþÒÑɾ³ý
node_modules/vite/src/client/overlay.ts
ÎļþÒÑɾ³ý
node_modules/vite/src/client/tsconfig.json
ÎļþÒÑɾ³ý
node_modules/vite/types/alias.d.ts
ÎļþÒÑɾ³ý
node_modules/vite/types/anymatch.d.ts
ÎļþÒÑɾ³ý
node_modules/vite/types/chokidar.d.ts
ÎļþÒÑɾ³ý
node_modules/vite/types/commonjs.d.ts
ÎļþÒÑɾ³ý
node_modules/vite/types/connect.d.ts
ÎļþÒÑɾ³ý
node_modules/vite/types/customEvent.d.ts
ÎļþÒÑɾ³ý
node_modules/vite/types/dynamicImportVars.d.ts
ÎļþÒÑɾ³ý
node_modules/vite/types/hmrPayload.d.ts
ÎļþÒÑɾ³ý
node_modules/vite/types/hot.d.ts
ÎļþÒÑɾ³ý
node_modules/vite/types/http-proxy.d.ts
ÎļþÒÑɾ³ý
node_modules/vite/types/importMeta.d.ts
ÎļþÒÑɾ³ý
node_modules/vite/types/package.json
ÎļþÒÑɾ³ý
node_modules/vite/types/shims.d.ts
ÎļþÒÑɾ³ý
node_modules/vite/types/terser.d.ts
ÎļþÒÑɾ³ý
node_modules/vite/types/ws.d.ts
ÎļþÒÑɾ³ý
package-lock.json
@@ -15,10 +15,8 @@
        "vue-i18n": "^9.2.2"
      },
      "devDependencies": {
        "@vitejs/plugin-vue": "^1.10.2",
        "@vue/compiler-sfc": "^3.3.0",
        "typescript": "^5.0.0",
        "vite": "^2.9.0",
        "vue-cli-plugin-i18n": "~2.3.2",
        "webpack": "^5.103.0",
        "webpack-cli": "^6.0.1"
@@ -78,22 +76,6 @@
      "dev": true,
      "engines": {
        "node": ">=14.17.0"
      }
    },
    "node_modules/@esbuild/linux-loong64": {
      "version": "0.14.54",
      "resolved": "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.14.54.tgz",
      "integrity": "sha512-bZBrLAIX1kpWelV0XemxBZllyRmM6vgFQQG2GdNb+r3Fkp0FOh1NJSvekXDs7jq70k4euu1cryLMfU+mTXlEpw==",
      "cpu": [
        "loong64"
      ],
      "dev": true,
      "optional": true,
      "os": [
        "linux"
      ],
      "engines": {
        "node": ">=12"
      }
    },
    "node_modules/@intlify/core-base": {
@@ -220,18 +202,6 @@
      "dev": true,
      "dependencies": {
        "undici-types": "~7.19.0"
      }
    },
    "node_modules/@vitejs/plugin-vue": {
      "version": "1.10.2",
      "resolved": "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-1.10.2.tgz",
      "integrity": "sha512-/QJ0Z9qfhAFtKRY+r57ziY4BSbGUTGsPRMpB/Ron3QPwBZM4OZAZHdTa4a8PafCwU5DTatXG8TMDoP8z+oDqJw==",
      "dev": true,
      "engines": {
        "node": ">=12.0.0"
      },
      "peerDependencies": {
        "vite": "^2.5.10"
      }
    },
    "node_modules/@vue/compiler-core": {
@@ -938,362 +908,6 @@
      "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==",
      "dev": true
    },
    "node_modules/esbuild": {
      "version": "0.14.54",
      "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.14.54.tgz",
      "integrity": "sha512-Cy9llcy8DvET5uznocPyqL3BFRrFXSVqbgpMJ9Wz8oVjZlh/zUSNbPRbov0VX7VxN2JH1Oa0uNxZ7eLRb62pJA==",
      "dev": true,
      "hasInstallScript": true,
      "bin": {
        "esbuild": "bin/esbuild"
      },
      "engines": {
        "node": ">=12"
      },
      "optionalDependencies": {
        "@esbuild/linux-loong64": "0.14.54",
        "esbuild-android-64": "0.14.54",
        "esbuild-android-arm64": "0.14.54",
        "esbuild-darwin-64": "0.14.54",
        "esbuild-darwin-arm64": "0.14.54",
        "esbuild-freebsd-64": "0.14.54",
        "esbuild-freebsd-arm64": "0.14.54",
        "esbuild-linux-32": "0.14.54",
        "esbuild-linux-64": "0.14.54",
        "esbuild-linux-arm": "0.14.54",
        "esbuild-linux-arm64": "0.14.54",
        "esbuild-linux-mips64le": "0.14.54",
        "esbuild-linux-ppc64le": "0.14.54",
        "esbuild-linux-riscv64": "0.14.54",
        "esbuild-linux-s390x": "0.14.54",
        "esbuild-netbsd-64": "0.14.54",
        "esbuild-openbsd-64": "0.14.54",
        "esbuild-sunos-64": "0.14.54",
        "esbuild-windows-32": "0.14.54",
        "esbuild-windows-64": "0.14.54",
        "esbuild-windows-arm64": "0.14.54"
      }
    },
    "node_modules/esbuild-android-64": {
      "version": "0.14.54",
      "resolved": "https://registry.npmmirror.com/esbuild-android-64/-/esbuild-android-64-0.14.54.tgz",
      "integrity": "sha512-Tz2++Aqqz0rJ7kYBfz+iqyE3QMycD4vk7LBRyWaAVFgFtQ/O8EJOnVmTOiDWYZ/uYzB4kvP+bqejYdVKzE5lAQ==",
      "cpu": [
        "x64"
      ],
      "dev": true,
      "optional": true,
      "os": [
        "android"
      ],
      "engines": {
        "node": ">=12"
      }
    },
    "node_modules/esbuild-android-arm64": {
      "version": "0.14.54",
      "resolved": "https://registry.npmmirror.com/esbuild-android-arm64/-/esbuild-android-arm64-0.14.54.tgz",
      "integrity": "sha512-F9E+/QDi9sSkLaClO8SOV6etqPd+5DgJje1F9lOWoNncDdOBL2YF59IhsWATSt0TLZbYCf3pNlTHvVV5VfHdvg==",
      "cpu": [
        "arm64"
      ],
      "dev": true,
      "optional": true,
      "os": [
        "android"
      ],
      "engines": {
        "node": ">=12"
      }
    },
    "node_modules/esbuild-darwin-64": {
      "version": "0.14.54",
      "resolved": "https://registry.npmmirror.com/esbuild-darwin-64/-/esbuild-darwin-64-0.14.54.tgz",
      "integrity": "sha512-jtdKWV3nBviOd5v4hOpkVmpxsBy90CGzebpbO9beiqUYVMBtSc0AL9zGftFuBon7PNDcdvNCEuQqw2x0wP9yug==",
      "cpu": [
        "x64"
      ],
      "dev": true,
      "optional": true,
      "os": [
        "darwin"
      ],
      "engines": {
        "node": ">=12"
      }
    },
    "node_modules/esbuild-darwin-arm64": {
      "version": "0.14.54",
      "resolved": "https://registry.npmmirror.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.54.tgz",
      "integrity": "sha512-OPafJHD2oUPyvJMrsCvDGkRrVCar5aVyHfWGQzY1dWnzErjrDuSETxwA2HSsyg2jORLY8yBfzc1MIpUkXlctmw==",
      "cpu": [
        "arm64"
      ],
      "dev": true,
      "optional": true,
      "os": [
        "darwin"
      ],
      "engines": {
        "node": ">=12"
      }
    },
    "node_modules/esbuild-freebsd-64": {
      "version": "0.14.54",
      "resolved": "https://registry.npmmirror.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.54.tgz",
      "integrity": "sha512-OKwd4gmwHqOTp4mOGZKe/XUlbDJ4Q9TjX0hMPIDBUWWu/kwhBAudJdBoxnjNf9ocIB6GN6CPowYpR/hRCbSYAg==",
      "cpu": [
        "x64"
      ],
      "dev": true,
      "optional": true,
      "os": [
        "freebsd"
      ],
      "engines": {
        "node": ">=12"
      }
    },
    "node_modules/esbuild-freebsd-arm64": {
      "version": "0.14.54",
      "resolved": "https://registry.npmmirror.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.54.tgz",
      "integrity": "sha512-sFwueGr7OvIFiQT6WeG0jRLjkjdqWWSrfbVwZp8iMP+8UHEHRBvlaxL6IuKNDwAozNUmbb8nIMXa7oAOARGs1Q==",
      "cpu": [
        "arm64"
      ],
      "dev": true,
      "optional": true,
      "os": [
        "freebsd"
      ],
      "engines": {
        "node": ">=12"
      }
    },
    "node_modules/esbuild-linux-32": {
      "version": "0.14.54",
      "resolved": "https://registry.npmmirror.com/esbuild-linux-32/-/esbuild-linux-32-0.14.54.tgz",
      "integrity": "sha512-1ZuY+JDI//WmklKlBgJnglpUL1owm2OX+8E1syCD6UAxcMM/XoWd76OHSjl/0MR0LisSAXDqgjT3uJqT67O3qw==",
      "cpu": [
        "ia32"
      ],
      "dev": true,
      "optional": true,
      "os": [
        "linux"
      ],
      "engines": {
        "node": ">=12"
      }
    },
    "node_modules/esbuild-linux-64": {
      "version": "0.14.54",
      "resolved": "https://registry.npmmirror.com/esbuild-linux-64/-/esbuild-linux-64-0.14.54.tgz",
      "integrity": "sha512-EgjAgH5HwTbtNsTqQOXWApBaPVdDn7XcK+/PtJwZLT1UmpLoznPd8c5CxqsH2dQK3j05YsB3L17T8vE7cp4cCg==",
      "cpu": [
        "x64"
      ],
      "dev": true,
      "optional": true,
      "os": [
        "linux"
      ],
      "engines": {
        "node": ">=12"
      }
    },
    "node_modules/esbuild-linux-arm": {
      "version": "0.14.54",
      "resolved": "https://registry.npmmirror.com/esbuild-linux-arm/-/esbuild-linux-arm-0.14.54.tgz",
      "integrity": "sha512-qqz/SjemQhVMTnvcLGoLOdFpCYbz4v4fUo+TfsWG+1aOu70/80RV6bgNpR2JCrppV2moUQkww+6bWxXRL9YMGw==",
      "cpu": [
        "arm"
      ],
      "dev": true,
      "optional": true,
      "os": [
        "linux"
      ],
      "engines": {
        "node": ">=12"
      }
    },
    "node_modules/esbuild-linux-arm64": {
      "version": "0.14.54",
      "resolved": "https://registry.npmmirror.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.54.tgz",
      "integrity": "sha512-WL71L+0Rwv+Gv/HTmxTEmpv0UgmxYa5ftZILVi2QmZBgX3q7+tDeOQNqGtdXSdsL8TQi1vIaVFHUPDe0O0kdig==",
      "cpu": [
        "arm64"
      ],
      "dev": true,
      "optional": true,
      "os": [
        "linux"
      ],
      "engines": {
        "node": ">=12"
      }
    },
    "node_modules/esbuild-linux-mips64le": {
      "version": "0.14.54",
      "resolved": "https://registry.npmmirror.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.54.tgz",
      "integrity": "sha512-qTHGQB8D1etd0u1+sB6p0ikLKRVuCWhYQhAHRPkO+OF3I/iSlTKNNS0Lh2Oc0g0UFGguaFZZiPJdJey3AGpAlw==",
      "cpu": [
        "mips64el"
      ],
      "dev": true,
      "optional": true,
      "os": [
        "linux"
      ],
      "engines": {
        "node": ">=12"
      }
    },
    "node_modules/esbuild-linux-ppc64le": {
      "version": "0.14.54",
      "resolved": "https://registry.npmmirror.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.54.tgz",
      "integrity": "sha512-j3OMlzHiqwZBDPRCDFKcx595XVfOfOnv68Ax3U4UKZ3MTYQB5Yz3X1mn5GnodEVYzhtZgxEBidLWeIs8FDSfrQ==",
      "cpu": [
        "ppc64"
      ],
      "dev": true,
      "optional": true,
      "os": [
        "linux"
      ],
      "engines": {
        "node": ">=12"
      }
    },
    "node_modules/esbuild-linux-riscv64": {
      "version": "0.14.54",
      "resolved": "https://registry.npmmirror.com/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.54.tgz",
      "integrity": "sha512-y7Vt7Wl9dkOGZjxQZnDAqqn+XOqFD7IMWiewY5SPlNlzMX39ocPQlOaoxvT4FllA5viyV26/QzHtvTjVNOxHZg==",
      "cpu": [
        "riscv64"
      ],
      "dev": true,
      "optional": true,
      "os": [
        "linux"
      ],
      "engines": {
        "node": ">=12"
      }
    },
    "node_modules/esbuild-linux-s390x": {
      "version": "0.14.54",
      "resolved": "https://registry.npmmirror.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.54.tgz",
      "integrity": "sha512-zaHpW9dziAsi7lRcyV4r8dhfG1qBidQWUXweUjnw+lliChJqQr+6XD71K41oEIC3Mx1KStovEmlzm+MkGZHnHA==",
      "cpu": [
        "s390x"
      ],
      "dev": true,
      "optional": true,
      "os": [
        "linux"
      ],
      "engines": {
        "node": ">=12"
      }
    },
    "node_modules/esbuild-netbsd-64": {
      "version": "0.14.54",
      "resolved": "https://registry.npmmirror.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.54.tgz",
      "integrity": "sha512-PR01lmIMnfJTgeU9VJTDY9ZerDWVFIUzAtJuDHwwceppW7cQWjBBqP48NdeRtoP04/AtO9a7w3viI+PIDr6d+w==",
      "cpu": [
        "x64"
      ],
      "dev": true,
      "optional": true,
      "os": [
        "netbsd"
      ],
      "engines": {
        "node": ">=12"
      }
    },
    "node_modules/esbuild-openbsd-64": {
      "version": "0.14.54",
      "resolved": "https://registry.npmmirror.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.54.tgz",
      "integrity": "sha512-Qyk7ikT2o7Wu76UsvvDS5q0amJvmRzDyVlL0qf5VLsLchjCa1+IAvd8kTBgUxD7VBUUVgItLkk609ZHUc1oCaw==",
      "cpu": [
        "x64"
      ],
      "dev": true,
      "optional": true,
      "os": [
        "openbsd"
      ],
      "engines": {
        "node": ">=12"
      }
    },
    "node_modules/esbuild-sunos-64": {
      "version": "0.14.54",
      "resolved": "https://registry.npmmirror.com/esbuild-sunos-64/-/esbuild-sunos-64-0.14.54.tgz",
      "integrity": "sha512-28GZ24KmMSeKi5ueWzMcco6EBHStL3B6ubM7M51RmPwXQGLe0teBGJocmWhgwccA1GeFXqxzILIxXpHbl9Q/Kw==",
      "cpu": [
        "x64"
      ],
      "dev": true,
      "optional": true,
      "os": [
        "sunos"
      ],
      "engines": {
        "node": ">=12"
      }
    },
    "node_modules/esbuild-windows-32": {
      "version": "0.14.54",
      "resolved": "https://registry.npmmirror.com/esbuild-windows-32/-/esbuild-windows-32-0.14.54.tgz",
      "integrity": "sha512-T+rdZW19ql9MjS7pixmZYVObd9G7kcaZo+sETqNH4RCkuuYSuv9AGHUVnPoP9hhuE1WM1ZimHz1CIBHBboLU7w==",
      "cpu": [
        "ia32"
      ],
      "dev": true,
      "optional": true,
      "os": [
        "win32"
      ],
      "engines": {
        "node": ">=12"
      }
    },
    "node_modules/esbuild-windows-64": {
      "version": "0.14.54",
      "resolved": "https://registry.npmmirror.com/esbuild-windows-64/-/esbuild-windows-64-0.14.54.tgz",
      "integrity": "sha512-AoHTRBUuYwXtZhjXZbA1pGfTo8cJo3vZIcWGLiUcTNgHpJJMC1rVA44ZereBHMJtotyN71S8Qw0npiCIkW96cQ==",
      "cpu": [
        "x64"
      ],
      "dev": true,
      "optional": true,
      "os": [
        "win32"
      ],
      "engines": {
        "node": ">=12"
      }
    },
    "node_modules/esbuild-windows-arm64": {
      "version": "0.14.54",
      "resolved": "https://registry.npmmirror.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.54.tgz",
      "integrity": "sha512-M0kuUvXhot1zOISQGXwWn6YtS+Y/1RT9WrVIOywZnJHo3jCDyewAc79aKNQWFCQm+xNHVTq9h8dZKvygoXQQRg==",
      "cpu": [
        "arm64"
      ],
      "dev": true,
      "optional": true,
      "os": [
        "win32"
      ],
      "engines": {
        "node": ">=12"
      }
    },
    "node_modules/escalade": {
      "version": "3.2.0",
      "resolved": "https://registry.npmmirror.com/escalade/-/escalade-3.2.0.tgz",
@@ -1431,20 +1045,6 @@
      "resolved": "https://registry.npmmirror.com/fs.realpath/-/fs.realpath-1.0.0.tgz",
      "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
      "dev": true
    },
    "node_modules/fsevents": {
      "version": "2.3.3",
      "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz",
      "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
      "dev": true,
      "hasInstallScript": true,
      "optional": true,
      "os": [
        "darwin"
      ],
      "engines": {
        "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
      }
    },
    "node_modules/function-bind": {
      "version": "1.1.2",
@@ -2035,21 +1635,6 @@
        "url": "https://github.com/sponsors/isaacs"
      }
    },
    "node_modules/rollup": {
      "version": "2.77.3",
      "resolved": "https://registry.npmmirror.com/rollup/-/rollup-2.77.3.tgz",
      "integrity": "sha512-/qxNTG7FbmefJWoeeYJFbHehJ2HNWnjkAFRKzWN/45eNBBF/r8lo992CwcJXEzyVxs5FmfId+vTSTQDb+bxA+g==",
      "dev": true,
      "bin": {
        "rollup": "dist/bin/rollup"
      },
      "engines": {
        "node": ">=10.0.0"
      },
      "optionalDependencies": {
        "fsevents": "~2.3.2"
      }
    },
    "node_modules/schema-utils": {
      "version": "4.3.3",
      "resolved": "https://registry.npmmirror.com/schema-utils/-/schema-utils-4.3.3.tgz",
@@ -2318,43 +1903,6 @@
        "HBuilderX": "^3.1.0",
        "uni-app": "^4.66",
        "uni-app-x": ""
      }
    },
    "node_modules/vite": {
      "version": "2.9.18",
      "resolved": "https://registry.npmmirror.com/vite/-/vite-2.9.18.tgz",
      "integrity": "sha512-sAOqI5wNM9QvSEE70W3UGMdT8cyEn0+PmJMTFvTB8wB0YbYUWw3gUbY62AOyrXosGieF2htmeLATvNxpv/zNyQ==",
      "dev": true,
      "dependencies": {
        "esbuild": "^0.14.27",
        "postcss": "^8.4.13",
        "resolve": "^1.22.0",
        "rollup": ">=2.59.0 <2.78.0"
      },
      "bin": {
        "vite": "bin/vite.js"
      },
      "engines": {
        "node": ">=12.2.0"
      },
      "optionalDependencies": {
        "fsevents": "~2.3.2"
      },
      "peerDependencies": {
        "less": "*",
        "sass": "*",
        "stylus": "*"
      },
      "peerDependenciesMeta": {
        "less": {
          "optional": true
        },
        "sass": {
          "optional": true
        },
        "stylus": {
          "optional": true
        }
      }
    },
    "node_modules/vue": {
@@ -2677,13 +2225,6 @@
      "integrity": "sha512-4B4OijXeVNOPZlYA2oEwWOTkzyltLao+xbotHQeqN++Rv27Y6s818+n2Qkp8q+Fxhn0t/5lA5X1Mxktud8eayQ==",
      "dev": true
    },
    "@esbuild/linux-loong64": {
      "version": "0.14.54",
      "resolved": "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.14.54.tgz",
      "integrity": "sha512-bZBrLAIX1kpWelV0XemxBZllyRmM6vgFQQG2GdNb+r3Fkp0FOh1NJSvekXDs7jq70k4euu1cryLMfU+mTXlEpw==",
      "dev": true,
      "optional": true
    },
    "@intlify/core-base": {
      "version": "9.14.4",
      "resolved": "https://registry.npmmirror.com/@intlify/core-base/-/core-base-9.14.4.tgz",
@@ -2788,13 +2329,6 @@
      "requires": {
        "undici-types": "~7.19.0"
      }
    },
    "@vitejs/plugin-vue": {
      "version": "1.10.2",
      "resolved": "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-1.10.2.tgz",
      "integrity": "sha512-/QJ0Z9qfhAFtKRY+r57ziY4BSbGUTGsPRMpB/Ron3QPwBZM4OZAZHdTa4a8PafCwU5DTatXG8TMDoP8z+oDqJw==",
      "dev": true,
      "requires": {}
    },
    "@vue/compiler-core": {
      "version": "3.5.32",
@@ -3351,175 +2885,6 @@
      "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==",
      "dev": true
    },
    "esbuild": {
      "version": "0.14.54",
      "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.14.54.tgz",
      "integrity": "sha512-Cy9llcy8DvET5uznocPyqL3BFRrFXSVqbgpMJ9Wz8oVjZlh/zUSNbPRbov0VX7VxN2JH1Oa0uNxZ7eLRb62pJA==",
      "dev": true,
      "requires": {
        "@esbuild/linux-loong64": "0.14.54",
        "esbuild-android-64": "0.14.54",
        "esbuild-android-arm64": "0.14.54",
        "esbuild-darwin-64": "0.14.54",
        "esbuild-darwin-arm64": "0.14.54",
        "esbuild-freebsd-64": "0.14.54",
        "esbuild-freebsd-arm64": "0.14.54",
        "esbuild-linux-32": "0.14.54",
        "esbuild-linux-64": "0.14.54",
        "esbuild-linux-arm": "0.14.54",
        "esbuild-linux-arm64": "0.14.54",
        "esbuild-linux-mips64le": "0.14.54",
        "esbuild-linux-ppc64le": "0.14.54",
        "esbuild-linux-riscv64": "0.14.54",
        "esbuild-linux-s390x": "0.14.54",
        "esbuild-netbsd-64": "0.14.54",
        "esbuild-openbsd-64": "0.14.54",
        "esbuild-sunos-64": "0.14.54",
        "esbuild-windows-32": "0.14.54",
        "esbuild-windows-64": "0.14.54",
        "esbuild-windows-arm64": "0.14.54"
      }
    },
    "esbuild-android-64": {
      "version": "0.14.54",
      "resolved": "https://registry.npmmirror.com/esbuild-android-64/-/esbuild-android-64-0.14.54.tgz",
      "integrity": "sha512-Tz2++Aqqz0rJ7kYBfz+iqyE3QMycD4vk7LBRyWaAVFgFtQ/O8EJOnVmTOiDWYZ/uYzB4kvP+bqejYdVKzE5lAQ==",
      "dev": true,
      "optional": true
    },
    "esbuild-android-arm64": {
      "version": "0.14.54",
      "resolved": "https://registry.npmmirror.com/esbuild-android-arm64/-/esbuild-android-arm64-0.14.54.tgz",
      "integrity": "sha512-F9E+/QDi9sSkLaClO8SOV6etqPd+5DgJje1F9lOWoNncDdOBL2YF59IhsWATSt0TLZbYCf3pNlTHvVV5VfHdvg==",
      "dev": true,
      "optional": true
    },
    "esbuild-darwin-64": {
      "version": "0.14.54",
      "resolved": "https://registry.npmmirror.com/esbuild-darwin-64/-/esbuild-darwin-64-0.14.54.tgz",
      "integrity": "sha512-jtdKWV3nBviOd5v4hOpkVmpxsBy90CGzebpbO9beiqUYVMBtSc0AL9zGftFuBon7PNDcdvNCEuQqw2x0wP9yug==",
      "dev": true,
      "optional": true
    },
    "esbuild-darwin-arm64": {
      "version": "0.14.54",
      "resolved": "https://registry.npmmirror.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.54.tgz",
      "integrity": "sha512-OPafJHD2oUPyvJMrsCvDGkRrVCar5aVyHfWGQzY1dWnzErjrDuSETxwA2HSsyg2jORLY8yBfzc1MIpUkXlctmw==",
      "dev": true,
      "optional": true
    },
    "esbuild-freebsd-64": {
      "version": "0.14.54",
      "resolved": "https://registry.npmmirror.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.54.tgz",
      "integrity": "sha512-OKwd4gmwHqOTp4mOGZKe/XUlbDJ4Q9TjX0hMPIDBUWWu/kwhBAudJdBoxnjNf9ocIB6GN6CPowYpR/hRCbSYAg==",
      "dev": true,
      "optional": true
    },
    "esbuild-freebsd-arm64": {
      "version": "0.14.54",
      "resolved": "https://registry.npmmirror.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.54.tgz",
      "integrity": "sha512-sFwueGr7OvIFiQT6WeG0jRLjkjdqWWSrfbVwZp8iMP+8UHEHRBvlaxL6IuKNDwAozNUmbb8nIMXa7oAOARGs1Q==",
      "dev": true,
      "optional": true
    },
    "esbuild-linux-32": {
      "version": "0.14.54",
      "resolved": "https://registry.npmmirror.com/esbuild-linux-32/-/esbuild-linux-32-0.14.54.tgz",
      "integrity": "sha512-1ZuY+JDI//WmklKlBgJnglpUL1owm2OX+8E1syCD6UAxcMM/XoWd76OHSjl/0MR0LisSAXDqgjT3uJqT67O3qw==",
      "dev": true,
      "optional": true
    },
    "esbuild-linux-64": {
      "version": "0.14.54",
      "resolved": "https://registry.npmmirror.com/esbuild-linux-64/-/esbuild-linux-64-0.14.54.tgz",
      "integrity": "sha512-EgjAgH5HwTbtNsTqQOXWApBaPVdDn7XcK+/PtJwZLT1UmpLoznPd8c5CxqsH2dQK3j05YsB3L17T8vE7cp4cCg==",
      "dev": true,
      "optional": true
    },
    "esbuild-linux-arm": {
      "version": "0.14.54",
      "resolved": "https://registry.npmmirror.com/esbuild-linux-arm/-/esbuild-linux-arm-0.14.54.tgz",
      "integrity": "sha512-qqz/SjemQhVMTnvcLGoLOdFpCYbz4v4fUo+TfsWG+1aOu70/80RV6bgNpR2JCrppV2moUQkww+6bWxXRL9YMGw==",
      "dev": true,
      "optional": true
    },
    "esbuild-linux-arm64": {
      "version": "0.14.54",
      "resolved": "https://registry.npmmirror.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.54.tgz",
      "integrity": "sha512-WL71L+0Rwv+Gv/HTmxTEmpv0UgmxYa5ftZILVi2QmZBgX3q7+tDeOQNqGtdXSdsL8TQi1vIaVFHUPDe0O0kdig==",
      "dev": true,
      "optional": true
    },
    "esbuild-linux-mips64le": {
      "version": "0.14.54",
      "resolved": "https://registry.npmmirror.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.54.tgz",
      "integrity": "sha512-qTHGQB8D1etd0u1+sB6p0ikLKRVuCWhYQhAHRPkO+OF3I/iSlTKNNS0Lh2Oc0g0UFGguaFZZiPJdJey3AGpAlw==",
      "dev": true,
      "optional": true
    },
    "esbuild-linux-ppc64le": {
      "version": "0.14.54",
      "resolved": "https://registry.npmmirror.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.54.tgz",
      "integrity": "sha512-j3OMlzHiqwZBDPRCDFKcx595XVfOfOnv68Ax3U4UKZ3MTYQB5Yz3X1mn5GnodEVYzhtZgxEBidLWeIs8FDSfrQ==",
      "dev": true,
      "optional": true
    },
    "esbuild-linux-riscv64": {
      "version": "0.14.54",
      "resolved": "https://registry.npmmirror.com/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.54.tgz",
      "integrity": "sha512-y7Vt7Wl9dkOGZjxQZnDAqqn+XOqFD7IMWiewY5SPlNlzMX39ocPQlOaoxvT4FllA5viyV26/QzHtvTjVNOxHZg==",
      "dev": true,
      "optional": true
    },
    "esbuild-linux-s390x": {
      "version": "0.14.54",
      "resolved": "https://registry.npmmirror.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.54.tgz",
      "integrity": "sha512-zaHpW9dziAsi7lRcyV4r8dhfG1qBidQWUXweUjnw+lliChJqQr+6XD71K41oEIC3Mx1KStovEmlzm+MkGZHnHA==",
      "dev": true,
      "optional": true
    },
    "esbuild-netbsd-64": {
      "version": "0.14.54",
      "resolved": "https://registry.npmmirror.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.54.tgz",
      "integrity": "sha512-PR01lmIMnfJTgeU9VJTDY9ZerDWVFIUzAtJuDHwwceppW7cQWjBBqP48NdeRtoP04/AtO9a7w3viI+PIDr6d+w==",
      "dev": true,
      "optional": true
    },
    "esbuild-openbsd-64": {
      "version": "0.14.54",
      "resolved": "https://registry.npmmirror.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.54.tgz",
      "integrity": "sha512-Qyk7ikT2o7Wu76UsvvDS5q0amJvmRzDyVlL0qf5VLsLchjCa1+IAvd8kTBgUxD7VBUUVgItLkk609ZHUc1oCaw==",
      "dev": true,
      "optional": true
    },
    "esbuild-sunos-64": {
      "version": "0.14.54",
      "resolved": "https://registry.npmmirror.com/esbuild-sunos-64/-/esbuild-sunos-64-0.14.54.tgz",
      "integrity": "sha512-28GZ24KmMSeKi5ueWzMcco6EBHStL3B6ubM7M51RmPwXQGLe0teBGJocmWhgwccA1GeFXqxzILIxXpHbl9Q/Kw==",
      "dev": true,
      "optional": true
    },
    "esbuild-windows-32": {
      "version": "0.14.54",
      "resolved": "https://registry.npmmirror.com/esbuild-windows-32/-/esbuild-windows-32-0.14.54.tgz",
      "integrity": "sha512-T+rdZW19ql9MjS7pixmZYVObd9G7kcaZo+sETqNH4RCkuuYSuv9AGHUVnPoP9hhuE1WM1ZimHz1CIBHBboLU7w==",
      "dev": true,
      "optional": true
    },
    "esbuild-windows-64": {
      "version": "0.14.54",
      "resolved": "https://registry.npmmirror.com/esbuild-windows-64/-/esbuild-windows-64-0.14.54.tgz",
      "integrity": "sha512-AoHTRBUuYwXtZhjXZbA1pGfTo8cJo3vZIcWGLiUcTNgHpJJMC1rVA44ZereBHMJtotyN71S8Qw0npiCIkW96cQ==",
      "dev": true,
      "optional": true
    },
    "esbuild-windows-arm64": {
      "version": "0.14.54",
      "resolved": "https://registry.npmmirror.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.54.tgz",
      "integrity": "sha512-M0kuUvXhot1zOISQGXwWn6YtS+Y/1RT9WrVIOywZnJHo3jCDyewAc79aKNQWFCQm+xNHVTq9h8dZKvygoXQQRg==",
      "dev": true,
      "optional": true
    },
    "escalade": {
      "version": "3.2.0",
      "resolved": "https://registry.npmmirror.com/escalade/-/escalade-3.2.0.tgz",
@@ -3615,13 +2980,6 @@
      "resolved": "https://registry.npmmirror.com/fs.realpath/-/fs.realpath-1.0.0.tgz",
      "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
      "dev": true
    },
    "fsevents": {
      "version": "2.3.3",
      "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz",
      "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
      "dev": true,
      "optional": true
    },
    "function-bind": {
      "version": "1.1.2",
@@ -4027,15 +3385,6 @@
        "glob": "^7.1.3"
      }
    },
    "rollup": {
      "version": "2.77.3",
      "resolved": "https://registry.npmmirror.com/rollup/-/rollup-2.77.3.tgz",
      "integrity": "sha512-/qxNTG7FbmefJWoeeYJFbHehJ2HNWnjkAFRKzWN/45eNBBF/r8lo992CwcJXEzyVxs5FmfId+vTSTQDb+bxA+g==",
      "dev": true,
      "requires": {
        "fsevents": "~2.3.2"
      }
    },
    "schema-utils": {
      "version": "4.3.3",
      "resolved": "https://registry.npmmirror.com/schema-utils/-/schema-utils-4.3.3.tgz",
@@ -4201,19 +3550,6 @@
      "version": "3.7.36",
      "resolved": "https://registry.npmmirror.com/uview-plus/-/uview-plus-3.7.36.tgz",
      "integrity": "sha512-44pW0oKKatYxCHhXPljaNv5E+CESSJlhsz0FRZRNpMv1ms02m5Agk+CNpgDnv/XNHt9YxHdYSYerN+xnNP5orw=="
    },
    "vite": {
      "version": "2.9.18",
      "resolved": "https://registry.npmmirror.com/vite/-/vite-2.9.18.tgz",
      "integrity": "sha512-sAOqI5wNM9QvSEE70W3UGMdT8cyEn0+PmJMTFvTB8wB0YbYUWw3gUbY62AOyrXosGieF2htmeLATvNxpv/zNyQ==",
      "dev": true,
      "requires": {
        "esbuild": "^0.14.27",
        "fsevents": "~2.3.2",
        "postcss": "^8.4.13",
        "resolve": "^1.22.0",
        "rollup": ">=2.59.0 <2.78.0"
      }
    },
    "vue": {
      "version": "3.5.32",
package.json
@@ -9,12 +9,9 @@
    "vue": "^3.3.0",
    "vue-i18n": "^9.2.2"
  },
  "type": "module",
  "devDependencies": {
    "@vitejs/plugin-vue": "^1.10.2",
    "@vue/compiler-sfc": "^3.3.0",
    "typescript": "^5.0.0",
    "vite": "^2.9.0",
    "vue-cli-plugin-i18n": "~2.3.2",
    "webpack": "^5.103.0",
    "webpack-cli": "^6.0.1"
pages.json
@@ -181,6 +181,7 @@
      "path": "pages/case/index",
      "style": {
        "navigationBarTitleText": "我的上报"
      }
    },
    {
@@ -199,6 +200,7 @@
      "path": "pages/case/transfer",
      "style": {
        "navigationBarTitleText": "转运登记"
      }
    },
     {
pages/case/CaseDetails.vue
@@ -207,7 +207,23 @@
                :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">
@@ -540,7 +556,10 @@
  { label: "O型", value: "O" },
  { label: "AB型", value: "AB" },
]);
const isTransportOptions = ref([
  { label: "需要", value: "2" },
  { label: "不需要", value: "1" },
]);
const rhOptions = ref([
  { label: "阳性", value: "positive" },
  { label: "阴性", value: "negative" },
@@ -615,7 +634,6 @@
    ? idCardTypeLabels.value[idCardTypeIndex.value]
    : "请选择证件类型";
});
const onNationChange = (e) => {
  const index = parseInt(e.detail.value);
@@ -804,16 +822,19 @@
// å¤„理基础附件上传
const handleBaseUpload = (file) => {
  console.log("基础附件上传成功:", file);
  attachments.value.push(file);
};
// å¤„理其他附件上传
const handleFilesUpdate = (files) => {
  formData.attachments = files.map((file) => ({
  console.log(files, "files");
  attachments.value = files.map((file) => ({
    ...file,
    // ç¡®ä¿åªå­˜å‚¨åŠè·¯å¾„
    url: file.url.startsWith("http")
      ? file.url.replace(baseUrlHt, "")
      : file.url,
    // url: file.url.startsWith("http")
    //   ? file.url.replace(baseUrlHt, "")
    //   : file.url,
  }));
};
@@ -825,7 +846,7 @@
  if (file.type.includes("image")) {
    uni.previewImage({
      urls: formData.attachments
      urls: attachments.value
        .filter((f) => f.type.includes("image"))
        .map((f) =>
          f.url.startsWith("http")
@@ -946,14 +967,13 @@
  try {
    uni.showLoading({ title: isEditMode.value ? "修改中..." : "提交中..." });
    // å‡†å¤‡æäº¤æ•°æ®
    const submitData = {
      ...form.value,
      age: parseInt(form.value.age) || 0,
      annexfilesList: attachments.value.map((file) => ({
        url: file.url,
        name: file.name,
        path: file.url,
        fileName: file.name,
        type: file.type,
      })),
      phone: form.value.infophone,
@@ -1013,47 +1033,26 @@
};
const loadCaseData = async (id) => {
  // æ¨¡æ‹ŸåŠ è½½ç¼–è¾‘æ•°æ®
  // form.value = {
  //   caseNo: "DON20241216001",
  //   treatmenthospitalname: "青岛镜湖医院",
  //   treatmentdeptname: "神经外科",
  //   name: "张三",
  //   nation: "汉族",
  //   nationality: "中国",
  //   idcardtype: "居民身份证",
  //   idcardno: "370203198510123456",
  //   sex: "1",
  //   birthday: "1985-10-12",
  //   age: "38",
  //   inpatientno: "ZY20241216001",
  //   diagnosisname: "脑外伤导致脑死亡",
  //   bloodType: "A",
  //   rhYin: "positive",
  //   infoname: "李医生",
  //   infophone: "13800138000",
  //   reporterno: "张医生",
  //   reporttime: currentTime.value,
  // };
  try {
    loading.value = true;
    const res = await uni.$uapi.get(
      `/project/donatebaseinforeport/getInfo/${id}`,
    );
    if (res) {
      console.log(res, "res");
      form.value = res;
      console.log(1, "res");
    if (res.code) {
      form.value = res.data;
      // å¤„理选择器索引
      // updatePickerIndexes();
      console.log(2, "res");
      // å¤„理附件
      if (res.annexfilesList) {
        attachments.value = res.annexfilesList;
      if (res.data.annexfilesList) {
        attachments.value = res.data.annexfilesList;
        attachments.value.forEach((item) => {
          item.url = item.path;
          item.name = item.fileName;
        });
      }
      console.log(3, "res");
@@ -1234,6 +1233,16 @@
  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: 9;
}
.btn {
@@ -1457,12 +1466,6 @@
  border-radius: 12rpx !important;
  padding: 20rpx 24rpx !important;
  background: #fff !important;
}
.action-buttons {
  display: flex;
  gap: 20rpx;
  margin-top: 40rpx;
}
.btn {
pages/case/CaseInfo.vue
@@ -6,24 +6,24 @@
        <view class="hospital-info">
          <image :src="caseDetail.hospitalLogo" mode="aspectFit" class="hospital-logo" />
          <view class="hospital-details">
            <text class="hospital-name">{{ caseDetail.hospitalName }}</text>
            <text class="case-type">{{ caseDetail.caseType }}</text>
            <text class="hospital-name">{{ caseDetail.treatmenthospitalname || '未填写治疗医院' }}</text>
            <text class="case-type">{{ caseDetail.donorNo ? '器官捐献案例' : '案例详情' }}</text>
          </view>
        </view>
        <view class="case-status" :class="caseDetail.status">
          {{ caseDetail.statusText }}
        <view class="case-status" :class="getStatusClass(caseDetail.reportStatus)">
          {{ getStatusText(caseDetail.reportStatus) }}
        </view>
      </view>
      
      <view class="case-basic-info">
        <view class="info-row">
          <view class="info-item">
            <text class="label">捐献编号</text>
            <text class="value">{{ caseDetail.donorNo }}</text>
            <text class="label">案例编号</text>
            <text class="value">{{ caseDetail.caseNo || '未生成' }}</text>
          </view>
          <view class="info-item">
            <text class="label">上报时间</text>
            <text class="value">{{ caseDetail.reportTime }}</text>
            <text class="value">{{ formatDateTime(caseDetail.reporttime) }}</text>
          </view>
        </view>
      </view>
@@ -51,31 +51,51 @@
        <view class="info-grid">
          <view class="info-item">
            <text class="label">姓名</text>
            <text class="value">{{ caseDetail.donorName }}</text>
            <text class="value">{{ caseDetail.name || '未填写' }}</text>
          </view>
          <view class="info-item">
            <text class="label">性别</text>
            <text class="value">{{ caseDetail.gender }}</text>
            <text class="value">{{ getGenderText(caseDetail.sex) }}</text>
          </view>
          <view class="info-item">
            <text class="label">年龄</text>
            <text class="value">{{ caseDetail.age }}岁</text>
            <text class="value">{{ caseDetail.age || '0' }} {{ getAgeUnitText(caseDetail.ageunit) }}</text>
          </view>
          <view class="info-item">
            <text class="label">证件号码</text>
            <text class="value">{{ caseDetail.idCardNo }}</text>
            <text class="value">{{ caseDetail.idcardno || '未填写' }}</text>
          </view>
          <view class="info-item">
            <text class="label">血型</text>
            <text class="value">{{ caseDetail.bloodType }}</text>
            <text class="value">{{ getBloodTypeText(caseDetail.bloodType) }}</text>
          </view>
          <view class="info-item">
            <text class="label">民族</text>
            <text class="value">{{ caseDetail.nation }}</text>
            <text class="value">{{ caseDetail.nation || '未填写' }}</text>
          </view>
          <view class="info-item">
            <text class="label">国籍</text>
            <text class="value">{{ caseDetail.nationality || '未填写' }}</text>
          </view>
          <view class="info-item">
            <text class="label">籍贯</text>
            <text class="value">{{ caseDetail.nativeplace || '未填写' }}</text>
          </view>
          <view class="info-item">
            <text class="label">学历</text>
            <text class="value">{{ caseDetail.education || '未填写' }}</text>
          </view>
          <view class="info-item">
            <text class="label">职业</text>
            <text class="value">{{ caseDetail.occupation || '未填写' }}</text>
          </view>
          <view class="info-item full-width">
            <text class="label">住址</text>
            <text class="value">{{ caseDetail.address }}</text>
            <text class="label">户籍地址</text>
            <text class="value">{{ getFullRegisterAddress() || '未填写' }}</text>
          </view>
          <view class="info-item full-width">
            <text class="label">现住地址</text>
            <text class="value">{{ getFullResidenceAddress() || '未填写' }}</text>
          </view>
        </view>
      </view>
@@ -90,135 +110,484 @@
        <view class="info-content">
          <view class="info-group">
            <text class="group-title">疾病诊断</text>
            <text class="group-content">{{ caseDetail.diagnosis }}</text>
            <text class="group-content">{{ caseDetail.diagnosisname || '未填写' }}</text>
          </view>
          <view class="info-group">
            <text class="group-title">病情概况</text>
            <text class="group-content">{{ caseDetail.illnessoverview || '未填写' }}</text>
          </view>
          <view class="info-group">
            <text class="group-title">病人状况</text>
            <text class="group-content">{{ caseDetail.patientstate || '未填写' }}</text>
          </view>
          <view class="info-group">
            <text class="group-title">住院号</text>
            <text class="group-content">{{ caseDetail.inpatientNo }}</text>
            <text class="group-content">{{ caseDetail.inpatientno || '未填写' }}</text>
          </view>
          <view class="info-group">
            <text class="group-title">所在科室</text>
            <text class="group-content">{{ caseDetail.departmentName }}</text>
            <text class="group-title">GCS评分</text>
            <text class="group-content">{{ caseDetail.gcsScore || '未评估' }}</text>
          </view>
          <view class="info-group">
            <text class="group-title">传染病情况</text>
            <text class="group-content">{{ caseDetail.infectiousDisease || '无' }}</text>
            <text class="group-content">{{ caseDetail.infectious || '无' }}{{ caseDetail.infectiousOther ? `(${caseDetail.infectiousOther})` : '' }}</text>
          </view>
          <view class="info-group">
            <text class="group-title">Rh阴性</text>
            <text class="group-content">{{ caseDetail.rhYin === '1' ? '是' : '否' }}</text>
          </view>
        </view>
      </view>
    </view>
    <!-- æçŒ®æµç¨‹ä¿¡æ¯ -->
    <view v-if="activeTab === 'process'" class="info-section fade-in-up">
    <!-- åŒ»é™¢ä¸Žè”系信息 -->
    <view v-if="activeTab === 'contact'" class="info-section fade-in-up">
      <view class="section-card">
        <view class="section-header">
          <text class="section-title">捐献流程信息</text>
          <text class="section-title">医院与联系信息</text>
        </view>
        <view class="process-timeline">
          <view class="timeline-item" v-for="step in processSteps" :key="step.id">
            <view class="timeline-marker" :class="{ active: step.completed }"></view>
            <view class="timeline-content">
              <text class="step-title">{{ step.title }}</text>
              <text class="step-time" v-if="step.time">{{ step.time }}</text>
              <text class="step-person" v-if="step.person">经办人:{{ step.person }}</text>
        <view class="info-grid">
          <view class="info-item full-width">
            <text class="label">治疗医院</text>
            <text class="value">{{ caseDetail.treatmenthospitalname || '未填写' }}</text>
          </view>
          <view class="info-item">
            <text class="label">治疗科室</text>
            <text class="value">{{ caseDetail.treatmentdeptname || '未填写' }}</text>
          </view>
          <view class="info-item">
            <text class="label">上报医院</text>
            <text class="value">{{ caseDetail.toHospital || '未填写' }}</text>
          </view>
          <view class="info-item full-width">
            <text class="label">联系电话</text>
            <text class="value">{{ caseDetail.phone || '未填写' }}</text>
          </view>
          <view class="info-item">
            <text class="label">信息员</text>
            <text class="value">{{ caseDetail.infoName || '未填写' }}</text>
          </view>
          <view class="info-item">
            <text class="label">信息员编号</text>
            <text class="value">{{ caseDetail.infoNo || '未填写' }}</text>
          </view>
          <view class="info-item">
            <text class="label">报告者</text>
            <text class="value">{{ caseDetail.reportername || '未填写' }}</text>
          </view>
          <view class="info-item">
            <text class="label">报告者电话</text>
            <text class="value">{{ caseDetail.reporterphone || '未填写' }}</text>
          </view>
          <view class="info-item">
            <text class="label">协调员</text>
            <text class="value">{{ caseDetail.coordinatorName || '未填写' }}</text>
          </view>
          <view class="info-item">
            <text class="label">协调员编号</text>
            <text class="value">{{ caseDetail.coordinatorNo || '未填写' }}</text>
          </view>
        </view>
      </view>
    </view>
    <!-- è½¬è¿ä¿¡æ¯ -->
    <view v-if="activeTab === 'transport'" class="info-section fade-in-up">
      <view class="section-card">
        <view class="section-header">
          <view style="display: flex; justify-content: space-between; align-items: center;">
            <text class="section-title">转运信息</text>
            <!-- è½¬è¿æ“ä½œæŒ‰é’® -->
            <view v-if="caseDetail.reportStatus === '3'" style="display: flex; gap: 20rpx;">
              <button
                v-if="caseDetail.isTransport === '2' && !hasTransport"
                class="small-btn primary"
                @tap.stop="createTransport"
              >
                åˆ›å»ºè½¬è¿å•
              </button>
              <button
                v-if="hasTransport"
                class="small-btn secondary"
                @tap.stop="viewTransportDetail"
              >
                æŸ¥çœ‹è½¬è¿å•
              </button>
            </view>
          </view>
        </view>  +
        </view>
        <view class="info-content">
          <view class="info-group">
            <text class="group-title">是否需要转运</text>
            <text class="group-content">{{ caseDetail.isTransport === '2' ? '需要' : '不需要' }}</text>
          </view>
          <!-- æœ‰è½¬è¿ä¿¡æ¯æ—¶æ˜¾ç¤º -->
          <view v-if="hasTransport && caseDetail.serviceTransport" class="transport-info">
            <view class="info-group" v-for="transport in caseDetail.serviceTransport" :key="transport.id">
              <view class="sub-group">
                <text class="sub-label">转运单号:</text>
                <text class="sub-value">{{ transport.reportId || transport.id }}</text>
              </view>
              <view class="sub-group">
                <text class="sub-label">出发地点:</text>
                <text class="sub-value">{{ transport.transportStartPlace }}</text>
              </view>
              <view class="sub-group">
                <text class="sub-label">出发时间:</text>
                <text class="sub-value">{{ formatDateTime(transport.transportStartTime) }}</text>
              </view>
              <view class="sub-group">
                <text class="sub-label">负责协调员:</text>
                <text class="sub-value">{{ transport.contactPerson }}</text>
              </view>
              <view class="sub-group">
                <text class="sub-label">转运状态:</text>
                <text class="sub-value status" :class="getTransportStatusClass(transport.transitStatus)">
                  {{ getTransportStatusText(transport.transitStatus) }}
                </text>
              </view>
              <view class="sub-group" v-if="transport.doctor">
                <text class="sub-label">急诊科医生:</text>
                <text class="sub-value">{{ transport.doctor }}</text>
              </view>
              <view class="sub-group" v-if="transport.nurse">
                <text class="sub-label">护士:</text>
                <text class="sub-value">{{ transport.nurse }}</text>
              </view>
              <view class="sub-group" v-if="transport.driver">
                <text class="sub-label">驾驶员:</text>
                <text class="sub-value">{{ transport.driver }}</text>
              </view>
              <view class="sub-group" v-if="transport.icuDoctor">
                <text class="sub-label">ICU评估医生:</text>
                <text class="sub-value">{{ transport.icuDoctor }}</text>
              </view>
            </view>
          </view>
          <!-- æ— è½¬è¿ä¿¡æ¯ä½†éœ€è¦è½¬è¿ -->
          <view v-else-if="caseDetail.isTransport === '2'" class="transport-info">
            <view class="empty-transport">
              <text>该案例需要转运,但尚未创建转运单</text>
              <text v-if="caseDetail.reportStatus !== '3'" style="color: #f0ad4e; font-size: 24rpx; margin-top: 10rpx;">
                éœ€å…ˆå®¡æ‰¹åŒæ„æ‰èƒ½åˆ›å»ºè½¬è¿å•
              </text>
            </view>
          </view>
          <!-- æ— éœ€è½¬è¿ -->
          <view v-else class="transport-info">
            <view class="empty-transport">
              <text>该案例无需转运</text>
            </view>
          </view>
        </view>
      </view>
    </view>
    <!-- æ“ä½œæŒ‰é’® -->
    <view class="action-bar">
      <button class="action-btn secondary" @tap="goBack">返回</button>
      <button class="action-btn primary" v-if="caseDetail.status === 'reported'"
              @tap="withdrawCase">撤回案例</button>
      <button class="action-btn primary" v-else @tap="contactCoordinator">联系协调员</button>
      <!-- æ ¹æ®çŠ¶æ€æ˜¾ç¤ºä¸åŒæ“ä½œ -->
      <button v-if="caseDetail.reportStatus === '1' || caseDetail.reportStatus === '2'"
              class="action-btn primary"
              @tap="handleEdit">
        ç¼–辑案例
      </button>
      <!-- <button v-if="canDelete"
              class="action-btn error"
              @tap="handleDelete">
        åˆ é™¤æ¡ˆä¾‹
      </button> -->
    </view>
    <!-- åŠ è½½çŠ¶æ€ -->
    <u-loading-icon v-if="loading" :show="loading" text="加载中..." />
  </view>
</template>
<script setup>
import { ref, computed, onMounted } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import { useDict } from "@/utils/dict"
import {  onLoad } from '@dcloudio/uni-app'
// å­—典数据
const dict = ref({})
const caseDetail = ref({
  id: 1,
  donorNo: 'DON20240325001',
  hospitalName: '青岛镜湖医院',
  hospitalLogo: '/static/hospital/kiang-wu.jpg',
  caseType: '器官捐献案例',
  donorName: '张三',
  idCardNo: '370203198510123456',
  gender: '男',
  age: 38,
  bloodType: 'A型',
  nation: '汉族',
  address: '山东省青岛市市南区香港中路100号',
  diagnosis: '脑外伤导致脑死亡',
  inpatientNo: 'ZY20240325001',
  departmentName: '神经外科',
  infectiousDisease: '无',
  reportTime: '2024-03-25 09:30:00',
  status: 'reported',
  statusText: '已上报'
})
// æ•°æ®
const caseDetail = ref({})
const loading = ref(false)
const activeTab = ref('basic')
const caseId = ref(null)
// é€‰é¡¹å¡
const tabs = ref([
  { id: 'basic', label: '基本信息' },
  { id: 'medical', label: '医疗信息' },
  { id: 'process', label: '流程信息' }
  { id: 'contact', label: '联系信息' },
  { id: 'transport', label: '转运信息' }
])
const activeTab = ref('basic')
// è®¡ç®—属性
const hasTransport = computed(() => {
  return caseDetail.value.serviceTransport
})
const processSteps = ref([
  { id: 1, title: '案例上报', completed: true, time: '2024-03-25 09:30', person: '李医生' },
  { id: 2, title: '信息审核', completed: false, time: null, person: null },
  { id: 3, title: '家属沟通', completed: false, time: null, person: null },
  { id: 4, title: '捐献确认', completed: false, time: null, person: null },
  { id: 5, title: '器官获取', completed: false, time: null, person: null }
])
const canDelete = computed(() => {
  // å…è®¸åˆ é™¤æœªå®¡æ‰¹æˆ–已驳回的案例
  return caseDetail.value.reportStatus === '1' ||
         caseDetail.value.reportStatus === '2' ||
         caseDetail.value.reportStatus === '4'
})
onLoad((options) => {
onLoad(async (options) => {
  if (options.id) {
    // æ ¹æ®ID加载案例详情
    loadCaseDetail(options.id)
    caseId.value = options.id
    // èŽ·å–å­—å…¸æ•°æ®
    dict.value = await useDict(
      "sys_user_sex",
      "sys_BloodType",
      "sys_IDType",
      "sys_AgeUnit"
    )
    // åŠ è½½æ¡ˆä¾‹è¯¦æƒ…
    await loadCaseDetail(options.id)
  }
})
// åŠ è½½æ¡ˆä¾‹è¯¦æƒ…
const loadCaseDetail = async (id) => {
  loading.value = true
  try {
    const res = await uni.$uapi.get(`/project/donatebaseinforeport/getInfo/${id}`)
    if (res.data) {
      caseDetail.value = res.data
      // å¦‚果状态是"已上报"(1),自动更新为"已阅读"(2)
      if (caseDetail.value.reportStatus === '1') {
        await updateCaseStatus('2')
      }
    } else {
      throw new Error(res.msg || '数据加载失败')
    }
  } catch (error) {
    console.error('加载案例详情失败:', error)
    uni.showToast({
      title: '数据加载失败,请重试',
      icon: 'none'
    })
  } finally {
    loading.value = false
  }
}
// æ›´æ–°æ¡ˆä¾‹çŠ¶æ€
const updateCaseStatus = async (newStatus) => {
  try {
    const updateData = {
      ...caseDetail.value,
      reportStatus: newStatus,
      updateTime: new Date().toISOString().replace('T', ' ').substring(0, 19),
      updateBy: '移动端用户'
    }
    const res = await uni.$uapi.post("/project/donatebaseinforeport/edit", updateData)
    if (res.code === 200) {
      caseDetail.value.reportStatus = newStatus
    }
  } catch (error) {
    console.error('更新状态失败:', error)
  }
}
// èŽ·å–çŠ¶æ€æ ·å¼
const getStatusClass = (status) => {
  const map = {
    '1': 'reported',
    '2': 'read',
    '3': 'agreed',
    '4': 'rejected'
  }
  return map[status] || 'reported'
}
// èŽ·å–çŠ¶æ€æ–‡æœ¬
const getStatusText = (status) => {
  const map = {
    '1': '已上报',
    '2': '已阅读',
    '3': '已同意',
    '4': '已驳回'
  }
  return map[status] || '已上报'
}
// èŽ·å–æ€§åˆ«æ–‡æœ¬
const getGenderText = (gender) => {
  if (!dict.value.sys_user_sex) return gender
  const genderItem = dict.value.sys_user_sex.find(item => item.dictValue === gender)
  return genderItem ? genderItem.dictLabel : gender
}
// èŽ·å–è¡€åž‹æ–‡æœ¬
const getBloodTypeText = (bloodType) => {
  if (!dict.value.sys_BloodType) return bloodType
  const bloodTypeItem = dict.value.sys_BloodType.find(item => item.dictValue === bloodType)
  return bloodTypeItem ? bloodTypeItem.dictLabel : bloodType
}
// èŽ·å–å¹´é¾„å•ä½æ–‡æœ¬
const getAgeUnitText = (ageunit) => {
  if (!ageunit) return ''
  const unitMap = {
    'year': '岁',
    'month': '个月',
    'day': '天'
  }
  return unitMap[ageunit] || ageunit
}
// èŽ·å–å®Œæ•´æˆ·ç±åœ°å€
const getFullRegisterAddress = () => {
  const {
    registerprovincename,
    registercityname,
    registertownname,
    registercommunityname,
    registeraddress
  } = caseDetail.value
  const parts = [
    registerprovincename,
    registercityname,
    registertownname,
    registercommunityname,
    registeraddress
  ]
  return parts.filter(part => part).join('')
}
// èŽ·å–å®Œæ•´çŽ°ä½åœ°å€
const getFullResidenceAddress = () => {
  const {
    residenceprovincename,
    residencecountyname,
    residencetownname,
    residencecommunityname,
    residenceaddress
  } = caseDetail.value
  const parts = [
    residenceprovincename,
    residencecountyname,
    residencetownname,
    residencecommunityname,
    residenceaddress
  ]
  return parts.filter(part => part).join('')
}
// èŽ·å–è½¬è¿çŠ¶æ€æ–‡æœ¬
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] || 'pending'
}
// æ ¼å¼åŒ–日期时间
const formatDateTime = (dateTime) => {
  if (!dateTime) return ''
  return dateTime.replace('T', ' ').substring(0, 16)
}
// é€‰é¡¹å¡åˆ‡æ¢
const switchTab = (tabId) => {
  activeTab.value = tabId
}
// è¿”回
const goBack = () => {
  uni.navigateBack()
}
const withdrawCase = () => {
// ç¼–辑案例
const handleEdit = () => {
  uni.navigateTo({
    url: `/pages/case/CaseDetails?id=${caseId.value}&edit=true`
  })
}
// åˆ é™¤æ¡ˆä¾‹
const handleDelete = () => {
  uni.showModal({
    title: '确认撤回',
    content: '确定要撤回这个捐献案例吗?',
    success: (res) => {
    title: '确认删除',
    content: `确定要删除案例 ${caseDetail.value.caseNo} å—?`,
    success: async (res) => {
      if (res.confirm) {
        uni.showToast({ title: '撤回成功', icon: 'success' })
        setTimeout(() => {
          uni.navigateBack()
        }, 1500)
        try {
          const result = await uni.$uapi.delete(`/project/donatebaseinforeport/${caseId.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' })
        }
      }
    }
  })
}
const contactCoordinator = () => {
  uni.makePhoneCall({
    phoneNumber: '13800138000'
// åˆ›å»ºè½¬è¿å•
const createTransport = () => {
  if (caseDetail.value.reportStatus !== '3') {
    uni.showToast({ title: '案例需先审批同意', icon: 'none' })
    return
  }
  uni.navigateTo({
    url: `/pages/transport/create?caseId=${caseId.value}&caseNo=${caseDetail.value.caseNo}`
  })
}
const loadCaseDetail = (id) => {
  // æ¨¡æ‹ŸAPI调用
  console.log('加载案例详情:', id)
// æŸ¥çœ‹è½¬è¿å•详情
const viewTransportDetail = () => {
  if (hasTransport.value && caseDetail.value.serviceTransport[0]) {
    const transport = caseDetail.value.serviceTransport[0]
    uni.navigateTo({
      url: `/pages/transport/detail?id=${transport.id}`
    })
  }
}
</script>
@@ -227,6 +596,7 @@
  min-height: 100vh;
  background: linear-gradient(135deg, #fafdff 0%, #e3f0ff 100%);
  padding: 20rpx;
  padding-bottom: 120rpx; /* ä¸ºæ“ä½œæ ç•™å‡ºç©ºé—´ */
}
.header-card {
@@ -255,6 +625,7 @@
  height: 80rpx;
  border-radius: 16rpx;
  margin-right: 20rpx;
  background: #f5f5f7;
}
.hospital-details {
@@ -267,6 +638,10 @@
  font-weight: 600;
  color: #1d1d1f;
  margin-bottom: 8rpx;
  max-width: 400rpx;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.case-type {
@@ -293,6 +668,11 @@
  &.agreed {
    background: rgba(52, 199, 89, 0.1);
    color: #34c759;
  }
  &.rejected {
    background: rgba(255, 59, 48, 0.1);
    color: #ff3b30;
  }
}
@@ -327,10 +707,17 @@
  padding: 8rpx;
  margin-bottom: 30rpx;
  box-shadow: 0 4px 16px 0 rgba(0, 0, 0, 0.05);
  overflow-x: auto;
  white-space: nowrap;
  &::-webkit-scrollbar {
    display: none;
  }
}
.tab-item {
  flex: 1;
  min-width: 140rpx;
  text-align: center;
  padding: 20rpx;
  font-size: 28rpx;
@@ -391,15 +778,20 @@
    font-size: 28rpx;
    color: #1d1d1f;
    font-weight: 500;
    word-break: break-all;
  }
}
.info-content {
  .info-group {
    margin-bottom: 32rpx;
    padding-bottom: 20rpx;
    border-bottom: 1rpx solid #f0f0f0;
    
    &:last-child {
      margin-bottom: 0;
      padding-bottom: 0;
      border-bottom: none;
    }
  }
  
@@ -408,6 +800,7 @@
    color: #86868b;
    margin-bottom: 12rpx;
    display: block;
    font-weight: 500;
  }
  
  .group-content {
@@ -417,70 +810,118 @@
  }
}
.process-timeline {
  position: relative;
  padding-left: 40rpx;
/* è½¬è¿ä¿¡æ¯æ ·å¼ */
.transport-info {
  .info-group {
    border: 2rpx solid #f0f0f0;
    border-radius: 12rpx;
    padding: 20rpx;
    margin-bottom: 20rpx;
    background: #fafafa;
    &:last-child {
      margin-bottom: 0;
    }
  }
  
  &::before {
    content: '';
    position: absolute;
    left: 15rpx;
    top: 0;
    bottom: 0;
    width: 2rpx;
    background: #e5e5e7;
  .sub-group {
    display: flex;
    margin-bottom: 12rpx;
    align-items: center;
    &:last-child {
      margin-bottom: 0;
    }
  }
  .sub-label {
    font-size: 26rpx;
    color: #606266;
    min-width: 160rpx;
    margin-right: 10rpx;
  }
  .sub-value {
    font-size: 26rpx;
    color: #303133;
    flex: 1;
    &.status {
      padding: 4rpx 12rpx;
      border-radius: 6rpx;
      font-size: 24rpx;
      &.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;
      }
    }
  }
  .empty-transport {
    text-align: center;
    padding: 40rpx 0;
    color: #909399;
    font-size: 28rpx;
  }
}
.timeline-item {
  position: relative;
  margin-bottom: 40rpx;
  &:last-child {
    margin-bottom: 0;
  }
}
.timeline-marker {
  position: absolute;
  left: -40rpx;
  top: 8rpx;
  width: 32rpx;
  height: 32rpx;
  border-radius: 50%;
  background: #e5e5e7;
  border: 4rpx solid #fff;
  box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
  &.active {
    background: #007aff;
  }
}
.timeline-content {
  padding-bottom: 20rpx;
}
.step-title {
  display: block;
  font-size: 28rpx;
  font-weight: 600;
  color: #1d1d1f;
  margin-bottom: 8rpx;
}
.step-time, .step-person {
  display: block;
/* å°åž‹æŒ‰é’® */
.small-btn {
  padding: 8rpx 20rpx;
  font-size: 24rpx;
  color: #86868b;
  margin-bottom: 4rpx;
  border-radius: 6rpx;
  border: none;
  &.primary {
    background: #007aff;
    color: #fff;
  }
  &.secondary {
    background: #ecf5ff;
    color: #007aff;
    border: 1rpx solid #007aff;
  }
  &:active {
    opacity: 0.8;
  }
}
.action-bar {
  display: flex;
  gap: 20rpx;
  padding: 40rpx 0;
  background: transparent;
  padding: 20rpx 0;
  background: #fff;
  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;
}
.action-btn {
@@ -509,6 +950,24 @@
      transform: scale(0.98);
    }
  }
  &.success {
    background: linear-gradient(90deg, #34c759 0%, #4cd964 100%);
    color: #fff;
    &:active {
      transform: scale(0.98);
    }
  }
  &.error {
    background: linear-gradient(90deg, #ff3b30 0%, #ff5a5a 100%);
    color: #fff;
    &:active {
      transform: scale(0.98);
    }
  }
}
.fade-in-up {
pages/case/index.vue
@@ -77,7 +77,7 @@
          </view>
          <text
            class="status"
            :class="caseItem.reportStatus.replace('ed', '')"
            :class="getStatusClass(caseItem.reportStatus)"
            >{{ caseItem.statusText }}</text
          >
        </view>
@@ -197,15 +197,6 @@
              åˆ›å»ºè½¬è¿å•
            </button>
            <!-- éœ€è½¬è¿ä½†æœªåŒæ„ -->
            <button
              v-if="caseItem.isTransport == '2' && !hasTransport(caseItem)"
              class="transport-btn disabled"
              disabled
            >
              éœ€å…ˆåŒæ„æ¡ˆä¾‹
            </button>
            <!-- æœ‰è½¬è¿å•可查看 -->
            <button
              v-if="hasTransport(caseItem)"
@@ -233,7 +224,7 @@
          <view class="actions">
            <button
              class="action-btn"
              v-if="caseItem.reportStatus != '1'"
              v-if="caseItem.reportStatus == '1' || caseItem.reportStatus == '2'"
              @tap.stop="withdrawCase(caseItem)"
            >
              æ’¤å›ž
@@ -243,7 +234,7 @@
            </button>
            <button
              class="action-btn secondary"
              v-if="caseItem.reportStatus != '1'"
              v-if="caseItem.reportStatus == '1' || caseItem.reportStatus == '2'"
              @tap.stop="editCase(caseItem)"
            >
              ç¼–辑
@@ -253,19 +244,19 @@
      </view>
      <!-- åŠ è½½æ›´å¤š -->
      <view class="load-more" v-if="hasMore">
        <text>加载中...</text>
      <view class="load-more" v-if="loadingMore">
        <u-loading-icon text="加载中..."></u-loading-icon>
      </view>
      <!-- æ— æ›´å¤šæ•°æ® -->
      <view class="no-more" v-if="!hasMore && filteredCases.length > 0">
        <text>已加载全部数据</text>
      </view>
      <!-- ç©ºçŠ¶æ€ -->
      <view class="empty-state" v-if="!loading && filteredCases.length == 0">
        <image src="/static/empty/no-case.png" mode="aspectFit" />
        <text>暂无器官捐献案例记录</text>
      </view>
      <!-- åŠ è½½çŠ¶æ€ -->
      <view class="empty-state" v-if="loading">
        <text>数据加载中...</text>
      </view>
    </scroll-view>
@@ -286,17 +277,25 @@
        </view>
      </view>
    </view>
    <!-- åŠ è½½çŠ¶æ€ -->
    <u-loading-page v-if="initLoading" :loading="true" text="数据加载中..." />
  </view>
   <view class="float-button" @tap="createNewCase">
    <u-icon name="plus" color="#fff" size="24"></u-icon>
  </view>
</template>
<script setup>
import { ref, computed, onMounted } from "vue";
import { onLoad, onShow } from "@dcloudio/uni-app";
import { onLoad, onShow, onReachBottom } from "@dcloudio/uni-app";
import { useDict } from "@/utils/dict";
// å“åº”式数据
const dict = ref({});
const loading = ref(false);
const initLoading = ref(false);
const loadingMore = ref(false);
const cases = ref([]);
const total = ref(0);
const pageNum = ref(1);
@@ -324,22 +323,6 @@
  };
  const statusInfo = statusMap[apiData.reportStatus] || statusMap["1"];
  // è½¬è¿çŠ¶æ€æ˜ å°„
  const getTransportStatusClass = (caseData) => {
    if (!hasTransport(caseData)) {
      return "not-transported";
    }
    const status = getTransportStatus(caseData);
    const map = {
      1: "pending",
      2: "transporting",
      3: "completed",
      4: "cancelled",
      5: "draft",
    };
    return map[status] || "pending";
  };
  return {
    id: apiData.id || apiData.donatebaseinfoReportId,
@@ -393,14 +376,15 @@
};
// è½¬è¿åˆ¤æ–­æ–¹æ³• - ä¸ŽPC端保持一致
const hasTransport = (caseData) => {
  console.log(caseData.serviceTransport);
  return caseData.serviceTransport;
  return caseData.serviceTransport && caseData.serviceTransport.length > 0;
};
const createNewCase = () => {
  uni.navigateTo({
    url: '/pages/case/CaseDetails'
  });
};
const canCreateTransport = (caseData) => {
  return (
    caseData.status == "3" && // å·²åŒæ„
    (caseData.isTransport == "2" || caseData.isTransport == 2) && // éœ€è¦è½¬è¿
    !hasTransport(caseData)
  ); // æ— è½¬è¿å•
@@ -489,22 +473,30 @@
// åŽŸæœ‰çš„è½¬è¿æ“ä½œæ–¹æ³•ä¿æŒä¸å˜
const createTransportOrder = (caseItem) => {
  uni.navigateTo({
    url: `/pages/transport/create?caseId=${caseItem.id}&caseNo=${caseItem.donorNo}`,
    url: `/pages/case/transferinfo?caseId=${caseItem.id}&caseNo=${caseItem.donorNo}`,
  });
};
const getStatusClass = (status) => {
  const map = {
    '1': 'reported',     // å·²ä¸ŠæŠ¥
    '2': 'read',         // å·²é˜…读
    '3': 'agreed',       // å·²åŒæ„
    '4': 'rejected'      // å·²é©³å›ž
  };
  return map[status] || 'reported';
}
const viewTransportDetail = (caseItem) => {
  if (hasTransport(caseItem)) {
    const transport = caseItem.serviceTransport[0];
    uni.navigateTo({
      url: `/pages/transport/detail?orderNo=${transport.id}`,
      url: `/pages/case/transferinfo?id=${transport.id}`,
    });
  }
};
// ç­›é€‰ç›¸å…³
const caseTypes = [
  { label: "全部", value: "" },
  { label: "全部", value: "all" },
  { label: "已上报", value: "1" },
  { label: "已阅读", value: "2" },
  { label: "已同意", value: "3" },
@@ -513,17 +505,6 @@
const currentType = ref("all");
const startDate = ref("");
const endDate = ref("");
// è½¬è¿çŠ¶æ€æ˜ å°„
const transportStatusMap = {
  not_transported: {
    text: "未转运",
    color: "warning",
    class: "not-transported",
  },
  transporting: { text: "转运中", color: "primary", class: "transporting" },
  completed: { text: "已完成", color: "success", class: "completed" },
};
// ç”Ÿå‘½å‘¨æœŸ
onLoad(async (options) => {
@@ -539,6 +520,12 @@
  await loadInitialData();
});
onReachBottom(() => {
  if (hasMore.value && !loading.value && !loadingMore.value) {
    onLoadMore();
  }
});
onShow(() => {
  const transportUpdate = uni.getStorageSync("transportStatusUpdate");
  if (transportUpdate) {
@@ -549,46 +536,90 @@
// æ•°æ®åŠ è½½å‡½æ•°
const loadInitialData = async () => {
  loading.value = true;
  initLoading.value = true;
  try {
    await Promise.all([donatebaseinforeportList(), donateTotal()]);
    await Promise.all([donatebaseinforeportList(true), donateTotal()]);
  } catch (error) {
    console.error("初始化数据失败:", error);
  } finally {
    loading.value = false;
    initLoading.value = false;
  }
};
// èŽ·å–æ¡ˆä¾‹åˆ—è¡¨
const donatebaseinforeportList = async () => {
const donatebaseinforeportList = async (reset = false) => {
  if (reset) {
    pageNum.value = 1;
    hasMore.value = true;
  }
  if (loading.value || loadingMore.value || !hasMore.value) return;
  if (reset) {
    loading.value = true;
  } else {
    loadingMore.value = true;
  }
  try {
    const params = {
      pageNum: pageNum.value,
      pageSize: pageSize.value,
    };
    // ç­›é€‰æ¡ä»¶ - å¦‚果选择了"全部",不传reportStatus参数
    if (currentType.value !== "all") {
      params.reportStatus = currentType.value;
    }
    // æ—¶é—´ç­›é€‰æ¡ä»¶
    if (startDate.value && endDate.value) {
      // å°†æ—¶é—´æ ¼å¼è½¬æ¢ä¸ºæŽ¥å£éœ€è¦çš„æ ¼å¼
      params.startDate = startDate.value;
      params.endDate = endDate.value;
    }
    console.log("请求参数:", params);
    const res = await uni.$uapi.post(
      "/project/donatebaseinforeport/list",
      params,
    );
    console.log(res, "res");
    const mappedData = res.map((item) => mapApiDataToCaseItem(item));
    if (pageNum.value == 1) {
      cases.value = mappedData;
    console.log("接口返回数据:", res);
    if (res.code == 200) {
      const data =res.data || [];
      const mappedData = data.map((item) => mapApiDataToCaseItem(item));
      if (reset || pageNum.value == 1) {
        console.log(mappedData,'mappedData');
        cases.value = mappedData;
      } else {
        cases.value = [...cases.value, ...mappedData];
      }
      // åˆ¤æ–­æ˜¯å¦è¿˜æœ‰æ›´å¤šæ•°æ®
      hasMore.value = data.length >= pageSize.value;
      total.value = res.total || 0;
      // å¦‚果有数据加载成功,增加页码
      if (data.length > 0) {
        pageNum.value++;
      }
    } else {
      cases.value = [...cases.value, ...mappedData];
      throw new Error(res.msg || "加载失败");
    }
    hasMore.value = pageNum.value * pageSize.value < res.total;
    total.value = res.total;
  } catch (error) {
    console.error("获取案例列表失败:", error);
    uni.showToast({
      title: "网络请求失败",
      icon: "none",
    });
  } finally {
    loading.value = false;
    loadingMore.value = false;
  }
};
@@ -596,62 +627,73 @@
const donateTotal = async () => {
  try {
    const res = await uni.$uapi.post("/project/donatebaseinforeport/getTotal");
    stats.value = {
      totalCases: res["1"] || 0,
      readCases: res["2"] || 0,
      agreedCases: res["3"] || 0,
    };
    if (res.code === 200) {
      stats.value = {
        totalCases: res.data["all"] || 0,
        readCases: res.data["2"] || 0,
        agreedCases: res.data["3"] || 0,
      };
    } else {
      throw new Error(res.msg || "获取统计失败");
    }
  } catch (error) {
    console.error("获取统计数据失败:", error);
  }
};
// è®¡ç®—属性:筛选记录
// è®¡ç®—属性:筛选记录 - çŽ°åœ¨åªåšå‰ç«¯çŠ¶æ€ç­›é€‰
const filteredCases = computed(() => {
  let result = cases.value;
  if (currentType.value !== "all") {
    result = result.filter(
      (caseItem) => caseItem.reportStatus == currentType.value,
    );
  }
  if (startDate.value && endDate.value) {
    result = result.filter((caseItem) => {
      const caseDate = caseItem.reportTime.split(" ")[0];
      return caseDate >= startDate.value && caseDate <= endDate.value;
    });
  }
  // åªåšå‰ç«¯çŠ¶æ€ç­›é€‰ï¼Œæ—¶é—´ç­›é€‰å·²ç»é€šè¿‡æŽ¥å£å®žçŽ°
  // if (currentType.value !== "all") {
  //   result = result.filter(
  //     (caseItem) => caseItem.reportStatus == currentType.value,
  //   );
  // }
  return result;
});
// äº‹ä»¶å¤„理函数
const selectType = (type) => {
  currentType.value = type;
  // é‡ç½®åˆ†é¡µï¼Œé‡æ–°åŠ è½½æ•°æ®
  pageNum.value = 1;
  donatebaseinforeportList(true);
};
const onStartDateChange = (e) => {
  startDate.value = e.detail.value;
  // å¦‚果结束日期已选择,立即触发筛选
  if (endDate.value) {
    pageNum.value = 1;
    donatebaseinforeportList(true);
  }
};
const onEndDateChange = (e) => {
  endDate.value = e.detail.value;
  // å¦‚果开始日期已选择,立即触发筛选
  if (startDate.value) {
    pageNum.value = 1;
    donatebaseinforeportList(true);
  }
};
// åˆ·æ–°å’ŒåŠ è½½æ›´å¤š
const onRefresh = async () => {
  refreshing.value = true;
  pageNum.value = 1;
  await donatebaseinforeportList();
  await donatebaseinforeportList(true);
  await donateTotal();
  setTimeout(() => {
    refreshing.value = false;
  }, 1000);
};
const onLoadMore = async () => {
  if (!hasMore.value || loading.value) return;
  pageNum.value += 1;
  if (!hasMore.value || loading.value || loadingMore.value) return;
  await donatebaseinforeportList();
};
@@ -679,19 +721,36 @@
  showWithdrawModal.value = true;
};
const confirmWithdraw = () => {
  const index = cases.value.findIndex(
    (item) => item.id == currentCase.value.id,
  );
  if (index !== -1) {
    cases.value.splice(index, 1);
    stats.value.totalCases -= 1;
const confirmWithdraw = async () => {
  try {
    const res = await uni.$uapi.delete(`/project/donatebaseinforeport/${currentCase.value.id}`);
    if (res.code === 200) {
      // ä»Žåˆ—表中移除
      const index = cases.value.findIndex(
        (item) => item.id == currentCase.value.id
      );
      if (index !== -1) {
        cases.value.splice(index, 1);
        stats.value.totalCases -= 1;
      }
      uni.showToast({
        title: "撤回成功",
        icon: "success",
      });
    } else {
      throw new Error(res.msg || "撤回失败");
    }
  } catch (error) {
    console.error("撤回失败:", error);
    uni.showToast({
      title: "撤回成功",
      icon: "success",
      title: "撤回失败,请重试",
      icon: "none",
    });
  } finally {
    showWithdrawModal.value = false;
  }
  showWithdrawModal.value = false;
};
const cancelWithdraw = () => {
@@ -1072,6 +1131,14 @@
      }
    }
  }
  .load-more, .no-more {
    text-align: center;
    padding: 40rpx 0;
    color: $text-secondary;
    font-size: 28rpx;
  }
  .empty-state {
    padding: 120rpx 0;
    text-align: center;
@@ -1156,4 +1223,25 @@
    }
  }
}
</style>
/* æµ®åŠ¨æŒ‰é’®æ ·å¼ */
.float-button {
  position: fixed;
  bottom: 120rpx;
  right: 40rpx;
  width: 100rpx;
  height: 100rpx;
  background: $primary-color;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 8rpx 20rpx rgba($primary-color, 0.3);
  z-index: 100;
  transition: all 0.3s ease;
  &:active {
    opacity: 0.8;
    transform: scale(0.95);
  }
}
</style>
pages/case/transfer.vue
@@ -24,7 +24,7 @@
        <text
          v-for="(type, index) in transportTypes"
          :key="index"
          :class="{ active: currentType === type.value }"
          :class="{ active: currentType == type.value }"
          @tap="selectType(type.value)"
          >{{ type.label }}</text
        >
@@ -70,61 +70,68 @@
        <view class="header">
          <view class="case-info">
            <view class="info">
              <text class="case-no">{{ item.caseNo }}</text>
              <text class="case-no">{{ item.caseNo || item.reportId }}</text>
              <text class="patient"
                >{{ item.donorName }} | {{ item.gender }} |
                >{{ item.patName }} | {{ getGenderText(item.sex) }} |
                {{ item.age }}岁</text
              >
            </view>
          </view>
          <text class="status" :class="item.status">{{ item.statusText }}</text>
          <text class="status" :class="getStatusClass(item.transitStatus)">{{
            getStatusText(item.transitStatus)
          }}</text>
        </view>
        <view class="detail-info">
          <view class="info-item">
            <text class="label">疾病诊断</text>
            <text class="value">{{ item.diagnosis }}</text>
            <text class="value">{{ item.diagnosisname || "未填写" }}</text>
          </view>
          <view class="info-item">
            <text class="label">所在医疗机构</text>
            <text class="value">{{ item.hospitalName }}</text>
            <text class="value">{{
              item.treatmentHospitalName || "未填写"
            }}</text>
          </view>
          <view class="info-item">
            <text class="label">计划转运时间</text>
            <text class="value">{{ item.transportTime }}</text>
            <text class="value">{{ formatTime(item.transportStartTime) }}</text>
          </view>
          <view class="info-item">
            <text class="label">负责协调员</text>
            <text class="value">{{ item.coordinator }}</text>
            <text class="value">{{ item.contactPerson || "未指定" }}</text>
          </view>
          <view class="info-item">
            <text class="label">创建时间</text>
            <text class="value">{{ item.createTime }}</text>
            <text class="value">{{ formatTime(item.createTime) }}</text>
          </view>
        </view>
        <view class="footer">
          <view class="action-info">
            <text class="label">转运状态</text>
            <text class="transport-status">{{ item.statusText }}</text>
            <text class="transport-status">{{
              getStatusText(item.transitStatus)
            }}</text>
          </view>
          <view class="actions">
            <button
              class="action-btn"
              v-if="item.status === 'pending'"
              v-if="item.transitStatus === 1"
              @tap.stop="startTransport(item)"
            >
              å¼€å§‹è½¬è¿
            </button>
            <button
              class="action-btn"
              v-if="item.status === 'transporting'"
              v-if="item.transitStatus === 2"
              @tap.stop="completeTransport(item)"
            >
              å®Œæˆè½¬è¿
            </button>
            <button
              class="action-btn secondary"
              v-if="item.transitStatus != 3"
              @tap.stop="editTransport(item)"
            >
              ç¼–辑
@@ -137,12 +144,20 @@
      </view>
      <!-- åŠ è½½æ›´å¤š -->
      <view class="load-more" v-if="hasMore">
        <text>加载中...</text>
      <view class="load-more" v-if="loadingMore">
        <u-loading-icon text="加载中..."></u-loading-icon>
      </view>
      <!-- æ— æ›´å¤šæ•°æ® -->
      <view class="no-more" v-if="!hasMore && filteredTransports.length > 0">
        <text>已加载全部数据</text>
      </view>
      <!-- ç©ºçŠ¶æ€ -->
      <view class="empty-state" v-if="filteredTransports.length === 0">
      <view
        class="empty-state"
        v-if="!loading && filteredTransports.length === 0"
      >
        <image src="/static/empty/no-transport.png" mode="aspectFit" />
        <text>暂无转运单记录</text>
      </view>
@@ -166,154 +181,210 @@
        </view>
      </view>
    </view>
    <!-- åŠ è½½çŠ¶æ€ -->
    <u-loading-page v-if="initLoading" :loading="true" text="数据加载中..." />
    <!-- æµ®åŠ¨æŒ‰é’® -->
    <!-- <view class="float-button" @tap="createTransport">
      <u-icon name="plus" color="#fff" size="24"></u-icon>
    </view> -->
  </view>
</template>
<script setup>
import { ref, computed } from "vue";
import { onLoad } from "@dcloudio/uni-app";
import { ref, computed, onMounted } from "vue";
import { onLoad, onShow, onReachBottom } from "@dcloudio/uni-app";
import { useDict } from "@/utils/dict";
// å­—典数据
const dict = ref({});
// ç»Ÿè®¡æ•°æ®
const stats = ref({
  totalTransports: 12,
  pendingTransports: 4,
  completedTransports: 6,
  totalTransports: 0,
  pendingTransports: 0,
  completedTransports: 0,
});
// è½¬è¿å•数据
const transports = ref([]);
const loading = ref(false);
const initLoading = ref(false);
const loadingMore = ref(false);
const refreshing = ref(false);
const hasMore = ref(true);
const pageNum = ref(1);
const pageSize = ref(10);
// æ“ä½œç¡®è®¤å¼¹çª—相关
const showActionModal = ref(false);
const currentTransport = ref({});
const modalTitle = ref("");
const modalAction = ref("");
onLoad(async (options) => {
  // åˆå§‹åŒ–数据
  loadTransports();
});
// ç­›é€‰ç›¸å…³
const transportTypes = [
  { label: "全部", value: "all" },
  { label: "待出发", value: "pending" },
  { label: "转运中", value: "transporting" },
  { label: "已完成", value: "completed" },
  { label: "已取消", value: "cancelled" },
  { label: "全部", value: "" },
  { label: "待转运", value: 1 },
  { label: "转运中", value: 2 },
  { label: "已完成", value: 3 },
  { label: "已取消", value: 4 },
  { label: "暂存", value: 5 },
];
const currentType = ref("all");
const currentType = ref("");
const startDate = ref("");
const endDate = ref("");
// è½¬è¿å•数据
const transports = ref([
  {
    id: "T20241217001",
    caseNo: "DON20241216001",
    donorName: "张三",
    gender: "男",
    age: 38,
    diagnosis: "脑外伤导致脑死亡",
    hospitalName: "青岛镜湖医院",
    transportTime: "2024-12-17 14:30",
    coordinator: "张医生",
    createTime: "2024-12-16 09:30",
    status: "pending",
    statusText: "待出发",
    departureLocation: "青岛市立医院急诊科",
    destinationHospital: "青岛镜湖医院",
  },
  {
    id: "T20241217002",
    caseNo: "DON20241216002",
    donorName: "李四",
    gender: "女",
    age: 45,
    diagnosis: "脑梗死",
    hospitalName: "青岛大学附属医院",
    transportTime: "2024-12-17 16:00",
    coordinator: "李医生",
    createTime: "2024-12-16 11:20",
    status: "transporting",
    statusText: "转运中",
    departureLocation: "青岛大学附属医院ICU",
    destinationHospital: "青岛器官移植中心",
  },
  {
    id: "T20241216003",
    caseNo: "DON20241215001",
    donorName: "王五",
    gender: "男",
    age: 52,
    diagnosis: "心脏骤停",
    hospitalName: "青岛市立医院",
    transportTime: "2024-12-16 10:15",
    coordinator: "王医生",
    createTime: "2024-12-15 14:45",
    status: "completed",
    statusText: "已完成",
    departureLocation: "青岛市立医院心内科",
    destinationHospital: "青岛器官移植中心",
  },
  {
    id: "T20241216004",
    caseNo: "DON20241214001",
    donorName: "赵六",
    gender: "女",
    age: 29,
    diagnosis: "急性肝衰竭",
    hospitalName: "青岛科大医院",
    transportTime: "2024-12-16 08:30",
    coordinator: "赵医生",
    createTime: "2024-12-14 16:20",
    status: "cancelled",
    statusText: "已取消",
    departureLocation: "青岛科大医院消化科",
    destinationHospital: "青岛器官移植中心",
  },
]);
onLoad(async (options) => {
  // èŽ·å–å­—å…¸æ•°æ®
  dict.value = await useDict("sys_user_sex");
  // åˆå§‹åŒ–数据
  await loadInitialData();
});
// ç­›é€‰è®°å½•
onReachBottom(() => {
  if (hasMore.value && !loading.value && !loadingMore.value) {
    onLoadMore();
  }
});
onShow(() => {
  // æ£€æŸ¥æ˜¯å¦æœ‰è½¬è¿çŠ¶æ€æ›´æ–°
  const update = uni.getStorageSync("transportStatusUpdate");
  if (update) {
    handleStatusUpdate(update);
    uni.removeStorageSync("transportStatusUpdate");
  }
});
// æ•°æ®æ˜ å°„函数
const mapApiDataToTransportItem = (apiData) => {
  return {
    id: apiData.id,
    reportId: apiData.reportId,
    caseNo: apiData.caseNo,
    patName: apiData.patName,
    sex: apiData.sex,
    age: apiData.age,
    diagnosisname: apiData.diagnosisname,
    treatmentHospitalName: apiData.treatmentHospitalName,
    transportStartTime: apiData.transportStartTime,
    contactPerson: apiData.contactPerson,
    createTime: apiData.createTime,
    transitStatus: apiData.transitStatus,
    // åŒ»æŠ¤äººå‘˜ä¿¡æ¯
    doctor: apiData.doctor,
    nurse: apiData.nurse,
    driver: apiData.driver,
    // å…¶ä»–字段
    transportStartPlace: apiData.transportStartPlace,
    remark: apiData.remark,
  };
};
// è®¡ç®—属性:筛选记录
const filteredTransports = computed(() => {
  let result = transports.value;
  // çŠ¶æ€ç­›é€‰
  if (currentType.value !== "all") {
    result = result.filter((item) => item.status === currentType.value);
  // å‰ç«¯çŠ¶æ€ç­›é€‰
  if (currentType.value !== "") {
    result = result.filter((item) => item.transitStatus === currentType.value);
  }
  // æ—¥æœŸç­›é€‰
  if (startDate.value && endDate.value) {
    result = result.filter((item) => {
      const transportDate = item.createTime.split(" ")[0];
      return transportDate >= startDate.value && transportDate <= endDate.value;
    });
  }
  return result;
});
// åˆ†é¡µç›¸å…³
const hasMore = ref(true);
const refreshing = ref(false);
// èŽ·å–çŠ¶æ€æ ·å¼
const getStatusClass = (status) => {
  const map = {
    1: "pending", // å¾…转运
    2: "transporting", // è½¬è¿ä¸­
    3: "completed", // å·²å®Œæˆ
    4: "cancelled", // å·²å–消
    5: "cancelled", // æš‚å­˜
  };
  return map[status] || "pending";
};
// èŽ·å–çŠ¶æ€æ–‡æœ¬
const getStatusText = (status) => {
  const map = {
    1: "待出发",
    2: "转运中",
    3: "已完成",
    4: "已取消",
    5: "暂存",
  };
  return map[status] || "未知";
};
// èŽ·å–æ€§åˆ«æ–‡æœ¬
const getGenderText = (gender) => {
  if (!gender) return "未知";
  if (!dict.value.sys_user_sex) return gender;
  const genderItem = dict.value.sys_user_sex.find(
    (item) => item.dictValue === gender,
  );
  return genderItem ? genderItem.dictLabel : gender;
};
// æ ¼å¼åŒ–æ—¶é—´
const formatTime = (timeStr) => {
  if (!timeStr) return "未设置";
  return timeStr.replace("T", " ").substring(0, 16);
};
// é€‰æ‹©ç±»åž‹
const selectType = (type) => {
  currentType.value = type;
  // é‡ç½®åˆ†é¡µï¼Œé‡æ–°åŠ è½½æ•°æ®
  pageNum.value = 1;
  loadTransports(true);
};
// æ—¥æœŸé€‰æ‹©
const onStartDateChange = (e) => {
  startDate.value = e.detail.value;
  // å¦‚果结束日期已选择,立即触发筛选
  if (endDate.value) {
    pageNum.value = 1;
    loadTransports(true);
  }
};
const onEndDateChange = (e) => {
  endDate.value = e.detail.value;
  // å¦‚果开始日期已选择,立即触发筛选
  if (startDate.value) {
    pageNum.value = 1;
    loadTransports(true);
  }
};
// æŸ¥çœ‹è¯¦æƒ…
const viewDetail = (item) => {
  viewDetails(item);
};
// æŸ¥çœ‹è¯¦æƒ…
const viewDetails = (item) => {
  uni.navigateTo({
    url: `/pages/transport/detail?id=${item.id}`,
    url: `/pages/case/transferinfo?id=${item.id}`,
  });
};
// ç¼–辑转运单
const editTransport = (item) => {
  uni.navigateTo({
    url: `/pages/case/transferinfo?id=${item.id}&edit=true`,
  });
};
// åˆ›å»ºè½¬è¿å•
const createTransport = () => {
  uni.navigateTo({
    url: '/pages/transport/create'
  });
};
@@ -334,27 +405,27 @@
};
// ç¡®è®¤æ“ä½œ
const confirmAction = () => {
  const index = transports.value.findIndex(
    (item) => item.id === currentTransport.value.id
  );
  if (index !== -1) {
const confirmAction = async () => {
  try {
    if (modalAction.value === "开始") {
      transports.value[index].status = "transporting";
      transports.value[index].statusText = "转运中";
      stats.value.pendingTransports -= 1;
      await updateTransportStatus(2, "开始转运");
    } else if (modalAction.value === "完成") {
      transports.value[index].status = "completed";
      transports.value[index].statusText = "已完成";
      stats.value.completedTransports += 1;
      await updateTransportStatus(3, "完成转运");
    }
    uni.showToast({
      title: `${modalAction.value}成功`,
      icon: "success",
    });
  } catch (error) {
    console.error(`${modalAction.value}失败:`, error);
    uni.showToast({
      title: `${modalAction.value}失败,请重试`,
      icon: "none",
    });
  } finally {
    showActionModal.value = false;
  }
  showActionModal.value = false;
};
// å–消操作
@@ -362,42 +433,181 @@
  showActionModal.value = false;
};
// æŸ¥çœ‹è¯¦æƒ…
const viewDetails = (item) => {
  uni.navigateTo({
    url: `/pages/case/transferinfo?id=${item.id}`,
  });
};
// ç¼–辑转运单
const editTransport = (item) => {
  uni.navigateTo({
    url: `/pages/case/transferinfo?id=${item.id}`,
  });
// æ•°æ®åŠ è½½å‡½æ•°
const loadInitialData = async () => {
  initLoading.value = true;
  try {
    await Promise.all([loadTransports(true), loadStats()]);
  } catch (error) {
    console.error("初始化数据失败:", error);
  } finally {
    initLoading.value = false;
  }
};
// ä¸‹æ‹‰åˆ·æ–°
const onRefresh = () => {
const onRefresh = async () => {
  refreshing.value = true;
  loadTransports();
  pageNum.value = 1;
  await loadTransports(true);
  await loadStats();
  setTimeout(() => {
    refreshing.value = false;
  }, 1000);
};
// åŠ è½½æ›´å¤š
const onLoadMore = () => {
  if (!hasMore.value) return;
  loadTransports();
const onLoadMore = async () => {
  if (!hasMore.value || loading.value || loadingMore.value) return;
  await loadTransports();
};
// åŠ è½½è®°å½•
const loadTransports = async () => {
// åŠ è½½è½¬è¿å•åˆ—è¡¨
const loadTransports = async (reset = false) => {
  if (reset) {
    pageNum.value = 1;
    hasMore.value = true;
  }
  if (loading.value || loadingMore.value || !hasMore.value) return;
  if (reset) {
    loading.value = true;
  } else {
    loadingMore.value = true;
  }
  try {
    const params = {
      pageNum: pageNum.value,
      pageSize: pageSize.value,
    };
    // ç­›é€‰æ¡ä»¶
    if (currentType.value !== "") {
      params.transitStatus = currentType.value;
    }
    // æ—¶é—´ç­›é€‰æ¡ä»¶
    if (startDate.value && endDate.value) {
      params.startDate = startDate.value;
      params.endDate = endDate.value;
    }
    console.log("请求参数:", params);
    const res = await uni.$uapi.post("/project/transport/list", params);
    console.log("接口返回数据:", res);
    if (res && res.code === 200) {
      // å¤„理不同的数据结构
      let data = [];
      if (res.rows && Array.isArray(res.rows)) {
        data = res.rows;
      } else if (res.data && Array.isArray(res.data)) {
        data = res.data;
      } else if (Array.isArray(res)) {
        data = res;
      } else {
        console.error("接口返回格式不正确:", res);
        throw new Error("接口返回格式不正确");
      }
      const mappedData = data.map((item) => mapApiDataToTransportItem(item));
      if (reset || pageNum.value === 1) {
        transports.value = mappedData;
      } else {
        transports.value = [...transports.value, ...mappedData];
      }
      // åˆ¤æ–­æ˜¯å¦è¿˜æœ‰æ›´å¤šæ•°æ®
      hasMore.value = data.length >= pageSize.value;
      // å¦‚果有数据加载成功,增加页码
      if (data.length > 0) {
        pageNum.value++;
      }
    } else {
      throw new Error(res?.msg || "加载失败");
    }
  } catch (error) {
    console.error("加载转运单列表失败:", error);
    uni.showToast({
      title: "网络请求失败",
      icon: "none",
    });
  } finally {
    loading.value = false;
    loadingMore.value = false;
  }
};
  // è¿™é‡Œè°ƒç”¨API加载数据
  setTimeout(() => {
    hasMore.value = false;
  }, 1000);
// åŠ è½½ç»Ÿè®¡æ•°æ®
const loadStats = async () => {
  try {
    const res = await uni.$uapi.post("/api/totalServiceTransportState");
    if (res.data) {
      stats.value = {
        totalTransports:
          res.data.reduce((sum, item) => sum + item.count, 0) || 0,
        pendingTransports: res.data[0].count || 0,
        completedTransports: res.data[3].count || 0,
      };
    }
  } catch (error) {
    console.error("加载统计失败:", error);
  }
};
// æ›´æ–°è½¬è¿çŠ¶æ€
const updateTransportStatus = async (newStatus, actionName) => {
  try {
    const updateData = {
      id: currentTransport.value.id,
      transitStatus: newStatus,
    };
    const res = await uni.$uapi.post("/project/transport/edit", updateData);
    if (res && res.code === 200) {
      // æ›´æ–°æœ¬åœ°æ•°æ®
      const index = transports.value.findIndex(
        (item) => item.id === currentTransport.value.id,
      );
      if (index !== -1) {
        transports.value[index].transitStatus = newStatus;
      }
      // æ›´æ–°ç»Ÿè®¡æ•°æ®
      await loadStats();
      // å­˜å‚¨çŠ¶æ€æ›´æ–°
      uni.setStorageSync("transportStatusUpdate", {
        orderId: currentTransport.value.id,
        status: newStatus,
      });
      return true;
    } else {
      throw new Error(res?.msg || `${actionName}失败`);
    }
  } catch (error) {
    console.error(`${actionName}失败:`, error);
    throw error;
  }
};
// å¤„理状态更新
const handleStatusUpdate = (update) => {
  const index = transports.value.findIndex(
    (item) => item.id === update.orderId,
  );
  if (index !== -1) {
    transports.value[index].transitStatus = update.status;
  }
};
</script>
@@ -405,6 +615,7 @@
.transport-record {
  min-height: 100vh;
  background: linear-gradient(135deg, #fafdff 0%, #e3f0ff 100%);
  padding-bottom: 100rpx;
  .stats-card {
    margin: 20rpx;
@@ -675,6 +886,13 @@
      }
    }
    .load-more, .no-more {
      text-align: center;
      padding: 40rpx 0;
      color: #86868b;
      font-size: 28rpx;
    }
    .empty-state {
      padding: 120rpx 0;
      text-align: center;
@@ -767,5 +985,27 @@
      }
    }
  }
  /* æµ®åŠ¨æŒ‰é’® */
  .float-button {
    position: fixed;
    bottom: 100rpx;
    right: 40rpx;
    width: 100rpx;
    height: 100rpx;
    background: #0071e3;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 8rpx 20rpx rgba(0, 113, 227, 0.3);
    z-index: 100;
    transition: all 0.3s ease;
    &:active {
      opacity: 0.8;
      transform: scale(0.95);
    }
  }
}
</style>
</style>
pages/case/transferinfo.vue
@@ -3,217 +3,269 @@
    <!-- è¡¨å•内容 -->
    <scroll-view scroll-y class="form-scroll" :show-scrollbar="false">
      <view class="form-content">
        <!-- æ¡ˆä¾‹ä¿¡æ¯å¡ç‰‡ -->
        <view class="form-section" v-if="transportData.reportId">
          <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">
          <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 +273,56 @@
        <!-- æ“ä½œæŒ‰é’® -->
        <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>
    <attachment-upload
      ref="attachment"
      :files="attachments"
      :readonly="isReadonly"
      :maxCount="5"
      @update:files="handleFilesUpdate"
      @upload-base="handleBaseUpload"
      @preview="handlePreview"
    />
    <!-- æ—¶é—´é€‰æ‹©å™¨ -->
    <u-datetime-picker
      :show="showTimePicker"
      v-model="departureTimeValue"
@@ -247,385 +332,496 @@
      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 attachmentUpload from "@/components/attachment";
import { useUserStore } from "@/stores/user";
// è¡¨å•数据
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: ''
})
import { onLoad } from "@dcloudio/uni-app";
// é€‰æ‹©å™¨çŠ¶æ€
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 dict = ref({});
// é€‰é¡¹æ•°æ®
const caseOptions = ref([
  {
    label: '张三 - è„‘外伤导致脑死亡 - é’岛镜湖医院',
    value: 'DON20241216001',
    data: {
      donorName: '张三',
      gender: '男',
      age: '38',
      diagnosis: '脑外伤导致脑死亡',
      hospital: '青岛镜湖医院'
    }
  },
  {
    label: '李四 - è„‘梗死 - é’岛大学附属医院',
    value: 'DON20241216002',
    data: {
      donorName: '李四',
      gender: '女',
      age: '45',
      diagnosis: '脑梗死',
      hospital: '青岛大学附属医院'
    }
  }
])
// æ•°æ®
const transportData = ref({
  annexfilesList: [], // é™„件文件地址集合
});
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 isReadonly = ref(false);
const attachments = ref([]);
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 statusOptions = ref([
  { label: "待转运", value: 1 },
  { label: "转运中", value: 2 },
  { label: "转运完成", value: 3 },
  { label: "转运取消", value: 4 },
  { label: "暂存", value: 5 },
]);
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.get(`/project/transport/getInfo/${id}`);
const handleSubmit = async () => {
  if (!validateForm()) return
    if (res.data) {
      transportData.value = res.data;
        if (res.data.annexfilesList) {
           attachments.value = res.data.annexfilesList;
        attachments.value.forEach(item=>{
          item.url=item.opath,
          item.name=item.fileName
        })
        }
    } 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.get(
        `/project/donatebaseinforeport/getInfo/${caseId}`,
      );
      if (res.data) {
        const caseData = res.data;
        console.log(caseData);
        transportData.value = {
          ...transportData.value,
          caseNo: caseData.caseNo || "",
          patName: caseData.name || "",
          sex: caseData.sex || "",
          age: caseData.age || "",
          reportId: caseData.id || null,
          diagnosisname: caseData.diagnosisname || "",
          treatmentHospitalName: caseData.treatmenthospitalname || "",
          treatmentDeptName: caseData.treatmentdeptname || "",
          // å¯ä»¥è®¾ç½®ä¸€äº›é»˜è®¤å€¼
          transportStartPlace: caseData.treatmenthospitalname || "",
          contactPerson: caseData.coordinatorName || "",
        };
        console.log(transportData.value, "transportData.value");
      }
    } 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")}:${date
    .getSeconds()
    .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,
    // };
    const submitData = {
      ...transportData.value,
      annexfilesList: attachments.value.map((file) => ({
        path: file.url,
        fileName: file.name,
        type: file.type,
      })),
    };
    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
        try {
          await new Promise(resolve => setTimeout(resolve, 1500))
          await saveTransport('pending')
          uni.showToast({ title: '提交成功', icon: 'success' })
          setTimeout(() => {
            uni.navigateBack()
          }, 1500)
        } catch (error) {
          console.error('提交失败:', error)
          uni.showToast({ title: '提交失败,请重试', icon: 'none' })
        } finally {
          loading.value = false
        }
        await updateTransportStatus(2, "开始转运");
      }
    }
  })
}
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)
// å®Œæˆè½¬è¿
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,
      ...transportData.value,
       annexfilesList: attachments.value.map((file) => ({
        path: file.url,
        fileName: file.name,
        type: file.type,
      })),
    };
    const res = await uni.$uapi.post("/project/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 handleBaseUpload = (file) => {
  console.log("基础附件上传成功:", 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,
  }));
  console.log(attachments.value);
};
// é¢„览文件 - ä¿®æ”¹ä¸ºä½¿ç”¨å®Œæ•´URL
const handlePreview = (file) => {
  const fullUrl = file.url.startsWith("http")
    ? file.url
    : baseUrlHt + (file.url.startsWith("/") ? "" : "/") + file.url;
  if (file.type.includes("image")) {
    uni.previewImage({
      urls: attachments.value
        .filter((f) => f.type.includes("image"))
        .map((f) =>
          f.url.startsWith("http")
            ? f.url
            : baseUrlHt + (f.url.startsWith("/") ? "" : "/") + f.url,
        ),
      current: fullUrl,
    });
  } else if (file.type.includes("pdf")) {
    uni.downloadFile({
      url: fullUrl,
      success: (res) => {
        uni.openDocument({
          filePath: res.tempFilePath,
          fileType: "pdf",
          showMenu: true,
        });
      },
      fail: (err) => {
        console.error("打开文档失败:", err);
        uni.showToast({ title: "打开文件失败", icon: "none" });
      },
    });
  } else {
    uni.showToast({ title: "暂不支持此文件类型预览", icon: "none" });
  }
};
</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 +838,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 +927,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 +975,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: 9;
}
.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>
unpackage/dist/cache/.vite/deps/_metadata.json
@@ -1,13 +1,13 @@
{
  "hash": "6bd4bfe4",
  "hash": "02d31505",
  "configHash": "878f8b71",
  "lockfileHash": "91f3418f",
  "browserHash": "376444c4",
  "lockfileHash": "e59b7d0b",
  "browserHash": "95fcf7a4",
  "optimized": {
    "dayjs/esm/index": {
      "src": "../../../../../node_modules/dayjs/esm/index.js",
      "file": "dayjs_esm_index.js",
      "fileHash": "6282f232",
      "fileHash": "318c5b84",
      "needsInterop": false
    }
  },
utils/dict.js
@@ -16,7 +16,7 @@
    } else {
      try {
        const resp = await uni.$uapi.get("/system/dict/data/type/" + dictType);
        res.value[dictType] = resp.map(p => ({
        res.value[dictType] = resp.data.map(p => ({
          label: p.dictLabel,
          value: p.dictValue,
          elTagType: p.listClass,
@@ -29,7 +29,7 @@
      }
    }
  }
  console.log(res.value.sys_user_sex,'2');
  // console.log(res.value.sys_user_sex,'2');
  
  return toRefs(res.value);
}
utils/request.js
@@ -6,35 +6,34 @@
 */
const showToast = (message) => {
  if (uni.$u?.toast) {
    uni.$u.toast(message)
    uni.$u.toast(message);
  } else {
    uni.showToast({
      title: message,
      icon: 'none'
    })
      icon: "none",
    });
  }
}
};
// åŸºç¡€é…ç½® - ä»ŽçŽ¯å¢ƒå˜é‡ä¸­èŽ·å–baseURL
const config = {
  baseURL: '/api', // ä½¿ç”¨çŽ¯å¢ƒå˜é‡ä¸­çš„é…ç½®
  baseURL: "/api", // ä½¿ç”¨çŽ¯å¢ƒå˜é‡ä¸­çš„é…ç½®
  timeout: 60000,
  header: {
    'Content-Type': 'application/json',
    'X-Business-System': 'medical-system',
    "Content-Type": "application/json",
    "X-Business-System": "medical-system",
  },
  // æ–°å¢žé…ç½®é¡¹
  loginPage: '/pages/login/Login', // ç™»å½•页路径
  loginPage: "/pages/login/Login", // ç™»å½•页路径
  tokenExpiredCode: 401, // åŽç«¯è¿”回的Token过期状态码
  noPermissionCode: 403, // æ— æƒé™çŠ¶æ€ç 
  // æ·»åŠ ç™½åå•é…ç½®ï¼ˆä¸éœ€è¦æ ¡éªŒtoken的接口)
  whiteList: [
    '/login', // ç™»å½•接口
    "/login", // ç™»å½•接口
    // '/dingtalk/auth/login', // é’‰é’‰æŽˆæƒç™»å½•接口
    // '/dingtalk/auth/bind' // é’‰é’‰æŽˆæƒç™»å½•绑定接口
  ]
}
  ],
};
/**
 * æ£€æŸ¥è¯·æ±‚是否在白名单中
@@ -42,33 +41,36 @@
 */
const isInWhiteList = (url) => {
  // æå–相对路径(移除baseURL)并忽略查询参数
  const relativeUrl = url.replace(config.baseURL, '').split('?')[0];
  return config.whiteList.some(path => {
  const relativeUrl = url.replace(config.baseURL, "").split("?")[0];
  return config.whiteList.some((path) => {
    // å¤„理通配符情况
    if (path.endsWith('/')) {
      return relativeUrl.startsWith(path)
    if (path.endsWith("/")) {
      return relativeUrl.startsWith(path);
    }
    // ç²¾ç¡®åŒ¹é…è·¯å¾„
    return relativeUrl === path
  })
}
    return relativeUrl === path;
  });
};
/**
 * è·³è½¬åˆ°ç™»å½•页
 */
const navigateToLogin = () => {
  uni.redirectTo({
    url: config.loginPage + '?redirect=' + encodeURIComponent(getCurrentPagePath())
  })
}
    url:
      config.loginPage +
      "?redirect=" +
      encodeURIComponent(getCurrentPagePath()),
  });
};
/**
 * èŽ·å–å½“å‰é¡µé¢è·¯å¾„ï¼ˆç”¨äºŽç™»å½•åŽè·³å›žï¼‰
 */
const getCurrentPagePath = () => {
  const pages = getCurrentPages()
  return pages[pages.length - 1]?.route || ''
}
  const pages = getCurrentPages();
  return pages[pages.length - 1]?.route || "";
};
/**
 * æ£€æŸ¥Token是否过期
@@ -76,72 +78,72 @@
 */
const checkTokenExpired = (statusCode) => {
  if (statusCode === config.tokenExpiredCode) {
    showToast('登录已过期,请重新登录')
    navigateToLogin()
    return true
    showToast("登录已过期,请重新登录");
    navigateToLogin();
    return true;
  }
  return false
}
  return false;
};
/**
 * è¯·æ±‚拦截器
 */
const requestInterceptor = (options) => {
  const token = uni.getStorageSync('token')
  const token = uni.getStorageSync("token");
  // å¦‚果请求在白名单中,直接放行
  if (isInWhiteList(options.url)) {
    return options
    return options;
  }
  // å¦‚果未登录且不是白名单接口,跳转登录
  console.log(token,'token');
  // console.log(token,'token');
  if (!token) {
    navigateToLogin()
    throw new Error('未登录')
    navigateToLogin();
    throw new Error("未登录");
  }
  // æ·»åŠ Token到Header
  options.header = {
    ...options.header,
    'Authorization': `Bearer ${token}`
  }
  return options
}
    Authorization: `Bearer ${token}`,
  };
  return options;
};
/**
 * å“åº”拦截器
 */
const responseInterceptor = (response) => {
  const { statusCode, data } = response
  const { statusCode, data } = response;
  // Token过期处理
  if (checkTokenExpired(statusCode)) {
    return Promise.reject(data)
    return Promise.reject(data);
  }
  // æ— æƒé™å¤„理
  if (statusCode === config.noPermissionCode) {
    showToast('无权限访问')
    return Promise.reject(data)
    showToast("无权限访问");
    return Promise.reject(data);
  }
  // å…¶ä»–错误状态码
  if (statusCode !== 200) {
    showToast(`请求失败: ${statusCode}`)
    return Promise.reject(data)
    showToast(`请求失败: ${statusCode}`);
    return Promise.reject(data);
  }
  // æŽ¥å£è‡ªå®šä¹‰é”™è¯¯ç å¤„理(假设data.code为0表示成功)
  if (data?.code !== 200) {
    showToast(data?.msg || '操作失败')
    return Promise.reject(data)
    showToast(data?.msg || "操作失败");
    return Promise.reject(data);
  }
  return data.data || data // è¿”回实际业务数据
}
  return data; // è¿”回实际业务数据
};
/**
 * æ ¸å¿ƒè¯·æ±‚方法
@@ -153,58 +155,58 @@
      ...config,
      ...options,
      url: config.baseURL + options.url,
      header: { ...config.header, ...options.header }
    }
      header: { ...config.header, ...options.header },
    };
    // è¯·æ±‚拦截
    options = await requestInterceptor(options)
    options = await requestInterceptor(options);
    // å‘起请求
    return new Promise((resolve, reject) => {
      uni.request({
        ...options,
        success: (res) => {
          resolve(responseInterceptor(res))
          resolve(responseInterceptor(res));
        },
        fail: (err) => {
          showToast('网络错误,请重试')
          reject(err)
        }
      })
    })
          showToast("网络错误,请重试");
          reject(err);
        },
      });
    });
  } catch (err) {
    return Promise.reject(err)
    return Promise.reject(err);
  }
}
};
// å¿«æ·æ–¹æ³•封装
const http = {
  get(url, data = {}, options = {}) {
    return request({ url, data, method: 'GET', ...options })
    return request({ url, data, method: "GET", ...options });
  },
  post(url, data = {}, options = {}) {
    return request({ url, data, method: 'POST', ...options })
    return request({ url, data, method: "POST", ...options });
  },
  put(url, data = {}, options = {}) {
    return request({ url, data, method: 'PUT', ...options })
    return request({ url, data, method: "PUT", ...options });
  },
  delete(url, data = {}, options = {}) {
    return request({ url, data, method: 'DELETE', ...options })
    return request({ url, data, method: "DELETE", ...options });
  },
  // æ–°å¢žï¼šä¸Šä¼ æ–‡ä»¶æ–¹æ³•
  upload(url, filePath, name = 'file', formData = {}) {
  upload(url, filePath, name = "file", formData = {}) {
    return request({
      url,
      method: 'POST',
      method: "POST",
      filePath,
      name,
      formData,
      header: { 'Content-Type': 'multipart/form-data' }
    })
  }
}
      header: { "Content-Type": "multipart/form-data" },
    });
  },
};
// æŒ‚载到全局
uni.$uapi = http
uni.$uapi = http;
export default http
export default http;