From 51fd06c6a15071e3b4ce4c300363d8944f00e2be Mon Sep 17 00:00:00 2001 From: xiaoxian521 <1923740402@qq.com> Date: Thu, 3 Mar 2022 23:30:08 +0800 Subject: [PATCH] =?UTF-8?q?perf:=20=E5=90=8C=E6=AD=A5=E7=B2=BE=E7=AE=80?= =?UTF-8?q?=E7=89=88=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 14 +- package.json | 10 +- pnpm-lock.yaml | 248 +++++++++++++------------- public/serverConfig.json | 2 +- src/layout/components/sidebar/sidebarItem.vue | 4 + src/layout/frameView.vue | 63 +++++++ src/layout/types.ts | 1 + src/main.ts | 5 +- src/router/index.ts | 11 +- src/router/modules/externalLink.ts | 9 +- src/router/utils.ts | 7 + src/store/modules/multiTags.ts | 2 + src/style/index.scss | 4 +- src/utils/http/index.ts | 4 +- src/utils/http/types.d.ts | 4 +- src/utils/is.ts | 3 +- src/utils/link.ts | 3 +- src/utils/loaders/index.ts | 54 ++++++ src/utils/operate/index.ts | 15 ++ src/utils/print.ts | 226 +++++++++++++++++++++++ src/utils/resize/index.ts | 35 ++++ src/utils/watermark.ts | 116 ++++++++++++ types/global.d.ts | 9 + vite.config.ts | 11 +- 24 files changed, 703 insertions(+), 157 deletions(-) create mode 100644 src/layout/frameView.vue create mode 100644 src/utils/loaders/index.ts create mode 100644 src/utils/print.ts create mode 100644 src/utils/resize/index.ts create mode 100644 src/utils/watermark.ts diff --git a/index.html b/index.html index 7d57d3c..3375b39 100644 --- a/index.html +++ b/index.html @@ -13,20 +13,16 @@
-
Loading...
+
diff --git a/package.json b/package.json index 40b1d44..31819ed 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pure-admin-thin", - "version": "3.0", + "version": "3.1.0", "private": true, "engines": { "node": ">= 16", @@ -53,7 +53,7 @@ "rgb-hex": "^4.0.0", "vue": "^3.2.31", "vue-i18n": "^9.2.0-beta.30", - "vue-router": "^4.0.12", + "vue-router": "^4.0.13", "vue-types": "^4.1.1" }, "devDependencies": { @@ -105,15 +105,15 @@ "stylelint-order": "^5.0.0", "typescript": "^4.5.5", "unplugin-element-plus": "^0.2.0", - "vite": "^2.8.5", + "vite": "^2.8.6", "vite-plugin-live-reload": "^2.1.0", "vite-plugin-mock": "^2.9.6", "vite-plugin-remove-console": "^0.0.6", "vite-plugin-style-import": "1.4.1", - "vite-plugin-windicss": "^1.7.0", + "vite-plugin-windicss": "^1.8.2", "vite-svg-loader": "2.2.0", "vue-eslint-parser": "^8.2.0", - "windicss": "^3.4.3" + "windicss": "^3.5.1" }, "repository": "git@github.com:xiaoxian521/vue-pure-admin.git", "author": "xiaoxian521", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 09b1a5b..6b9d9d0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -71,19 +71,19 @@ specifiers: stylelint-order: ^5.0.0 typescript: ^4.5.5 unplugin-element-plus: ^0.2.0 - vite: ^2.8.5 + vite: ^2.8.6 vite-plugin-live-reload: ^2.1.0 vite-plugin-mock: ^2.9.6 vite-plugin-remove-console: ^0.0.6 vite-plugin-style-import: 1.4.1 - vite-plugin-windicss: ^1.7.0 + vite-plugin-windicss: ^1.8.2 vite-svg-loader: 2.2.0 vue: ^3.2.31 vue-eslint-parser: ^8.2.0 vue-i18n: ^9.2.0-beta.30 - vue-router: ^4.0.12 + vue-router: ^4.0.13 vue-types: ^4.1.1 - windicss: ^3.4.3 + windicss: ^3.5.1 dependencies: "@ctrl/tinycolor": 3.4.0 @@ -110,7 +110,7 @@ dependencies: rgb-hex: 4.0.0 vue: 3.2.31 vue-i18n: 9.2.0-beta.30_vue@3.2.31 - vue-router: 4.0.12_vue@3.2.31 + vue-router: 4.0.13_vue@3.2.31 vue-types: 4.1.1_vue@3.2.31 devDependencies: @@ -130,8 +130,8 @@ devDependencies: "@types/qs": 6.9.7 "@typescript-eslint/eslint-plugin": 5.12.0_c467cf9bb49b295941e83ce479a578b7 "@typescript-eslint/parser": 5.12.0_eslint@8.9.0+typescript@4.5.5 - "@vitejs/plugin-legacy": 1.7.1_vite@2.8.5 - "@vitejs/plugin-vue": 2.2.4_vite@2.8.5+vue@3.2.31 + "@vitejs/plugin-legacy": 1.7.1_vite@2.8.6 + "@vitejs/plugin-vue": 2.2.4_vite@2.8.6+vue@3.2.31 "@vitejs/plugin-vue-jsx": 1.3.8 "@vue/eslint-config-prettier": 7.0.0_eslint@8.9.0+prettier@2.5.1 "@vue/eslint-config-typescript": 10.0.0_cd100ca74b8c3cfb64acbb3ff997764b @@ -161,16 +161,16 @@ devDependencies: stylelint-config-standard: 24.0.0_stylelint@14.5.0 stylelint-order: 5.0.0_stylelint@14.5.0 typescript: 4.5.5 - unplugin-element-plus: 0.2.0_vite@2.8.5+vue@3.2.31 - vite: 2.8.5_sass@1.49.7 + unplugin-element-plus: 0.2.0_vite@2.8.6+vue@3.2.31 + vite: 2.8.6_sass@1.49.7 vite-plugin-live-reload: 2.1.0 - vite-plugin-mock: 2.9.6_mockjs@1.1.0+vite@2.8.5 + vite-plugin-mock: 2.9.6_mockjs@1.1.0+vite@2.8.6 vite-plugin-remove-console: 0.0.6 - vite-plugin-style-import: 1.4.1_vite@2.8.5 - vite-plugin-windicss: 1.7.0_vite@2.8.5 + vite-plugin-style-import: 1.4.1_vite@2.8.6 + vite-plugin-windicss: 1.8.2_vite@2.8.6 vite-svg-loader: 2.2.0 vue-eslint-parser: 8.2.0_eslint@8.9.0 - windicss: 3.4.3 + windicss: 3.5.1 packages: /@ampproject/remapping/2.1.2: @@ -183,13 +183,11 @@ packages: "@jridgewell/trace-mapping": 0.3.4 dev: true - /@antfu/utils/0.4.0: + /@antfu/utils/0.5.0: resolution: { - integrity: sha512-gqkpvjkgFUu+s3kP+Ly33OKpo5zvVY3FDFhv5BIb98SncS3KD6DNxPfNDjwHIoyXbz1leWo1j8DtRLZ1D2Jv+Q== + integrity: sha512-MrAQ/MrPSxbh1bBrmwJjORfJymw4IqSHFBXqvxaga3ZdDM+/zokYF8DjyJpSjY2QmpmgQrajDUBJOWrYeARfzA== } - dependencies: - "@types/throttle-debounce": 2.1.0 dev: true /@babel/code-frame/7.16.7: @@ -1201,13 +1199,6 @@ packages: "@types/node": 14.14.14 dev: true - /@types/throttle-debounce/2.1.0: - resolution: - { - integrity: sha512-5eQEtSCoESnh2FsiLTxE121IiE60hnMqcb435fShf4bpLRjEu1Eoekht23y6zXS9Ts3l+Szu3TARnTsA0GkOkQ== - } - dev: true - /@typescript-eslint/eslint-plugin/5.12.0_c467cf9bb49b295941e83ce479a578b7: resolution: { @@ -1358,7 +1349,7 @@ packages: eslint-visitor-keys: 3.3.0 dev: true - /@vitejs/plugin-legacy/1.7.1_vite@2.8.5: + /@vitejs/plugin-legacy/1.7.1_vite@2.8.6: resolution: { integrity: sha512-RqgILXsGpfV7NHodVCdBVau8ss5+ynMXp6JGF/F7nhSy0bnwSQPlMS3KFqh7twfifXK8VuMriqfU4CxOiqmNnA== @@ -1372,7 +1363,7 @@ packages: magic-string: 0.25.7 regenerator-runtime: 0.13.9 systemjs: 6.12.1 - vite: 2.8.5_sass@1.49.7 + vite: 2.8.6_sass@1.49.7 dev: true /@vitejs/plugin-vue-jsx/1.3.8: @@ -1392,7 +1383,7 @@ packages: - supports-color dev: true - /@vitejs/plugin-vue/2.2.4_vite@2.8.5+vue@3.2.31: + /@vitejs/plugin-vue/2.2.4_vite@2.8.6+vue@3.2.31: resolution: { integrity: sha512-ev9AOlp0ljCaDkFZF3JwC/pD2N4Hh+r5srl5JHM6BKg5+99jiiK0rE/XaRs3pVm1wzyKkjUy/StBSoXX5fFzcw== @@ -1402,7 +1393,7 @@ packages: vite: ^2.5.10 vue: ^3.2.25 dependencies: - vite: 2.8.5_sass@1.49.7 + vite: 2.8.6_sass@1.49.7 vue: 3.2.31 dev: true @@ -1637,32 +1628,32 @@ packages: vue-demi: 0.12.1_vue@3.2.31 dev: false - /@windicss/config/1.7.0: + /@windicss/config/1.8.2: resolution: { - integrity: sha512-jP+SYEUMTcvEQexYAeaIGKWq3sE+yv0myyOCph7Glm/YZE2ZCK1GukI1oDG6fcVer121EQzCY4Rx11trb3oSZg== + integrity: sha512-dGXkzcH1Bnm9716/pE63YSewLQIZXGWerHEotUKf2EMlz/JqsI9Z3yBy/lXVL9HsEoTNpyvMPLk75oquH0vXGg== } dependencies: debug: 4.3.3 - jiti: 1.12.15 - windicss: 3.4.3 + jiti: 1.13.0 + windicss: 3.5.1 transitivePeerDependencies: - supports-color dev: true - /@windicss/plugin-utils/1.7.0: + /@windicss/plugin-utils/1.8.2: resolution: { - integrity: sha512-4zxTIhpGaia4FTxL/c20GQU2bK3bqToerdErvDzwLqWQECVGt7vTGFQd3e4XMpfR6Ujgk4/p7fCHv/F15R/pkA== + integrity: sha512-UlinWxojyGxWV18AyQ1ISeGvtpbw4ITQpcRe0v4PyuJZHwnrrHmxp8o/pg10oEcDKnsTIbjGeZfW5DC+mkjYYQ== } dependencies: - "@antfu/utils": 0.4.0 - "@windicss/config": 1.7.0 + "@antfu/utils": 0.5.0 + "@windicss/config": 1.8.2 debug: 4.3.3 fast-glob: 3.2.11 magic-string: 0.25.7 micromatch: 4.0.4 - windicss: 3.4.3 + windicss: 3.5.1 transitivePeerDependencies: - supports-color dev: true @@ -2932,10 +2923,22 @@ packages: } dev: true - /esbuild-android-arm64/0.14.23: + /esbuild-android-64/0.14.24: + resolution: + { + integrity: sha512-mbhO8NepmUZ84cP/axGR8IzH1Trth+uknEJzz36cZl8FfMA3ooaiBsMyzJ35s70QEAreiEt1XzltZ4pcfOsVUA== + } + engines: { node: ">=12" } + cpu: [x64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /esbuild-android-arm64/0.14.24: resolution: { - integrity: sha512-k9sXem++mINrZty1v4FVt6nC5BQCFG4K2geCIUUqHNlTdFnuvcqsY7prcKZLFhqVC1rbcJAr9VSUGFL/vD4vsw== + integrity: sha512-wM3iuLZjaA9BhlMOH6mWvTGXwPJsLOuAbMkGiczSY+NLeG2WF1ouCcuhFz2jZCbnw9lnI30QWgzebNBQi9K8SA== } engines: { node: ">=12" } cpu: [arm64] @@ -2944,10 +2947,10 @@ packages: dev: true optional: true - /esbuild-darwin-64/0.14.23: + /esbuild-darwin-64/0.14.24: resolution: { - integrity: sha512-lB0XRbtOYYL1tLcYw8BoBaYsFYiR48RPrA0KfA/7RFTr4MV7Bwy/J4+7nLsVnv9FGuQummM3uJ93J3ptaTqFug== + integrity: sha512-GDaCV5e9mdrJkrGT91W8WCqQ/+fvB/nsULIu4l7Ik7dlQd5uB4qeKRcFFl5Vz5ODK/C/UWZmKmMQWokZsLNWLQ== } engines: { node: ">=12" } cpu: [x64] @@ -2956,10 +2959,10 @@ packages: dev: true optional: true - /esbuild-darwin-arm64/0.14.23: + /esbuild-darwin-arm64/0.14.24: resolution: { - integrity: sha512-yat73Z/uJ5tRcfRiI4CCTv0FSnwErm3BJQeZAh+1tIP0TUNh6o+mXg338Zl5EKChD+YGp6PN+Dbhs7qa34RxSw== + integrity: sha512-reU7/vEdXsg+zZWxKL/gaHsJkGMCC49Y4pqbsaBmx0YAF00K0+V7w5BHBF+iY5jvtJ1ZCYRHTN/iAbYVOnoV0w== } engines: { node: ">=12" } cpu: [arm64] @@ -2968,10 +2971,10 @@ packages: dev: true optional: true - /esbuild-freebsd-64/0.14.23: + /esbuild-freebsd-64/0.14.24: resolution: { - integrity: sha512-/1xiTjoLuQ+LlbfjJdKkX45qK/M7ARrbLmyf7x3JhyQGMjcxRYVR6Dw81uH3qlMHwT4cfLW4aEVBhP1aNV7VsA== + integrity: sha512-Mp35Rz/XoixG7Uka6l54hU/XUxAEwQozgKoHPusJzX+Fu1vANil0Ypos0RJkidu7skSkd0xisNIT+gtD36BxpA== } engines: { node: ">=12" } cpu: [x64] @@ -2980,10 +2983,10 @@ packages: dev: true optional: true - /esbuild-freebsd-arm64/0.14.23: + /esbuild-freebsd-arm64/0.14.24: resolution: { - integrity: sha512-uyPqBU/Zcp6yEAZS4LKj5jEE0q2s4HmlMBIPzbW6cTunZ8cyvjG6YWpIZXb1KK3KTJDe62ltCrk3VzmWHp+iLg== + integrity: sha512-+tf4a4zYaHP1XXPt286mxOc2bmj13K57GZYjqYz/G3c3sgNXa0JBkcPlUATIj96WfXhWM115n3nHe9wF88+ZGQ== } engines: { node: ">=12" } cpu: [arm64] @@ -2992,10 +2995,10 @@ packages: dev: true optional: true - /esbuild-linux-32/0.14.23: + /esbuild-linux-32/0.14.24: resolution: { - integrity: sha512-37R/WMkQyUfNhbH7aJrr1uCjDVdnPeTHGeDhZPUNhfoHV0lQuZNCKuNnDvlH/u/nwIYZNdVvz1Igv5rY/zfrzQ== + integrity: sha512-8jMZErn5aLnlSQqzK365yoWRr67ZkGNcoTmk1CK5Bk1EB9g7uwCfdZsmWcclLWPGkIhMbdk4OvzQ+Wp0popwWA== } engines: { node: ">=12" } cpu: [ia32] @@ -3004,10 +3007,10 @@ packages: dev: true optional: true - /esbuild-linux-64/0.14.23: + /esbuild-linux-64/0.14.24: resolution: { - integrity: sha512-H0gztDP60qqr8zoFhAO64waoN5yBXkmYCElFklpd6LPoobtNGNnDe99xOQm28+fuD75YJ7GKHzp/MLCLhw2+vQ== + integrity: sha512-D/JCsk9OY2IZj+fkU74pKD4rD2pjeiYUbze1cS5D6+U0pz8j71GjZY5UkfwHhBBbNyPe6DPCyex97txQUlHwWw== } engines: { node: ">=12" } cpu: [x64] @@ -3016,10 +3019,10 @@ packages: dev: true optional: true - /esbuild-linux-arm/0.14.23: + /esbuild-linux-arm/0.14.24: resolution: { - integrity: sha512-x64CEUxi8+EzOAIpCUeuni0bZfzPw/65r8tC5cy5zOq9dY7ysOi5EVQHnzaxS+1NmV+/RVRpmrzGw1QgY2Xpmw== + integrity: sha512-N+vvGpJAUWv3j+YZGOMEtrHwrrSG582TuAThBwoRE7d2N4zFE2WQBCiSYaAVckMQhvMOPqnCdqeTDUse5nlKTw== } engines: { node: ">=12" } cpu: [arm] @@ -3028,10 +3031,10 @@ packages: dev: true optional: true - /esbuild-linux-arm64/0.14.23: + /esbuild-linux-arm64/0.14.24: resolution: { - integrity: sha512-c4MLOIByNHR55n3KoYf9hYDfBRghMjOiHLaoYLhkQkIabb452RWi+HsNgB41sUpSlOAqfpqKPFNg7VrxL3UX9g== + integrity: sha512-DypWEDQLE+PoHGMa4FLcmKvS+yQLsYlsN03R496rTpDOiVQGrRdo0LbYtf+uHpDxa1KRrHZsQim6n8m3VBHP6g== } engines: { node: ">=12" } cpu: [arm64] @@ -3040,10 +3043,10 @@ packages: dev: true optional: true - /esbuild-linux-mips64le/0.14.23: + /esbuild-linux-mips64le/0.14.24: resolution: { - integrity: sha512-kHKyKRIAedYhKug2EJpyJxOUj3VYuamOVA1pY7EimoFPzaF3NeY7e4cFBAISC/Av0/tiV0xlFCt9q0HJ68IBIw== + integrity: sha512-eMk9pEHba1yd5bOuPZUJfFucigvysdcE2d/wV4M0eUdb/VjyH9fcGqz8byvSjmYSOt3WCn/V4jLVI+pwDSHWYw== } engines: { node: ">=12" } cpu: [mips64el] @@ -3052,10 +3055,10 @@ packages: dev: true optional: true - /esbuild-linux-ppc64le/0.14.23: + /esbuild-linux-ppc64le/0.14.24: resolution: { - integrity: sha512-7ilAiJEPuJJnJp/LiDO0oJm5ygbBPzhchJJh9HsHZzeqO+3PUzItXi+8PuicY08r0AaaOe25LA7sGJ0MzbfBag== + integrity: sha512-4vQ/Y6EV5Z2BjO7RdpEyTCv702WmOPc95d2CbUcFvg78FpGQAmrbIrHXu/yX4+rdUU6vMNBn3M+7M7/lxmxjjg== } engines: { node: ">=12" } cpu: [ppc64] @@ -3064,10 +3067,10 @@ packages: dev: true optional: true - /esbuild-linux-riscv64/0.14.23: + /esbuild-linux-riscv64/0.14.24: resolution: { - integrity: sha512-fbL3ggK2wY0D8I5raPIMPhpCvODFE+Bhb5QGtNP3r5aUsRR6TQV+ZBXIaw84iyvKC8vlXiA4fWLGhghAd/h/Zg== + integrity: sha512-pAN9/+NZ487Wo9PmlOM6Ra95SrhG8JQw7fCgi3z7dUufwTApTNTPGs5UOMD4Bmorju+DeGb0f0GddLaeabvqDg== } engines: { node: ">=12" } cpu: [riscv64] @@ -3076,10 +3079,10 @@ packages: dev: true optional: true - /esbuild-linux-s390x/0.14.23: + /esbuild-linux-s390x/0.14.24: resolution: { - integrity: sha512-GHMDCyfy7+FaNSO8RJ8KCFsnax8fLUsOrj9q5Gi2JmZMY0Zhp75keb5abTFCq2/Oy6KVcT0Dcbyo/bFb4rIFJA== + integrity: sha512-ZR+VMHP2WS3022x2sK/85cBfKGgPalIZzpquDWjra9nUb+WdEzuK9i9bRsstLmjIPs3uIkGfe6xXUh/7PNLllw== } engines: { node: ">=12" } cpu: [s390x] @@ -3088,10 +3091,10 @@ packages: dev: true optional: true - /esbuild-netbsd-64/0.14.23: + /esbuild-netbsd-64/0.14.24: resolution: { - integrity: sha512-ovk2EX+3rrO1M2lowJfgMb/JPN1VwVYrx0QPUyudxkxLYrWeBxDKQvc6ffO+kB4QlDyTfdtAURrVzu3JeNdA2g== + integrity: sha512-1PzXU++e0PEaSuGpkhrVb+fDUw9mSp4laY9KRsjJkAuXPDj0rHz7KxK7CAbzY/ucufeIR9Ca8/oMpdVyWdaOGw== } engines: { node: ">=12" } cpu: [x64] @@ -3100,10 +3103,10 @@ packages: dev: true optional: true - /esbuild-openbsd-64/0.14.23: + /esbuild-openbsd-64/0.14.24: resolution: { - integrity: sha512-uYYNqbVR+i7k8ojP/oIROAHO9lATLN7H2QeXKt2H310Fc8FJj4y3Wce6hx0VgnJ4k1JDrgbbiXM8rbEgQyg8KA== + integrity: sha512-PvXh7JJAFM1kR87XDWbRrUkaOGVMS6Dq/IRXE2E02maio21JELk/jNRijTe81ztr8v+8K9osB3rG9zKqIdTxhQ== } engines: { node: ">=12" } cpu: [x64] @@ -3112,10 +3115,10 @@ packages: dev: true optional: true - /esbuild-sunos-64/0.14.23: + /esbuild-sunos-64/0.14.24: resolution: { - integrity: sha512-hAzeBeET0+SbScknPzS2LBY6FVDpgE+CsHSpe6CEoR51PApdn2IB0SyJX7vGelXzlyrnorM4CAsRyb9Qev4h9g== + integrity: sha512-5iYi76kGQdyCqvSUknqjTZ0T19KvQD6hiklPAY6kVoQ1YoDUGCGILRI9eM/3zLNLG1bUFgcdJ2ktaBxwyXuHyA== } engines: { node: ">=12" } cpu: [x64] @@ -3124,10 +3127,10 @@ packages: dev: true optional: true - /esbuild-windows-32/0.14.23: + /esbuild-windows-32/0.14.24: resolution: { - integrity: sha512-Kttmi3JnohdaREbk6o9e25kieJR379TsEWF0l39PQVHXq3FR6sFKtVPgY8wk055o6IB+rllrzLnbqOw/UV60EA== + integrity: sha512-oDxcNu4P1FWTk2ompKB0uKHfxYw1QuubH189+PlfrrWT9tVu+mxT9dSwJu2erfUDz5dnr6h8rgkg95NGboeJxg== } engines: { node: ">=12" } cpu: [ia32] @@ -3136,10 +3139,10 @@ packages: dev: true optional: true - /esbuild-windows-64/0.14.23: + /esbuild-windows-64/0.14.24: resolution: { - integrity: sha512-JtIT0t8ymkpl6YlmOl6zoSWL5cnCgyLaBdf/SiU/Eg3C13r0NbHZWNT/RDEMKK91Y6t79kTs3vyRcNZbfu5a8g== + integrity: sha512-0uxXF1yLcGEM2es0OMDgQYQGZXQEEIdq8cG3IWhY2GGfFRLXpMgic1iUE+SKCh+b82t1ftUVoyG0zIFRn5NOIA== } engines: { node: ">=12" } cpu: [x64] @@ -3148,10 +3151,10 @@ packages: dev: true optional: true - /esbuild-windows-arm64/0.14.23: + /esbuild-windows-arm64/0.14.24: resolution: { - integrity: sha512-cTFaQqT2+ik9e4hePvYtRZQ3pqOvKDVNarzql0VFIzhc0tru/ZgdLoXd6epLiKT+SzoSce6V9YJ+nn6RCn6SHw== + integrity: sha512-unwaYRaIK/4OaZm0jnM3pLKMPEjaQqmT5teTciSZ86VYaiYZF27Ki7BW7R5ngk27gIw0ovIfUcn9DhJgp7qAlw== } engines: { node: ">=12" } cpu: [arm64] @@ -3169,34 +3172,35 @@ packages: requiresBuild: true dev: true - /esbuild/0.14.23: + /esbuild/0.14.24: resolution: { - integrity: sha512-XjnIcZ9KB6lfonCa+jRguXyRYcldmkyZ99ieDksqW/C8bnyEX299yA4QH2XcgijCgaddEZePPTgvx/2imsq7Ig== + integrity: sha512-NjfmycVQqY0+iKXoHXsvMAKx4XF/bD/dDm8pK6C/3aJO/i/uby+7AR4z8vu0qkiihkB5Y43+9BjdY2MGnswC/A== } engines: { node: ">=12" } hasBin: true requiresBuild: true optionalDependencies: - esbuild-android-arm64: 0.14.23 - esbuild-darwin-64: 0.14.23 - esbuild-darwin-arm64: 0.14.23 - esbuild-freebsd-64: 0.14.23 - esbuild-freebsd-arm64: 0.14.23 - esbuild-linux-32: 0.14.23 - esbuild-linux-64: 0.14.23 - esbuild-linux-arm: 0.14.23 - esbuild-linux-arm64: 0.14.23 - esbuild-linux-mips64le: 0.14.23 - esbuild-linux-ppc64le: 0.14.23 - esbuild-linux-riscv64: 0.14.23 - esbuild-linux-s390x: 0.14.23 - esbuild-netbsd-64: 0.14.23 - esbuild-openbsd-64: 0.14.23 - esbuild-sunos-64: 0.14.23 - esbuild-windows-32: 0.14.23 - esbuild-windows-64: 0.14.23 - esbuild-windows-arm64: 0.14.23 + esbuild-android-64: 0.14.24 + esbuild-android-arm64: 0.14.24 + esbuild-darwin-64: 0.14.24 + esbuild-darwin-arm64: 0.14.24 + esbuild-freebsd-64: 0.14.24 + esbuild-freebsd-arm64: 0.14.24 + esbuild-linux-32: 0.14.24 + esbuild-linux-64: 0.14.24 + esbuild-linux-arm: 0.14.24 + esbuild-linux-arm64: 0.14.24 + esbuild-linux-mips64le: 0.14.24 + esbuild-linux-ppc64le: 0.14.24 + esbuild-linux-riscv64: 0.14.24 + esbuild-linux-s390x: 0.14.24 + esbuild-netbsd-64: 0.14.24 + esbuild-openbsd-64: 0.14.24 + esbuild-sunos-64: 0.14.24 + esbuild-windows-32: 0.14.24 + esbuild-windows-64: 0.14.24 + esbuild-windows-arm64: 0.14.24 dev: true /escalade/3.1.1: @@ -4238,10 +4242,10 @@ packages: resolution: { integrity: sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= } dev: true - /jiti/1.12.15: + /jiti/1.13.0: resolution: { - integrity: sha512-/+K89y6KJA2nISbWrlc/773XdpDgSQq/LdQ+ZZyw2jRxUNyquPtbsDCCCMRzzNORUgroUGc4nAXxJEnQvpViCA== + integrity: sha512-/n9mNxZj/HDSrincJ6RP+L+yXbpnB8FybySBa+IjIaoH9FIxBbrbRT5XUbe8R7zuVM2AQqNMNDDqz0bzx3znOQ== } hasBin: true dev: true @@ -5972,10 +5976,10 @@ packages: yargs: 17.3.1 dev: true - /rollup/2.68.0: + /rollup/2.69.0: resolution: { - integrity: sha512-XrMKOYK7oQcTio4wyTz466mucnd8LzkiZLozZ4Rz0zQD+HeX4nUK4B8GrTX/2EvN2/vBF/i2WnaXboPxo0JylA== + integrity: sha512-kjER91tHyek8gAkuz7+558vSnTQ+pITEok1P0aNOS45ZXyngaqPsXJmSel4QPQnJo7EJMjXUU1/GErWkWiKORg== } engines: { node: ">=10.0.0" } hasBin: true @@ -6766,7 +6770,7 @@ packages: engines: { node: ">= 0.8" } dev: true - /unplugin-element-plus/0.2.0_vite@2.8.5+vue@3.2.31: + /unplugin-element-plus/0.2.0_vite@2.8.6+vue@3.2.31: resolution: { integrity: sha512-eBgNLCZUUCfl68J+pb9MWVh8amBjLWL5yZ8BuNuJfhS6FFGJ/dMtCmAoaeHyI9wE3k+7C4gbfEM78dkX48gfVA== @@ -6777,7 +6781,7 @@ packages: "@rollup/pluginutils": 4.1.2 es-module-lexer: 0.9.3 magic-string: 0.25.7 - unplugin: 0.3.2_vite@2.8.5 + unplugin: 0.3.2_vite@2.8.6 vue: 3.2.31 transitivePeerDependencies: - esbuild @@ -6786,7 +6790,7 @@ packages: - webpack dev: true - /unplugin/0.3.2_vite@2.8.5: + /unplugin/0.3.2_vite@2.8.6: resolution: { integrity: sha512-5d0DMYNKZU+S9eZUiBfw6Co32eRg8myUgBPoWSqG/wDFCUE/WznfSsJnZWi1P9l69x4uLJqt2qVq1xW/AsXFrw== @@ -6806,7 +6810,7 @@ packages: webpack: optional: true dependencies: - vite: 2.8.5_sass@1.49.7 + vite: 2.8.6_sass@1.49.7 webpack-virtual-modules: 0.4.3 dev: true @@ -6890,7 +6894,7 @@ packages: chokidar: 3.5.3 dev: true - /vite-plugin-mock/2.9.6_mockjs@1.1.0+vite@2.8.5: + /vite-plugin-mock/2.9.6_mockjs@1.1.0+vite@2.8.6: resolution: { integrity: sha512-/Rm59oPppe/ncbkSrUuAxIQihlI2YcBmnbR4ST1RA2VzM1C0tEQc1KlbQvnUGhXECAGTaQN2JyasiwXP6EtKgg== @@ -6910,7 +6914,7 @@ packages: fast-glob: 3.2.11 mockjs: 1.1.0 path-to-regexp: 6.2.0 - vite: 2.8.5_sass@1.49.7 + vite: 2.8.6_sass@1.49.7 transitivePeerDependencies: - rollup - supports-color @@ -6923,7 +6927,7 @@ packages: } dev: true - /vite-plugin-style-import/1.4.1_vite@2.8.5: + /vite-plugin-style-import/1.4.1_vite@2.8.6: resolution: { integrity: sha512-lJCRvm7+So0hHdnSJiJPg9gD5mxtL6YY0jmhEph+k7ArpsyvqOh6han2kG5htbWWDZxHkUN9d1BuTFL//yCLLQ== @@ -6937,24 +6941,24 @@ packages: es-module-lexer: 0.9.3 fs-extra: 10.0.0 magic-string: 0.25.7 - vite: 2.8.5_sass@1.49.7 + vite: 2.8.6_sass@1.49.7 transitivePeerDependencies: - supports-color dev: true - /vite-plugin-windicss/1.7.0_vite@2.8.5: + /vite-plugin-windicss/1.8.2_vite@2.8.6: resolution: { - integrity: sha512-1ps7hk6Pr9TqsW9Y+QXmJ9PMowVLjM0h32c+jh9vdQr5Jzyim3hHivR0rXSkDV9znIB9RkjRQD1znRbAMX0OcQ== + integrity: sha512-tO9bCoqIW945ehwMr9D41YPods8b7HXtVtYVPx62dxadxlbcoD7PQ/8wSvLEiIkMMfuDG5WQ6LZaUdmfALC/vQ== } peerDependencies: vite: ^2.0.1 dependencies: - "@windicss/plugin-utils": 1.7.0 + "@windicss/plugin-utils": 1.8.2 debug: 4.3.3 kolorist: 1.5.1 - vite: 2.8.5_sass@1.49.7 - windicss: 3.4.3 + vite: 2.8.6_sass@1.49.7 + windicss: 3.5.1 transitivePeerDependencies: - supports-color dev: true @@ -6969,10 +6973,10 @@ packages: svgo: 2.8.0 dev: true - /vite/2.8.5_sass@1.49.7: + /vite/2.8.6_sass@1.49.7: resolution: { - integrity: sha512-C/7EGNa1ugWejol6nOcd/0d8PR70Nzd+XXwsPbnNOfzZw0NN2xyXfmw/GNDHgr5fcaTSO4gjxCJCrwNhQUMhmA== + integrity: sha512-e4H0QpludOVKkmOsRyqQ7LTcMUDF3mcgyNU4lmi0B5JUbe0ZxeBBl8VoZ8Y6Rfn9eFKYtdXNPcYK97ZwH+K2ug== } engines: { node: ">=12.2.0" } hasBin: true @@ -6988,10 +6992,10 @@ packages: stylus: optional: true dependencies: - esbuild: 0.14.23 + esbuild: 0.14.24 postcss: 8.4.6 resolve: 1.22.0 - rollup: 2.68.0 + rollup: 2.69.0 sass: 1.49.7 optionalDependencies: fsevents: 2.3.2 @@ -7052,13 +7056,13 @@ packages: vue: 3.2.31 dev: false - /vue-router/4.0.12_vue@3.2.31: + /vue-router/4.0.13_vue@3.2.31: resolution: { - integrity: sha512-CPXvfqe+mZLB1kBWssssTiWg4EQERyqJZes7USiqfW9B5N2x+nHlnsM1D3b5CaJ6qgCvMmYJnz+G0iWjNCvXrg== + integrity: sha512-LmXrC+BkDRLak+d5xTMgUYraT3Nj0H/vCbP+7usGvIl9Viqd1UP6AsP0i69pSbn9O0dXK/xCdp4yPw21HqV9Jw== } peerDependencies: - vue: ^3.0.0 + vue: ^3.2.0 dependencies: "@vue/devtools-api": 6.0.11 vue: 3.2.31 @@ -7129,10 +7133,10 @@ packages: isexe: 2.0.0 dev: true - /windicss/3.4.3: + /windicss/3.5.1: resolution: { - integrity: sha512-UnugThsvEgy8RsPm4/B5DYMCAqvZzD6yWU7Anh+f07t5RSJ8zvmAylGLbXrHPJEmCKzo2Mf+fOUvISH7IJqM3A== + integrity: sha512-E1hYZATcZFci/XhGS0sJAMRxULjnK+glNukE78Ku7xeb3jxgMY55fFOdIrav+GjQCsgR+IZxPq9/DwmO6eyc4Q== } engines: { node: ">= 12" } hasBin: true diff --git a/public/serverConfig.json b/public/serverConfig.json index 9f673b1..3cccf6e 100644 --- a/public/serverConfig.json +++ b/public/serverConfig.json @@ -1,5 +1,5 @@ { - "Version": "3.0", + "Version": "3.1.0", "Title": "PureAdmin", "FixedHeader": true, "HiddenSideBar": false, diff --git a/src/layout/components/sidebar/sidebarItem.vue b/src/layout/components/sidebar/sidebarItem.vue index ca404d6..8eddd0a 100644 --- a/src/layout/components/sidebar/sidebarItem.vue +++ b/src/layout/components/sidebar/sidebarItem.vue @@ -111,6 +111,10 @@ function hasOneShowingChild( return true; }); + if (showingChildren[0]?.meta?.showParent) { + return false; + } + if (showingChildren.length === 1) { return true; } diff --git a/src/layout/frameView.vue b/src/layout/frameView.vue new file mode 100644 index 0000000..5899442 --- /dev/null +++ b/src/layout/frameView.vue @@ -0,0 +1,63 @@ + + + + diff --git a/src/layout/types.ts b/src/layout/types.ts index 908f1b0..405f8d8 100644 --- a/src/layout/types.ts +++ b/src/layout/types.ts @@ -67,6 +67,7 @@ export type childrenType = { icon?: string; title?: string; i18n?: boolean; + showParent?: boolean; extraIcon?: { svg?: boolean; name?: string; diff --git a/src/main.ts b/src/main.ts index 6272641..298efb3 100644 --- a/src/main.ts +++ b/src/main.ts @@ -35,9 +35,10 @@ app.component("IconifyIconOnline", IconifyIconOnline); app.component("FontIcon", FontIcon); getServerConfig(app).then(async config => { + app.use(router); + await router.isReady(); injectResponsiveStorage(app, config); setupStore(app); - app.use(router).use(MotionPlugin).use(useElementPlus).use(usI18n); - await router.isReady(); + app.use(MotionPlugin).use(useElementPlus).use(usI18n); app.mount("#app"); }); diff --git a/src/router/index.ts b/src/router/index.ts index c95e1c3..241c6f5 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -1,8 +1,9 @@ +import { isUrl } from "/@/utils/is"; import { toRouteType } from "./types"; import { openLink } from "/@/utils/link"; import NProgress from "/@/utils/progress"; import { constantRoutes } from "./modules"; -import { split, findIndex } from "lodash-unified"; +import { findIndex } from "lodash-unified"; import { transformI18n } from "/@/plugins/i18n"; import remainingRouter from "./modules/remaining"; import { storageSession } from "/@/utils/storage"; @@ -52,7 +53,7 @@ router.beforeEach((to: toRouteType, _from, next) => { } const name = storageSession.getItem("info"); NProgress.start(); - const externalLink = to?.redirectedFrom?.fullPath; + const externalLink = isUrl(to?.name); if (!externalLink) to.matched.some(item => { if (!item.meta.title) return ""; @@ -65,9 +66,9 @@ router.beforeEach((to: toRouteType, _from, next) => { }); if (name) { if (_from?.name) { - // 如果路由包含http 则是超链接 反之是普通路由 - if (externalLink && externalLink.includes("http")) { - openLink(`http${split(externalLink, "http")[1]}`); + // name为超链接 + if (externalLink) { + openLink(to?.name); NProgress.done(); } else { next(); diff --git a/src/router/modules/externalLink.ts b/src/router/modules/externalLink.ts index e00bc77..fe3dff7 100644 --- a/src/router/modules/externalLink.ts +++ b/src/router/modules/externalLink.ts @@ -2,8 +2,7 @@ import { $t } from "/@/plugins/i18n"; const Layout = () => import("/@/layout/index.vue"); const externalLink = { - path: "/external", - name: "external", + path: "/externals", component: Layout, meta: { icon: "link", @@ -13,11 +12,11 @@ const externalLink = { }, children: [ { - path: "https://github.com/xiaoxian521/vue-pure-admin", + path: "/external", + name: "https://pure-admin-doc.vercel.app", meta: { title: $t("menus.externalLink"), - i18n: true, - rank: 191 + i18n: true } } ] diff --git a/src/router/utils.ts b/src/router/utils.ts index 9b2fc3a..57e687a 100644 --- a/src/router/utils.ts +++ b/src/router/utils.ts @@ -13,6 +13,7 @@ import { RouteConfigs } from "/@/layout/types"; import { buildHierarchyTree } from "/@/utils/tree"; import { usePermissionStoreHook } from "/@/store/modules/permission"; const Layout = () => import("/@/layout/index.vue"); +const IFrame = () => import("/@/layout/frameView.vue"); // https://cn.vitejs.dev/guide/features.html#glob-import const modulesRoutes = import.meta.glob("/src/views/**/*.{vue,tsx}"); @@ -126,6 +127,10 @@ function initRouter(name: string) { // 最终路由进行升序 ascending(router.options.routes[0].children); if (!router.hasRoute(v?.name)) router.addRoute(v); + const flattenRouters = router + .getRoutes() + .find(n => n.path === "/"); + router.addRoute(flattenRouters); } resolve(router); } @@ -218,6 +223,8 @@ function addAsyncRoutes(arrRoutes: Array) { arrRoutes.forEach((v: RouteRecordRaw) => { if (v.redirect) { v.component = Layout; + } else if (v.meta?.frameSrc) { + v.component = IFrame; } else { const index = modulesRoutesKeys.findIndex(ev => ev.includes(v.path)); v.component = modulesRoutes[modulesRoutesKeys[index]]; diff --git a/src/store/modules/multiTags.ts b/src/store/modules/multiTags.ts index 71c60ab..406e4e0 100644 --- a/src/store/modules/multiTags.ts +++ b/src/store/modules/multiTags.ts @@ -1,5 +1,6 @@ import { defineStore } from "pinia"; import { store } from "/@/store"; +import { isUrl } from "/@/utils/is"; import { isEqual } from "lodash-unified"; import { storageLocal } from "/@/utils/storage"; import { multiType, positionType } from "./types"; @@ -54,6 +55,7 @@ export const useMultiTagsStore = defineStore({ case "push": { const tagVal = value as multiType; + if (isUrl(tagVal?.name)) return; const tagPath = tagVal?.path; // 判断tag是否已存在 const tagHasExits = this.multiTags.some(tag => { diff --git a/src/style/index.scss b/src/style/index.scss index 60f5ac0..991bac4 100644 --- a/src/style/index.scss +++ b/src/style/index.scss @@ -12,8 +12,8 @@ body { -moz-osx-font-smoothing: grayscale; -webkit-font-smoothing: antialiased; text-rendering: optimizelegibility; - font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, - Microsoft YaHei, Arial, sans-serif; + font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", + "Microsoft YaHei", "微软雅黑", Arial, sans-serif; } html { diff --git a/src/utils/http/index.ts b/src/utils/http/index.ts index 625ca61..59d5bd8 100644 --- a/src/utils/http/index.ts +++ b/src/utils/http/index.ts @@ -3,7 +3,7 @@ import { resultType, PureHttpError, RequestMethods, - PureHttpResoponse, + PureHttpResponse, PureHttpRequestConfig } from "./types.d"; import qs from "qs"; @@ -91,7 +91,7 @@ class PureHttp { private httpInterceptorsResponse(): void { const instance = PureHttp.axiosInstance; instance.interceptors.response.use( - (response: PureHttpResoponse) => { + (response: PureHttpResponse) => { const $config = response.config; // 关闭进度条动画 NProgress.done(); diff --git a/src/utils/http/types.d.ts b/src/utils/http/types.d.ts index 55a7db9..197b152 100644 --- a/src/utils/http/types.d.ts +++ b/src/utils/http/types.d.ts @@ -18,13 +18,13 @@ export interface PureHttpError extends AxiosError { isCancelRequest?: boolean; } -export interface PureHttpResoponse extends AxiosResponse { +export interface PureHttpResponse extends AxiosResponse { config: PureHttpRequestConfig; } export interface PureHttpRequestConfig extends AxiosRequestConfig { beforeRequestCallback?: (request: PureHttpRequestConfig) => void; - beforeResponseCallback?: (response: PureHttpResoponse) => void; + beforeResponseCallback?: (response: PureHttpResponse) => void; } export default class PureHttp { diff --git a/src/utils/is.ts b/src/utils/is.ts index 7d4f345..3a351c6 100644 --- a/src/utils/is.ts +++ b/src/utils/is.ts @@ -94,8 +94,9 @@ export const isServer = typeof window === "undefined"; export const isClient = !isServer; -export function isUrl(path: string): boolean { +export function isUrl(path: T): boolean { const reg = /(((^https?:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)$/; + // @ts-expect-error return reg.test(path); } diff --git a/src/utils/link.ts b/src/utils/link.ts index db04e7c..144cf77 100644 --- a/src/utils/link.ts +++ b/src/utils/link.ts @@ -1,5 +1,6 @@ -export const openLink = (link: string) => { +export const openLink = (link: T): void => { const $a: HTMLElement = document.createElement("a"); + // @ts-expect-error $a.setAttribute("href", link); $a.setAttribute("target", "_blank"); $a.setAttribute("rel", "noreferrer noopener"); diff --git a/src/utils/loaders/index.ts b/src/utils/loaders/index.ts new file mode 100644 index 0000000..066ed01 --- /dev/null +++ b/src/utils/loaders/index.ts @@ -0,0 +1,54 @@ +interface ProxyLoader { + loadCss(src: string): any; + loadScript(src: string): Promise; + loadScriptConcurrent(src: Array): Promise; +} + +class loaderProxy implements ProxyLoader { + constructor() {} + + protected scriptLoaderCache: Array = []; + + public loadCss = (src: string): any => { + const element: HTMLLinkElement = document.createElement("link"); + element.rel = "stylesheet"; + element.href = src; + document.body.appendChild(element); + }; + + public loadScript = async (src: string): Promise => { + if (this.scriptLoaderCache.includes(src)) { + return src; + } else { + const element: HTMLScriptElement = document.createElement("script"); + element.src = src; + document.body.appendChild(element); + element.onload = () => { + return this.scriptLoaderCache.push(src); + }; + } + }; + + public loadScriptConcurrent = async ( + srcList: Array + ): Promise => { + if (Array.isArray(srcList)) { + const len: number = srcList.length; + if (len > 0) { + let count = 0; + srcList.map(src => { + if (src) { + this.loadScript(src).then(() => { + count++; + if (count === len) { + return; + } + }); + } + }); + } + } + }; +} + +export const loader = new loaderProxy(); diff --git a/src/utils/operate/index.ts b/src/utils/operate/index.ts index 13da7cf..605cf04 100644 --- a/src/utils/operate/index.ts +++ b/src/utils/operate/index.ts @@ -1,3 +1,5 @@ +import type { FunctionArgs } from "@vueuse/core"; + export const hasClass = (ele: RefType, cls: string): any => { return !!ele.className.match(new RegExp("(\\s|^)" + cls + "(\\s|$)")); }; @@ -40,3 +42,16 @@ export const toggleClass = ( className = className.replace(clsName, ""); targetEl.className = flag ? `${className} ${clsName} ` : className; }; + +export function useRafThrottle(fn: T): T { + let locked = false; + // @ts-ignore + return function (...args) { + if (locked) return; + locked = true; + window.requestAnimationFrame(() => { + fn.apply(this, args); + locked = false; + }); + }; +} diff --git a/src/utils/print.ts b/src/utils/print.ts new file mode 100644 index 0000000..c788eb7 --- /dev/null +++ b/src/utils/print.ts @@ -0,0 +1,226 @@ +interface PrintFunction { + extendOptions: Function; + getStyle: Function; + setDomHeight: Function; + toPrint: Function; +} + +const Print = function (dom, options?: object): PrintFunction { + options = options || {}; + // @ts-expect-error + if (!(this instanceof Print)) return new Print(dom, options); + this.conf = { + styleStr: "", + // Elements that need to dynamically get and set the height + setDomHeightArr: [], + // Echart dom List + echartDomArr: [], + // Callback before printing + printBeforeFn: null, + // Callback after printing + printDoneCallBack: null + }; + for (const key in this.conf) { + // eslint-disable-next-line no-prototype-builtins + if (key && options.hasOwnProperty(key)) { + this.conf[key] = options[key]; + } + } + if (typeof dom === "string") { + this.dom = document.querySelector(dom); + } else { + this.dom = this.isDOM(dom) ? dom : dom.$el; + } + if (this.conf.setDomHeightArr && this.conf.setDomHeightArr.length) { + this.setDomHeight(this.conf.setDomHeightArr); + } + this.init(); +}; + +Print.prototype = { + /** + * init + */ + init: function (): void { + const content = this.getStyle() + this.getHtml(); + this.writeIframe(content); + }, + /** + * Configuration property extension + * @param {Object} obj + * @param {Object} obj2 + */ + extendOptions: function (obj, obj2: T): T { + for (const k in obj2) { + obj[k] = obj2[k]; + } + return obj; + }, + /** + Copy all styles of the original page + */ + getStyle: function (): string { + let str = ""; + const styles: NodeListOf = document.querySelectorAll("style,link"); + for (let i = 0; i < styles.length; i++) { + str += styles[i].outerHTML; + } + str += ``; + return str; + }, + // form assignment + getHtml: function (): Element { + const inputs = document.querySelectorAll("input"); + const selects = document.querySelectorAll("select"); + const textareas = document.querySelectorAll("textarea"); + for (let k = 0; k < inputs.length; k++) { + if (inputs[k].type == "checkbox" || inputs[k].type == "radio") { + if (inputs[k].checked == true) { + inputs[k].setAttribute("checked", "checked"); + } else { + inputs[k].removeAttribute("checked"); + } + } else if (inputs[k].type == "text") { + inputs[k].setAttribute("value", inputs[k].value); + } else { + inputs[k].setAttribute("value", inputs[k].value); + } + } + + for (let k2 = 0; k2 < textareas.length; k2++) { + if (textareas[k2].type == "textarea") { + textareas[k2].innerHTML = textareas[k2].value; + } + } + + for (let k3 = 0; k3 < selects.length; k3++) { + if (selects[k3].type == "select-one") { + const child = selects[k3].children; + for (const i in child) { + if (child[i].tagName == "OPTION") { + // @ts-ignore + if (child[i].selected == true) { + child[i].setAttribute("selected", "selected"); + } else { + child[i].removeAttribute("selected"); + } + } + } + } + } + + return this.dom.outerHTML; + }, + /** + create iframe + */ + writeIframe: function (content) { + let w: Document | Window; + let doc: Document; + const iframe: HTMLIFrameElement = document.createElement("iframe"); + const f: HTMLIFrameElement = document.body.appendChild(iframe); + iframe.id = "myIframe"; + iframe.setAttribute( + "style", + "position:absolute;width:0;height:0;top:-10px;left:-10px;" + ); + // eslint-disable-next-line prefer-const + w = f.contentWindow || f.contentDocument; + // eslint-disable-next-line prefer-const + doc = f.contentDocument || f.contentWindow.document; + doc.open(); + doc.write(content); + doc.close(); + // eslint-disable-next-line @typescript-eslint/no-this-alias + const _this = this; + iframe.onload = function (): void { + // Before popping, callback + if (_this.conf.printBeforeFn) { + _this.conf.printBeforeFn({ doc }); + } + + _this.drawEchartImg(doc).then(() => { + _this.toPrint(w); + setTimeout(function () { + document.body.removeChild(iframe); + // After popup, callback + if (_this.conf.printDoneCallBack) { + _this.conf.printDoneCallBack(); + } + }, 100); + }); + }; + }, + /** + * echarts printing + * @param {Object} doc iframe window + */ + drawEchartImg(doc): Promise { + return new Promise(resolve => { + if (this.conf.echartDomArr && this.conf.echartDomArr.length > 0) { + this.conf.echartDomArr.forEach(e => { + const dom = doc.querySelector("#" + e.$el.id); + const img = new Image(); + const w = dom.offsetWidth + "px"; + const H = dom.offsetHeight + "px"; + + img.style.width = w; + img.style.height = H; + img.src = e.imgSrc; + dom.innerHTML = ""; + dom.appendChild(img); + }); + } + resolve(); + }); + }, + /** + Print + */ + toPrint: function (frameWindow): void { + try { + setTimeout(function () { + frameWindow.focus(); + try { + if (!frameWindow.document.execCommand("print", false, null)) { + frameWindow.print(); + } + } catch (e) { + frameWindow.print(); + } + frameWindow.close(); + }, 10); + } catch (err) { + console.error(err); + } + }, + isDOM: + typeof HTMLElement === "object" + ? function (obj) { + return obj instanceof HTMLElement; + } + : function (obj) { + return ( + obj && + typeof obj === "object" && + obj.nodeType === 1 && + typeof obj.nodeName === "string" + ); + }, + /** + * Set the height of the specified dom element by getting the existing height of the dom element and setting + * @param {Array} arr + */ + setDomHeight(arr) { + if (arr && arr.length) { + arr.forEach(name => { + const domArr = document.querySelectorAll(name); + domArr.forEach(dom => { + dom.style.height = dom.offsetHeight + "px"; + }); + }); + } + } +}; + +export default Print; diff --git a/src/utils/resize/index.ts b/src/utils/resize/index.ts new file mode 100644 index 0000000..cb94a2d --- /dev/null +++ b/src/utils/resize/index.ts @@ -0,0 +1,35 @@ +import ResizeObserver from "resize-observer-polyfill"; + +const isServer = typeof window === "undefined"; + +const resizeHandler = (entries: any[]): void => { + for (const entry of entries) { + const listeners = entry.target.__resizeListeners__ || []; + if (listeners.length) { + listeners.forEach((fn: () => any) => { + fn(); + }); + } + } +}; + +export const addResizeListener = (element: any, fn: () => any): any => { + if (isServer) return; + if (!element.__resizeListeners__) { + element.__resizeListeners__ = []; + element.__ro__ = new ResizeObserver(resizeHandler); + element.__ro__.observe(element); + } + element.__resizeListeners__.push(fn); +}; + +export const removeResizeListener = (element: any, fn: () => any): any => { + if (!element || !element.__resizeListeners__) return; + element.__resizeListeners__.splice( + element.__resizeListeners__.indexOf(fn), + 1 + ); + if (!element.__resizeListeners__.length) { + element.__ro__.disconnect(); + } +}; diff --git a/src/utils/watermark.ts b/src/utils/watermark.ts new file mode 100644 index 0000000..5c4327b --- /dev/null +++ b/src/utils/watermark.ts @@ -0,0 +1,116 @@ +import { + ref, + Ref, + unref, + shallowRef, + onBeforeUnmount, + getCurrentInstance +} from "vue"; +import { isDef } from "/@/utils/is"; +import { useRafThrottle } from "/@/utils/operate"; +import { addResizeListener, removeResizeListener } from "/@/utils/resize"; + +const domSymbol = Symbol("watermark-dom"); + +type attr = { + font?: string; + fillStyle?: string; +}; + +export function useWatermark( + appendEl: Ref = ref(document.body) as Ref +) { + const func = useRafThrottle(function () { + const el = unref(appendEl); + if (!el) return; + const { clientHeight: height, clientWidth: width } = el; + updateWatermark({ height, width }); + }); + const id = domSymbol.toString(); + const watermarkEl = shallowRef(); + + const clear = () => { + const domId = unref(watermarkEl); + watermarkEl.value = undefined; + const el = unref(appendEl); + if (!el) return; + domId && el.removeChild(domId); + removeResizeListener(el, func); + }; + + function createBase64(str: string, attr?: attr) { + const can = document.createElement("canvas"); + const width = 300; + const height = 240; + Object.assign(can, { width, height }); + + const cans = can.getContext("2d"); + if (cans) { + cans.rotate((-20 * Math.PI) / 120); + cans.font = attr?.font ?? "15px Reggae One"; + cans.fillStyle = attr?.fillStyle ?? "rgba(0, 0, 0, 0.15)"; + cans.textAlign = "left"; + cans.textBaseline = "middle"; + cans.fillText(str, width / 20, height); + } + return can.toDataURL("image/png"); + } + + function updateWatermark( + options: { + width?: number; + height?: number; + str?: string; + attr?: attr; + } = {} + ) { + const el = unref(watermarkEl); + if (!el) return; + if (isDef(options.width)) { + el.style.width = `${options.width}px`; + } + if (isDef(options.height)) { + el.style.height = `${options.height}px`; + } + if (isDef(options.str)) { + el.style.background = `url(${createBase64( + options.str, + options.attr + )}) left top repeat`; + } + } + + const createWatermark = (str: string, attr?: attr) => { + if (unref(watermarkEl)) { + updateWatermark({ str, attr }); + return id; + } + const div = document.createElement("div"); + watermarkEl.value = div; + div.id = id; + div.style.pointerEvents = "none"; + div.style.top = "0px"; + div.style.left = "0px"; + div.style.position = "absolute"; + div.style.zIndex = "100000"; + const el = unref(appendEl); + if (!el) return id; + const { clientHeight: height, clientWidth: width } = el; + updateWatermark({ str, width, height, attr }); + el.appendChild(div); + return id; + }; + + function setWatermark(str: string, attr?: attr) { + createWatermark(str, attr); + addResizeListener(document.documentElement, func); + const instance = getCurrentInstance(); + if (instance) { + onBeforeUnmount(() => { + clear(); + }); + } + } + + return { setWatermark, clear }; +} diff --git a/types/global.d.ts b/types/global.d.ts index 40f075e..a9bb9ca 100644 --- a/types/global.d.ts +++ b/types/global.d.ts @@ -16,6 +16,15 @@ declare module "vue" { } declare global { + const __APP_INFO__: { + pkg: { + name: string; + version: string; + dependencies: Recordable; + devDependencies: Recordable; + }; + lastBuildTime: string; + }; interface Window { // Global vue app instance __APP__: App; diff --git a/vite.config.ts b/vite.config.ts index 786a950..2618f13 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,4 +1,6 @@ +import dayjs from "dayjs"; import { resolve } from "path"; +import pkg from "./package.json"; import { warpperEnv, regExps } from "./build"; import { getPluginsList } from "./build/plugins"; import { UserConfigExport, ConfigEnv, loadEnv } from "vite"; @@ -19,6 +21,12 @@ const alias: Record = { "vue-i18n": "vue-i18n/dist/vue-i18n.cjs.js" }; +const { dependencies, devDependencies, name, version } = pkg; +const __APP_INFO__ = { + pkg: { dependencies, devDependencies, name, version }, + lastBuildTime: dayjs(new Date()).format("YYYY-MM-DD HH:mm:ss") +}; + export default ({ command, mode }: ConfigEnv): UserConfigExport => { const { VITE_PORT, @@ -90,7 +98,8 @@ export default ({ command, mode }: ConfigEnv): UserConfigExport => { chunkSizeWarningLimit: 2000 }, define: { - __INTLIFY_PROD_DEVTOOLS__: false + __INTLIFY_PROD_DEVTOOLS__: false, + __APP_INFO__: JSON.stringify(__APP_INFO__) } }; };