完善部分审核

This commit is contained in:
LiuQAQQWQ 2025-12-10 09:13:06 +08:00
parent 104dc73597
commit 4a50879d5d
9 changed files with 1293 additions and 505 deletions

503
admin/package-lock.json generated
View File

@ -24,6 +24,7 @@
"lodash-es": "^4.17.21",
"nprogress": "^0.2.0",
"pinia": "^2.2.2",
"qrcode": "^1.5.4",
"vue": "^3.4.38",
"vue-clipboard3": "^2.0.0",
"vue-echarts": "^6.7.3",
@ -1817,7 +1818,6 @@
"version": "5.0.1",
"resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
"dev": true,
"engines": {
"node": ">=8"
}
@ -2420,6 +2420,84 @@
"tiny-emitter": "^2.0.0"
}
},
"node_modules/cliui": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
"integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
"license": "ISC",
"dependencies": {
"string-width": "^4.2.0",
"strip-ansi": "^6.0.0",
"wrap-ansi": "^6.2.0"
}
},
"node_modules/cliui/node_modules/ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"license": "MIT",
"dependencies": {
"color-convert": "^2.0.1"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/cliui/node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"license": "MIT",
"dependencies": {
"color-name": "~1.1.4"
},
"engines": {
"node": ">=7.0.0"
}
},
"node_modules/cliui/node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"license": "MIT"
},
"node_modules/cliui/node_modules/emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
"license": "MIT"
},
"node_modules/cliui/node_modules/string-width": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"license": "MIT",
"dependencies": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
"strip-ansi": "^6.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/cliui/node_modules/wrap-ansi": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
"integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
"license": "MIT",
"dependencies": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
"strip-ansi": "^6.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/clone": {
"version": "1.0.4",
"resolved": "https://registry.npmmirror.com/clone/-/clone-1.0.4.tgz",
@ -2832,6 +2910,15 @@
}
}
},
"node_modules/decamelize": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
"integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==",
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/decode-uri-component": {
"version": "0.2.2",
"resolved": "https://registry.npmmirror.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz",
@ -2912,6 +2999,12 @@
"integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==",
"dev": true
},
"node_modules/dijkstrajs": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.3.tgz",
"integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==",
"license": "MIT"
},
"node_modules/dir-glob": {
"version": "3.0.1",
"resolved": "https://registry.npmmirror.com/dir-glob/-/dir-glob-3.0.1.tgz",
@ -4560,6 +4653,15 @@
"node": ">=6.9.0"
}
},
"node_modules/get-caller-file": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
"license": "ISC",
"engines": {
"node": "6.* || 8.* || >= 10.*"
}
},
"node_modules/get-intrinsic": {
"version": "1.2.4",
"resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
@ -5262,7 +5364,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
"dev": true,
"engines": {
"node": ">=8"
}
@ -6441,6 +6542,15 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/p-try": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/package-json-from-dist": {
"version": "1.0.0",
"resolved": "https://registry.npmmirror.com/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz",
@ -6502,7 +6612,6 @@
"version": "4.0.0",
"resolved": "https://registry.npmmirror.com/path-exists/-/path-exists-4.0.0.tgz",
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
"dev": true,
"engines": {
"node": ">=8"
}
@ -6682,6 +6791,15 @@
"integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==",
"dev": true
},
"node_modules/pngjs": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz",
"integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==",
"license": "MIT",
"engines": {
"node": ">=10.13.0"
}
},
"node_modules/posix-character-classes": {
"version": "0.1.1",
"resolved": "https://registry.npmmirror.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
@ -6980,6 +7098,23 @@
"node": ">=6"
}
},
"node_modules/qrcode": {
"version": "1.5.4",
"resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.4.tgz",
"integrity": "sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==",
"license": "MIT",
"dependencies": {
"dijkstrajs": "^1.0.1",
"pngjs": "^5.0.0",
"yargs": "^15.3.1"
},
"bin": {
"qrcode": "bin/qrcode"
},
"engines": {
"node": ">=10.13.0"
}
},
"node_modules/query-string": {
"version": "4.3.4",
"resolved": "https://registry.npmmirror.com/query-string/-/query-string-4.3.4.tgz",
@ -7149,6 +7284,21 @@
"node": ">=0.10"
}
},
"node_modules/require-directory": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
"integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/require-main-filename": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
"integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
"license": "ISC"
},
"node_modules/resize-detector": {
"version": "0.3.0",
"resolved": "https://registry.npmmirror.com/resize-detector/-/resize-detector-0.3.0.tgz",
@ -7396,6 +7546,12 @@
"upper-case-first": "^2.0.2"
}
},
"node_modules/set-blocking": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
"integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==",
"license": "ISC"
},
"node_modules/set-function-length": {
"version": "1.2.2",
"resolved": "https://registry.npmmirror.com/set-function-length/-/set-function-length-1.2.2.tgz",
@ -7978,7 +8134,6 @@
"version": "6.0.1",
"resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"dev": true,
"dependencies": {
"ansi-regex": "^5.0.1"
},
@ -9528,6 +9683,12 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/which-module": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz",
"integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==",
"license": "ISC"
},
"node_modules/which-typed-array": {
"version": "1.1.15",
"resolved": "https://registry.npmmirror.com/which-typed-array/-/which-typed-array-1.1.15.tgz",
@ -9703,6 +9864,12 @@
"node": ">=12"
}
},
"node_modules/y18n": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
"integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==",
"license": "ISC"
},
"node_modules/yallist": {
"version": "3.1.1",
"resolved": "https://registry.npmmirror.com/yallist/-/yallist-3.1.1.tgz",
@ -9721,6 +9888,122 @@
"node": ">= 14"
}
},
"node_modules/yargs": {
"version": "15.4.1",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",
"integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
"license": "MIT",
"dependencies": {
"cliui": "^6.0.0",
"decamelize": "^1.2.0",
"find-up": "^4.1.0",
"get-caller-file": "^2.0.1",
"require-directory": "^2.1.1",
"require-main-filename": "^2.0.0",
"set-blocking": "^2.0.0",
"string-width": "^4.2.0",
"which-module": "^2.0.0",
"y18n": "^4.0.0",
"yargs-parser": "^18.1.2"
},
"engines": {
"node": ">=8"
}
},
"node_modules/yargs-parser": {
"version": "18.1.3",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz",
"integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
"license": "ISC",
"dependencies": {
"camelcase": "^5.0.0",
"decamelize": "^1.2.0"
},
"engines": {
"node": ">=6"
}
},
"node_modules/yargs-parser/node_modules/camelcase": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/yargs/node_modules/emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
"license": "MIT"
},
"node_modules/yargs/node_modules/find-up": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
"integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
"license": "MIT",
"dependencies": {
"locate-path": "^5.0.0",
"path-exists": "^4.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/yargs/node_modules/locate-path": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
"integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
"license": "MIT",
"dependencies": {
"p-locate": "^4.1.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/yargs/node_modules/p-limit": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
"integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
"license": "MIT",
"dependencies": {
"p-try": "^2.0.0"
},
"engines": {
"node": ">=6"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/yargs/node_modules/p-locate": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
"integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
"license": "MIT",
"dependencies": {
"p-limit": "^2.2.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/yargs/node_modules/string-width": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"license": "MIT",
"dependencies": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
"strip-ansi": "^6.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/yocto-queue": {
"version": "0.1.0",
"resolved": "https://registry.npmmirror.com/yocto-queue/-/yocto-queue-0.1.0.tgz",
@ -10995,8 +11278,7 @@
"ansi-regex": {
"version": "5.0.1",
"resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
"dev": true
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
},
"ansi-styles": {
"version": "3.2.1",
@ -11433,6 +11715,64 @@
"tiny-emitter": "^2.0.0"
}
},
"cliui": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
"integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
"requires": {
"string-width": "^4.2.0",
"strip-ansi": "^6.0.0",
"wrap-ansi": "^6.2.0"
},
"dependencies": {
"ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"requires": {
"color-convert": "^2.0.1"
}
},
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"requires": {
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
"emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
},
"string-width": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"requires": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
"strip-ansi": "^6.0.1"
}
},
"wrap-ansi": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
"integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
"requires": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
"strip-ansi": "^6.0.0"
}
}
}
},
"clone": {
"version": "1.0.4",
"resolved": "https://registry.npmmirror.com/clone/-/clone-1.0.4.tgz",
@ -11749,6 +12089,11 @@
"ms": "2.1.2"
}
},
"decamelize": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
"integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA=="
},
"decode-uri-component": {
"version": "0.2.2",
"resolved": "https://registry.npmmirror.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz",
@ -11808,6 +12153,11 @@
"integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==",
"dev": true
},
"dijkstrajs": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.3.tgz",
"integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA=="
},
"dir-glob": {
"version": "3.0.1",
"resolved": "https://registry.npmmirror.com/dir-glob/-/dir-glob-3.0.1.tgz",
@ -12942,6 +13292,11 @@
"integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
"dev": true
},
"get-caller-file": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="
},
"get-intrinsic": {
"version": "1.2.4",
"resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
@ -13448,8 +13803,7 @@
"is-fullwidth-code-point": {
"version": "3.0.0",
"resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
"dev": true
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
},
"is-glob": {
"version": "4.0.3",
@ -14342,6 +14696,11 @@
"p-limit": "^3.0.2"
}
},
"p-try": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="
},
"package-json-from-dist": {
"version": "1.0.0",
"resolved": "https://registry.npmmirror.com/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz",
@ -14396,8 +14755,7 @@
"path-exists": {
"version": "4.0.0",
"resolved": "https://registry.npmmirror.com/path-exists/-/path-exists-4.0.0.tgz",
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
"dev": true
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="
},
"path-is-absolute": {
"version": "1.0.1",
@ -14518,6 +14876,11 @@
}
}
},
"pngjs": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz",
"integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw=="
},
"posix-character-classes": {
"version": "0.1.1",
"resolved": "https://registry.npmmirror.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
@ -14696,6 +15059,16 @@
"integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
"dev": true
},
"qrcode": {
"version": "1.5.4",
"resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.4.tgz",
"integrity": "sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==",
"requires": {
"dijkstrajs": "^1.0.1",
"pngjs": "^5.0.0",
"yargs": "^15.3.1"
}
},
"query-string": {
"version": "4.3.4",
"resolved": "https://registry.npmmirror.com/query-string/-/query-string-4.3.4.tgz",
@ -14817,6 +15190,16 @@
"integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==",
"dev": true
},
"require-directory": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
"integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="
},
"require-main-filename": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
"integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg=="
},
"resize-detector": {
"version": "0.3.0",
"resolved": "https://registry.npmmirror.com/resize-detector/-/resize-detector-0.3.0.tgz",
@ -14984,6 +15367,11 @@
"upper-case-first": "^2.0.2"
}
},
"set-blocking": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
"integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw=="
},
"set-function-length": {
"version": "1.2.2",
"resolved": "https://registry.npmmirror.com/set-function-length/-/set-function-length-1.2.2.tgz",
@ -15448,7 +15836,6 @@
"version": "6.0.1",
"resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"dev": true,
"requires": {
"ansi-regex": "^5.0.1"
}
@ -16569,6 +16956,11 @@
"is-symbol": "^1.0.3"
}
},
"which-module": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz",
"integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ=="
},
"which-typed-array": {
"version": "1.1.15",
"resolved": "https://registry.npmmirror.com/which-typed-array/-/which-typed-array-1.1.15.tgz",
@ -16693,6 +17085,11 @@
"integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==",
"dev": true
},
"y18n": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
"integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ=="
},
"yallist": {
"version": "3.1.1",
"resolved": "https://registry.npmmirror.com/yallist/-/yallist-3.1.1.tgz",
@ -16705,6 +17102,90 @@
"integrity": "sha512-2wWLbGbYDiSqqIKoPjar3MPgB94ErzCtrNE1FdqGuaO0pi2JGjmE8aW8TDZwzU7vuxcGRdL/4gPQwQ7hD5AMSw==",
"dev": true
},
"yargs": {
"version": "15.4.1",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",
"integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
"requires": {
"cliui": "^6.0.0",
"decamelize": "^1.2.0",
"find-up": "^4.1.0",
"get-caller-file": "^2.0.1",
"require-directory": "^2.1.1",
"require-main-filename": "^2.0.0",
"set-blocking": "^2.0.0",
"string-width": "^4.2.0",
"which-module": "^2.0.0",
"y18n": "^4.0.0",
"yargs-parser": "^18.1.2"
},
"dependencies": {
"emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
},
"find-up": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
"integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
"requires": {
"locate-path": "^5.0.0",
"path-exists": "^4.0.0"
}
},
"locate-path": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
"integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
"requires": {
"p-locate": "^4.1.0"
}
},
"p-limit": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
"integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
"requires": {
"p-try": "^2.0.0"
}
},
"p-locate": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
"integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
"requires": {
"p-limit": "^2.2.0"
}
},
"string-width": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"requires": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
"strip-ansi": "^6.0.1"
}
}
}
},
"yargs-parser": {
"version": "18.1.3",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz",
"integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
"requires": {
"camelcase": "^5.0.0",
"decamelize": "^1.2.0"
},
"dependencies": {
"camelcase": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="
}
}
},
"yocto-queue": {
"version": "0.1.0",
"resolved": "https://registry.npmmirror.com/yocto-queue/-/yocto-queue-0.1.0.tgz",

View File

@ -25,6 +25,7 @@
"lodash-es": "^4.17.21",
"nprogress": "^0.2.0",
"pinia": "^2.2.2",
"qrcode": "^1.5.4",
"vue": "^3.4.38",
"vue-clipboard3": "^2.0.0",
"vue-echarts": "^6.7.3",

View File

@ -44,3 +44,23 @@ export function stuRegistrationEdit(params: Record<string, any>) {
export function stuRegistrationDelete(params: Record<string, any>) {
return request.post({ url: '/stuRegistration/del', params })
}
// 学生注册录取操作
export function stuRegistrationAdmission(params: Record<string, any>) {
return request.post({ url: '/stuRegistration/op/admission', params })
}
// 学生注册审核操作
export function stuRegistrationRegistration(params: Record<string, any>) {
return request.post({ url: '/stuRegistration/op/audit', params })
}
// 学生注册入学操作
export function stuRegistrationEnrollment(params: Record<string, any>) {
return request.post({ url: '/stuRegistration/op/enrollment', params })
}
// 学生注册缴费操作
export function stuRegistrationPayment(params: Record<string, any>) {
return request.post({ url: '/stuRegistration/op/payment', params })
}

View File

@ -0,0 +1,515 @@
<template>
<div class="qrcode-generator">
<!-- 主容器 -->
<div class="container">
<!-- 配置区域 -->
<el-card class="config-card">
<h2 class="card-title">二维码配置</h2>
<!-- 输入区域 -->
<el-form :model="form" label-width="80px" class="config-form">
<!-- 内容输入 -->
<el-form-item label="输入内容">
<el-input
v-model="form.content"
type="textarea"
:rows="4"
placeholder="请输入文本、URL或其他内容"
@input="debounceGenerateQrCode"
></el-input>
</el-form-item>
<!-- 尺寸调整 -->
<el-form-item label="二维码尺寸">
<div class="size-control">
<el-slider
v-model="form.size"
:min="128"
:max="512"
:step="32"
@change="generateQrCode"
></el-slider>
<span class="size-value">{{ form.size }}px</span>
</div>
</el-form-item>
<!-- 颜色配置 -->
<el-form-item label="颜色配置">
<div class="color-group">
<div class="color-item">
<span>前景色</span>
<el-color-picker
v-model="form.foregroundColor"
@change="generateQrCode"
></el-color-picker>
</div>
<div class="color-item">
<span>背景色</span>
<el-color-picker
v-model="form.backgroundColor"
@change="generateQrCode"
></el-color-picker>
</div>
</div>
</el-form-item>
<!-- Logo上传 -->
<el-form-item label="添加Logo">
<el-upload
class="logo-upload"
action="#"
:auto-upload="false"
:on-change="handleLogoUpload"
:file-list="logoFileList"
list-type="picture-card"
>
<i class="el-icon-plus"></i>
</el-upload>
<p class="upload-tip">支持PNGJPG格式建议尺寸不超过二维码的1/4</p>
</el-form-item>
<!-- 容错级别 -->
<el-form-item label="容错级别">
<el-select
v-model="form.errorLevel"
placeholder="请选择"
@change="generateQrCode"
>
<el-option label="低 (7%)" value="L"></el-option>
<el-option label="中 (15%)" value="M"></el-option>
<el-option label="高 (25%)" value="Q"></el-option>
<el-option label="最高 (30%)" value="H"></el-option>
</el-select>
</el-form-item>
<!-- 操作按钮 -->
<div class="action-buttons">
<el-button
type="primary"
icon="el-icon-download"
@click="downloadQrCode"
:disabled="!qrCodeDataUrl"
class="download-btn"
>
下载二维码
</el-button>
<el-button type="default" @click="resetConfig" class="reset-btn">
重置配置
</el-button>
</div>
</el-form>
</el-card>
<!-- 预览区域 -->
<el-card class="preview-card">
<h2 class="card-title">二维码预览</h2>
<div class="preview-container">
<div
class="qr-code-wrapper"
:style="{
width: form.size + 'px',
height: form.size + 'px',
backgroundColor: form.backgroundColor
}"
>
<!-- 加载状态 -->
<el-loading
v-if="isGenerating"
:text="form.content ? '生成中...' : '请输入内容生成二维码'"
:spinner="form.content ? 'el-icon-loading' : ''"
:background="'rgba(255, 255, 255, 0.8)'"
fullscreen="false"
></el-loading>
<!-- 二维码图片 -->
<img
v-if="qrCodeDataUrl && !isGenerating"
:src="qrCodeDataUrl"
:width="form.size"
:height="form.size"
alt="二维码"
class="qr-code-img"
/>
<!-- 初始提示 -->
<div
v-if="!qrCodeDataUrl && !isGenerating && !form.content"
class="empty-tip"
>
<i class="el-icon-qrcode"></i>
<p>输入内容后生成二维码</p>
</div>
</div>
</div>
</el-card>
</div>
</div>
</template>
<script>
import QRCode from 'qrcode'
export default {
name: 'QrCodeGenerator',
data() {
return {
//
form: {
content: '',
size: 256,
foregroundColor: '#000000',
backgroundColor: '#ffffff',
errorLevel: 'M' // L, M, Q, H
},
// URL
qrCodeDataUrl: '',
// Logo
logoFileList: [],
//
isGenerating: false,
//
debounceTimer: null
}
},
methods: {
/**
* 生成二维码防抖处理
*/
debounceGenerateQrCode() {
clearTimeout(this.debounceTimer)
this.debounceTimer = setTimeout(() => {
this.generateQrCode()
}, 500)
},
/**
* 生成二维码核心方法
*/
async generateQrCode() {
if (!this.form.content.trim()) {
this.qrCodeDataUrl = ''
return
}
this.isGenerating = true
try {
//
const opts = {
errorCorrectionLevel: this.form.errorLevel,
type: 'image/png',
margin: 1,
color: {
dark: this.form.foregroundColor,
light: this.form.backgroundColor
}
}
let qrDataUrl = await QRCode.toDataURL(this.form.content.trim(), opts)
// Logo
if (this.logoFileList.length > 0) {
qrDataUrl = await this.addLogoToQrCode(qrDataUrl, this.logoFileList[0].raw)
}
this.qrCodeDataUrl = qrDataUrl
} catch (error) {
console.error('生成二维码失败:', error)
this.$message.error('生成二维码失败,请重试')
} finally {
this.isGenerating = false
}
},
/**
* 给二维码添加Logo
* @param {string} qrDataUrl - 二维码DataURL
* @param {File} logoFile - Logo文件
*/
async addLogoToQrCode(qrDataUrl, logoFile) {
return new Promise((resolve) => {
const qrImage = new Image()
qrImage.src = qrDataUrl
qrImage.onload = function () {
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')
// canvas
canvas.width = this.width
canvas.height = this.height
//
ctx.drawImage(this, 0, 0)
// Logo
const logoImage = new Image()
logoImage.src = URL.createObjectURL(logoFile)
logoImage.onload = function () {
// Logo1/4
const logoSize = canvas.width / 4
const x = (canvas.width - logoSize) / 2
const y = (canvas.height - logoSize) / 2
//
ctx.beginPath()
ctx.arc(
x + logoSize / 2,
y + logoSize / 2,
logoSize / 2 + 5,
0,
2 * Math.PI
)
ctx.fillStyle = '#ffffff'
ctx.fill()
// Logo
ctx.beginPath()
ctx.arc(x + logoSize / 2, y + logoSize / 2, logoSize / 2, 0, 2 * Math.PI)
ctx.clip()
ctx.drawImage(logoImage, x, y, logoSize, logoSize)
resolve(canvas.toDataURL('image/png'))
}
}
})
},
/**
* 处理Logo上传
*/
handleLogoUpload(file) {
//
const isImage =
file.raw.type === 'image/png' ||
file.raw.type === 'image/jpeg' ||
file.raw.type === 'image/jpg'
if (!isImage) {
this.$message.error('请上传PNG或JPG格式的图片')
return
}
// 2MB
const isLt2M = file.size / 1024 / 1024 < 2
if (!isLt2M) {
this.$message.error('Logo文件大小不能超过2MB')
return
}
this.logoFileList = [file]
this.generateQrCode()
},
/**
* 下载二维码
*/
downloadQrCode() {
if (!this.qrCodeDataUrl) return
const link = document.createElement('a')
link.href = this.qrCodeDataUrl
// 10 +
const fileName = `${this.form.content.trim().substring(0, 10)}_${Date.now()}.png`
link.download = fileName
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
this.$message.success('二维码下载成功')
},
/**
* 重置配置
*/
resetConfig() {
this.form = {
content: '',
size: 256,
foregroundColor: '#000000',
backgroundColor: '#ffffff',
errorLevel: 'M'
}
this.logoFileList = []
this.qrCodeDataUrl = ''
this.$message.info('配置已重置')
}
},
mounted() {
//
if (this.form.content) {
this.generateQrCode()
}
}
}
</script>
<style scoped lang="scss">
.qrcode-generator {
min-height: 100vh;
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
padding: 2rem;
}
.container {
max-width: 1200px;
margin: 0 auto;
display: grid;
grid-template-columns: 1fr 1fr;
gap: 2rem;
@media (max-width: 768px) {
grid-template-columns: 1fr;
}
}
.card-title {
font-size: 1.5rem;
font-weight: 600;
color: #1989fa;
margin-bottom: 1.5rem;
display: flex;
align-items: center;
&::before {
content: '';
display: inline-block;
width: 4px;
height: 20px;
background: #1989fa;
margin-right: 0.8rem;
border-radius: 2px;
}
}
.config-card,
.preview-card {
background: rgba(255, 255, 255, 0.9);
border-radius: 12px;
box-shadow: 0 8px 32px rgba(31, 38, 135, 0.1);
backdrop-filter: blur(4px);
border: 1px solid rgba(255, 255, 255, 0.18);
overflow: hidden;
padding: 2rem;
}
.config-form {
.el-form-item {
margin-bottom: 1.5rem;
}
.el-input__inner,
.el-textarea__inner,
.el-select-dropdown {
border-radius: 8px;
}
}
.size-control {
display: flex;
align-items: center;
gap: 1rem;
.size-value {
min-width: 60px;
text-align: center;
font-weight: 500;
color: #1989fa;
}
}
.color-group {
display: flex;
gap: 2rem;
flex-wrap: wrap;
.color-item {
display: flex;
align-items: center;
gap: 0.8rem;
span {
width: 60px;
text-align: right;
}
}
}
.logo-upload {
margin-bottom: 0.5rem;
.el-upload--picture-card {
width: 80px;
height: 80px;
border-radius: 8px;
}
}
.upload-tip {
color: #666;
font-size: 0.875rem;
margin: 0;
}
.action-buttons {
display: flex;
gap: 1rem;
margin-top: 1rem;
.download-btn,
.reset-btn {
flex: 1;
border-radius: 8px;
padding: 0.6rem 0;
transition: all 0.3s ease;
&:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
}
.download-btn {
background: #1989fa;
border-color: #1989fa;
}
}
.preview-container {
display: flex;
justify-content: center;
align-items: center;
min-height: calc(100% - 50px);
padding: 2rem 0;
}
.qr-code-wrapper {
border-radius: 8px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
transition: all 0.3s ease;
&:hover {
box-shadow: 0 15px 35px rgba(0, 0, 0, 0.15);
transform: translateY(-3px);
}
}
.qr-code-img {
display: block;
}
.empty-tip {
text-align: center;
color: #666;
i {
font-size: 3rem;
margin-bottom: 1rem;
color: #c0c4cc;
display: block;
}
p {
font-size: 1rem;
}
}
/* 加载状态样式 */
.el-loading {
.el-loading-text {
color: #1989fa;
font-size: 1rem;
}
.el-loading-spinner .path {
stroke: #1989fa;
}
}
/* 响应式调整 */
@media (max-width: 768px) {
.qrcode-generator {
padding: 1rem;
}
.config-card,
.preview-card {
padding: 1.5rem;
}
.color-group {
flex-direction: column;
gap: 1rem;
.color-item {
span {
width: auto;
text-align: left;
}
}
}
.action-buttons {
flex-direction: column;
}
.qr-code-wrapper {
max-width: 90vw;
max-height: 90vw;
}
}
</style>

View File

@ -0,0 +1,111 @@
<template>
<popup
ref="popupRef"
title="学生基本信息详情"
width="650px"
:clickModalClose="true"
@close="handleClose"
>
<div class="detail-container">
<el-descriptions :column="2" border>
<el-descriptions-item label="姓名">{{ formData.name }}</el-descriptions-item>
<el-descriptions-item label="性别">{{ formatGender(formData.gender) }}</el-descriptions-item>
<el-descriptions-item label="出生日期">{{ formData.birthday }}</el-descriptions-item>
<el-descriptions-item label="身份证号">{{ formData.idCard }}</el-descriptions-item>
<el-descriptions-item label="民族">{{ formData.nationality }}</el-descriptions-item>
<el-descriptions-item label="籍贯">{{ formData.nativePlace }}</el-descriptions-item>
<el-descriptions-item label="政治面貌">{{ formatPoliticalStatus(formData.politicalStatus) }}</el-descriptions-item>
<el-descriptions-item label="手机号码">{{ formData.phone }}</el-descriptions-item>
<el-descriptions-item label="邮箱">{{ formData.email }}</el-descriptions-item>
<el-descriptions-item label="家庭住址">{{ formData.homeAddress }}</el-descriptions-item>
<el-descriptions-item label="邀请码">{{ formData.invitationCode }}</el-descriptions-item>
<el-descriptions-item label="毕业学校">{{ formData.previousSchool }}</el-descriptions-item>
<el-descriptions-item label="学校类型">{{ formatSchoolType(formData.schoolType) }}</el-descriptions-item>
<el-descriptions-item label="毕业年份">{{ formData.graduationYear }}</el-descriptions-item>
<el-descriptions-item label="紧急联系人">{{ formData.emergencyContact }}</el-descriptions-item>
<el-descriptions-item label="与紧急联系人关系">{{ formData.relationship }}</el-descriptions-item>
<el-descriptions-item label="紧急联系电话">{{ formData.emergencyPhone }}</el-descriptions-item>
</el-descriptions>
</div>
</popup>
</template>
<script lang="ts" setup>
import { reactive, ref } from 'vue'
import { stuBaseInfoDetail } from '@/api/stuBaseInfo'
import Popup from '@/components/popup/index.vue'
const popupRef = ref<InstanceType<typeof Popup>>()
const emit = defineEmits(['close'])
const formData = reactive({
birthday: '',
email: '',
emergencyContact: '',
emergencyPhone: '',
gender: 0,
graduationYear: 0,
homeAddress: '',
id: 0,
idCard: '',
invitationCode: '', //
name: '',
nationality: '',
nativePlace: '',
phone: '',
politicalStatus: 0,
previousSchool: '',
relationship: '',
schoolType: 0 // 1- 2-
})
const formatGender = (value: number) => {
const map: Record<number, string> = {
0: '未知',
1: '男',
2: '女'
}
return map[value] || '未知'
}
const formatPoliticalStatus = (value: number) => {
const map: Record<number, string> = {
0: '群众',
1: '团员',
2: '党员',
3: '其他'
}
return map[value] || '未知'
}
const formatSchoolType = (value: number) => {
const map: Record<number, string> = {
1: '普高',
2: '中职'
}
return map[value] || '未知'
}
const open = async (id: number) => {
const data = await stuBaseInfoDetail({ id })
Object.assign(formData, data)
popupRef.value?.open()
}
const handleClose = () => {
emit('close')
}
defineExpose({
open
})
</script>
<style scoped>
.detail-container {
max-height: 600px;
overflow-y: auto;
padding: 10px;
}
</style>

View File

@ -11,51 +11,39 @@
>
<el-form ref="formRef" :model="formData" label-width="84px" :rules="formRules">
<el-form-item label="报名编号" prop="applicationNumber">
<el-input v-model="formData.applicationNumber" placeholder="请输入报名编号" />
<el-button type="primary" link @click="handleShowDetail">
{{ formData.applicationNumber }}
</el-button>
</el-form-item>
<el-form-item label="邀请码" prop="invitationCode">
<el-input v-model="formData.invitationCode" placeholder="请输入邀请码" />
</el-form-item>
<el-form-item label="录取状态" prop="admissionStatus">
<el-radio-group v-model="formData.admissionStatus" placeholder="请选择录取状态">
<el-radio :label="0">待审核</el-radio>
<el-form-item label="录取状态" prop="operation">
<el-radio-group v-model="formData.operation" placeholder="请选择录取状态">
<el-radio :label="0">未录取</el-radio>
<el-radio :label="1">已录取</el-radio>
<el-radio :label="2">录取</el-radio>
<el-radio :label="2">拒绝录取</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="拒绝原因" prop="rejectionReason">
<el-form-item label="拒绝原因" prop="reason">
<el-input
v-model="formData.rejectionReason"
v-model="formData.reason"
placeholder="请输入拒绝原因"
type="textarea"
:disabled="formData.operation != 2"
:autosize="{ minRows: 4, maxRows: 6 }"
/>
</el-form-item>
<el-form-item label="录取时间" prop="admissionTime">
<el-date-picker
class="flex-1 !flex"
v-model="formData.admissionTime"
type="datetime"
clearable
value-format="YYYY-MM-DD hh:mm:ss"
placeholder="请选择录取时间"
/>
</el-form-item>
</el-form>
</popup>
<base-popup ref="detailRef" />
</div>
</template>
<script lang="ts" setup>
import type { FormInstance } from 'element-plus'
import type { PropType } from 'vue'
import {
stuRegistrationAdd,
stuRegistrationDetail,
stuRegistrationEdit
} from '@/api/stuRegistration'
import { stuRegistrationAdmission, stuRegistrationDetail } from '@/api/stuRegistration'
import Popup from '@/components/popup/index.vue'
import feedback from '@/utils/feedback'
import BasePopup from '../Base.vue'
defineProps({
dictData: {
type: Object as PropType<Record<string, any[]>>,
@ -65,29 +53,18 @@ defineProps({
const emit = defineEmits(['success', 'close'])
const formRef = shallowRef<FormInstance>()
const popupRef = shallowRef<InstanceType<typeof Popup>>()
const detailRef = shallowRef<InstanceType<typeof BasePopup>>()
const mode = ref('add')
const popupTitle = computed(() => {
return mode.value == 'edit' ? '编辑学生注册状态' : '新增学生注册状态'
return mode.value == 'edit' ? '编辑学生注册状态' : '未知错误'
})
const formData = reactive({
id: '',
userId: '',
baseInfoId: '',
operation: 0,
reason: '',
applicationNumber: '',
invitationCode: '',
intendedCollegeId: '',
intendedMajorId: '',
admissionStatus: '',
paymentStatus: '',
registrationStatus: '',
approvalStatus: '',
rejectionReason: '',
applicationTime: '',
admissionTime: '',
paymentTime: '',
approvedTime: '',
registrationTime: ''
baseInfoId: 0
})
const formRules = {
@ -98,59 +75,17 @@ const formRules = {
trigger: ['blur']
}
],
userId: [
operation: [
{
required: true,
message: '请输入用户ID',
trigger: ['blur']
message: '请选择录取状态',
trigger: ['change']
}
],
baseInfoId: [
reason: [
{
required: true,
message: '请输入关联基本信息ID',
trigger: ['blur']
}
],
applicationNumber: [
{
required: true,
message: '请输入报名编号',
trigger: ['blur']
}
],
admissionStatus: [
{
required: true,
message: '请选择录取状态0-待审核 1-已录取 2-未录取',
trigger: ['blur']
}
],
paymentStatus: [
{
required: true,
message: '请选择缴费状态0-未缴费 1-部分缴费 2-已缴费',
trigger: ['blur']
}
],
registrationStatus: [
{
required: true,
message: '请选择入学状态0-未入学 1-已入学',
trigger: ['blur']
}
],
approvalStatus: [
{
required: true,
message: '请选择审核状态0-待审核 1-审核通过 2-审核不通过',
trigger: ['blur']
}
],
applicationTime: [
{
required: true,
message: '请选择报名时间',
required: formData.operation == 2,
message: '请输入拒绝原因',
trigger: ['blur']
}
]
@ -159,12 +94,16 @@ const formRules = {
const handleSubmit = async () => {
await formRef.value?.validate()
const data: any = { ...formData }
mode.value == 'edit' ? await stuRegistrationEdit(data) : await stuRegistrationAdd(data)
await stuRegistrationAdmission(data)
popupRef.value?.close()
feedback.msgSuccess('操作成功')
emit('success')
}
const handleShowDetail = async () => {
await nextTick()
detailRef.value?.open(formData.baseInfoId)
}
const open = (type = 'add') => {
mode.value = type
popupRef.value?.open()
@ -175,6 +114,8 @@ const setFormData = async (data: Record<string, any>) => {
if (data[key] != null && data[key] != undefined) {
//@ts-ignore
formData[key] = data[key]
formData['operation'] = data['admissionStatus']
formData['reason'] = data['rejectionReason']
}
}
}

View File

@ -5,34 +5,18 @@
<el-form-item label="报名编号" prop="applicationNumber">
<el-input class="w-[280px]" v-model="queryParams.applicationNumber" />
</el-form-item>
<el-form-item label="邀请码" prop="invitationCode">
<el-input class="w-[280px]" v-model="queryParams.invitationCode" />
</el-form-item>
<el-form-item label="录取状态" prop="admissionStatus">
<el-select v-model="queryParams.admissionStatus" class="w-[280px]" clearable>
<el-option label="待审核" :value="0" />
<el-option label="未录取" :value="0" />
<el-option label="已录取" :value="1" />
<el-option label="录取" :value="2" />
<el-option label="拒绝录取" :value="2" />
</el-select>
</el-form-item>
<el-form-item label="缴费状态" prop="paymentStatus">
<el-select v-model="queryParams.paymentStatus" class="w-[280px]" clearable>
<el-option label="未缴费" :value="0" />
<el-option label="已缴费" :value="1" />
</el-select>
</el-form-item>
<el-form-item label="入学状态" prop="registrationStatus">
<el-select v-model="queryParams.registrationStatus" class="w-[280px]" clearable>
<el-option label="未入学" :value="0" />
<el-option label="已入学" :value="1" />
</el-select>
</el-form-item>
<el-form-item label="审核状态" prop="approvalStatus">
<el-select v-model="queryParams.approvalStatus" class="w-[280px]" clearable>
<el-option label="待审核" :value="0" />
<el-option label="审核通过" :value="1" />
<el-option label="审核不通过" :value="2" />
</el-select>
<el-form-item label="审核时间" prop="approvedTime">
<daterange-picker
v-model:startTime="queryParams.approvedTimeStart"
v-model:endTime="queryParams.approvedTimeEnd"
/>
</el-form-item>
<el-form-item label="报名时间" prop="applicationTime">
<daterange-picker
@ -40,24 +24,6 @@
v-model:endTime="queryParams.applicationTimeEnd"
/>
</el-form-item>
<el-form-item label="录取时间" prop="admissionTime">
<daterange-picker
v-model:startTime="queryParams.admissionTimeStart"
v-model:endTime="queryParams.admissionTimeEnd"
/>
</el-form-item>
<el-form-item label="缴费时间" prop="paymentTime">
<daterange-picker
v-model:startTime="queryParams.paymentTimeStart"
v-model:endTime="queryParams.paymentTimeEnd"
/>
</el-form-item>
<el-form-item label="入学登记时间" prop="registrationTime">
<daterange-picker
v-model:startTime="queryParams.registrationTimeStart"
v-model:endTime="queryParams.registrationTimeEnd"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="resetPage">查询</el-button>
<el-button @click="resetParams">重置</el-button>
@ -65,50 +31,23 @@
</el-form>
</el-card>
<el-card class="!border-none mt-4" shadow="never">
<div>
<el-button v-perms="['stuRegistration/add']" type="primary" @click="handleAdd()">
<template #icon>
<icon name="el-icon-Plus" />
</template>
新增
</el-button>
</div>
<el-table class="mt-4" size="large" v-loading="pager.loading" :data="pager.lists">
<el-table-column label="报名编号" prop="applicationNumber" min-width="100" />
<el-table-column label="邀请码" prop="invitationCode" min-width="100" />
<el-table-column label="报名编号" min-width="100">
<template #default="{ row }">
<el-button type="primary" link @click="handleShowDetail(row.baseInfoId)">
{{ row.applicationNumber }}
</el-button>
</template>
</el-table-column>
<el-table-column
label="录取状态"
prop="admissionStatus"
min-width="100"
:formatter="formatAdmissionStatus"
/>
<el-table-column
label="缴费状态"
prop="paymentStatus"
min-width="100"
:formatter="formatPaymentStatus"
/>
<el-table-column
label="入学状态"
prop="registrationStatus"
min-width="100"
:formatter="formatRegistrationStatus"
/>
<el-table-column
label="审核状态"
prop="approvalStatus"
min-width="100"
:formatter="formatApprovalStatus"
/>
<el-table-column label="审核人ID" prop="approvedBy" min-width="100" />
<el-table-column label="审核时间" prop="approvedTime" min-width="100" />
<el-table-column label="拒绝原因" prop="rejectionReason" min-width="100" />
<el-table-column label="报名时间" prop="applicationTime" min-width="100" />
<el-table-column label="录取时间" prop="admissionTime" min-width="100" />
<el-table-column label="缴费时间" prop="paymentTime" min-width="100" />
<el-table-column label="入学登记时间" prop="registrationTime" min-width="100" />
<el-table-column label="创建时间" prop="createTime" min-width="100" />
<el-table-column label="更新时间" prop="updateTime" min-width="100" />
<el-table-column label="操作" width="120" fixed="right">
<template #default="{ row }">
<el-button
@ -119,14 +58,6 @@
>
编辑
</el-button>
<el-button
v-perms="['stuRegistration/del']"
type="danger"
link
@click="handleDelete(row.id)"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
@ -135,65 +66,37 @@
</div>
</el-card>
<edit-popup v-if="showEdit" ref="editRef" @success="getLists" @close="showEdit = false" />
<base-popup ref="detailRef" />
</div>
</template>
<script lang="ts" setup name="stuRegistration">
import { stuRegistrationAdmissionLists, stuRegistrationDelete } from '@/api/stuRegistration'
import { stuRegistrationAdmissionLists } from '@/api/stuRegistration'
import { usePaging } from '@/hooks/usePaging'
import feedback from '@/utils/feedback'
import BasePopup from '../Base.vue'
import EditPopup from './edit.vue'
const editRef = shallowRef<InstanceType<typeof EditPopup>>()
const detailRef = shallowRef<InstanceType<typeof BasePopup>>()
const showEdit = ref(false)
const queryParams = reactive({
baseInfoId: '',
applicationNumber: '',
invitationCode: '',
admissionStatus: '',
paymentStatus: '',
registrationStatus: '',
approvalStatus: '',
approvedBy: '',
approvedTimeStart: '',
approvedTimeEnd: '',
applicationTimeStart: '',
applicationTimeEnd: '',
admissionTimeStart: '',
admissionTimeEnd: '',
paymentTimeStart: '',
paymentTimeEnd: '',
registrationTimeStart: '',
registrationTimeEnd: ''
applicationTimeEnd: ''
})
const formatAdmissionStatus = (row: any, column: any, cellValue: any) => {
const statusMap: Record<string | number, string> = {
'0': '待审核',
'0': '未录取',
'1': '已录取',
'2': '未录取'
}
return statusMap[String(cellValue)] || cellValue
}
const formatPaymentStatus = (row: any, column: any, cellValue: any) => {
const statusMap: Record<string | number, string> = {
'0': '未缴费',
'1': '已缴费'
}
return statusMap[String(cellValue)] || cellValue
}
const formatRegistrationStatus = (row: any, column: any, cellValue: any) => {
const statusMap: Record<string | number, string> = {
'0': '未入学',
'1': '已入学'
}
return statusMap[String(cellValue)] || cellValue
}
const formatApprovalStatus = (row: any, column: any, cellValue: any) => {
const statusMap: Record<string | number, string> = {
'0': '待审核',
'1': '已审核',
'2': '审核不通过'
'2': '拒绝录取'
}
return statusMap[String(cellValue)] || cellValue
}
@ -203,10 +106,9 @@ const { pager, getLists, resetPage, resetParams } = usePaging({
params: queryParams
})
const handleAdd = async () => {
showEdit.value = true
const handleShowDetail = async (id: number) => {
await nextTick()
editRef.value?.open('add')
detailRef.value?.open(id)
}
const handleEdit = async (data: any) => {
@ -216,12 +118,5 @@ const handleEdit = async (data: any) => {
editRef.value?.getDetail(data)
}
const handleDelete = async (id: number) => {
await feedback.confirm('确定要删除?')
await stuRegistrationDelete({ id })
feedback.msgSuccess('删除成功')
getLists()
}
getLists()
</script>

View File

@ -2,7 +2,6 @@
<div class="edit-popup">
<popup
ref="popupRef"
:title="popupTitle"
:async="true"
width="550px"
:clickModalClose="true"
@ -10,37 +9,14 @@
@close="handleClose"
>
<el-form ref="formRef" :model="formData" label-width="84px" :rules="formRules">
<el-form-item label="报名编号" prop="applicationNumber">
<el-input v-model="formData.applicationNumber" placeholder="请输入报名编号" />
</el-form-item>
<el-form-item label="邀请码" prop="invitationCode">
<el-input v-model="formData.invitationCode" placeholder="请输入邀请码" />
</el-form-item>
<el-form-item label="审核状态" prop="approvalStatus">
<el-radio-group v-model="formData.approvalStatus" placeholder="请选择审核状态">
<el-radio :label="0">待审核</el-radio>
<el-radio :label="1">审核通过</el-radio>
<el-radio :label="2">审核不通过</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="拒绝原因" prop="rejectionReason">
<el-form-item label="拒绝原因" prop="reason">
<el-input
v-model="formData.rejectionReason"
v-model="formData.reason"
placeholder="请输入拒绝原因"
type="textarea"
:autosize="{ minRows: 4, maxRows: 6 }"
/>
</el-form-item>
<el-form-item label="报名时间" prop="approvedTime">
<el-date-picker
class="flex-1 !flex"
v-model="formData.approvedTime"
type="datetime"
clearable
value-format="YYYY-MM-DD hh:mm:ss"
placeholder="请选择报名时间"
/>
</el-form-item>
</el-form>
</popup>
</div>
@ -49,14 +25,8 @@
import type { FormInstance } from 'element-plus'
import type { PropType } from 'vue'
import {
stuRegistrationAdd,
stuRegistrationDetail,
stuRegistrationEdit
} from '@/api/stuRegistration'
import { stuRegistrationDetail, stuRegistrationRegistration } from '@/api/stuRegistration'
import Popup from '@/components/popup/index.vue'
import useUserStore from '@/stores/modules/user'
import feedback from '@/utils/feedback'
defineProps({
dictData: {
type: Object as PropType<Record<string, any[]>>,
@ -64,32 +34,15 @@ defineProps({
}
})
const emit = defineEmits(['success', 'close'])
const userStore = useUserStore()
const formRef = shallowRef<FormInstance>()
const popupRef = shallowRef<InstanceType<typeof Popup>>()
const mode = ref('add')
const popupTitle = computed(() => {
return mode.value == 'edit' ? '编辑学生注册状态' : '新增学生注册状态'
})
const formData = reactive({
id: '',
userId: '',
baseInfoId: '',
operation: 2,
reason: '',
applicationNumber: '',
invitationCode: '',
intendedCollegeId: '',
intendedMajorId: '',
admissionStatus: '',
paymentStatus: '',
registrationStatus: '',
approvalStatus: '',
rejectionReason: '',
applicationTime: '',
admissionTime: '',
paymentTime: '',
approvedTime: '',
registrationTime: ''
baseInfoId: 0
})
const formRules = {
@ -99,102 +52,27 @@ const formRules = {
message: '请输入主键ID',
trigger: ['blur']
}
],
userId: [
{
required: true,
message: '请输入用户ID',
trigger: ['blur']
}
],
baseInfoId: [
{
required: true,
message: '请输入关联基本信息ID',
trigger: ['blur']
}
],
applicationNumber: [
{
required: true,
message: '请输入报名编号',
trigger: ['blur']
}
],
admissionStatus: [
{
required: true,
message: '请选择录取状态0-待审核 1-已录取 2-未录取',
trigger: ['blur']
}
],
paymentStatus: [
{
required: true,
message: '请选择缴费状态0-未缴费 1-部分缴费 2-已缴费',
trigger: ['blur']
}
],
registrationStatus: [
{
required: true,
message: '请选择入学状态0-未入学 1-已入学',
trigger: ['blur']
}
],
approvalStatus: [
{
required: true,
message: '请选择审核状态0-待审核 1-审核通过 2-审核不通过',
trigger: ['blur']
}
],
applicationTime: [
{
required: true,
message: '请选择报名时间',
trigger: ['blur']
}
]
}
const handleSubmit = async () => {
await formRef.value?.validate()
const data: any = { ...formData }
mode.value == 'edit' ? await stuRegistrationEdit(data) : await stuRegistrationAdd(data)
await stuRegistrationRegistration(data)
popupRef.value?.close()
feedback.msgSuccess('操作成功')
emit('success')
}
const open = (type = 'add') => {
mode.value = type
console.log('当前权限:', userStore.perms)
console.log('getFetchFun', getFetchFun())
const open = () => {
popupRef.value?.open()
}
const getFetchFun = () => {
const { perms } = userStore
if (perms.includes('stuRegistration/list')) {
return 5
} else if (perms.includes('stuRegistration/list.enrollment')) {
return 2
} else if (perms.includes('stuRegistration/list.payment')) {
return 3
} else if (perms.includes('stuRegistration/list.registration')) {
return 4
} else if (perms.includes('stuRegistration/list.admission')) {
return 1
}
return 0
}
const setFormData = async (data: Record<string, any>) => {
for (const key in formData) {
if (data[key] != null && data[key] != undefined) {
//@ts-ignore
formData[key] = data[key]
formData['reason'] = data['rejectionReason']
}
}
}

View File

@ -5,32 +5,15 @@
<el-form-item label="报名编号" prop="applicationNumber">
<el-input class="w-[280px]" v-model="queryParams.applicationNumber" />
</el-form-item>
<el-form-item label="邀请码" prop="invitationCode">
<el-input class="w-[280px]" v-model="queryParams.invitationCode" />
</el-form-item>
<el-form-item label="录取状态" prop="admissionStatus">
<el-select v-model="queryParams.admissionStatus" class="w-[280px]" clearable>
<el-option label="待审核" :value="0" />
<el-option label="已录取" :value="1" />
<el-option label="未录取" :value="2" />
</el-select>
</el-form-item>
<el-form-item label="缴费状态" prop="paymentStatus">
<el-select v-model="queryParams.paymentStatus" class="w-[280px]" clearable>
<el-option label="未缴费" :value="0" />
<el-option label="已缴费" :value="1" />
</el-select>
</el-form-item>
<el-form-item label="入学状态" prop="registrationStatus">
<el-select v-model="queryParams.registrationStatus" class="w-[280px]" clearable>
<el-option label="未入学" :value="0" />
<el-option label="已入学" :value="1" />
</el-select>
</el-form-item>
<el-form-item label="审核状态" prop="approvalStatus">
<el-select v-model="queryParams.approvalStatus" class="w-[280px]" clearable>
<el-select
v-model="queryParams.approvalStatus"
class="w-[280px]"
clearable
@change="getLists()"
>
<el-option label="待审核" :value="0" />
<el-option label="审核通过" :value="1" />
<el-option label="已审核" :value="1" />
<el-option label="审核不通过" :value="2" />
</el-select>
</el-form-item>
@ -40,24 +23,6 @@
v-model:endTime="queryParams.applicationTimeEnd"
/>
</el-form-item>
<el-form-item label="录取时间" prop="admissionTime">
<daterange-picker
v-model:startTime="queryParams.admissionTimeStart"
v-model:endTime="queryParams.admissionTimeEnd"
/>
</el-form-item>
<el-form-item label="缴费时间" prop="paymentTime">
<daterange-picker
v-model:startTime="queryParams.paymentTimeStart"
v-model:endTime="queryParams.paymentTimeEnd"
/>
</el-form-item>
<el-form-item label="入学登记时间" prop="registrationTime">
<daterange-picker
v-model:startTime="queryParams.registrationTimeStart"
v-model:endTime="queryParams.registrationTimeEnd"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="resetPage">查询</el-button>
<el-button @click="resetParams">重置</el-button>
@ -65,67 +30,56 @@
</el-form>
</el-card>
<el-card class="!border-none mt-4" shadow="never">
<div>
<el-button v-perms="['stuRegistration/add']" type="primary" @click="handleAdd()">
<template #icon>
<icon name="el-icon-Plus" />
</template>
新增
<el-table
class="mt-4"
size="large"
v-loading="pager.loading"
:data="pager.lists"
border
>
<el-table-column label="报名编号" min-width="100">
<template #default="{ row }">
<el-button
type="primary"
link
@click="handleShowDetail(row.baseInfoId)"
style="text-decoration: underline"
>
{{ row.applicationNumber }}
</el-button>
</div>
<el-table class="mt-4" size="large" v-loading="pager.loading" :data="pager.lists">
<el-table-column label="报名编号" prop="applicationNumber" min-width="100" />
<el-table-column label="邀请码" prop="invitationCode" min-width="100" />
<el-table-column
label="录取状态"
prop="admissionStatus"
min-width="100"
:formatter="formatAdmissionStatus"
/>
<el-table-column
label="缴费状态"
prop="paymentStatus"
min-width="100"
:formatter="formatPaymentStatus"
/>
<el-table-column
label="入学状态"
prop="registrationStatus"
min-width="100"
:formatter="formatRegistrationStatus"
/>
</template>
</el-table-column>
<el-table-column
label="审核状态"
prop="approvalStatus"
min-width="100"
:formatter="formatApprovalStatus"
:formatter="formatRegistrationStatus"
/>
<el-table-column label="审核人ID" prop="approvedBy" min-width="100" />
<el-table-column label="审核时间" prop="approvedTime" min-width="100" />
<el-table-column label="拒绝原因" prop="rejectionReason" min-width="100" />
<el-table-column label="报名时间" prop="applicationTime" min-width="100" />
<el-table-column label="录取时间" prop="admissionTime" min-width="100" />
<el-table-column label="缴费时间" prop="paymentTime" min-width="100" />
<el-table-column label="入学登记时间" prop="registrationTime" min-width="100" />
<el-table-column label="创建时间" prop="createTime" min-width="100" />
<el-table-column label="更新时间" prop="updateTime" min-width="100" />
<el-table-column label="操作" width="120" fixed="right">
<el-table-column label="操作" width="240" fixed="right">
<template #default="{ row }">
<el-button
v-perms="['stuRegistration/edit']"
type="primary"
link
@click="handleEdit(row)"
@click="handleRoEdit(row)"
:disabled="row.approvalStatus == 0"
>
编辑
撤销
</el-button>
<el-button
v-perms="['stuRegistration/del']"
type="danger"
link
@click="handleDelete(row.id)"
v-perms="['stuRegistration/edit']"
type="success"
@click="handleYesEdit(row)"
:disabled="row.approvalStatus != 0"
>
删除
通过
</el-button>
<el-button
v-perms="['stuRegistration/edit']"
type="danger"
@click="handleNoEdit(row)"
:disabled="row.approvalStatus != 0"
>
拒绝
</el-button>
</template>
</el-table-column>
@ -135,67 +89,51 @@
</div>
</el-card>
<edit-popup v-if="showEdit" ref="editRef" @success="getLists" @close="showEdit = false" />
<base-popup ref="detailRef" />
</div>
</template>
<script lang="ts" setup name="stuRegistration">
import { stuRegistrationDelete, stuRegistrationRegistrationLists } from '@/api/stuRegistration'
import {
stuRegistrationRegistration,
stuRegistrationRegistrationLists
} from '@/api/stuRegistration'
import { usePaging } from '@/hooks/usePaging'
import feedback from '@/utils/feedback'
import BasePopup from '../Base.vue'
import EditPopup from './edit.vue'
const editRef = shallowRef<InstanceType<typeof EditPopup>>()
const detailRef = shallowRef<InstanceType<typeof BasePopup>>()
const showEdit = ref(false)
const queryParams = reactive({
baseInfoId: '',
approvalStatus: '',
applicationNumber: '',
invitationCode: '',
rejectionReason: '',
admissionStatus: '',
paymentStatus: '',
registrationStatus: '',
approvalStatus: '',
approvedBy: '',
registrationStatus: 0,
applicationTimeStart: '',
applicationTimeEnd: '',
admissionTimeStart: '',
admissionTimeEnd: '',
paymentTimeStart: '',
paymentTimeEnd: '',
registrationTimeStart: '',
registrationTimeEnd: ''
applicationTimeEnd: ''
})
const formatAdmissionStatus = (row: any, column: any, cellValue: any) => {
const statusMap: Record<string | number, string> = {
'0': '待审核',
'1': '已录取',
'2': '未录取'
}
return statusMap[String(cellValue)] || cellValue
}
const formatPaymentStatus = (row: any, column: any, cellValue: any) => {
const statusMap: Record<string | number, string> = {
'0': '未缴费',
'1': '已缴费'
}
return statusMap[String(cellValue)] || cellValue
}
const formData = reactive({
id: '',
operation: 0,
reason: ''
})
const formatRegistrationStatus = (row: any, column: any, cellValue: any) => {
const statusMap: Record<string | number, string> = {
'0': '未入学',
'1': '已入学'
}
return statusMap[String(cellValue)] || cellValue
}
const formatApprovalStatus = (row: any, column: any, cellValue: any) => {
const statusMap: Record<string | number, string> = {
'0': '待审核',
'1': '已审核',
'2': '审核不通过'
}
return statusMap[String(cellValue)] || cellValue
const statusText = statusMap[String(cellValue)] || cellValue
// 2
if (cellValue === 2 && row.rejectionReason) {
return `${statusText} ${row.rejectionReason}`
}
return statusText
}
const { pager, getLists, resetPage, resetParams } = usePaging({
@ -203,25 +141,33 @@ const { pager, getLists, resetPage, resetParams } = usePaging({
params: queryParams
})
const handleAdd = async () => {
showEdit.value = true
const handleShowDetail = async (id: number) => {
await nextTick()
editRef.value?.open('add')
detailRef.value?.open(id)
}
const handleEdit = async (data: any) => {
showEdit.value = true
await nextTick()
editRef.value?.open('edit')
editRef.value?.getDetail(data)
}
const handleDelete = async (id: number) => {
await feedback.confirm('确定要删除?')
await stuRegistrationDelete({ id })
feedback.msgSuccess('删除成功')
const handleRoEdit = async (data: any) => {
formData.id = data.id
formData.operation = 0
const editData: any = { ...formData }
await stuRegistrationRegistration(editData)
getLists()
}
const handleYesEdit = async (data: any) => {
formData.id = data.id
formData.operation = 1
const editData: any = { ...formData }
await stuRegistrationRegistration(editData)
getLists()
}
const handleNoEdit = async (data: any) => {
showEdit.value = true
await nextTick()
editRef.value?.open()
editRef.value?.getDetail(data)
}
getLists()
</script>