From 64af1aa70e1893b7b12f267c363a6c8f3e569343 Mon Sep 17 00:00:00 2001 From: "2358328281@qq.com" <邮箱地址> Date: Tue, 30 Jun 2026 19:19:04 +0800 Subject: [PATCH] =?UTF-8?q?=E8=BF=9B=E5=BA=A6=E4=BF=9D=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jsconfig.json | 14 +- package-lock.json | 401 +++++- package.json | 7 +- src/assets/image/admin/accounts/add.svg | 6 + src/assets/image/admin/orders/dhhf.svg | 7 + src/assets/image/admin/orders/jnpjl.svg | 14 + src/assets/image/admin/orders/no.svg | 19 + src/assets/image/admin/orders/pxjl.svg | 7 + src/assets/image/admin/orders/xcxj.svg | 9 + src/assets/image/admin/orders/yes.svg | 18 + src/assets/image/admin/reports/pdf-icon.svg | 16 + .../image/admin/reports/report-bg-light.svg | 9 + src/assets/image/admin/reports/report-bg.svg | 9 + src/assets/image/admin/reports/summery-bg.svg | 9 + src/assets/image/admin/reports/word-icon.svg | 10 + src/assets/image/admin/score/complaint.svg | 5 + src/assets/image/admin/score/huifang.svg | 7 + src/assets/image/admin/score/inspector.svg | 9 + .../image/admin/score/manager-count.svg | 18 + src/assets/image/admin/score/service.svg | 5 + .../image/admin/score/success-count.svg | 18 + .../image/admin/score/success-ratio.svg | 18 + src/assets/image/admin/score/total.svg | 18 + src/assets/image/admin/score/train.svg | 5 + src/assets/style/admin-common.scss | 183 +++ src/assets/style/common.scss | 21 +- src/components/layout/AdminLayout.vue | 16 +- src/composables/useReportDocxExport.ts | 250 ++++ src/composables/useReportPdfExport.ts | 194 +++ src/service/modular/admin/index.js | 99 ++ src/stores/api/hospital.js | 38 + .../accounts/components/AccountEditDialog.vue | 448 +++++++ .../components/ResetPasswordDialog.vue | 102 ++ src/views/admin/accounts/list.vue | 242 ++-- .../components/HospitalDetailDialog.vue | 205 +-- .../components/HospitalEditDialog.vue | 91 +- .../components/MaintenanceDetailDialog.vue | 192 +++ .../components/MonthlyViewDialog.vue | 395 ++++++ .../components/ServiceRecordDialog.vue | 696 ++++++++++ src/views/admin/hospitals/list.vue | 235 ++-- src/views/admin/hospitals/service.vue | 511 +++++-- .../orders/components/OrderFormDialog.vue | 375 +++--- .../orders/components/OrderHandleDialog.vue | 2 +- .../orders/components/ReportDetailDialog.vue | 1192 +++++++++++++++++ .../components/ReportDownloadDialog.vue | 163 +++ .../components/ReportGenerateDialog.vue | 198 +++ .../orders/components/ReportRemarkDialog.vue | 124 ++ src/views/admin/orders/list.vue | 90 +- src/views/admin/orders/report.vue | 415 ++++-- src/views/admin/performance/score.vue | 715 ++++++++-- src/views/hospital/orders/OrderFormDialog.vue | 85 +- src/views/hospital/workbench.vue | 523 +++++--- 52 files changed, 7441 insertions(+), 1017 deletions(-) create mode 100644 src/assets/image/admin/accounts/add.svg create mode 100644 src/assets/image/admin/orders/dhhf.svg create mode 100644 src/assets/image/admin/orders/jnpjl.svg create mode 100644 src/assets/image/admin/orders/no.svg create mode 100644 src/assets/image/admin/orders/pxjl.svg create mode 100644 src/assets/image/admin/orders/xcxj.svg create mode 100644 src/assets/image/admin/orders/yes.svg create mode 100644 src/assets/image/admin/reports/pdf-icon.svg create mode 100644 src/assets/image/admin/reports/report-bg-light.svg create mode 100644 src/assets/image/admin/reports/report-bg.svg create mode 100644 src/assets/image/admin/reports/summery-bg.svg create mode 100644 src/assets/image/admin/reports/word-icon.svg create mode 100644 src/assets/image/admin/score/complaint.svg create mode 100644 src/assets/image/admin/score/huifang.svg create mode 100644 src/assets/image/admin/score/inspector.svg create mode 100644 src/assets/image/admin/score/manager-count.svg create mode 100644 src/assets/image/admin/score/service.svg create mode 100644 src/assets/image/admin/score/success-count.svg create mode 100644 src/assets/image/admin/score/success-ratio.svg create mode 100644 src/assets/image/admin/score/total.svg create mode 100644 src/assets/image/admin/score/train.svg create mode 100644 src/assets/style/admin-common.scss create mode 100644 src/composables/useReportDocxExport.ts create mode 100644 src/composables/useReportPdfExport.ts create mode 100644 src/stores/api/hospital.js create mode 100644 src/views/admin/accounts/components/AccountEditDialog.vue create mode 100644 src/views/admin/accounts/components/ResetPasswordDialog.vue create mode 100644 src/views/admin/hospitals/components/MaintenanceDetailDialog.vue create mode 100644 src/views/admin/hospitals/components/MonthlyViewDialog.vue create mode 100644 src/views/admin/hospitals/components/ServiceRecordDialog.vue create mode 100644 src/views/admin/orders/components/ReportDetailDialog.vue create mode 100644 src/views/admin/orders/components/ReportDownloadDialog.vue create mode 100644 src/views/admin/orders/components/ReportGenerateDialog.vue create mode 100644 src/views/admin/orders/components/ReportRemarkDialog.vue diff --git a/jsconfig.json b/jsconfig.json index 4aafc5f..6a87a47 100644 --- a/jsconfig.json +++ b/jsconfig.json @@ -1,9 +1,11 @@ { "compilerOptions": { - "target": "es5", + "target": "esnext", "module": "esnext", "baseUrl": "./", "moduleResolution": "node", + "allowJs": true, + "checkJs": false, "paths": { "@/*": [ "src/*" @@ -15,5 +17,13 @@ "dom.iterable", "scripthost" ] - } + }, + "include": [ + "src/**/*", + "src/**/*.vue" + ], + "exclude": [ + "node_modules", + "dist" + ] } diff --git a/package-lock.json b/package-lock.json index b60613b..b9d7e75 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,8 +14,12 @@ "@wangeditor/editor-for-vue": "^5.1.12", "axios": "^1.13.2", "dayjs": "^1.11.21", + "docx": "^9.7.1", "echarts": "^6.0.0", "element-plus": "^2.11.8", + "file-saver": "^2.0.5", + "html2canvas": "^1.4.1", + "jspdf": "^4.2.1", "pinia": "^3.0.4", "pinia-plugin-persistedstate": "^4.7.1", "qs": "^6.12.1", @@ -26,6 +30,7 @@ "vue-router": "^4.6.3" }, "devDependencies": { + "@types/file-saver": "^2.0.7", "@vitejs/plugin-vue": "^6.0.1", "fast-glob": "^3.3.3", "sass-embedded": "^1.93.3", @@ -67,9 +72,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", - "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz", + "integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -1604,6 +1609,13 @@ "integrity": "sha512-zx2/Gg0Eg7gwEiOIIh5w9TrhKKTeQh7CPCOPNc0el4pLSwzebA8SmnHwZs2dWlLONvyulykSwGSQxQHLhjGLvQ==", "license": "MIT" }, + "node_modules/@types/file-saver": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/file-saver/-/file-saver-2.0.7.tgz", + "integrity": "sha512-dNKVfHd/jk0SkR/exKGj2ggkB45MAkzvWCaqLUUgkyjITkGNzH8H+yUwr+BLJUBjZOe9w8X3wgmXhZDRg1ED6A==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/lodash": { "version": "4.17.20", "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.20.tgz", @@ -1623,12 +1635,24 @@ "version": "25.6.0", "resolved": "https://registry.npmjs.org/@types/node/-/node-25.6.0.tgz", "integrity": "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ==", - "dev": true, "license": "MIT", "dependencies": { "undici-types": "~7.19.0" } }, + "node_modules/@types/pako": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/pako/-/pako-2.0.4.tgz", + "integrity": "sha512-VWDCbrLeVXJM9fihYodcLiIv0ku+AlOa/TQ1SvYOaBuyrSKgEcro95LJyIsJ4vSo6BXIxOKxiJAat04CmST9Fw==", + "license": "MIT" + }, + "node_modules/@types/raf": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/@types/raf/-/raf-3.4.3.tgz", + "integrity": "sha512-c4YAvMedbPZ5tEyxzQdMoOhhJ4RD3rngZIdwC2/qDN3d7JpEhB6fiBRKVY1lg5B7Wk+uPBjn5f39j1/2MY1oOw==", + "license": "MIT", + "optional": true + }, "node_modules/@types/svgo": { "version": "2.6.4", "resolved": "https://registry.npmjs.org/@types/svgo/-/svgo-2.6.4.tgz", @@ -1639,6 +1663,13 @@ "@types/node": "*" } }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "license": "MIT", + "optional": true + }, "node_modules/@types/web-bluetooth": { "version": "0.0.16", "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz", @@ -2294,6 +2325,15 @@ "node": ">=0.10.0" } }, + "node_modules/base64-arraybuffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", + "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/big.js": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", @@ -2426,6 +2466,26 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/canvg": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/canvg/-/canvg-3.0.11.tgz", + "integrity": "sha512-5ON+q7jCTgMp9cjpu4Jo6XbvfYwSB2Ow3kzHKfIyJfaCAOHLbdKPQqGKgfED/R5B+3TFFfe8pegYA+b423SRyA==", + "license": "MIT", + "optional": true, + "dependencies": { + "@babel/runtime": "^7.12.5", + "@types/raf": "^3.4.0", + "core-js": "^3.8.3", + "raf": "^3.4.1", + "regenerator-runtime": "^0.13.7", + "rgbcolor": "^1.0.1", + "stackblur-canvas": "^2.0.0", + "svg-pathdata": "^6.0.3" + }, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/chalk": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", @@ -2617,6 +2677,24 @@ "node": ">=0.10.0" } }, + "node_modules/core-js": { + "version": "3.49.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.49.0.tgz", + "integrity": "sha512-es1U2+YTtzpwkxVLwAFdSpaIMyQaq0PBgm3YD1W3Qpsn1NAmO3KSgZfu+oGSWVu6NvLHoHCV/aYcsE5wiB7ALg==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "license": "MIT" + }, "node_modules/cors": { "version": "2.8.6", "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz", @@ -2635,6 +2713,15 @@ "url": "https://opencollective.com/express" } }, + "node_modules/css-line-break": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz", + "integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==", + "license": "MIT", + "dependencies": { + "utrie": "^1.0.2" + } + }, "node_modules/css-select": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", @@ -2946,6 +3033,41 @@ "node": ">=0.10" } }, + "node_modules/docx": { + "version": "9.7.1", + "resolved": "https://registry.npmjs.org/docx/-/docx-9.7.1.tgz", + "integrity": "sha512-ilXFf9Moz47ABjFpDiA5s1w9lpb4EFSp7+5iiJSbfyYDM+bpZdAgLlSr7fW4aXhVe/E+F6QCv0EvRVFEd5CsWg==", + "license": "MIT", + "dependencies": { + "@types/node": "^25.2.3", + "hash.js": "^1.1.7", + "jszip": "^3.10.1", + "nanoid": "^5.1.3", + "xml": "^1.0.1", + "xml-js": "^1.6.8" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/docx/node_modules/nanoid": { + "version": "5.1.16", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.16.tgz", + "integrity": "sha512-kVrnsrJqMR8+oLJnGEmSWw9BivK5mt7H3FZatVRjrc5wGqFYuBxX1yG7+A7Gi5AefkX6t/oCkizcQgpu0cY1dQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.js" + }, + "engines": { + "node": "^18 || >=20" + } + }, "node_modules/dom-serializer": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", @@ -3006,6 +3128,16 @@ "domelementtype": "1" } }, + "node_modules/dompurify": { + "version": "3.4.11", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.11.tgz", + "integrity": "sha512-zhlUV12GsaRzMsf9q5M254YhA4+VuF0fG+QFqu6aYpoGlKtz+w8//jBcGVYBgQkR5GHjUomejY84AV+/uPbWdw==", + "license": "(MPL-2.0 OR Apache-2.0)", + "optional": true, + "optionalDependencies": { + "@types/trusted-types": "^2.0.7" + } + }, "node_modules/domutils": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", @@ -3481,6 +3613,17 @@ "node": ">=8.6.0" } }, + "node_modules/fast-png": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/fast-png/-/fast-png-6.4.0.tgz", + "integrity": "sha512-kAqZq1TlgBjZcLr5mcN6NP5Rv4V2f22z00c3g8vRrwkcqjerx7BEhPbOnWCPqaHUl2XWQBJQvOT/FQhdMT7X/Q==", + "license": "MIT", + "dependencies": { + "@types/pako": "^2.0.3", + "iobuffer": "^5.3.2", + "pako": "^2.1.0" + } + }, "node_modules/fastq": { "version": "1.20.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", @@ -3509,6 +3652,18 @@ } } }, + "node_modules/fflate": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.3.tgz", + "integrity": "sha512-tbZNuJrLwGUp3zshBtdy4W+ORxZuIh8a5ilyIEQDC5rY1f3U20JMry0Ll3WBzU58EZKsEuJFXhb5gwv8CsPvgA==", + "license": "MIT" + }, + "node_modules/file-saver": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.5.tgz", + "integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==", + "license": "MIT" + }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -3961,6 +4116,16 @@ "node": ">=0.10.0" } }, + "node_modules/hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", @@ -3999,6 +4164,19 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/html2canvas": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz", + "integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==", + "license": "MIT", + "dependencies": { + "css-line-break": "^2.1.0", + "text-segmentation": "^1.0.3" + }, + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/htmlparser2": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", @@ -4043,6 +4221,12 @@ "node": ">=0.10.0" } }, + "node_modules/immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", + "license": "MIT" + }, "node_modules/immer": { "version": "9.0.21", "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz", @@ -4064,7 +4248,6 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true, "license": "ISC" }, "node_modules/internal-slot": { @@ -4082,6 +4265,12 @@ "node": ">= 0.4" } }, + "node_modules/iobuffer": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/iobuffer/-/iobuffer-5.4.0.tgz", + "integrity": "sha512-DRebOWuqDvxunfkNJAlc3IzWIPD5xVxwUNbHr7xKB8E6aLJxIPfNX3CoMJghcFjpv6RWQsrcJbghtEwSPoJqMA==", + "license": "MIT" + }, "node_modules/is-accessor-descriptor": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.1.tgz", @@ -4586,7 +4775,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true, "license": "MIT" }, "node_modules/isobject": { @@ -4635,6 +4823,71 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/jspdf": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/jspdf/-/jspdf-4.2.1.tgz", + "integrity": "sha512-YyAXyvnmjTbR4bHQRLzex3CuINCDlQnBqoSYyjJwTP2x9jDLuKDzy7aKUl0hgx3uhcl7xzg32agn5vlie6HIlQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.6", + "fast-png": "^6.2.0", + "fflate": "^0.8.1" + }, + "optionalDependencies": { + "canvg": "^3.0.11", + "core-js": "^3.6.0", + "dompurify": "^3.3.1", + "html2canvas": "^1.0.0-rc.5" + } + }, + "node_modules/jszip": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", + "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", + "license": "(MIT OR GPL-3.0-or-later)", + "dependencies": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "setimmediate": "^1.0.5" + } + }, + "node_modules/jszip/node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "license": "(MIT AND Zlib)" + }, + "node_modules/jszip/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/jszip/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/jszip/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/kind-of": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", @@ -4645,6 +4898,15 @@ "node": ">=0.10.0" } }, + "node_modules/lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "license": "MIT", + "dependencies": { + "immediate": "~3.0.5" + } + }, "node_modules/loader-utils": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz", @@ -4860,6 +5122,12 @@ "node": ">= 0.6" } }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "license": "ISC" + }, "node_modules/minimist": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", @@ -5223,6 +5491,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/pako": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pako/-/pako-2.2.0.tgz", + "integrity": "sha512-zJq6RP/5q+TO2OpFV3FHzlPnFjmkb7Nc99a5SNjJE+uu/PkpChs+NIZSSzbBoD+6kjiISXjfYdwj1ZRQ81dz/w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "(MIT AND Zlib)" + }, "node_modules/pascalcase": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", @@ -5258,6 +5542,13 @@ "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", "license": "MIT" }, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", + "license": "MIT", + "optional": true + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -5467,6 +5758,12 @@ "node": ">=6" } }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "license": "MIT" + }, "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", @@ -5523,6 +5820,16 @@ ], "license": "MIT" }, + "node_modules/raf": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", + "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", + "license": "MIT", + "optional": true, + "dependencies": { + "performance-now": "^2.1.0" + } + }, "node_modules/readable-stream": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", @@ -5576,6 +5883,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", + "license": "MIT", + "optional": true + }, "node_modules/regex-not": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", @@ -5693,6 +6007,16 @@ "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", "license": "MIT" }, + "node_modules/rgbcolor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/rgbcolor/-/rgbcolor-1.0.1.tgz", + "integrity": "sha512-9aZLIrhRaD97sgVhtJOW6ckOEh6/GnvQtdVNfdZ6s67+3/XwLS9lBcQYzEEhYVeUowN7pRzMLsyGhK2i/xvWbw==", + "license": "MIT OR SEE LICENSE IN FEEL-FREE.md", + "optional": true, + "engines": { + "node": ">= 0.8.15" + } + }, "node_modules/rollup": { "version": "4.53.2", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.2.tgz", @@ -6244,7 +6568,6 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.0.tgz", "integrity": "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==", - "dev": true, "license": "BlueOak-1.0.0", "engines": { "node": ">=11.0.0" @@ -6324,6 +6647,12 @@ "node": ">=0.10.0" } }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "license": "MIT" + }, "node_modules/side-channel": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", @@ -6676,6 +7005,16 @@ "dev": true, "license": "MIT" }, + "node_modules/stackblur-canvas": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/stackblur-canvas/-/stackblur-canvas-2.7.0.tgz", + "integrity": "sha512-yf7OENo23AGJhBriGx0QivY5JP6Y1HbrrDI6WLt6C5auYZXlQrheoY8hD4ibekFKz1HOfE48Ww8kMWMnJD/zcQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.1.14" + } + }, "node_modules/static-extend": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", @@ -7035,6 +7374,16 @@ "node": ">=0.10.0" } }, + "node_modules/svg-pathdata": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/svg-pathdata/-/svg-pathdata-6.0.3.tgz", + "integrity": "sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/svgo": { "version": "2.8.2", "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.2.tgz", @@ -7080,6 +7429,15 @@ "node": ">=16.0.0" } }, + "node_modules/text-segmentation": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz", + "integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==", + "license": "MIT", + "dependencies": { + "utrie": "^1.0.2" + } + }, "node_modules/tiny-warning": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", @@ -7364,7 +7722,6 @@ "version": "7.19.2", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.19.2.tgz", "integrity": "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg==", - "dev": true, "license": "MIT" }, "node_modules/union-value": { @@ -7477,9 +7834,17 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true, "license": "MIT" }, + "node_modules/utrie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz", + "integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==", + "license": "MIT", + "dependencies": { + "base64-arraybuffer": "^1.0.2" + } + }, "node_modules/varint": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz", @@ -7772,6 +8137,24 @@ "integrity": "sha512-DXukZJxpHA8LuotRwL0pP1+rS6CS7FF2qStDDE1C7DDg2rLud2PXRMuEDYIPhgEezwnlHNL4c+N6MfMTjCGTng==", "license": "MIT" }, + "node_modules/xml": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz", + "integrity": "sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==", + "license": "MIT" + }, + "node_modules/xml-js": { + "version": "1.6.11", + "resolved": "https://registry.npmjs.org/xml-js/-/xml-js-1.6.11.tgz", + "integrity": "sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==", + "license": "MIT", + "dependencies": { + "sax": "^1.2.4" + }, + "bin": { + "xml-js": "bin/cli.js" + } + }, "node_modules/zrender": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/zrender/-/zrender-6.0.0.tgz", diff --git a/package.json b/package.json index 837ef1b..8c41354 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "type": "module", "scripts": { "dev": "vite", - "build": "vite build", + "build": "node --max-old-space-size=8192 node_modules/vite/bin/vite.js build", "preview": "vite preview" }, "dependencies": { @@ -15,8 +15,12 @@ "@wangeditor/editor-for-vue": "^5.1.12", "axios": "^1.13.2", "dayjs": "^1.11.21", + "docx": "^9.7.1", "echarts": "^6.0.0", "element-plus": "^2.11.8", + "file-saver": "^2.0.5", + "html2canvas": "^1.4.1", + "jspdf": "^4.2.1", "pinia": "^3.0.4", "pinia-plugin-persistedstate": "^4.7.1", "qs": "^6.12.1", @@ -27,6 +31,7 @@ "vue-router": "^4.6.3" }, "devDependencies": { + "@types/file-saver": "^2.0.7", "@vitejs/plugin-vue": "^6.0.1", "fast-glob": "^3.3.3", "sass-embedded": "^1.93.3", diff --git a/src/assets/image/admin/accounts/add.svg b/src/assets/image/admin/accounts/add.svg new file mode 100644 index 0000000..9ea3141 --- /dev/null +++ b/src/assets/image/admin/accounts/add.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/assets/image/admin/orders/dhhf.svg b/src/assets/image/admin/orders/dhhf.svg new file mode 100644 index 0000000..40a8f51 --- /dev/null +++ b/src/assets/image/admin/orders/dhhf.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/assets/image/admin/orders/jnpjl.svg b/src/assets/image/admin/orders/jnpjl.svg new file mode 100644 index 0000000..b870c39 --- /dev/null +++ b/src/assets/image/admin/orders/jnpjl.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/assets/image/admin/orders/no.svg b/src/assets/image/admin/orders/no.svg new file mode 100644 index 0000000..85a044b --- /dev/null +++ b/src/assets/image/admin/orders/no.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/image/admin/orders/pxjl.svg b/src/assets/image/admin/orders/pxjl.svg new file mode 100644 index 0000000..5af1367 --- /dev/null +++ b/src/assets/image/admin/orders/pxjl.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/assets/image/admin/orders/xcxj.svg b/src/assets/image/admin/orders/xcxj.svg new file mode 100644 index 0000000..05e8b0b --- /dev/null +++ b/src/assets/image/admin/orders/xcxj.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/assets/image/admin/orders/yes.svg b/src/assets/image/admin/orders/yes.svg new file mode 100644 index 0000000..50dbb72 --- /dev/null +++ b/src/assets/image/admin/orders/yes.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/assets/image/admin/reports/pdf-icon.svg b/src/assets/image/admin/reports/pdf-icon.svg new file mode 100644 index 0000000..77dd87f --- /dev/null +++ b/src/assets/image/admin/reports/pdf-icon.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/src/assets/image/admin/reports/report-bg-light.svg b/src/assets/image/admin/reports/report-bg-light.svg new file mode 100644 index 0000000..695a975 --- /dev/null +++ b/src/assets/image/admin/reports/report-bg-light.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/assets/image/admin/reports/report-bg.svg b/src/assets/image/admin/reports/report-bg.svg new file mode 100644 index 0000000..83363e0 --- /dev/null +++ b/src/assets/image/admin/reports/report-bg.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/assets/image/admin/reports/summery-bg.svg b/src/assets/image/admin/reports/summery-bg.svg new file mode 100644 index 0000000..ac29ad1 --- /dev/null +++ b/src/assets/image/admin/reports/summery-bg.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/assets/image/admin/reports/word-icon.svg b/src/assets/image/admin/reports/word-icon.svg new file mode 100644 index 0000000..0a03b6b --- /dev/null +++ b/src/assets/image/admin/reports/word-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/assets/image/admin/score/complaint.svg b/src/assets/image/admin/score/complaint.svg new file mode 100644 index 0000000..f6aeccd --- /dev/null +++ b/src/assets/image/admin/score/complaint.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/assets/image/admin/score/huifang.svg b/src/assets/image/admin/score/huifang.svg new file mode 100644 index 0000000..8762a1c --- /dev/null +++ b/src/assets/image/admin/score/huifang.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/assets/image/admin/score/inspector.svg b/src/assets/image/admin/score/inspector.svg new file mode 100644 index 0000000..8ea9c8d --- /dev/null +++ b/src/assets/image/admin/score/inspector.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/assets/image/admin/score/manager-count.svg b/src/assets/image/admin/score/manager-count.svg new file mode 100644 index 0000000..309ac52 --- /dev/null +++ b/src/assets/image/admin/score/manager-count.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/assets/image/admin/score/service.svg b/src/assets/image/admin/score/service.svg new file mode 100644 index 0000000..c860b38 --- /dev/null +++ b/src/assets/image/admin/score/service.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/assets/image/admin/score/success-count.svg b/src/assets/image/admin/score/success-count.svg new file mode 100644 index 0000000..602de28 --- /dev/null +++ b/src/assets/image/admin/score/success-count.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/assets/image/admin/score/success-ratio.svg b/src/assets/image/admin/score/success-ratio.svg new file mode 100644 index 0000000..7abe319 --- /dev/null +++ b/src/assets/image/admin/score/success-ratio.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/assets/image/admin/score/total.svg b/src/assets/image/admin/score/total.svg new file mode 100644 index 0000000..4c6a558 --- /dev/null +++ b/src/assets/image/admin/score/total.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/assets/image/admin/score/train.svg b/src/assets/image/admin/score/train.svg new file mode 100644 index 0000000..99bbe7f --- /dev/null +++ b/src/assets/image/admin/score/train.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/assets/style/admin-common.scss b/src/assets/style/admin-common.scss new file mode 100644 index 0000000..5bcd420 --- /dev/null +++ b/src/assets/style/admin-common.scss @@ -0,0 +1,183 @@ +$primaryBlue: #2a7bfa; +$primaryLightBlue: #3289fb; + +// ========================================================== +// 管理后台通用页面样式(orders / hospitals / accounts 等复用) +// 全部规则加 !important,避免被 el-table / 全局样式覆盖。 +// ========================================================== + +// 业务页面外层卡片(圆角 + 边框 + 内边距) +.admin-page-card { + background: #ffffff !important; + border-radius: 16px !important; + border: 1px solid #e0e0e0 !important; + padding: 24px !important; + + // 表格主题(与 order-list 中一致): + // - 隐藏 el-table 外层伪元素边框,仅保留 cell 之间的分隔线 + // - 表头浅色背景 + 中等字重 + .admin-table { + border-radius: 12px !important; + border: 1px solid #e0e0e0 !important; + overflow: hidden !important; + + &::before, + &::after { + display: none !important; + } + + .el-table__inner-wrapper::before, + .el-table__inner-wrapper::after { + display: none !important; + } + + .admin-table-header-cell { + background: #f9faff !important; + font-weight: 500 !important; + font-size: 14px !important; + color: #666666 !important; + line-height: 18px !important; + } + } + + // 过滤表单(按钮右对齐最后一项) + .admin-filter-form { + margin-bottom: 16px !important; + display: flex !important; + flex-wrap: wrap !important; + gap: 12px !important; + align-items: center !important; + + .el-form-item, + .el-button { + margin: 0 !important; + } + + .el-button:last-child { + margin-left: auto !important; + } + } + + // 分页器 + .admin-pagination { + margin-top: 16px !important; + display: flex !important; + justify-content: flex-end !important; + } +} + +// ========================================================== +// 详情区块(label / value 行展示) +// ========================================================== +.admin-detail-block { + .detail-row + .detail-row { + margin-top: 15px !important; + } + + .detail-row { + display: grid !important; + gap: 15px !important; + + &.row-1 { + grid-template-columns: 1fr !important; + } + + &.row-2 { + grid-template-columns: repeat(2, 1fr) !important; + } + + &.row-3 { + grid-template-columns: repeat(3, 1fr) !important; + } + + &.row-4 { + grid-template-columns: repeat(4, 1fr) !important; + } + + .detail-item { + display: flex !important; + align-items: center !important; + gap: 10px !important; + + .label { + font-weight: 400 !important; + font-size: 14px !important; + color: #1d2129 !important; + width: 4em !important; + overflow: hidden !important; + text-overflow: ellipsis !important; + white-space: nowrap !important; + flex-shrink: 0 !important; + flex-grow: 0 !important; + } + + .value { + flex-shrink: 1 !important; + flex-grow: 1 !important; + font-weight: 400 !important; + font-size: 14px !important; + color: #666666 !important; + padding: 10px !important; + background: #f8f8f8 !important; + border-radius: 8px !important; + border: 1px solid #e0e0e0 !important; + min-width: 0 !important; + } + } + } +} + +// 通用 plain 按钮 hover/active 重置(避免视觉变化),与订单列表保持一致 +.el-button.is-plain { + background-color: transparent !important; + --el-button-hover-bg-color: var(--el-button-bg-color) !important; + --el-button-hover-text-color: var(--el-button-text-color) !important; + --el-button-hover-border-color: var(--el-button-border-color) !important; + --el-button-active-bg-color: var(--el-button-bg-color) !important; + --el-button-active-text-color: var(--el-button-text-color) !important; + --el-button-active-border-color: var(--el-button-border-color) !important; +} + +.el-button { + font-weight: 500 !important; + font-size: 14px !important; + padding: 8px 30px !important; + line-height: 18px !important; + border-radius: 8px !important; + + &.smaller { + padding: 6px 15px !important; + } + + &.rosein-sign { + --el-button-border-color: #cb30e0 !important; + + &.is-plain { + --el-button-text-color: #cb30e0 !important; + } + } + + &.purple-sign { + --el-button-border-color: #6155f5 !important; + + &.is-plain { + --el-button-text-color: #6155f5 !important; + } + } + + &.blue-sign { + --el-button-border-color: #3289fb !important; + + &.is-plain { + --el-button-text-color: #3289fb !important; + } + } + + &.cyan-sign { + --el-button-border-color: #00c0e8 !important; + + &.is-plain { + --el-button-text-color: #00c0e8 !important; + } + } +} diff --git a/src/assets/style/common.scss b/src/assets/style/common.scss index 150c03b..253fc37 100644 --- a/src/assets/style/common.scss +++ b/src/assets/style/common.scss @@ -831,9 +831,10 @@ img { display: flex; justify-content: space-between; align-items: center; + margin-bottom: 18px; .body-title { - font-weight: normal; + font-weight: 600; font-size: 20px; color: #1d2129; } @@ -857,3 +858,21 @@ img { border-top: 1px solid #e0e0e0; } } + +.border-title { + display: flex; + align-items: center; + gap: 8px; + font-weight: 600; + font-size: 16px; + color: #1d2129; + + &::before { + content: ""; + display: block; + width: 4px; + height: 16px; + background: #3289fb; + border-radius: 2px 2px 2px 2px; + } +} diff --git a/src/components/layout/AdminLayout.vue b/src/components/layout/AdminLayout.vue index 26dfb5f..cbdc3bc 100644 --- a/src/components/layout/AdminLayout.vue +++ b/src/components/layout/AdminLayout.vue @@ -281,7 +281,7 @@ const handleCommand = async (cmd) => { width: 100vw; height: 100vh; background-color: #f9faff; - padding: 32px 32px 84px; + padding: 32px; gap: 23px; background-image: url("@/assets/image/layout-bg.svg"); background-repeat: no-repeat; @@ -410,7 +410,7 @@ const handleCommand = async (cmd) => { align-items: center; &:hover { - background-color: rgba(50, 137, 251, 0.08) !important; + // background-color: rgba(50, 137, 251, 0.08) !important; color: #3289fb !important; } } @@ -432,7 +432,8 @@ const handleCommand = async (cmd) => { .admin-content { flex: 1; - overflow: auto; + overflow-x: hidden; + overflow-y: auto; } } @@ -461,6 +462,15 @@ const handleCommand = async (cmd) => { + + diff --git a/src/views/admin/accounts/components/ResetPasswordDialog.vue b/src/views/admin/accounts/components/ResetPasswordDialog.vue new file mode 100644 index 0000000..2919d36 --- /dev/null +++ b/src/views/admin/accounts/components/ResetPasswordDialog.vue @@ -0,0 +1,102 @@ + + !v && close()"> + + + {{ $t('account.resetPassword') }} + + + + + + {{ $t('account.confirmReset', { id: ` ${username} ` }) }} + + {{ $t('account.defaultPassword') }} + + + + + + + + + + + + diff --git a/src/views/admin/accounts/list.vue b/src/views/admin/accounts/list.vue index b7901b8..8052404 100644 --- a/src/views/admin/accounts/list.vue +++ b/src/views/admin/accounts/list.vue @@ -1,90 +1,91 @@ - - - - - - - - - - - - - - {{ $t('btn.query') }} - {{ $t('btn.reset') }} - {{ $t('common.add') }} - - - - - - - - - - - {{ row.userType === "Admin" ? "管理员" : "医院端" }} - - - - - - - - - - - - - {{ $t('btn.edit') }} - {{ $t('account.resetPassword') }} - - - - - - + + + + + {{ t.label }} + - + + {{ addBtnText }} + + + + + + + + + + + + + + + + + {{ formatDate(row.createdAt) }} + + + + + + + {{ $t('btn.edit') }} + + + {{ $t('account.resetPassword') }} + + + + + + + + + + + + + + diff --git a/src/views/admin/hospitals/components/HospitalDetailDialog.vue b/src/views/admin/hospitals/components/HospitalDetailDialog.vue index 4fc665c..a9a68ea 100644 --- a/src/views/admin/hospitals/components/HospitalDetailDialog.vue +++ b/src/views/admin/hospitals/components/HospitalDetailDialog.vue @@ -1,66 +1,72 @@ - !v && close()"> - + !v && close()"> + - - {{ $t("modal.detailHospital") }} - + {{ $t("modal.detailHospital") }} - - - - - {{ detail.name }} - - {{ detail.customerCategory }} - {{ $t("category.AShort").replace("A", "") }} - - - {{ $t("btn.edit") }} - - - - - - - {{ detail.contactDept }} - - - {{ detail.contactPerson }} - - - {{ detail.contactPosition }} - - - {{ detail.contactPhone }} - - - {{ formatDate(detail.signDate) }} - - - {{ formatDate(detail.acceptDate) }} - - - {{ detail.contractYears }}年 - - - {{ formatDate(detail.maintenanceEnd) }} - - - {{ detail.managerName }} - - - - - {{ $t("common.remark") }} - {{ detail.remark || "—" }} + + + + {{ $t('label.contactDept') }} + {{ detail.contactDept || '\u2014' }} - + + {{ $t('label.contactPerson') }} + {{ detail.contactPerson || '\u2014' }} + + + {{ $t('label.contactPosition') }} + {{ detail.contactPosition || '\u2014' }} + + + + + {{ $t('label.contactPhone') }} + {{ detail.contactPhone || '\u2014' }} + + + {{ $t('table.signDate') }} + {{ formatDate(detail.signDate) }} + + + {{ $t('label.acceptDate') }} + {{ formatDate(detail.acceptDate) }} + + + + + {{ $t('label.years') }} + {{ detail.contractYears }}年 + + + {{ $t('table.maintenanceEnd') }} + {{ formatDate(detail.maintenanceEnd) }} + + + {{ $t('table.manager') }} + {{ detail.managerName || '\u2014' }} + + + + + {{ $t('common.remark') }} + {{ detail.remark || '\u2014' }} + + + + @@ -80,7 +86,7 @@ const emit = defineEmits(["update:visible", "close", "edit"]); const loading = ref(false); const detail = ref({}); -const formatDate = (v) => (v ? dayjs(v).format("YYYY-MM-DD") : "—"); +const formatDate = (v) => (v ? dayjs(v).format("YYYY-MM-DD") : "\u2014"); const loadDetail = async (id) => { if (!id) { @@ -110,43 +116,66 @@ const close = () => emit("update:visible", false); const goEdit = () => emit("edit", props.hospitalId); - + \ No newline at end of file diff --git a/src/views/admin/hospitals/components/HospitalEditDialog.vue b/src/views/admin/hospitals/components/HospitalEditDialog.vue index 78bcbe4..7d88e6c 100644 --- a/src/views/admin/hospitals/components/HospitalEditDialog.vue +++ b/src/views/admin/hospitals/components/HospitalEditDialog.vue @@ -1,5 +1,5 @@ - !v && close()"> @@ -91,12 +91,19 @@ - - {{ $t("btn.upload") }} - - - {{ $t("label.acceptanceReportTip") }} + + + 添加文件 + (不超过50M) + + + + + + {{ file.name }} + {{ ((file.size || 0) / 1024 / 1024).toFixed(2) }}MB + 删除 @@ -208,6 +215,14 @@ const handleReportExceed = (files) => { form.attachmentPath = ""; }; +// 自定义"删除"按钮:删除后清空原报告路径,与 handleReportExceed 行为保持一致 +const handleReportDelete = (file) => { + reportFileList.value = (reportFileList.value || []).filter( + (f) => f.uid !== file?.uid, + ); + form.attachmentPath = ""; +}; + // 从带路径分隔符的地址中截取最后的文件名(兼容 / 与 \) const getAttachmentFileName = (path) => { if (!path) return ""; @@ -334,6 +349,7 @@ watch( .hospital-edit { max-height: 70vh; overflow-y: auto; + overflow-x: hidden; padding-right: 4px; } @@ -347,5 +363,68 @@ watch( .body-header { margin-bottom: 18px; } + + // ============== 附件上传(与 admin 端统一) ============== + .upload-wrap { + width: 100%; + + .el-upload-list__item { + &:hover { + background: transparent; + } + + .file-item { + display: flex; + align-items: center; + font-weight: 400; + font-size: 14px; + + .file-icon { + width: 18px; + height: 18px; + } + + .file-name, + .file-delete { + color: #1D2129; + + &:hover { + color: #1890ff; + } + } + + .file-delete { + margin-left: 14px; + cursor: pointer; + } + + .file-size { + color: #BCBCBC; + } + } + } + } + + .upload-btn { + display: flex; + align-items: center; + + .left { + font-weight: 400; + font-size: 14px; + color: #2B324C; + } + + .right { + font-weight: 400; + font-size: 14px; + color: #666666; + } + } + + // 强制上传按钮区域宽度铺满 + :deep(.el-form-item .el-form-item__content > .el-upload) { + width: 100%; + } } diff --git a/src/views/admin/hospitals/components/MaintenanceDetailDialog.vue b/src/views/admin/hospitals/components/MaintenanceDetailDialog.vue new file mode 100644 index 0000000..a28dd6b --- /dev/null +++ b/src/views/admin/hospitals/components/MaintenanceDetailDialog.vue @@ -0,0 +1,192 @@ + + $emit('update:modelValue', v)" @open="onOpen"> + + + 维保服务详情 - {{ detail.hospitalName || "—" }} + + + + + + + + + {{ detail.customerCategory || "—" }}类 + + + + + + {{ formatDate(detail.maintenanceEnd) }} + + + + + + + + {{ detail.managerName || "—" }} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/views/admin/hospitals/components/MonthlyViewDialog.vue b/src/views/admin/hospitals/components/MonthlyViewDialog.vue new file mode 100644 index 0000000..ab46594 --- /dev/null +++ b/src/views/admin/hospitals/components/MonthlyViewDialog.vue @@ -0,0 +1,395 @@ + + $emit('update:modelValue', v)" @open="onOpen"> + + + 客户服务月视图 + + + + + + + 选择年份 + + + 去年 + 今年 + 明年 + + + + + + + {{ m }}月 + 紧急 + + {{ monthList[m - 1]?.expiringCount ?? 0 }}家医院到期 + | + 已续费 + {{ monthList[m - 1]?.renewedCount ?? 0 }}家 + | + 未续费 + {{ monthList[m - 1]?.notRenewedCount ?? 0 }}家 + + + + + + + {{ h.hospitalName }} + + {{ h.customerCategory }}类 + + ✓已续费 + + + 到期: + {{ formatDate(h.maintenanceEnd) }} + + {{ formatDays(h.daysUntilExpiry) }} + + + + 客户经理: + {{ h.managerName || "—" }} + + + + 本月无到期医院 + + + + + + + + + + + diff --git a/src/views/admin/hospitals/components/ServiceRecordDialog.vue b/src/views/admin/hospitals/components/ServiceRecordDialog.vue new file mode 100644 index 0000000..de84db2 --- /dev/null +++ b/src/views/admin/hospitals/components/ServiceRecordDialog.vue @@ -0,0 +1,696 @@ + + $emit('update:modelValue', v)" @open="onOpen"> + + + {{ title }} - {{ hospitalName }} + + + + + + + 添加{{ typeLabel }}记录 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 添加文件 + (不超过50M) + + + + + {{ file.name }} + {{ ((file.size || 0) / 1024 / 1024).toFixed(2) }}MB + 删除 + + + + + + + + + + + + + + + + + + + + + + + + + + + 线上 + 线下 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 历史记录 + + + + + + + + 记录 {{ idx + 1 }} + {{ formatTime(item) }} + + + + 回访人:{{ item.callPerson }} + 回访情况:{{ item.content || "—" }} + + + 巡检人:{{ item.inspectionPerson }} + 巡检情况:{{ item.content || "—" }} + + 巡检报告: + + + {{ getInspectionFileName(item) }} + + + + + 培训主题:{{ item.topic }} + 参与人员:{{ item.participants || "—" }}人 + + + 纪念品名称:{{ item.name }} + 数量:{{ item.quantity || "—" }}份 + 记录时间:{{ dayjs(item.createdAt).format('YYYY-MM-DD HH:mm') || + "—" }} + + + + + + + + + + (previewVisible = v)" @close="cleanupPreview" + @download="onPreviewDownload" /> + + + + + + diff --git a/src/views/admin/hospitals/list.vue b/src/views/admin/hospitals/list.vue index 972a2f9..f18b5b0 100644 --- a/src/views/admin/hospitals/list.vue +++ b/src/views/admin/hospitals/list.vue @@ -1,116 +1,79 @@ - - - - - - - - - - - - - - - {{ $t('btn.query') }} - {{ $t('btn.reset') }} - {{ $t('btn.addHospital') }} - - - - - - - - - - - - {{ formatUsageYears(row.signDate) }} - - - - - {{ $t('btn.preview') }} - - — - - - - {{ formatDate(row.signDate) }} - - - {{ formatDate(row.maintenanceEnd) }} - - - - {{ $t('btn.detail') }} - {{ $t('btn.edit') }} - - - - - - - - - - (previewVisible = v)" - @close="cleanupPreview" - @download="onPreviewDownload" - /> - - - - + + + + + + + + + + + + + + + {{ $t('btn.query') }} + {{ $t('btn.reset') }} + {{ $t('btn.addHospital') }} + + + + + + + + + {{ row.customerCategory || "—" }}类 + + + + + + + + {{ formatDate(row.signDate) }} + + + {{ formatUsageYears(row.signDate) }} + + + {{ formatDate(row.maintenanceEnd) }} + + + + + {{ $t('btn.preview') }} + + — + + + + + {{ $t('btn.edit') }} + {{ $t('btn.detail') }} + + + + + + + + (previewVisible = v)" @close="cleanupPreview" + @download="onPreviewDownload" /> + + + + + + diff --git a/src/views/admin/hospitals/service.vue b/src/views/admin/hospitals/service.vue index 0f953c0..b367bf9 100644 --- a/src/views/admin/hospitals/service.vue +++ b/src/views/admin/hospitals/service.vue @@ -1,120 +1,465 @@ - - - - - - - - + + + + + 医院名称 + + - - - - - - - - - - - - - {{ $t('btn.query') }} - {{ $t('btn.reset') }} - {{ $t('btn.add') }} - - - - - - - - - - + 查询 + + + + + + < + + {{ currentMonthLabel }} + + > + + + + + + + 月视图 + + + + + + + + - {{ row.status }} + + {{ row.customerCategory || "—" }}类 + - - + + {{ formatDate(row.maintenanceEnd) }} + + + - {{ $t('btn.view') }} - {{ $t('status.completed') }} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 电话回访 + + + + + 现场巡检 + + + + + 培训记录 + + + + + 纪念品记录 + + + + + + + 详情 + - - + + + + + 本月到期提醒 + + + + + + {{ h.hospitalName }} + 紧急 + + + 到期日期: + {{ formatDate(h.maintenanceEnd) }} + + + 剩余天数: + {{ formatExpiringDays(h.daysUntilExpiry) }} + + + 未续保 + 未付款 + + - + + + + + + + + + + + + \ No newline at end of file diff --git a/src/views/admin/orders/components/OrderFormDialog.vue b/src/views/admin/orders/components/OrderFormDialog.vue index 54bf6e3..40b9cbe 100644 --- a/src/views/admin/orders/components/OrderFormDialog.vue +++ b/src/views/admin/orders/components/OrderFormDialog.vue @@ -3,7 +3,7 @@ @update:model-value="(v) => $emit('update:modelValue', v)" @closed="onClosed"> - {{ isEdit ? $t('modal.edit') : $t('modal.submit') }} + {{ isEdit ? '编辑工单' : '快速提交工单' }} @@ -64,7 +64,7 @@ {{ form.title.length - }}/300 + }}/300 {{ $t('common.cancel') }} {{ isEdit ? $t('common.save') : $t('common.submit') - }} + }} @@ -537,231 +537,232 @@ onBeforeUnmount(() => { diff --git a/src/views/admin/orders/components/OrderHandleDialog.vue b/src/views/admin/orders/components/OrderHandleDialog.vue index 19806a3..af6fe57 100644 --- a/src/views/admin/orders/components/OrderHandleDialog.vue +++ b/src/views/admin/orders/components/OrderHandleDialog.vue @@ -109,7 +109,7 @@ - diff --git a/src/views/admin/orders/components/ReportDetailDialog.vue b/src/views/admin/orders/components/ReportDetailDialog.vue new file mode 100644 index 0000000..4225b19 --- /dev/null +++ b/src/views/admin/orders/components/ReportDetailDialog.vue @@ -0,0 +1,1192 @@ + + { if (!silent) $emit('update:modelValue', v); }" @open="onOpen"> + + + {{ reportInfo }} + + + + + + + + + {{ detail.hospital || "—" }} + {{ coverPeriod }} + + + + 高效 · 主动 · 安心 + + + 上海康策软件有限公司 + 报告日期:{{ detail.date || "—" }} + + + + + + + + + + 服务综述 + + + 感谢贵院一直以来对上海康策的信任与配合。 + + 本期我们累计处理服务工单:{{ 28 + }}次,完成率达:{{ 95 }}%;同时安排回访:{{ 3 + }}次、现场巡检:{{ 1 }}次及参与培训:{{ 1 + }}次,力求从响应、预防到能力共建,全方位护航医院信息化环境。 + + + 每一次服务工单的闭环、每一次现场巡检,都承载着我们对医疗服务质量与患者安全的共同承诺。服务团队将持续精进,为医院智慧医疗建设提供坚实后盾。 + + + + + + + + + + + 月度请求趋势 + + + + 单位:次 + + + + + 科室服务请求数量 + + + + + + + + + 问题类型请求分布 + + + + + {{ item.name }} + {{ item.count }}次 + + + + + + 优先级分布 + + + + + 总计 + {{ priorityTotal }} + + + + + + {{ item.name }} {{ item.count }} + + + + + + + 反馈渠道占比 + + + + + 总计 + {{ feedbackChannelTotal }} + + + + + + {{ item.name }} {{ feedbackPercent(item.count) }} + + + + + + + + + 科室服务请求明细 + + + + + + + + {{ row.priority }} + + + + + {{ row.status }} + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/views/admin/orders/components/ReportDownloadDialog.vue b/src/views/admin/orders/components/ReportDownloadDialog.vue new file mode 100644 index 0000000..76b19ca --- /dev/null +++ b/src/views/admin/orders/components/ReportDownloadDialog.vue @@ -0,0 +1,163 @@ + + $emit('update:modelValue', v)" @closed="onClosed"> + + + 选择下载格式 + + + + + + + + + {{ fmt.label }} + + + + + + + + + \ No newline at end of file diff --git a/src/views/admin/orders/components/ReportGenerateDialog.vue b/src/views/admin/orders/components/ReportGenerateDialog.vue new file mode 100644 index 0000000..27b63e0 --- /dev/null +++ b/src/views/admin/orders/components/ReportGenerateDialog.vue @@ -0,0 +1,198 @@ + + $emit('update:modelValue', v)" + @open="onOpen" + > + + + 生成报告 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/views/admin/orders/components/ReportRemarkDialog.vue b/src/views/admin/orders/components/ReportRemarkDialog.vue new file mode 100644 index 0000000..4870a30 --- /dev/null +++ b/src/views/admin/orders/components/ReportRemarkDialog.vue @@ -0,0 +1,124 @@ + + $emit('update:modelValue', v)" @open="onOpen"> + + + 编辑备注 + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/views/admin/orders/list.vue b/src/views/admin/orders/list.vue index 580f5c5..f19636f 100644 --- a/src/views/admin/orders/list.vue +++ b/src/views/admin/orders/list.vue @@ -1,5 +1,5 @@ - + @@ -41,23 +41,23 @@ - + - + - + - + - + @@ -109,7 +109,7 @@ {{ row.title - }} + }} @@ -126,19 +126,17 @@ - {{ - row.status - }} + {{ row.status }} - {{ row.status === "已完成" ? $t("btn.modify") : $t("btn.process") }} - {{ + {{ $t("btn.detail") }} @@ -173,10 +171,10 @@ import { ElMessage } from "element-plus"; import { useI18n } from "vue-i18n"; import { createAdminOrder, - getAdminHospitals, getAdminOrders, } from "@/service/modular/admin"; import { useUserStore } from "@/stores/api/user"; +import { useHospitalStore } from "@/stores/api/hospital"; import OrderFormDialog from "./components/OrderFormDialog.vue"; import OrderDetailDialog from "./components/OrderDetailDialog.vue"; import OrderProcessDialog from "./components/OrderProcessDialog.vue"; @@ -188,8 +186,9 @@ import iconHigh from "@/assets/image/admin/orders/high.svg"; const { t: $t } = useI18n(); const userStore = useUserStore(); +const hospitalStore = useHospitalStore(); +const hospitals = computed(() => hospitalStore.list); const list = ref([]); -const hospitals = ref([]); const total = ref(0); const page = ref(1); const pageSize = ref(10); @@ -212,10 +211,8 @@ const loadHospitals = async () => { hospitals.value = []; } }; -const statusType = (s) => - ({ 待处理: "warning", 处理中: "primary", 已完成: "success", 已取消: "info" })[ - s - ] || "info"; +const statusClass = (s) => + s === "已完成" ? "done" : s === "待处理" ? "pending" : 'info'; // 工单总览统计 const stats = reactive({ @@ -349,7 +346,7 @@ const onQuickSubmit = async ({ formData }) => { }; // 视口宽度,用于动态计算 filter-form 的缩放比例(基准 1920) -const viewportWidth = ref(typeof window !== "undefined" ? (window.innerWidth - 120 ) : 1800); +const viewportWidth = ref(typeof window !== "undefined" ? (window.innerWidth - 120) : 1800); const onResize = () => { viewportWidth.value = window.innerWidth - 120; }; @@ -372,12 +369,45 @@ const formStyle = computed(() => { + + \ No newline at end of file diff --git a/src/views/admin/performance/score.vue b/src/views/admin/performance/score.vue index b62dfe3..727e57e 100644 --- a/src/views/admin/performance/score.vue +++ b/src/views/admin/performance/score.vue @@ -1,114 +1,643 @@ - - - - - - - - - - {{ $t('btn.query') }} - {{ $t('btn.reset') }} - - - - - - - - - - {{ row.totalScore }} - - - - - - - - - - - - {{ $t('points.detail') }} - - - - - - + + + + + {{ t.label }} + + 自定义 - + + + 查询 + + + + + + + + + 本期总积分 + {{ stats.totalPoints || 0 }} + + + + + + 客户经理人数 + {{ stats.managerCount || 0 }} + + + + + + 本期完成工单 + {{ stats.completedOrders || 0 }} + + + + + + 本期完成率 + {{ stats.completionRate || 0 }}% + + + + + + + + + 积分排行榜 + + + + + + {{ item.rank || idx + 1 }} + + + {{ item.managerName || "—" }} + + 负责 {{ item.hospitalCount || 0 }} 家医院 + | + 本期完成 {{ item.completedOrders || 0 }} 单 + + + {{ item.points || 0 }} + + + + + + + 积分规则 + + + + + + {{ r.event }} + + + {{ Number(r.points) >= 0 ? "+" : "" }}{{ r.points }} + + + + + + + + !v && (detailsVisible = false)" + @open="onDetailsOpen"> + + + 积分明细 - {{ currentManagerName }} + + + + + + + + + + {{ Number(row.changeAmount) >= 0 ? "+" : "" }}{{ row.changeAmount }} + + + + + + + + + + + - + + diff --git a/src/views/hospital/orders/OrderFormDialog.vue b/src/views/hospital/orders/OrderFormDialog.vue index 7f3df1d..6100946 100644 --- a/src/views/hospital/orders/OrderFormDialog.vue +++ b/src/views/hospital/orders/OrderFormDialog.vue @@ -4,7 +4,7 @@ - {{ isEdit ? '编辑工单' : $t('modal.submit') }} + {{ isEdit() ? '编辑工单' : $t('modal.submit') }} @@ -78,12 +78,19 @@ - - {{ $t('btn.upload') }} - - - {{ $t('label.attachmentTip') }} + + + + 添加文件 + {{ $t('label.attachmentTip') }} + + + + + + {{ file.name }} + {{ ((file.size || 0) / 1024 / 1024).toFixed(2) }}MB + 删除 @@ -316,6 +323,10 @@ const handleAttachmentExceed = () => { const handleAttachmentRemove = () => { // el-upload 会自动从 v-model:file-list 移除 }; +const handleAttachmentDelete = (file) => { + // 自定义"删除"按钮:按 uid 从 form.files 中移除(与 admin 端保持一致) + form.files = (form.files || []).filter((f) => f.uid !== file?.uid); +}; const nowDatetime = () => dayjs().format("YYYY-MM-DD HH:mm:ss"); @@ -683,6 +694,66 @@ onBeforeUnmount(() => { width: 100% !important; } + // ============== 附件上传(与 admin 端统一) ============== + .fujian { + .upload-wrap { + width: 100%; + + .el-upload-list__item { + &:hover { + background: transparent; + } + + .file-item { + display: flex; + align-items: center; + font-weight: 400; + font-size: 14px; + + .file-icon { + width: 18px; + height: 18px; + } + + .file-name, + .file-delete { + color: #1D2129; + + &:hover { + color: #1890ff; + } + } + + .file-delete { + margin-left: 14px; + cursor: pointer; + } + + .file-size { + color: #BCBCBC; + } + } + } + } + + .upload-btn { + display: flex; + align-items: center; + + .left { + font-weight: 400; + font-size: 14px; + color: #2B324C; + } + + .right { + font-weight: 400; + font-size: 14px; + color: #666666; + } + } + } + // ============== 提交后奖励弹窗 ============== :deep(.reward-dialog) { .el-dialog__header { diff --git a/src/views/hospital/workbench.vue b/src/views/hospital/workbench.vue index 6138059..333fc57 100644 --- a/src/views/hospital/workbench.vue +++ b/src/views/hospital/workbench.vue @@ -8,26 +8,18 @@ {{ $t('common.thisYear') }} {{ $t('common.customDate') }} - + - + + + {{ card.value }} @@ -42,33 +34,23 @@ {{ $t('chart.title') }} - - - {{ $t('chart.bar') }} + + {{ $t('chart.bar') }} - - - {{ $t('chart.line') }} + + {{ $t('chart.line') }} - +
+ {{ $t('account.confirmReset', { id: ` ${username} ` }) }} +
{{ $t('account.defaultPassword') }}