diff --git a/image.png b/image.png new file mode 100644 index 0000000..566d081 Binary files /dev/null and b/image.png differ diff --git a/package-lock.json b/package-lock.json index 10d54db..d0982ec 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,8 @@ "dependencies": { "@element-plus/icons-vue": "^2.3.2", "@jaames/iro": "^5.5.2", + "@wangeditor/editor": "^5.1.23", + "@wangeditor/editor-for-vue": "^5.1.12", "axios": "^1.13.2", "dayjs": "^1.11.21", "echarts": "^6.0.0", @@ -1320,6 +1322,12 @@ "win32" ] }, + "node_modules/@transloadit/prettier-bytes": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@transloadit/prettier-bytes/-/prettier-bytes-0.0.7.tgz", + "integrity": "sha512-VeJbUb0wEKbcwaSlj5n+LscBl9IPgLPkHVGBkh00cztv6X4L/TJXK58LzFuBKX7/GAfiGhIwH67YTLTlzvIzBA==", + "license": "MIT" + }, "node_modules/@types/estree": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", @@ -1327,6 +1335,12 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@types/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha512-zx2/Gg0Eg7gwEiOIIh5w9TrhKKTeQh7CPCOPNc0el4pLSwzebA8SmnHwZs2dWlLONvyulykSwGSQxQHLhjGLvQ==", + "license": "MIT" + }, "node_modules/@types/lodash": { "version": "4.17.20", "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.20.tgz", @@ -1368,6 +1382,61 @@ "integrity": "sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==", "license": "MIT" }, + "node_modules/@uppy/companion-client": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@uppy/companion-client/-/companion-client-2.2.2.tgz", + "integrity": "sha512-5mTp2iq97/mYSisMaBtFRry6PTgZA6SIL7LePteOV5x0/DxKfrZW3DEiQERJmYpHzy7k8johpm2gHnEKto56Og==", + "license": "MIT", + "dependencies": { + "@uppy/utils": "^4.1.2", + "namespace-emitter": "^2.0.1" + } + }, + "node_modules/@uppy/core": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/@uppy/core/-/core-2.3.4.tgz", + "integrity": "sha512-iWAqppC8FD8mMVqewavCz+TNaet6HPXitmGXpGGREGrakZ4FeuWytVdrelydzTdXx6vVKkOmI2FLztGg73sENQ==", + "license": "MIT", + "dependencies": { + "@transloadit/prettier-bytes": "0.0.7", + "@uppy/store-default": "^2.1.1", + "@uppy/utils": "^4.1.3", + "lodash.throttle": "^4.1.1", + "mime-match": "^1.0.2", + "namespace-emitter": "^2.0.1", + "nanoid": "^3.1.25", + "preact": "^10.5.13" + } + }, + "node_modules/@uppy/store-default": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@uppy/store-default/-/store-default-2.1.1.tgz", + "integrity": "sha512-xnpTxvot2SeAwGwbvmJ899ASk5tYXhmZzD/aCFsXePh/v8rNvR2pKlcQUH7cF/y4baUGq3FHO/daKCok/mpKqQ==", + "license": "MIT" + }, + "node_modules/@uppy/utils": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@uppy/utils/-/utils-4.1.3.tgz", + "integrity": "sha512-nTuMvwWYobnJcytDO3t+D6IkVq/Qs4Xv3vyoEZ+Iaf8gegZP+rEyoaFT2CK5XLRMienPyqRqNbIfRuFaOWSIFw==", + "license": "MIT", + "dependencies": { + "lodash.throttle": "^4.1.1" + } + }, + "node_modules/@uppy/xhr-upload": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@uppy/xhr-upload/-/xhr-upload-2.1.3.tgz", + "integrity": "sha512-YWOQ6myBVPs+mhNjfdWsQyMRWUlrDLMoaG7nvf/G6Y3GKZf8AyjFDjvvJ49XWQ+DaZOftGkHmF1uh/DBeGivJQ==", + "license": "MIT", + "dependencies": { + "@uppy/companion-client": "^2.2.2", + "@uppy/utils": "^4.1.2", + "nanoid": "^3.1.25" + }, + "peerDependencies": { + "@uppy/core": "^2.3.3" + } + }, "node_modules/@vitejs/plugin-vue": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-6.0.1.tgz", @@ -1603,6 +1672,165 @@ } } }, + "node_modules/@wangeditor/basic-modules": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@wangeditor/basic-modules/-/basic-modules-1.1.7.tgz", + "integrity": "sha512-cY9CPkLJaqF05STqfpZKWG4LpxTMeGSIIF1fHvfm/mz+JXatCagjdkbxdikOuKYlxDdeqvOeBmsUBItufDLXZg==", + "license": "MIT", + "dependencies": { + "is-url": "^1.2.4" + }, + "peerDependencies": { + "@wangeditor/core": "1.x", + "dom7": "^3.0.0", + "lodash.throttle": "^4.1.1", + "nanoid": "^3.2.0", + "slate": "^0.72.0", + "snabbdom": "^3.1.0" + } + }, + "node_modules/@wangeditor/code-highlight": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@wangeditor/code-highlight/-/code-highlight-1.0.3.tgz", + "integrity": "sha512-iazHwO14XpCuIWJNTQTikqUhGKyqj+dUNWJ9288Oym9M2xMVHvnsOmDU2sgUDWVy+pOLojReMPgXCsvvNlOOhw==", + "license": "MIT", + "dependencies": { + "prismjs": "^1.23.0" + }, + "peerDependencies": { + "@wangeditor/core": "1.x", + "dom7": "^3.0.0", + "slate": "^0.72.0", + "snabbdom": "^3.1.0" + } + }, + "node_modules/@wangeditor/core": { + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/@wangeditor/core/-/core-1.1.19.tgz", + "integrity": "sha512-KevkB47+7GhVszyYF2pKGKtCSj/YzmClsD03C3zTt+9SR2XWT5T0e3yQqg8baZpcMvkjs1D8Dv4fk8ok/UaS2Q==", + "license": "MIT", + "dependencies": { + "@types/event-emitter": "^0.3.3", + "event-emitter": "^0.3.5", + "html-void-elements": "^2.0.0", + "i18next": "^20.4.0", + "scroll-into-view-if-needed": "^2.2.28", + "slate-history": "^0.66.0" + }, + "peerDependencies": { + "@uppy/core": "^2.1.1", + "@uppy/xhr-upload": "^2.0.3", + "dom7": "^3.0.0", + "is-hotkey": "^0.2.0", + "lodash.camelcase": "^4.3.0", + "lodash.clonedeep": "^4.5.0", + "lodash.debounce": "^4.0.8", + "lodash.foreach": "^4.5.0", + "lodash.isequal": "^4.5.0", + "lodash.throttle": "^4.1.1", + "lodash.toarray": "^4.4.0", + "nanoid": "^3.2.0", + "slate": "^0.72.0", + "snabbdom": "^3.1.0" + } + }, + "node_modules/@wangeditor/editor": { + "version": "5.1.23", + "resolved": "https://registry.npmjs.org/@wangeditor/editor/-/editor-5.1.23.tgz", + "integrity": "sha512-0RxfeVTuK1tktUaPROnCoFfaHVJpRAIE2zdS0mpP+vq1axVQpLjM8+fCvKzqYIkH0Pg+C+44hJpe3VVroSkEuQ==", + "license": "MIT", + "dependencies": { + "@uppy/core": "^2.1.1", + "@uppy/xhr-upload": "^2.0.3", + "@wangeditor/basic-modules": "^1.1.7", + "@wangeditor/code-highlight": "^1.0.3", + "@wangeditor/core": "^1.1.19", + "@wangeditor/list-module": "^1.0.5", + "@wangeditor/table-module": "^1.1.4", + "@wangeditor/upload-image-module": "^1.0.2", + "@wangeditor/video-module": "^1.1.4", + "dom7": "^3.0.0", + "is-hotkey": "^0.2.0", + "lodash.camelcase": "^4.3.0", + "lodash.clonedeep": "^4.5.0", + "lodash.debounce": "^4.0.8", + "lodash.foreach": "^4.5.0", + "lodash.isequal": "^4.5.0", + "lodash.throttle": "^4.1.1", + "lodash.toarray": "^4.4.0", + "nanoid": "^3.2.0", + "slate": "^0.72.0", + "snabbdom": "^3.1.0" + } + }, + "node_modules/@wangeditor/editor-for-vue": { + "version": "5.1.12", + "resolved": "https://registry.npmjs.org/@wangeditor/editor-for-vue/-/editor-for-vue-5.1.12.tgz", + "integrity": "sha512-0Ds3D8I+xnpNWezAeO7HmPRgTfUxHLMd9JKcIw+QzvSmhC5xUHbpCcLU+KLmeBKTR/zffnS5GQo6qi3GhTMJWQ==", + "license": "MIT", + "peerDependencies": { + "@wangeditor/editor": ">=5.1.0", + "vue": "^3.0.5" + } + }, + "node_modules/@wangeditor/list-module": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@wangeditor/list-module/-/list-module-1.0.5.tgz", + "integrity": "sha512-uDuYTP6DVhcYf7mF1pTlmNn5jOb4QtcVhYwSSAkyg09zqxI1qBqsfUnveeDeDqIuptSJhkh81cyxi+MF8sEPOQ==", + "license": "MIT", + "peerDependencies": { + "@wangeditor/core": "1.x", + "dom7": "^3.0.0", + "slate": "^0.72.0", + "snabbdom": "^3.1.0" + } + }, + "node_modules/@wangeditor/table-module": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@wangeditor/table-module/-/table-module-1.1.4.tgz", + "integrity": "sha512-5saanU9xuEocxaemGdNi9t8MCDSucnykEC6jtuiT72kt+/Hhh4nERYx1J20OPsTCCdVr7hIyQenFD1iSRkIQ6w==", + "license": "MIT", + "peerDependencies": { + "@wangeditor/core": "1.x", + "dom7": "^3.0.0", + "lodash.isequal": "^4.5.0", + "lodash.throttle": "^4.1.1", + "nanoid": "^3.2.0", + "slate": "^0.72.0", + "snabbdom": "^3.1.0" + } + }, + "node_modules/@wangeditor/upload-image-module": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@wangeditor/upload-image-module/-/upload-image-module-1.0.2.tgz", + "integrity": "sha512-z81lk/v71OwPDYeQDxj6cVr81aDP90aFuywb8nPD6eQeECtOymrqRODjpO6VGvCVxVck8nUxBHtbxKtjgcwyiA==", + "license": "MIT", + "peerDependencies": { + "@uppy/core": "^2.0.3", + "@uppy/xhr-upload": "^2.0.3", + "@wangeditor/basic-modules": "1.x", + "@wangeditor/core": "1.x", + "dom7": "^3.0.0", + "lodash.foreach": "^4.5.0", + "slate": "^0.72.0", + "snabbdom": "^3.1.0" + } + }, + "node_modules/@wangeditor/video-module": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@wangeditor/video-module/-/video-module-1.1.4.tgz", + "integrity": "sha512-ZdodDPqKQrgx3IwWu4ZiQmXI8EXZ3hm2/fM6E3t5dB8tCaIGWQZhmqd6P5knfkRAd3z2+YRSRbxOGfoRSp/rLg==", + "license": "MIT", + "peerDependencies": { + "@uppy/core": "^2.1.4", + "@uppy/xhr-upload": "^2.0.7", + "@wangeditor/core": "1.x", + "dom7": "^3.0.0", + "nanoid": "^3.2.0", + "slate": "^0.72.0", + "snabbdom": "^3.1.0" + } + }, "node_modules/ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", @@ -2095,6 +2323,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/compute-scroll-into-view": { + "version": "1.0.20", + "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-1.0.20.tgz", + "integrity": "sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg==", + "license": "MIT" + }, "node_modules/copy-anything": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-4.0.5.tgz", @@ -2270,6 +2504,19 @@ "integrity": "sha512-D80T+tiqkd/8B0xNlbstWDG4x6aqVfO52+OlSUNIdkTvmNw0uQpJLeos2J/2XvpyidAFuTPmpad+tUxLndwj6g==", "license": "MIT" }, + "node_modules/d": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.2.tgz", + "integrity": "sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==", + "license": "ISC", + "dependencies": { + "es5-ext": "^0.10.64", + "type": "^2.7.2" + }, + "engines": { + "node": ">=0.12" + } + }, "node_modules/data-view-buffer": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", @@ -2470,6 +2717,15 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, + "node_modules/dom7": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/dom7/-/dom7-3.0.0.tgz", + "integrity": "sha512-oNlcUdHsC4zb7Msx7JN3K0Nro1dzJ48knvBOnDPKJ2GV9wl1i5vydJZUSyOfrkKFDZEud/jBsTk92S/VGSAe/g==", + "license": "MIT", + "dependencies": { + "ssr-window": "^3.0.0-alpha.1" + } + }, "node_modules/domelementtype": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", @@ -2707,6 +2963,46 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es5-ext": { + "version": "0.10.64", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz", + "integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==", + "hasInstallScript": true, + "license": "ISC", + "dependencies": { + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.3", + "esniff": "^2.0.1", + "next-tick": "^1.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", + "license": "MIT", + "dependencies": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/es6-symbol": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.4.tgz", + "integrity": "sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==", + "license": "ISC", + "dependencies": { + "d": "^1.0.2", + "ext": "^1.7.0" + }, + "engines": { + "node": ">=0.12" + } + }, "node_modules/esbuild": { "version": "0.25.12", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", @@ -2759,6 +3055,21 @@ "node": ">=0.8.0" } }, + "node_modules/esniff": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz", + "integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==", + "license": "ISC", + "dependencies": { + "d": "^1.0.1", + "es5-ext": "^0.10.62", + "event-emitter": "^0.3.5", + "type": "^2.7.2" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/estree-walker": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", @@ -2775,6 +3086,16 @@ "node": ">= 0.6" } }, + "node_modules/event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", + "license": "MIT", + "dependencies": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, "node_modules/expand-brackets": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", @@ -2838,6 +3159,15 @@ "dev": true, "license": "MIT" }, + "node_modules/ext": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", + "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", + "license": "ISC", + "dependencies": { + "type": "^2.7.2" + } + }, "node_modules/extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", @@ -3396,6 +3726,16 @@ "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", "license": "MIT" }, + "node_modules/html-void-elements": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-2.0.1.tgz", + "integrity": "sha512-0quDb7s97CfemeJAnW9wC0hw78MtW7NU3hqtCD75g2vFlDLt36llsYD7uB7SUzojLMP24N5IatXf7ylGXiGG9A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/htmlparser2": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", @@ -3418,6 +3758,15 @@ "dev": true, "license": "BSD-2-Clause" }, + "node_modules/i18next": { + "version": "20.6.1", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-20.6.1.tgz", + "integrity": "sha512-yCMYTMEJ9ihCwEQQ3phLo7I/Pwycf8uAx+sRHwwk5U9Aui/IZYgQRyMqXafQOw5QQ7DM1Z+WyEXWIqSuJHhG2A==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.0" + } + }, "node_modules/image-size": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", @@ -3431,6 +3780,16 @@ "node": ">=0.10.0" } }, + "node_modules/immer": { + "version": "9.0.21", + "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz", + "integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, "node_modules/immutable": { "version": "5.1.4", "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.4.tgz", @@ -3695,6 +4054,12 @@ "node": ">=0.10.0" } }, + "node_modules/is-hotkey": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/is-hotkey/-/is-hotkey-0.2.0.tgz", + "integrity": "sha512-UknnZK4RakDmTgz4PI1wIph5yxSs/mvChWs9ifnlXsKuXgWmOkY/hAE0H/k2MIqH0RlRye0i1oC07MCRSD28Mw==", + "license": "MIT" + }, "node_modules/is-map": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", @@ -3880,6 +4245,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-url": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", + "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==", + "license": "MIT" + }, "node_modules/is-weakmap": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", @@ -4049,6 +4420,49 @@ "lodash-es": "*" } }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "license": "MIT" + }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==", + "license": "MIT" + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "license": "MIT" + }, + "node_modules/lodash.foreach": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz", + "integrity": "sha512-aEXTF4d+m05rVOAUG3z4vZZ4xVexLKZGF0lIxuHZ1Hplpk/3B6Z1+/ICICYRLm7c41Z2xiejbkCkJoTlypoXhQ==", + "license": "MIT" + }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", + "deprecated": "This package is deprecated. Use require('node:util').isDeepStrictEqual instead.", + "license": "MIT" + }, + "node_modules/lodash.throttle": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", + "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==", + "license": "MIT" + }, + "node_modules/lodash.toarray": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.toarray/-/lodash.toarray-4.4.0.tgz", + "integrity": "sha512-QyffEA3i5dma5q2490+SgCvDN0pXLmRGSyAANuVi0HQ01Pkfr9fuoKQW8wm1wGBnJITs/mS7wQvS6VshUEBFCw==", + "license": "MIT" + }, "node_modules/magic-string": { "version": "0.30.21", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", @@ -4162,6 +4576,15 @@ "node": ">= 0.6" } }, + "node_modules/mime-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/mime-match/-/mime-match-1.0.2.tgz", + "integrity": "sha512-VXp/ugGDVh3eCLOBCiHZMYWQaTNUHv2IJrut+yXA6+JbLPXHglHwfS/5A5L0ll+jkCY7fIzRJcH6OIunF+c6Cg==", + "license": "ISC", + "dependencies": { + "wildcard": "^1.1.0" + } + }, "node_modules/mime-types": { "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", @@ -4224,6 +4647,12 @@ "dev": true, "license": "MIT" }, + "node_modules/namespace-emitter": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/namespace-emitter/-/namespace-emitter-2.0.1.tgz", + "integrity": "sha512-N/sMKHniSDJBjfrkbS/tpkPj4RAbvW3mr8UAzvlMHyun93XEm83IAvhWtJVHo+RHn/oO8Job5YN4b+wRjSVp5g==", + "license": "MIT" + }, "node_modules/nanoid": { "version": "3.3.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", @@ -4326,6 +4755,12 @@ "node": ">=0.10.0" } }, + "node_modules/next-tick": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", + "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", + "license": "ISC" + }, "node_modules/node-addon-api": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", @@ -4748,6 +5183,15 @@ "url": "https://opencollective.com/preact" } }, + "node_modules/prismjs": { + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz", + "integrity": "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", @@ -5531,6 +5975,15 @@ "node": ">=11.0.0" } }, + "node_modules/scroll-into-view-if-needed": { + "version": "2.2.31", + "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.31.tgz", + "integrity": "sha512-dGCXy99wZQivjmjIqihaBQNjryrz5rueJY7eHfTdyWEiR4ttYpsajb14rn9s5d4DY4EcY6+4+U/maARBXJedkA==", + "license": "MIT", + "dependencies": { + "compute-scroll-into-view": "^1.0.20" + } + }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", @@ -5668,6 +6121,56 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/slate": { + "version": "0.72.8", + "resolved": "https://registry.npmjs.org/slate/-/slate-0.72.8.tgz", + "integrity": "sha512-/nJwTswQgnRurpK+bGJFH1oM7naD5qDmHd89JyiKNT2oOKD8marW0QSBtuFnwEbL5aGCS8AmrhXQgNOsn4osAw==", + "license": "MIT", + "dependencies": { + "immer": "^9.0.6", + "is-plain-object": "^5.0.0", + "tiny-warning": "^1.0.3" + } + }, + "node_modules/slate-history": { + "version": "0.66.0", + "resolved": "https://registry.npmjs.org/slate-history/-/slate-history-0.66.0.tgz", + "integrity": "sha512-6MWpxGQZiMvSINlCbMW43E2YBSVMCMCIwQfBzGssjWw4kb0qfvj0pIdblWNRQZD0hR6WHP+dHHgGSeVdMWzfng==", + "license": "MIT", + "dependencies": { + "is-plain-object": "^5.0.0" + }, + "peerDependencies": { + "slate": ">=0.65.3" + } + }, + "node_modules/slate-history/node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/slate/node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snabbdom": { + "version": "3.6.4", + "resolved": "https://registry.npmjs.org/snabbdom/-/snabbdom-3.6.4.tgz", + "integrity": "sha512-VmxEfuw1/Y/eFj5VtMhYnukExpYiPkNzoo3+N3qwAOUDMl8wXgbli5ebR+j0knE3lZ/0eYskLxNcX64uy10N9w==", + "license": "MIT", + "engines": { + "node": ">=12.17.0" + } + }, "node_modules/snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", @@ -5793,13 +6296,6 @@ "node": ">=0.10.0" } }, - "node_modules/sortablejs": { - "version": "1.15.7", - "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.7.tgz", - "integrity": "sha512-Kk8wLQPlS+yi1ZEf48a4+fzHa4yxjC30M/Sr2AnQu+f/MPwvvX9XjZ6OWejiz8crBsLwSq8GHqaxaET7u6ux0A==", - "license": "MIT", - "peer": true - }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -5891,6 +6387,12 @@ "node": ">=0.10.0" } }, + "node_modules/ssr-window": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ssr-window/-/ssr-window-3.0.0.tgz", + "integrity": "sha512-q+8UfWDg9Itrg0yWK7oe5p/XRCJpJF9OBtXfOPgSJl+u3Xd5KI328RUEvUqSMVM9CiQUEf1QdBzJMkYGErj9QA==", + "license": "MIT" + }, "node_modules/stable": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", @@ -6322,6 +6824,12 @@ "node": ">=16.0.0" } }, + "node_modules/tiny-warning": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", + "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==", + "license": "MIT" + }, "node_modules/tinyglobby": { "version": "0.2.15", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", @@ -6470,6 +6978,12 @@ "dev": true, "license": "0BSD" }, + "node_modules/type": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/type/-/type-2.7.3.tgz", + "integrity": "sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==", + "license": "ISC" + }, "node_modules/typed-array-buffer": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", @@ -6994,6 +7508,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/wildcard": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-1.1.2.tgz", + "integrity": "sha512-DXukZJxpHA8LuotRwL0pP1+rS6CS7FF2qStDDE1C7DDg2rLud2PXRMuEDYIPhgEezwnlHNL4c+N6MfMTjCGTng==", + "license": "MIT" + }, "node_modules/wujie": { "version": "1.0.29", "resolved": "https://registry.npmjs.org/wujie/-/wujie-1.0.29.tgz", diff --git a/package.json b/package.json index 39e3d17..ab31d0e 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,8 @@ "dependencies": { "@element-plus/icons-vue": "^2.3.2", "@jaames/iro": "^5.5.2", + "@wangeditor/editor": "^5.1.23", + "@wangeditor/editor-for-vue": "^5.1.12", "axios": "^1.13.2", "dayjs": "^1.11.21", "echarts": "^6.0.0", diff --git a/src/assets/image/login/1@3x.png b/src/assets/image/login/1@3x.png deleted file mode 100644 index 57bbb16..0000000 Binary files a/src/assets/image/login/1@3x.png and /dev/null differ diff --git a/src/assets/image/login/2@3x.png b/src/assets/image/login/2@3x.png deleted file mode 100644 index a13c66b..0000000 Binary files a/src/assets/image/login/2@3x.png and /dev/null differ diff --git a/src/assets/image/login/3@3x.png b/src/assets/image/login/3@3x.png deleted file mode 100644 index a805963..0000000 Binary files a/src/assets/image/login/3@3x.png and /dev/null differ diff --git a/src/assets/image/login/4@3x.png b/src/assets/image/login/4@3x.png deleted file mode 100644 index 440ed9b..0000000 Binary files a/src/assets/image/login/4@3x.png and /dev/null differ diff --git a/src/assets/image/login/7@3x.png b/src/assets/image/login/7@3x.png deleted file mode 100644 index 62e3d5e..0000000 Binary files a/src/assets/image/login/7@3x.png and /dev/null differ diff --git a/src/assets/image/login/8@3x.png b/src/assets/image/login/8@3x.png deleted file mode 100644 index 6c7b346..0000000 Binary files a/src/assets/image/login/8@3x.png and /dev/null differ diff --git a/src/assets/image/login/9@3x.png b/src/assets/image/login/9@3x.png deleted file mode 100644 index 7f2bdf8..0000000 Binary files a/src/assets/image/login/9@3x.png and /dev/null differ diff --git a/src/assets/image/login/KcLogo.png b/src/assets/image/login/KcLogo.png deleted file mode 100644 index 380075b..0000000 Binary files a/src/assets/image/login/KcLogo.png and /dev/null differ diff --git a/src/assets/image/login/ai@3x.png b/src/assets/image/login/ai@3x.png deleted file mode 100644 index d1fab8b..0000000 Binary files a/src/assets/image/login/ai@3x.png and /dev/null differ diff --git a/src/assets/image/login/bg-login.png b/src/assets/image/login/bg-login.png deleted file mode 100644 index b622fcc..0000000 Binary files a/src/assets/image/login/bg-login.png and /dev/null differ diff --git a/src/assets/image/login/bg.gif b/src/assets/image/login/bg.gif new file mode 100644 index 0000000..0b04ef0 Binary files /dev/null and b/src/assets/image/login/bg.gif differ diff --git a/src/assets/image/login/code.png b/src/assets/image/login/code.png deleted file mode 100644 index 65c69a8..0000000 Binary files a/src/assets/image/login/code.png and /dev/null differ diff --git a/src/assets/image/login/download.svg b/src/assets/image/login/download.svg deleted file mode 100644 index 061bbe7..0000000 --- a/src/assets/image/login/download.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/assets/image/login/login-bg.png b/src/assets/image/login/login-bg.png deleted file mode 100644 index 0ef5b72..0000000 Binary files a/src/assets/image/login/login-bg.png and /dev/null differ diff --git a/src/assets/image/login/logo-bottom.png b/src/assets/image/login/logo-bottom.png deleted file mode 100644 index fa8281c..0000000 Binary files a/src/assets/image/login/logo-bottom.png and /dev/null differ diff --git a/src/assets/image/login/logo.png b/src/assets/image/login/logo.png deleted file mode 100644 index 8a0cc50..0000000 Binary files a/src/assets/image/login/logo.png and /dev/null differ diff --git a/src/assets/image/login/logoT.png b/src/assets/image/login/logoT.png deleted file mode 100644 index d507697..0000000 Binary files a/src/assets/image/login/logoT.png and /dev/null differ diff --git a/src/assets/image/login/name.png b/src/assets/image/login/name.png deleted file mode 100644 index 25c4d5c..0000000 Binary files a/src/assets/image/login/name.png and /dev/null differ diff --git a/src/assets/image/login/pass.png b/src/assets/image/login/pass.png deleted file mode 100644 index 1686dad..0000000 Binary files a/src/assets/image/login/pass.png and /dev/null differ diff --git a/src/assets/image/login/password.svg b/src/assets/image/login/password.svg new file mode 100644 index 0000000..96bdd8e --- /dev/null +++ b/src/assets/image/login/password.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/assets/image/login/share.svg b/src/assets/image/login/share.svg deleted file mode 100644 index c1a4d1b..0000000 --- a/src/assets/image/login/share.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/assets/image/login/text.png b/src/assets/image/login/text.png deleted file mode 100644 index a20cfa2..0000000 Binary files a/src/assets/image/login/text.png and /dev/null differ diff --git a/src/assets/image/login/user.svg b/src/assets/image/login/user.svg new file mode 100644 index 0000000..b0ce289 --- /dev/null +++ b/src/assets/image/login/user.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/assets/image/login/下载.png b/src/assets/image/login/下载.png deleted file mode 100644 index 1eb5ed6..0000000 Binary files a/src/assets/image/login/下载.png and /dev/null differ diff --git a/src/assets/image/login/分享.png b/src/assets/image/login/分享.png deleted file mode 100644 index 0b8c25a..0000000 Binary files a/src/assets/image/login/分享.png and /dev/null differ diff --git a/src/assets/image/login/容器 9@3x.png b/src/assets/image/login/容器 9@3x.png deleted file mode 100644 index e7003bb..0000000 Binary files a/src/assets/image/login/容器 9@3x.png and /dev/null differ diff --git a/src/assets/image/login/底图@3x.png b/src/assets/image/login/底图@3x.png deleted file mode 100644 index 9ea62eb..0000000 Binary files a/src/assets/image/login/底图@3x.png and /dev/null differ diff --git a/src/assets/image/login/快捷方式.png b/src/assets/image/login/快捷方式.png deleted file mode 100644 index feebefa..0000000 Binary files a/src/assets/image/login/快捷方式.png and /dev/null differ diff --git a/src/assets/image/login/数据@3x.png b/src/assets/image/login/数据@3x.png deleted file mode 100644 index e7b390f..0000000 Binary files a/src/assets/image/login/数据@3x.png and /dev/null differ diff --git a/src/assets/image/login/眼睛3.png b/src/assets/image/login/眼睛3.png deleted file mode 100644 index d4e2f82..0000000 Binary files a/src/assets/image/login/眼睛3.png and /dev/null differ diff --git a/src/assets/image/login/眼睛4.png b/src/assets/image/login/眼睛4.png deleted file mode 100644 index a916efa..0000000 Binary files a/src/assets/image/login/眼睛4.png and /dev/null differ diff --git a/src/assets/style/common.scss b/src/assets/style/common.scss index 5cd5bf9..2d12049 100644 --- a/src/assets/style/common.scss +++ b/src/assets/style/common.scss @@ -790,10 +790,6 @@ img { background-color: var(--brand-color-hover) !important; } -body { - color: #fff; -} - .mx-auto { margin-left: auto !important; margin-right: auto !important; diff --git a/src/components/i18nSwitch/index.vue b/src/components/i18nSwitch/index.vue index a0959e1..b7e7341 100644 --- a/src/components/i18nSwitch/index.vue +++ b/src/components/i18nSwitch/index.vue @@ -1,28 +1,60 @@ - - + diff --git a/src/components/layout/AdminLayout.vue b/src/components/layout/AdminLayout.vue index 0c96448..1ca2a22 100644 --- a/src/components/layout/AdminLayout.vue +++ b/src/components/layout/AdminLayout.vue @@ -15,12 +15,12 @@ :defaultOpeneds="defaultOpeneds" /> -
+
@@ -37,6 +37,7 @@ @@ -48,6 +49,32 @@
+ + + +
+
+
+
+
{{ t.name }}
+
{{ t.desc }}
+
+
+
+
@@ -59,12 +86,44 @@ import { Fold, Expand, ArrowDown } from "@element-plus/icons-vue"; import NavBar from "@/components/navBar/NavBar.vue"; import SvgIcon from "@/components/SvgIcon/index.vue"; import { useUserStore } from "@/stores/api/user"; +import { useThemeStore } from "@/stores/theme"; const route = useRoute(); const router = useRouter(); const userStore = useUserStore(); +const themeStore = useThemeStore(); const collapsed = ref(false); +// 主题弹窗显隐 +const themeDialogVisible = ref(false); + +// 预设主题配置(与现有 scss 主题保持一致) +const presetThemes = [ + { + value: "blue", + name: "穹宇蓝", + desc: "深邃星空,科技感十足", + preview: "linear-gradient(135deg, #6c7cf3 0%, #5868e6 100%)", + }, + { + value: "purple", + name: "星轨紫", + desc: "神秘优雅,梦幻氛围", + preview: "linear-gradient(135deg, #A06CFC 0%, #6B2EDB 100%)", + }, + { + value: "green", + name: "青峦绿", + desc: "清新自然,宁静致远", + preview: "linear-gradient(135deg, #34B693 0%, #228F72 100%)", + }, +]; + +// 选择预设主题 +const handlePresetTheme = (value) => { + themeStore.setTheme(value); +}; + // 菜单分组顺序(驱动侧边栏的顺序与分组) const GROUP_ORDER = ["工单管理", "客户管理", "绩效管理", "系统管理"]; @@ -132,6 +191,10 @@ const handleCommand = async (cmd) => { router.push("/admin/password"); return; } + if (cmd === "theme") { + themeDialogVisible.value = true; + return; + } if (cmd === "logout") { try { await ElMessageBox.confirm("确定要退出登录吗?", "提示", { @@ -293,4 +356,56 @@ const handleCommand = async (cmd) => { } } } - + +.theme-dialog { + padding: 4px 4px 0; + + .theme-grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 14px; + } + + .theme-card { + border: 2px solid #e8e8e8; + border-radius: 12px; + padding: 14px; + cursor: pointer; + transition: all 0.25s ease; + text-align: center; + background: #fff; + + &:hover { + border-color: var(--brand-color); + box-shadow: 0 4px 14px rgba(0, 0, 0, 0.08); + transform: translateY(-2px); + } + + &.active { + border-color: var(--brand-color); + background: var(--brand-color-light); + box-shadow: 0 4px 14px rgba(0, 0, 0, 0.08); + } + } + + .theme-preview { + height: 56px; + border-radius: 8px; + margin-bottom: 10px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); + } + + .theme-name { + font-size: 14px; + font-weight: 600; + color: #333; + margin-bottom: 4px; + } + + .theme-desc { + font-size: 12px; + color: #999; + min-height: 18px; + } +} + \ No newline at end of file diff --git a/src/i18n/lang/en-US.js b/src/i18n/lang/en-US.js index 2259478..a26b2c0 100644 --- a/src/i18n/lang/en-US.js +++ b/src/i18n/lang/en-US.js @@ -1,11 +1,472 @@ export default { - login:{ - title:'Welcome to log in', - name:'Hospital Customer Management', - userName:'Please enter your account number.', - passWord:'Please enter the password.', - code:'Please enter the verification code.', - jizhu:'Remember the account number', - denglu:'Log in' - }, -} \ No newline at end of file + // Common + common: { + confirm: 'Confirm', + cancel: 'Cancel', + save: 'Save', + submit: 'Submit', + reset: 'Reset', + query: 'Query', + search: 'Search', + add: 'Add', + edit: 'Edit', + delete: 'Delete', + view: 'View', + close: 'Close', + back: 'Back', + export: 'Export', + download: 'Download', + upload: 'Upload', + more: 'More', + all: 'All', + yes: 'Yes', + no: 'No', + enabled: 'Enabled', + disabled: 'Disabled', + pleaseSelect: 'Please select', + pleaseInput: 'Please input', + success: 'Success', + failed: 'Failed', + operating: 'Action', + remark: 'Remark', + time: 'Time', + today: 'Today', + yesterday: 'Yesterday', + thisWeek: 'This Week', + thisMonth: 'This Month', + thisQuarter: 'This Quarter', + thisYear: 'This Year', + customDate: 'Custom Date', + startDate: 'Start Date', + endDate: 'End Date', + language: 'Language', + }, + // Login page + login: { + title: 'Welcome to Log In', + name: '康策智能CSM系统', + headerTitle: 'Kangce Smart CSM System', + userName: 'Please enter your account', + passWord: 'Please enter your password', + code: 'Please enter the verification code', + jizhu: 'Remember me', + denglu: 'Login', + copyright: 'Copyright © Shanghai Kangce Software Co., Ltd.', + hotline: 'Hotline: 021-60713139', + loginSuccess: 'Login Successful', + loginFailed: 'Login Failed', + unknownUserType: 'Unknown user type, cannot log in', + pleaseEnterUserName: 'Please enter your account', + pleaseEnterPassWord: 'Please enter your password', + languageLabel: 'Language:', + }, + // Navigation menu + nav: { + workbench: 'Workbench', + submit: 'My Tickets', + points: 'My Points', + quickSubmit: 'Quick Submit', + workorders: 'Service Tickets', + reports: 'Service Reports', + hospitals: 'Hospitals', + customer: 'Customer Service', + managerPoints: 'Manager Points', + account: 'Accounts', + grades: 'Performance', + }, + // Page title + title: { + workbench: 'Workbench', + submit: 'My Tickets', + points: 'My Points', + workorders: 'Service Tickets', + reports: 'Service Reports', + hospitals: 'Hospitals', + customer: 'Customer Service', + managerPoints: 'Manager Points', + account: 'Account Management', + grades: 'Performance Management', + changePassword: 'Change Password', + }, + // Button text + btn: { + quickSubmit: 'Quick Submit', + view: 'View', + edit: 'Edit', + cancel: 'Cancel', + close: 'Close', + detail: 'Detail', + process: 'Process', + submit: 'Submit Ticket', + save: 'Save Changes', + cancelModal: 'Cancel', + saveChange: 'Save Changes', + query: 'Query', + reset: 'Reset', + export: 'Export', + download: 'Download', + upload: 'Upload', + generate: 'Generate', + add: 'Add', + delete: 'Delete', + addOrder: '+ New Ticket', + addHospital: '+ Add Hospital', + addAccount: '+ Add Account', + quickAddOrder: '+ Quick Submit Ticket', + back: '← Back', + preview: 'View Report', + downloadPdf: 'Download PDF Report', + confirm: 'Confirm', + downloadReport: 'Download Report', + }, + // Form labels + label: { + title: 'Issue Title', + description: 'Description', + attachment: 'Attachment', + dept: 'Department', + name: 'Submitter', + priority: 'Priority', + type: 'Service Type', + oldPassword: 'Old Password', + newPassword: 'New Password', + confirmPassword: 'Confirm Password', + hospital: 'Hospital Name', + hospitalName: 'Hospital Name', + contact: 'Contact', + contactPerson: 'Contact Person', + contactDept: 'Contact Department', + contactPosition: 'Position', + contactPhone: 'Phone', + category: 'Customer Category', + signDate: 'Signing Date', + acceptDate: 'Acceptance Date', + years: 'Years', + maintenanceEndDate: 'Maintenance End Date', + manager: 'Account Manager', + acceptanceReport: 'Acceptance Report', + account: 'Account', + accountType: 'Account Type', + password: 'Password', + gender: 'Gender', + role: 'Role', + status: 'Status', + renewal: 'Renewal', + contractSigned: 'Contract Signed', + paymentPaid: 'Payment', + visited: 'Visit Status', + visitResult: 'Visit Result', + createTime: 'Created At', + colorTag: 'Color Tag', + currentPassword: 'Current Password', + }, + // Form placeholder + placeholder: { + title: 'Enter issue title', + description: 'Describe the issue in detail...', + dept: 'Enter department', + name: 'Enter submitter name', + type: 'Select service type', + hospital: 'Enter hospital name', + contactPerson: 'Enter contact person', + contactDept: 'Enter contact department', + contactPosition: 'Enter position', + contactPhone: 'Enter phone', + search: 'Please input', + keyword: 'Search title/ticket no.', + account: 'Enter account', + password: 'Enter password', + newPassword: 'Enter new password (at least 6 chars)', + confirmPassword: 'Confirm new password', + currentPassword: 'Enter current password', + remark: 'Enter remark...', + }, + // Messages + msg: { + pleaseInputTitle: 'Please enter the issue title', + pleaseInputDescription: 'Please enter the description', + pleaseSelectPriority: 'Please select priority', + pleaseSelectType: 'Please select service type', + pleaseSelectHospital: 'Please select hospital', + pleaseInputDept: 'Please enter department', + pleaseInputName: 'Please enter submitter name', + passwordTooShort: 'New password must be at least 6 characters!', + passwordMismatch: 'Passwords do not match!', + pleaseFillRequired: 'Please fill in required fields!', + submitSuccess: 'Ticket submitted successfully!', + editSuccess: 'Ticket updated successfully!', + cancelSuccess: 'Ticket cancelled successfully!', + closeSuccess: 'Ticket closed successfully!', + passwordChangeSuccess: 'Password changed successfully!', + languageChangeSuccess: 'Language changed successfully!', + themeChangeSuccess: 'Theme changed successfully!', + hospitalAddSuccess: 'Hospital added successfully!', + hospitalEditSuccess: 'Hospital updated successfully!', + accountAddSuccess: 'Account added successfully!', + accountEditSuccess: 'Account updated successfully!', + passwordResetSuccess: 'Password reset successfully!', + reportGenerateSuccess: 'Report generated successfully!', + confirmCancelOrder: 'Are you sure you want to cancel ticket {orderId}? This cannot be undone.', + confirmCloseOrder: 'Are you sure you want to close ticket {orderId}?', + }, + // Statistics + stat: { + total: 'Total Submitted', + completed: 'Completed', + pending: 'Pending', + highPriority: 'High Priority', + totalOrders: 'Total', + pendingOrders: 'Pending', + completedOrders: 'Completed', + highPriorityOrders: 'High Priority', + high: 'High Priority', + medium: 'Medium Priority', + low: 'Low Priority', + mediumPriority: 'Medium Priority', + lowPriority: 'Low Priority', + processing: 'Processing', + }, + // Table columns + table: { + id: 'Ticket No.', + priority: 'Priority', + title: 'Title', + type: 'Service Type', + status: 'Status', + time: 'Submit Time', + submitter: 'Submitter', + action: 'Action', + hospital: 'Hospital', + handler: 'Handler', + handleTime: 'Handle Time', + handleDesc: 'Handle Description', + registrar: 'Registrar', + dept: 'Department', + category: 'Category', + contact: 'Contact', + phone: 'Phone', + manager: 'Manager', + signDate: 'Sign Date', + usageYears: 'Usage Years', + maintenanceEnd: 'Maintenance End', + acceptanceReport: 'Acceptance Report', + account: 'Account', + name: 'Name', + gender: 'Gender', + role: 'Role', + createTime: 'Created', + hospitalName: 'Hospital Name', + }, + // Status + status: { + pending: 'Pending', + processing: 'Processing', + completed: 'Completed', + closed: 'Closed', + active: 'Active', + inactive: 'Inactive', + normal: 'Normal', + warning: 'Warning', + urgent: 'Urgent', + expired: 'Expired', + renewed: 'Renewed', + notRenewed: 'Not Renewed', + paid: 'Paid', + notPaid: 'Unpaid', + }, + // Priority + priority: { + high: '🔴 High', + medium: '🟠 Medium', + low: '🟢 Low', + }, + // Type + type: { + issue: 'Issue', + consult: 'Consultation', + feature: 'Feature Request', + other: 'Other', + }, + // Chart + chart: { + title: 'Ticket Trend', + submit: 'Submitted', + complete: 'Completed', + bar: 'Bar Chart', + line: 'Line Chart', + }, + // Date buttons + dateBtn: { + thisMonth: 'This Month', + thisQuarter: 'This Quarter', + thisYear: 'This Year', + customDate: 'Custom Date', + }, + // Theme + theme: { + blue: 'Cosmic Blue', + purple: 'Orbital Purple', + green: 'Mountain Green', + title: 'Change Theme', + }, + // Language + languageSwitch: { + title: 'Change Language', + zhCN: 'Chinese (Simplified)', + zhTW: 'Chinese (Traditional)', + enUS: 'English', + }, + // Modal + modal: { + detail: 'Ticket Detail', + edit: 'Edit Ticket', + submit: 'Quick Submit Ticket', + changePassword: 'Change Password', + changeTheme: 'Change Theme', + changeLanguage: 'Change Language', + addAccount: 'Add Account', + editAccount: 'Edit Account', + resetPassword: 'Reset Password', + addHospital: 'Add Hospital', + editHospital: 'Edit Hospital', + detailHospital: 'Hospital Detail', + generateReport: 'Generate Service Report', + }, + // User menu + userMenu: { + changePassword: 'Change Password', + changeTheme: 'Change Theme', + changeLanguage: 'Change Language', + logout: 'Logout', + }, + // Customer category + category: { + A: 'Class A (Active)', + B: 'Class B (Inactive)', + C: 'Class C (To Recover)', + AShort: 'Class A', + BShort: 'Class B', + CShort: 'Class C', + }, + // Role + role: { + super: 'Super Admin', + manager: 'Account Manager', + }, + // Gender + gender: { + male: 'Male', + female: 'Female', + }, + // File upload + upload: { + text: 'Click or drag files here to upload', + hint: 'Files up to 50MB supported', + uploaded: 'Uploaded Files', + remove: 'Remove', + rename: 'Rename', + maxSize50M: '(max 50M)', + }, + // Points page + points: { + title: '🎁 My Points', + unit: 'pts', + rewards: 'Received 15 service rewards', + detail: 'Points History', + points: 'Points', + pointsTime: 'Time', + pointsSource: 'Source', + pointsOrder: 'Ticket No.', + pointsChange: 'Points Change', + pointsDesc: 'Description', + }, + // Report page + report: { + list: 'Service Reports', + generate: 'Generate Report', + view: 'View', + download: 'Download', + remark: 'Remark', + search: 'Search by hospital name', + typeAll: 'All Types', + quarterly: 'Quarterly Report', + annual: 'Annual Report', + period: 'Report Period', + quarter: 'Quarter', + year: 'Annual', + querySuccess: 'Query complete, found {count} report(s).', + }, + // Order detail + orderDetail: { + submitTime: 'Submit Time', + statusChange: 'Status Change Log', + operator: 'Operator', + beforeChange: 'Before', + afterChange: 'After', + noAttachment: 'No attachments', + currentStatus: 'Current Status', + dept: 'Department', + name: 'Submitter', + handler: 'Handler', + }, + // Change password + password: { + title: 'Change Password', + oldPassword: 'Old Password', + newPassword: 'New Password', + confirmPassword: 'Confirm Password', + submit: 'Submit', + cancel: 'Cancel', + success: 'Password changed', + pleaseInputOld: 'Please enter old password', + pleaseInputNew: 'Please enter new password', + pleaseInputConfirm: 'Please confirm new password', + passwordTooShort: 'Password must be at least 6 characters', + passwordMismatch: 'Passwords do not match', + oldPasswordError: 'Old password is incorrect', + accountNotFound: 'Account does not exist', + }, + // Account management + account: { + hospitalAccount: 'Hospital Accounts', + adminAccount: 'Admin Accounts', + list: 'Account List', + addHospital: '+ Add Hospital Account', + addAdmin: '+ Add Admin Account', + enable: 'Enable', + disable: 'Disable', + enableSuccess: 'Account {id} enabled', + disableSuccess: 'Account {id} disabled', + resetPassword: 'Reset Password', + defaultPassword: 'After reset, password will be: 123456', + confirmReset: 'Are you sure you want to reset the password of account {id}?', + resetSuccess: 'Account {id} password has been reset to default: 123456', + pleaseInputName: 'Please enter name!', + }, + // Customer service + service: { + title: 'Customer Service', + monthlyView: '📅 Monthly View', + prevMonth: '← Prev Month', + nextMonth: 'Next Month →', + phoneVisit: '📞 Phone Visit', + onSiteInspection: '🔍 On-site Inspection', + training: '📚 Training Records', + gift: '🎁 Gift Records', + expiring: 'Expiring This Month', + searchHospital: 'Search by hospital name', + noRecords: 'No records', + }, + // Validation + validation: { + required: 'Required', + }, + // Date range + dateRange: { + today: 'Today', + yesterday: 'Yesterday', + thisWeek: 'This Week', + thisMonth: 'This Month', + thisQuarter: 'This Quarter', + }, +} diff --git a/src/i18n/lang/zh-CN.js b/src/i18n/lang/zh-CN.js index 189bd3e..de9cf79 100644 --- a/src/i18n/lang/zh-CN.js +++ b/src/i18n/lang/zh-CN.js @@ -1,11 +1,472 @@ export default { - login:{ - title:'欢迎登录', - name:'医院客户关系管理系统', - userName:'请输入账号', - passWord:'请输入密码', - code:'请输入验证码', - jizhu:'记住账号', - denglu:'登录' - }, -} \ No newline at end of file + // 公共 + common: { + confirm: '确认', + cancel: '取消', + save: '保存', + submit: '提交', + reset: '重置', + query: '查询', + search: '搜索', + add: '添加', + edit: '编辑', + delete: '删除', + view: '查看', + close: '关闭', + back: '返回', + export: '导出', + download: '下载', + upload: '上传', + more: '更多', + all: '全部', + yes: '是', + no: '否', + enabled: '启用', + disabled: '禁用', + pleaseSelect: '请选择', + pleaseInput: '请输入', + success: '成功', + failed: '失败', + operating: '操作', + remark: '备注', + time: '时间', + today: '今日', + yesterday: '昨日', + thisWeek: '本周', + thisMonth: '本月', + thisQuarter: '本季度', + thisYear: '本年', + customDate: '自定义日期', + startDate: '开始日期', + endDate: '结束日期', + language: '语言', + }, + // 登录页 + login: { + title: '欢迎登录', + name: '康策智能CSM系统', + headerTitle: '康策智能CSM系统', + userName: '请输入账号', + passWord: '请输入密码', + code: '请输入验证码', + jizhu: '记住账号', + denglu: '登 录', + copyright: '上海康策软件有限公司版权所有', + hotline: '服务热线:021-60713139', + loginSuccess: '登录成功', + loginFailed: '登录失败', + unknownUserType: '未知用户类型,无法登录', + pleaseEnterUserName: '请输入账号', + pleaseEnterPassWord: '请输入密码', + languageLabel: '语言:', + }, + // 导航菜单 + nav: { + workbench: '我的工作台', + submit: '我的工单', + points: '我的积分', + quickSubmit: '快速提交', + workorders: '服务工单', + reports: '服务报告', + hospitals: '医院信息', + customer: '客户服务', + managerPoints: '客户经理积分', + account: '账号管理', + grades: '绩效管理', + }, + // 页面标题 + title: { + workbench: '我的工作台', + submit: '我的工单', + points: '我的积分', + workorders: '服务工单', + reports: '服务报告', + hospitals: '医院信息', + customer: '客户服务', + managerPoints: '客户经理积分', + account: '账号管理', + grades: '绩效管理', + changePassword: '修改密码', + }, + // 按钮文本 + btn: { + quickSubmit: '快速提交', + view: '查看', + edit: '编辑', + cancel: '取消', + close: '关闭', + detail: '详情', + process: '处理', + submit: '提交工单', + save: '保存修改', + cancelModal: '取消', + saveChange: '保存修改', + query: '查询', + reset: '重置', + export: '导出', + download: '下载', + upload: '上传', + generate: '生成', + add: '添加', + delete: '删除', + addOrder: '+ 新建工单', + addHospital: '+ 添加医院', + addAccount: '+ 添加账号', + quickAddOrder: '+ 快速提交工单', + back: '← 返回', + preview: '查看报告', + downloadPdf: '下载PDF报告', + confirm: '确认修改', + downloadReport: '下载报告', + }, + // 表单标签 + label: { + title: '问题名称', + description: '问题描述', + attachment: '附件', + dept: '提出科室', + name: '提出人员', + priority: '优先级', + type: '服务类型', + oldPassword: '原密码', + newPassword: '新密码', + confirmPassword: '确认密码', + hospital: '医院名称', + hospitalName: '医院名称', + contact: '联系人', + contactPerson: '联系人', + contactDept: '联系科室', + contactPosition: '职务', + contactPhone: '联系电话', + category: '客户分类', + signDate: '签约时间', + acceptDate: '验收时间', + years: '年限', + maintenanceEndDate: '维保截止时间', + manager: '客户经理', + acceptanceReport: '验收报告', + account: '账号', + accountType: '账号类型', + password: '密码', + gender: '性别', + role: '角色', + status: '状态', + renewal: '续保完成', + contractSigned: '合同签署', + paymentPaid: '款项支付', + visited: '回访状态', + visitResult: '回访结果', + createTime: '创建时间', + colorTag: '颜色标签', + currentPassword: '当前密码', + }, + // 表单 placeholder + placeholder: { + title: '请输入问题名称', + description: '请详细描述问题,并可以编辑器直接贴图', + dept: '请输入提出科室', + name: '请输入提出人员', + type: '请选择服务类型', + hospital: '请输入医院名称', + contactPerson: '请输入联系人', + contactDept: '请输入联系科室', + contactPosition: '请输入职务', + contactPhone: '请输入联系电话', + search: '请输入', + keyword: '搜索标题/工单号', + account: '请输入账号', + password: '请输入密码', + newPassword: '请输入新密码(至少6位)', + confirmPassword: '请再次输入新密码', + currentPassword: '请输入当前密码', + remark: '请输入备注信息...', + }, + // 提示消息 + msg: { + pleaseInputTitle: '请输入问题名称', + pleaseInputDescription: '请输入问题描述', + pleaseSelectPriority: '请选择优先级', + pleaseSelectType: '请选择服务类型', + pleaseSelectHospital: '请选择医院', + pleaseInputDept: '请输入提出科室', + pleaseInputName: '请输入提出人员', + passwordTooShort: '新密码至少需要6位!', + passwordMismatch: '两次输入的新密码不一致!', + pleaseFillRequired: '请填写必填项!', + submitSuccess: '工单提交成功!', + editSuccess: '工单修改成功!', + cancelSuccess: '工单已成功取消!', + closeSuccess: '工单已成功关闭!', + passwordChangeSuccess: '密码修改成功!', + languageChangeSuccess: '语言切换成功!', + themeChangeSuccess: '主题切换成功!', + hospitalAddSuccess: '医院添加成功!', + hospitalEditSuccess: '医院信息修改成功!', + accountAddSuccess: '账号添加成功!', + accountEditSuccess: '账号更新成功!', + passwordResetSuccess: '密码重置成功!', + reportGenerateSuccess: '报告生成成功!', + confirmCancelOrder: '确定要取消工单 {orderId} 吗?取消后将无法恢复。', + confirmCloseOrder: '确定要关闭工单 {orderId} 吗?', + }, + // 统计 + stat: { + total: '累计提交工单', + completed: '已完成工单', + pending: '待处理工单', + highPriority: '高优先级工单', + totalOrders: '总工单', + pendingOrders: '待处理', + completedOrders: '已完成', + highPriorityOrders: '高优先级', + high: '高优先级', + medium: '中优先级', + low: '低优先级', + mediumPriority: '中优先级', + lowPriority: '低优先级', + processing: '处理中', + }, + // 表格列 + table: { + id: '工单号', + priority: '优先级', + title: '问题名称', + type: '服务类型', + status: '状态', + time: '提交时间', + submitter: '提交人', + action: '操作', + hospital: '医院名称', + handler: '处理人', + handleTime: '处理时间', + handleDesc: '处理说明', + registrar: '登记人', + dept: '提出科室', + category: '客户分类', + contact: '联系人', + phone: '联系电话', + manager: '客户经理', + signDate: '签约日期', + usageYears: '客户使用年限', + maintenanceEnd: '维保截止时间', + acceptanceReport: '验收报告', + account: '账号', + name: '姓名', + gender: '性别', + role: '角色', + createTime: '创建时间', + hospitalName: '医院名称', + }, + // 状态 + status: { + pending: '待处理', + processing: '处理中', + completed: '已完成', + closed: '已关闭', + active: '活跃', + inactive: '不活跃', + normal: '正常', + warning: '预警', + urgent: '紧急', + expired: '已过期', + renewed: '已续保', + notRenewed: '未续保', + paid: '已付款', + notPaid: '未付款', + }, + // 优先级 + priority: { + high: '🔴 高', + medium: '🟠 中', + low: '🟢 低', + }, + // 类型 + type: { + issue: '故障问题', + consult: '使用咨询', + feature: '功能需求', + other: '其他', + }, + // 图表 + chart: { + title: '工单趋势', + submit: '提交工单', + complete: '完成工单', + bar: '柱状图', + line: '折线图', + }, + // 日期按钮 + dateBtn: { + thisMonth: '本月', + thisQuarter: '本季度', + thisYear: '本年', + customDate: '自定义日期', + }, + // 主题 + theme: { + blue: '穹宇蓝', + purple: '星轨紫', + green: '青峦绿', + title: '更换主题', + }, + // 语言 + languageSwitch: { + title: '更换语言', + zhCN: '中文简体', + zhTW: '中文繁体', + enUS: 'English', + }, + // 模态框 + modal: { + detail: '工单详情', + edit: '编辑工单', + submit: '快速提交工单', + changePassword: '修改密码', + changeTheme: '更换主题', + changeLanguage: '更换语言', + addAccount: '添加账号', + editAccount: '编辑账号', + resetPassword: '重置密码', + addHospital: '添加医院', + editHospital: '编辑医院', + detailHospital: '医院详情', + generateReport: '生成服务报告', + }, + // 用户菜单 + userMenu: { + changePassword: '修改密码', + changeTheme: '更换主题', + changeLanguage: '更换语言', + logout: '退出登录', + }, + // 客户分类 + category: { + A: 'A类(活跃)', + B: 'B类(不活跃)', + C: 'C类(待挽回)', + AShort: 'A类', + BShort: 'B类', + CShort: 'C类', + }, + // 角色 + role: { + super: '超级管理员', + manager: '客户经理', + }, + // 性别 + gender: { + male: '男', + female: '女', + }, + // 文件上传 + upload: { + text: '点击或拖拽文件到此处添加', + hint: '支持上传不超过50M的文件', + uploaded: '已上传文件', + remove: '删除', + rename: '重命名', + maxSize50M: '(不超过50M)', + }, + // 积分页面 + points: { + title: '🎁 我的积分', + unit: '分', + rewards: '已获得15次服务奖励', + detail: '积分明细', + points: '积分', + pointsTime: '时间', + pointsSource: '来源', + pointsOrder: '工单号', + pointsChange: '积分变动', + pointsDesc: '说明', + }, + // 报告页面 + report: { + list: '服务报告列表', + generate: '生成服务报告', + view: '查看', + download: '下载', + remark: '备注', + search: '输入医院名称搜索', + typeAll: '全部类型', + quarterly: '季度报告', + annual: '年度报告', + period: '报告周期', + quarter: '季度', + year: '年度', + querySuccess: '查询完成,找到 {count} 条报告记录。', + }, + // 工单详情 + orderDetail: { + submitTime: '提交时间', + statusChange: '状态变更日志', + operator: '操作人', + beforeChange: '变更前', + afterChange: '变更后', + noAttachment: '暂无附件', + currentStatus: '当前状态', + dept: '提出科室', + name: '提出人员', + handler: '负责人员', + }, + // 修改密码 + password: { + title: '修改密码', + oldPassword: '原密码', + newPassword: '新密码', + confirmPassword: '确认密码', + submit: '提交', + cancel: '取消', + success: '密码已修改', + pleaseInputOld: '请输入原密码', + pleaseInputNew: '请输入新密码', + pleaseInputConfirm: '请再次输入新密码', + passwordTooShort: '密码长度至少 6 位', + passwordMismatch: '两次密码不一致', + oldPasswordError: '原密码错误', + accountNotFound: '账号不存在', + }, + // 账号管理 + account: { + hospitalAccount: '医院账号', + adminAccount: '管理员账号', + list: '账号列表', + addHospital: '+ 添加医院账号', + addAdmin: '+ 添加管理员账号', + enable: '启用', + disable: '禁用', + enableSuccess: '账号 {id} 已启用', + disableSuccess: '账号 {id} 已禁用', + resetPassword: '重置密码', + defaultPassword: '重置后密码将变为默认密码:123456', + confirmReset: '确定要重置账号 {id} 的密码吗?', + resetSuccess: '账号 {id} 的密码已重置为默认密码: 123456', + pleaseInputName: '请输入姓名!', + }, + // 客户服务 + service: { + title: '客户服务', + monthlyView: '📅 月视图', + prevMonth: '← 上月', + nextMonth: '下月 →', + phoneVisit: '📞 电话回访', + onSiteInspection: '🔍 现场巡检', + training: '📚 培训记录', + gift: '🎁 纪念品记录', + expiring: '本月到期提醒', + searchHospital: '按医院名称搜索', + noRecords: '暂无记录', + }, + // 通用验证 + validation: { + required: '此项必填', + }, + // 通用日期范围 + dateRange: { + today: '今日', + yesterday: '昨天', + thisWeek: '本周', + thisMonth: '本月', + thisQuarter: '本季度', + }, +} diff --git a/src/i18n/lang/zh-TW.js b/src/i18n/lang/zh-TW.js index b3d4884..9f961f5 100644 --- a/src/i18n/lang/zh-TW.js +++ b/src/i18n/lang/zh-TW.js @@ -1,11 +1,472 @@ export default { - login:{ - title:'歡迎登錄', - name:'醫院客戶關係管理系統', - userName:'請輸入賬號', - passWord:'請輸入密碼', - code:'請輸入驗證碼', - jizhu:'記住賬號', - denglu:'登錄' - }, -} \ No newline at end of file + // 公共 + common: { + confirm: '確認', + cancel: '取消', + save: '保存', + submit: '提交', + reset: '重置', + query: '查詢', + search: '搜索', + add: '添加', + edit: '編輯', + delete: '刪除', + view: '查看', + close: '關閉', + back: '返回', + export: '導出', + download: '下載', + upload: '上傳', + more: '更多', + all: '全部', + yes: '是', + no: '否', + enabled: '啟用', + disabled: '禁用', + pleaseSelect: '請選擇', + pleaseInput: '請輸入', + success: '成功', + failed: '失敗', + operating: '操作', + remark: '備註', + time: '時間', + today: '今日', + yesterday: '昨日', + thisWeek: '本週', + thisMonth: '本月', + thisQuarter: '本季度', + thisYear: '本年', + customDate: '自定義日期', + startDate: '開始日期', + endDate: '結束日期', + language: '語言', + }, + // 登录页 + login: { + title: '歡迎登錄', + name: '康策智能CSM系統', + headerTitle: '康策智能CSM系統', + userName: '請輸入賬號', + passWord: '請輸入密碼', + code: '請輸入驗證碼', + jizhu: '記住賬號', + denglu: '登 錄', + copyright: '上海康策軟件有限公司版權所有', + hotline: '服務熱線:021-60713139', + loginSuccess: '登錄成功', + loginFailed: '登錄失敗', + unknownUserType: '未知用戶類型,無法登錄', + pleaseEnterUserName: '請輸入賬號', + pleaseEnterPassWord: '請輸入密碼', + languageLabel: '語言:', + }, + // 导航菜单 + nav: { + workbench: '我的工作台', + submit: '我的工單', + points: '我的積分', + quickSubmit: '快速提交', + workorders: '服務工單', + reports: '服務報告', + hospitals: '醫院資訊', + customer: '客戶服務', + managerPoints: '客戶經理積分', + account: '帳號管理', + grades: '績效管理', + }, + // 页面标题 + title: { + workbench: '我的工作台', + submit: '我的工單', + points: '我的積分', + workorders: '服務工單', + reports: '服務報告', + hospitals: '醫院資訊', + customer: '客戶服務', + managerPoints: '客戶經理積分', + account: '帳號管理', + grades: '績效管理', + changePassword: '修改密碼', + }, + // 按钮文本 + btn: { + quickSubmit: '快速提交', + view: '查看', + edit: '編輯', + cancel: '取消', + close: '關閉', + detail: '詳情', + process: '處理', + submit: '提交工單', + save: '保存修改', + cancelModal: '取消', + saveChange: '保存修改', + query: '查詢', + reset: '重置', + export: '導出', + download: '下載', + upload: '上傳', + generate: '生成', + add: '添加', + delete: '刪除', + addOrder: '+ 新建工單', + addHospital: '+ 添加醫院', + addAccount: '+ 添加帳號', + quickAddOrder: '+ 快速提交工單', + back: '← 返回', + preview: '查看報告', + downloadPdf: '下載PDF報告', + confirm: '確認修改', + downloadReport: '下載報告', + }, + // 表单标签 + label: { + title: '問題名稱', + description: '問題描述', + attachment: '附件', + dept: '提出科室', + name: '提出人員', + priority: '優先級', + type: '服務類型', + oldPassword: '原密碼', + newPassword: '新密碼', + confirmPassword: '確認密碼', + hospital: '醫院名稱', + hospitalName: '醫院名稱', + contact: '聯繫人', + contactPerson: '聯繫人', + contactDept: '聯繫科室', + contactPosition: '職務', + contactPhone: '聯繫電話', + category: '客戶分類', + signDate: '簽約時間', + acceptDate: '驗收時間', + years: '年限', + maintenanceEndDate: '維保截止時間', + manager: '客戶經理', + acceptanceReport: '驗收報告', + account: '帳號', + accountType: '帳號類型', + password: '密碼', + gender: '性別', + role: '角色', + status: '狀態', + renewal: '續保完成', + contractSigned: '合同簽署', + paymentPaid: '款項支付', + visited: '回訪狀態', + visitResult: '回訪結果', + createTime: '創建時間', + colorTag: '顏色標籤', + currentPassword: '當前密碼', + }, + // 表单 placeholder + placeholder: { + title: '請輸入問題名稱', + description: '請詳細描述問題,並可以編輯器直接貼圖', + dept: '請輸入提出科室', + name: '請輸入提出人員', + type: '請選擇服務類型', + hospital: '請輸入醫院名稱', + contactPerson: '請輸入聯繫人', + contactDept: '請輸入聯繫科室', + contactPosition: '請輸入職務', + contactPhone: '請輸入聯繫電話', + search: '請輸入', + keyword: '搜索標題/工單號', + account: '請輸入帳號', + password: '請輸入密碼', + newPassword: '請輸入新密碼(至少6位)', + confirmPassword: '請再次輸入新密碼', + currentPassword: '請輸入當前密碼', + remark: '請輸入備註資訊...', + }, + // 提示消息 + msg: { + pleaseInputTitle: '請輸入問題名稱', + pleaseInputDescription: '請輸入問題描述', + pleaseSelectPriority: '請選擇優先級', + pleaseSelectType: '請選擇服務類型', + pleaseSelectHospital: '請選擇醫院', + pleaseInputDept: '請輸入提出科室', + pleaseInputName: '請輸入提出人員', + passwordTooShort: '新密碼至少需要6位!', + passwordMismatch: '兩次輸入的新密碼不一致!', + pleaseFillRequired: '請填寫必填項!', + submitSuccess: '工單提交成功!', + editSuccess: '工單修改成功!', + cancelSuccess: '工單已成功取消!', + closeSuccess: '工單已成功關閉!', + passwordChangeSuccess: '密碼修改成功!', + languageChangeSuccess: '語言切換成功!', + themeChangeSuccess: '主題切換成功!', + hospitalAddSuccess: '醫院添加成功!', + hospitalEditSuccess: '醫院資訊修改成功!', + accountAddSuccess: '帳號添加成功!', + accountEditSuccess: '帳號更新成功!', + passwordResetSuccess: '密碼重設成功!', + reportGenerateSuccess: '報告生成成功!', + confirmCancelOrder: '確定要取消工單 {orderId} 嗎?取消後將無法恢復。', + confirmCloseOrder: '確定要關閉工單 {orderId} 嗎?', + }, + // 统计 + stat: { + total: '累計提交工單', + completed: '已完成工單', + pending: '待處理工單', + highPriority: '高優先級工單', + totalOrders: '總工單', + pendingOrders: '待處理', + completedOrders: '已完成', + highPriorityOrders: '高優先級', + high: '高優先級', + medium: '中優先級', + low: '低優先級', + mediumPriority: '中優先級', + lowPriority: '低優先級', + processing: '處理中', + }, + // 表格列 + table: { + id: '工單號', + priority: '優先級', + title: '問題名稱', + type: '服務類型', + status: '狀態', + time: '提交時間', + submitter: '提交人', + action: '操作', + hospital: '醫院名稱', + handler: '處理人', + handleTime: '處理時間', + handleDesc: '處理說明', + registrar: '登記人', + dept: '提出科室', + category: '客戶分類', + contact: '聯繫人', + phone: '聯繫電話', + manager: '客戶經理', + signDate: '簽約日期', + usageYears: '客戶使用年限', + maintenanceEnd: '維保截止時間', + acceptanceReport: '驗收報告', + account: '帳號', + name: '姓名', + gender: '性別', + role: '角色', + createTime: '創建時間', + hospitalName: '醫院名稱', + }, + // 状态 + status: { + pending: '待處理', + processing: '處理中', + completed: '已完成', + closed: '已關閉', + active: '活躍', + inactive: '不活躍', + normal: '正常', + warning: '預警', + urgent: '緊急', + expired: '已過期', + renewed: '已續保', + notRenewed: '未續保', + paid: '已付款', + notPaid: '未付款', + }, + // 优先级 + priority: { + high: '🔴 高', + medium: '🟠 中', + low: '🟢 低', + }, + // 类型 + type: { + issue: '故障問題', + consult: '使用諮詢', + feature: '功能需求', + other: '其他', + }, + // 图表 + chart: { + title: '工單趨勢', + submit: '提交工單', + complete: '完成工單', + bar: '柱狀圖', + line: '折線圖', + }, + // 日期按钮 + dateBtn: { + thisMonth: '本月', + thisQuarter: '本季度', + thisYear: '本年', + customDate: '自定義日期', + }, + // 主题 + theme: { + blue: '穹宇藍', + purple: '星軌紫', + green: '青巒綠', + title: '更換主題', + }, + // 语言 + languageSwitch: { + title: '更換語言', + zhCN: '中文簡體', + zhTW: '中文繁體', + enUS: 'English', + }, + // 模态框 + modal: { + detail: '工單詳情', + edit: '編輯工單', + submit: '快速提交工單', + changePassword: '修改密碼', + changeTheme: '更換主題', + changeLanguage: '更換語言', + addAccount: '添加帳號', + editAccount: '編輯帳號', + resetPassword: '重設密碼', + addHospital: '添加醫院', + editHospital: '編輯醫院', + detailHospital: '醫院詳情', + generateReport: '生成服務報告', + }, + // 用户菜单 + userMenu: { + changePassword: '修改密碼', + changeTheme: '更換主題', + changeLanguage: '更換語言', + logout: '退出登錄', + }, + // 客户分类 + category: { + A: 'A類(活躍)', + B: 'B類(不活躍)', + C: 'C類(待挽回)', + AShort: 'A類', + BShort: 'B類', + CShort: 'C類', + }, + // 角色 + role: { + super: '超級管理員', + manager: '客戶經理', + }, + // 性别 + gender: { + male: '男', + female: '女', + }, + // 文件上传 + upload: { + text: '點擊或拖拽文件到此處添加', + hint: '支持上傳不超過50M的文件', + uploaded: '已上傳文件', + remove: '刪除', + rename: '重新命名', + maxSize50M: '(不超過50M)', + }, + // 积分页面 + points: { + title: '🎁 我的積分', + unit: '分', + rewards: '已獲得15次服務獎勵', + detail: '積分明細', + points: '積分', + pointsTime: '時間', + pointsSource: '來源', + pointsOrder: '工單號', + pointsChange: '積分變動', + pointsDesc: '說明', + }, + // 报告页面 + report: { + list: '服務報告列表', + generate: '生成服務報告', + view: '查看', + download: '下載', + remark: '備註', + search: '輸入醫院名稱搜索', + typeAll: '全部類型', + quarterly: '季度報告', + annual: '年度報告', + period: '報告週期', + quarter: '季度', + year: '年度', + querySuccess: '查詢完成,找到 {count} 條報告記錄。', + }, + // 工单详情 + orderDetail: { + submitTime: '提交時間', + statusChange: '狀態變更日誌', + operator: '操作人', + beforeChange: '變更前', + afterChange: '變更後', + noAttachment: '暫無附件', + currentStatus: '當前狀態', + dept: '提出科室', + name: '提出人員', + handler: '負責人員', + }, + // 修改密码 + password: { + title: '修改密碼', + oldPassword: '原密碼', + newPassword: '新密碼', + confirmPassword: '確認密碼', + submit: '提交', + cancel: '取消', + success: '密碼已修改', + pleaseInputOld: '請輸入原密碼', + pleaseInputNew: '請輸入新密碼', + pleaseInputConfirm: '請再次輸入新密碼', + passwordTooShort: '密碼長度至少 6 位', + passwordMismatch: '兩次密碼不一致', + oldPasswordError: '原密碼錯誤', + accountNotFound: '帳號不存在', + }, + // 账号管理 + account: { + hospitalAccount: '醫院帳號', + adminAccount: '管理員帳號', + list: '帳號列表', + addHospital: '+ 添加醫院帳號', + addAdmin: '+ 添加管理員帳號', + enable: '啟用', + disable: '禁用', + enableSuccess: '帳號 {id} 已啟用', + disableSuccess: '帳號 {id} 已禁用', + resetPassword: '重設密碼', + defaultPassword: '重設後密碼將變為默認密碼:123456', + confirmReset: '確定要重設帳號 {id} 的密碼嗎?', + resetSuccess: '帳號 {id} 的密碼已重設為默認密碼: 123456', + pleaseInputName: '請輸入姓名!', + }, + // 客户服务 + service: { + title: '客戶服務', + monthlyView: '📅 月視圖', + prevMonth: '← 上月', + nextMonth: '下月 →', + phoneVisit: '📞 電話回訪', + onSiteInspection: '🔍 現場巡檢', + training: '📚 培訓記錄', + gift: '🎁 紀念品記錄', + expiring: '本月到期提醒', + searchHospital: '按醫院名稱搜索', + noRecords: '暫無記錄', + }, + // 通用验证 + validation: { + required: '此項必填', + }, + // 通用日期范围 + dateRange: { + today: '今日', + yesterday: '昨天', + thisWeek: '本週', + thisMonth: '本月', + thisQuarter: '本季度', + }, +} diff --git a/src/service/modular/admin/index.js b/src/service/modular/admin/index.js index 6384885..3c30265 100644 --- a/src/service/modular/admin/index.js +++ b/src/service/modular/admin/index.js @@ -9,9 +9,9 @@ export const getAdminOrders = (params) => { export const getAdminOrderDetail = (id) => { return kcRequest.request(`/admin/orders/${id}`, "get"); }; -// 提交工单 -export const createAdminOrder = (data) => { - return kcRequest.request(`/admin/orders`, "post", data); +// 提交工单(multipart/form-data,承载附件 files) +export const createAdminOrder = (formData) => { + return kcRequest.uploadFile(`/admin/orders`, formData); }; // 处理工单 export const processAdminOrder = (id, data) => { @@ -25,11 +25,18 @@ export const getAdminHospitals = (params) => { export const getAdminHospitalDetail = (id) => { return kcRequest.request(`/admin/hospitals/${id}`, "get"); }; -export const createAdminHospital = (data) => { - return kcRequest.request(`/admin/hospitals`, "post", data); +// 新增/编辑医院:使用 multipart/form-data,承载表单字段与验收报告 file[] +export const createAdminHospital = (formData) => { + return kcRequest.uploadFile(`/admin/hospitals`, formData); }; -export const updateAdminHospital = (id, data) => { - return kcRequest.request(`/admin/hospitals/${id}`, "put", data); +export const updateAdminHospital = (id, formData) => { + return kcRequest.uploadFile(`/admin/hospitals/${id}`, formData, true, "PUT"); +}; + +// ============== 通用文件 ============== +// 下载/预览上传的文件(医院验收报告等),GET,返回 Blob +export const getUploadFile = (fileName) => { + return kcRequest.downloadFile(`/upload/${fileName}`); }; // ============== 账号管理 ============== @@ -48,3 +55,8 @@ export const toggleAdminAccountStatus = (id) => { export const resetAdminAccountPassword = (id) => { return kcRequest.request(`/admin/accounts/${id}/reset-password`, "post"); }; + +// 当前登录用户修改自己的密码(401 = 旧密码错误,使用 silent 避免误跳登录页) +export const changeMyPassword = (data) => { + return kcRequest.request(`/admin/accounts/change-password`, "put", data, true, "json", true); +}; diff --git a/src/service/request/index.js b/src/service/request/index.js index cb37c01..b7b8397 100644 --- a/src/service/request/index.js +++ b/src/service/request/index.js @@ -12,7 +12,9 @@ class Request { this.instance = axios.create({ timeout: timeOut, baseURL: - process.env.NODE_ENV == "development" ? "/api/api" : window.location.origin + "/api", + process.env.NODE_ENV == "development" + ? "/api/api" + : window.location.origin + "/api", withCredentials: IS_COOKIES, }); @@ -41,28 +43,43 @@ class Request { (res) => res, (error) => { const status = error?.response?.status; - if (status === 401) { - ElMessage.error("登录已过期,请重新登录"); - useUserStore().clear(); - // 跳到登录页 - if (window.location.hash !== "#/login") { - window.location.hash = "/login"; + // silent 模式下(如修改密码场景,401 仅代表旧密码错误),不弹通用提示、不跳登录页 + const silent = error?.config?.__silent; + if ( + status === 401 && + !error?.config?.url.endsWith("/login") && + !error?.config?.url.endsWith("/change-password") + ) { + if (!silent) { + ElMessage.error("登录已过期,请重新登录"); + useUserStore().clear(); + if (window.location.hash !== "#/login") { + window.location.hash = "/login"; + } } } else if (status === 403) { - ElMessage.error("无操作权限"); + if (!silent) ElMessage.error("无操作权限"); } else if (status >= 500) { - ElMessage.error("服务器内部错误"); + if (!silent) ElMessage.error("服务器内部错误"); } return Promise.reject(error); }, ); } - async request(url, method, params, requireToken = true, headerType = "json") { + async request( + url, + method, + params, + requireToken = true, + headerType = "json", + silent = false, + ) { const config = { url, method, requireToken, + __silent: silent, }; if (headerType === "json") config.jsonHeader = true; if (headerType === "form") config.formHeader = true; @@ -83,8 +100,15 @@ class Request { const body = res.data; if (body && typeof body === "object" && "code" in body) { if (body.code === 200) { - resolve(body.data); - } else if (body.code === 401) { + resolve(body.data || { + code: 200 + }); + } else if ( + body.code === 401 && + // 登录相关接口不弹提示(如登录页本身、修改密码页),其他接口统一处理 + !config.url.endsWith("/login") && + !config.url.endsWith("/change-password") + ) { ElMessage.error(body.message || "未登录"); useUserStore().clear(); if (window.location.hash !== "#/login") { @@ -106,9 +130,25 @@ class Request { }); } - async uploadFile(url, formData, requireToken = true) { + // 下载二进制文件,返回 Blob + async downloadFile(url, requireToken = true) { + const config = { + method: "GET", + url, + requireToken, + responseType: "blob", + }; + return new Promise((resolve, reject) => { + this.instance(config) + .then((res) => resolve(res.data)) + .catch((err) => reject(err)); + }); + } + + // multipart/form-data 上传;method 默认 POST,编辑接口需要 PUT 时可传入 + async uploadFile(url, formData, requireToken = true, method = "POST") { const config = { - method: "POST", + method, url, data: formData, requireToken, diff --git a/src/views/admin/accounts/edit.vue b/src/views/admin/accounts/edit.vue index 6a0aaf0..9deae7c 100644 --- a/src/views/admin/accounts/edit.vue +++ b/src/views/admin/accounts/edit.vue @@ -1,8 +1,8 @@ diff --git a/src/views/admin/password.vue b/src/views/admin/password.vue index 3581fe5..d9b2f44 100644 --- a/src/views/admin/password.vue +++ b/src/views/admin/password.vue @@ -1,33 +1,39 @@ @@ -36,37 +42,73 @@ import { reactive, ref } from "vue"; import { useRouter } from "vue-router"; import { ElMessage } from "element-plus"; +import { useI18n } from "vue-i18n"; +import { changeMyPassword } from "@/service/modular/admin"; +const { t } = useI18n(); const router = useRouter(); const formRef = ref(); const submitting = ref(false); -const form = reactive({ oldPassword: "", newPassword: "", confirmPassword: "" }); +const form = reactive({ + oldPassword: "", + newPassword: "", + confirmPassword: "", +}); const rules = { - oldPassword: [{ required: true, message: "请输入原密码", trigger: "blur" }], + oldPassword: [ + { + required: true, + message: () => t("password.pleaseInputOld"), + trigger: "blur", + }, + ], newPassword: [ - { required: true, message: "请输入新密码", trigger: "blur" }, - { min: 6, message: "密码长度至少 6 位", trigger: "blur" }, + { + required: true, + message: () => t("password.pleaseInputNew"), + trigger: "blur", + }, + { min: 6, message: () => t("password.passwordTooShort"), trigger: "blur" }, ], confirmPassword: [ - { required: true, message: "请再次输入新密码", trigger: "blur" }, { - validator: (_, val, cb) => (val === form.newPassword ? cb() : cb(new Error("两次密码不一致"))), + required: true, + message: () => t("password.pleaseInputConfirm"), + trigger: "blur", + }, + { + validator: (_, val, cb) => + val === form.newPassword + ? cb() + : cb(new Error(t("password.passwordMismatch"))), trigger: "blur", }, ], }; const submit = async () => { - await formRef.value.validate((valid) => { + await formRef.value.validate(async (valid) => { if (!valid) return; submitting.value = true; - // TODO: 调后端接口 - setTimeout(() => { + try { + const res = await changeMyPassword({ + oldPassword: form.oldPassword, + newPassword: form.newPassword, + }); + const status = res.code; + console.log(res); + if (status === 200) { + ElMessage.success(t("password.success")); + setTimeout(() => { + router.replace("/login"); + }, 1000); + } + } catch (err) { + console.log(err?.message || t("common.failed")); + } finally { submitting.value = false; - ElMessage.success("密码已修改"); - router.back(); - }, 600); + } }); }; diff --git a/src/views/admin/performance/score.vue b/src/views/admin/performance/score.vue index 163b5b7..b62dfe3 100644 --- a/src/views/admin/performance/score.vue +++ b/src/views/admin/performance/score.vue @@ -2,43 +2,43 @@
- - + + - + - 查询 - 重置 + {{ $t('btn.query') }} + {{ $t('btn.reset') }} - - - - + + + + - - - + + + - + @@ -61,8 +61,10 @@ diff --git a/src/views/hospital/orders/detail.vue b/src/views/hospital/orders/detail.vue index 3da2f54..1946b6d 100644 --- a/src/views/hospital/orders/detail.vue +++ b/src/views/hospital/orders/detail.vue @@ -1,8 +1,8 @@ - {{ detail.orderNo }} - {{ detail.serviceType }} - {{ detail.createdAt }} - {{ detail.submitter }} - {{ detail.department }} - {{ detail.colorTag }} + {{ detail.orderNo }} + {{ detail.serviceType }} + {{ detail.createdAt }} + {{ detail.submitter }} + {{ detail.department }} + {{ detail.colorTag }}
-
详细描述
+
{{ $t('label.description') }}
-
附件 ({{ (detail.attachments || []).length }})
- +
{{ $t('label.attachment') }} ({{ (detail.attachments || []).length }})
+
-
流转记录
+
{{ $t('orderDetail.statusChange') }}
- - + + - - + + - - + + - 查询 - 重置 - 快速提交 + {{ $t('btn.query') }} + {{ $t('btn.reset') }} + {{ $t('btn.quickSubmit') }} - - - - + + + + - + - - + + @@ -71,8 +71,10 @@ import { onMounted, reactive, ref } from "vue"; import { useRouter } from "vue-router"; import { ElMessage, ElMessageBox } from "element-plus"; +import { useI18n } from "vue-i18n"; import { getHospitalOrders, cancelHospitalOrder } from "@/service/modular/hospital"; +const { t: $t } = useI18n(); const router = useRouter(); const list = ref([]); const total = ref(0); @@ -121,13 +123,13 @@ const goQuick = () => router.push("/hospital/orders/quick"); const cancel = async (row) => { try { - await ElMessageBox.confirm(`确定取消工单「${row.title}」吗?`, "提示", { + await ElMessageBox.confirm(`${$t('msg.confirmCancelOrder').replace('{orderId}', row.title)}`, $t('common.confirm'), { type: "warning", - confirmButtonText: "确定", - cancelButtonText: "再想想", + confirmButtonText: $t('common.confirm'), + cancelButtonText: $t('common.cancel'), }); await cancelHospitalOrder(row.id); - ElMessage.success("已取消"); + ElMessage.success($t('msg.cancelSuccess')); loadList(); } catch (_) { /* canceled */ diff --git a/src/views/hospital/orders/quick.vue b/src/views/hospital/orders/quick.vue index 25eb95a..b9e7edb 100644 --- a/src/views/hospital/orders/quick.vue +++ b/src/views/hospital/orders/quick.vue @@ -2,38 +2,38 @@
- - + + - - + + - + - - + + - + @@ -41,17 +41,17 @@ - + - 提交 - 取消 + {{ $t('common.submit') }} + {{ $t('common.cancel') }} @@ -62,8 +62,10 @@ import { reactive, ref } from "vue"; import { useRouter } from "vue-router"; import { ElMessage } from "element-plus"; +import { useI18n } from "vue-i18n"; import { createHospitalOrder } from "@/service/modular/hospital"; +const { t: $t } = useI18n(); const router = useRouter(); const formRef = ref(); const submitting = ref(false); @@ -78,10 +80,10 @@ const form = reactive({ }); const rules = { - title: [{ required: true, message: "请输入标题", trigger: "blur" }], - serviceType: [{ required: true, message: "请选择服务类型", trigger: "change" }], - priority: [{ required: true, message: "请选择优先级", trigger: "change" }], - description: [{ required: true, message: "请输入详细描述", trigger: "blur" }], + title: [{ required: true, message: () => $t('msg.pleaseInputTitle'), trigger: "blur" }], + serviceType: [{ required: true, message: () => $t('msg.pleaseSelectType'), trigger: "change" }], + priority: [{ required: true, message: () => $t('msg.pleaseSelectPriority'), trigger: "change" }], + description: [{ required: true, message: () => $t('msg.pleaseInputDescription'), trigger: "blur" }], }; const submit = async () => { @@ -90,7 +92,7 @@ const submit = async () => { submitting.value = true; try { await createHospitalOrder(form); - ElMessage.success("提交成功"); + ElMessage.success($t('msg.submitSuccess')); router.replace("/hospital/orders"); } finally { submitting.value = false; diff --git a/src/views/hospital/password.vue b/src/views/hospital/password.vue index 3581fe5..5375bec 100644 --- a/src/views/hospital/password.vue +++ b/src/views/hospital/password.vue @@ -1,33 +1,28 @@ @@ -36,22 +31,24 @@ import { reactive, ref } from "vue"; import { useRouter } from "vue-router"; import { ElMessage } from "element-plus"; +import { useI18n } from "vue-i18n"; +const { t } = useI18n(); const router = useRouter(); const formRef = ref(); const submitting = ref(false); const form = reactive({ oldPassword: "", newPassword: "", confirmPassword: "" }); const rules = { - oldPassword: [{ required: true, message: "请输入原密码", trigger: "blur" }], + oldPassword: [{ required: true, message: () => t('password.pleaseInputOld'), trigger: "blur" }], newPassword: [ - { required: true, message: "请输入新密码", trigger: "blur" }, - { min: 6, message: "密码长度至少 6 位", trigger: "blur" }, + { required: true, message: () => t('password.pleaseInputNew'), trigger: "blur" }, + { min: 6, message: () => t('password.passwordTooShort'), trigger: "blur" }, ], confirmPassword: [ - { required: true, message: "请再次输入新密码", trigger: "blur" }, + { required: true, message: () => t('password.pleaseInputConfirm'), trigger: "blur" }, { - validator: (_, val, cb) => (val === form.newPassword ? cb() : cb(new Error("两次密码不一致"))), + validator: (_, val, cb) => (val === form.newPassword ? cb() : cb(new Error(t('password.passwordMismatch')))), trigger: "blur", }, ], @@ -61,10 +58,9 @@ const submit = async () => { await formRef.value.validate((valid) => { if (!valid) return; submitting.value = true; - // TODO: 调后端接口 setTimeout(() => { submitting.value = false; - ElMessage.success("密码已修改"); + ElMessage.success(t('password.success')); router.back(); }, 600); }); diff --git a/src/views/hospital/points.vue b/src/views/hospital/points.vue index c717219..e61b80c 100644 --- a/src/views/hospital/points.vue +++ b/src/views/hospital/points.vue @@ -4,30 +4,30 @@
{{ summary.totalPoints ?? 0 }}
-
累计积分
+
{{ $t('points.title') }}
{{ summary.rewardCount ?? 0 }}
-
奖励次数
+
{{ $t('points.rewards') }}
- + - - - + + + - - + +