登入注册页面优化

This commit is contained in:
YuNan 2025-02-18 14:02:00 +08:00
parent 8a19c93d22
commit c676a1b470
7 changed files with 985 additions and 126 deletions

371
package-lock.json generated
View File

@ -9,6 +9,7 @@
"version": "0.1.0", "version": "0.1.0",
"dependencies": { "dependencies": {
"core-js": "^3.8.3", "core-js": "^3.8.3",
"element-plus": "^2.9.4",
"vue": "^3.2.13", "vue": "^3.2.13",
"vue-router": "^4.0.3", "vue-router": "^4.0.3",
"vuex": "^4.0.0" "vuex": "^4.0.0"
@ -1665,6 +1666,14 @@
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@ctrl/tinycolor": {
"version": "3.6.1",
"resolved": "https://registry.npmmirror.com/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz",
"integrity": "sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==",
"engines": {
"node": ">=10"
}
},
"node_modules/@discoveryjs/json-ext": { "node_modules/@discoveryjs/json-ext": {
"version": "0.5.7", "version": "0.5.7",
"resolved": "https://registry.npmmirror.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", "resolved": "https://registry.npmmirror.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz",
@ -1674,6 +1683,14 @@
"node": ">=10.0.0" "node": ">=10.0.0"
} }
}, },
"node_modules/@element-plus/icons-vue": {
"version": "2.3.1",
"resolved": "https://registry.npmmirror.com/@element-plus/icons-vue/-/icons-vue-2.3.1.tgz",
"integrity": "sha512-XxVUZv48RZAd87ucGS48jPf6pKu0yV5UCg9f4FFwtrYxXOwWuVJo6wOvSLKEoMQKjv8GsX/mhP6UsC1lRwbUWg==",
"peerDependencies": {
"vue": "^3.2.0"
}
},
"node_modules/@eslint/eslintrc": { "node_modules/@eslint/eslintrc": {
"version": "0.4.3", "version": "0.4.3",
"resolved": "https://registry.npmmirror.com/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", "resolved": "https://registry.npmmirror.com/@eslint/eslintrc/-/eslintrc-0.4.3.tgz",
@ -1730,6 +1747,28 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/@floating-ui/core": {
"version": "1.6.9",
"resolved": "https://registry.npmmirror.com/@floating-ui/core/-/core-1.6.9.tgz",
"integrity": "sha512-uMXCuQ3BItDUbAMhIXw7UPXRfAlOAvZzdK9BWpE60MCn+Svt3aLn9jsPTi/WNGlRUu2uI0v5S7JiIUsbsvh3fw==",
"dependencies": {
"@floating-ui/utils": "^0.2.9"
}
},
"node_modules/@floating-ui/dom": {
"version": "1.6.13",
"resolved": "https://registry.npmmirror.com/@floating-ui/dom/-/dom-1.6.13.tgz",
"integrity": "sha512-umqzocjDgNRGTuO7Q8CU32dkHkECqI8ZdMZ5Swb6QAM0t5rnlrN3lGo1hdpscRd3WS8T6DKYK4ephgIH9iRh3w==",
"dependencies": {
"@floating-ui/core": "^1.6.0",
"@floating-ui/utils": "^0.2.9"
}
},
"node_modules/@floating-ui/utils": {
"version": "0.2.9",
"resolved": "https://registry.npmmirror.com/@floating-ui/utils/-/utils-0.2.9.tgz",
"integrity": "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg=="
},
"node_modules/@hapi/hoek": { "node_modules/@hapi/hoek": {
"version": "9.3.0", "version": "9.3.0",
"resolved": "https://registry.npmmirror.com/@hapi/hoek/-/hoek-9.3.0.tgz", "resolved": "https://registry.npmmirror.com/@hapi/hoek/-/hoek-9.3.0.tgz",
@ -1892,6 +1931,16 @@
"integrity": "sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==", "integrity": "sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==",
"dev": true "dev": true
}, },
"node_modules/@popperjs/core": {
"name": "@sxzz/popperjs-es",
"version": "2.11.7",
"resolved": "https://registry.npmmirror.com/@sxzz/popperjs-es/-/popperjs-es-2.11.7.tgz",
"integrity": "sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ==",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/popperjs"
}
},
"node_modules/@rtsao/scc": { "node_modules/@rtsao/scc": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmmirror.com/@rtsao/scc/-/scc-1.1.0.tgz", "resolved": "https://registry.npmmirror.com/@rtsao/scc/-/scc-1.1.0.tgz",
@ -2085,6 +2134,19 @@
"integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
"dev": true "dev": true
}, },
"node_modules/@types/lodash": {
"version": "4.17.15",
"resolved": "https://registry.npmmirror.com/@types/lodash/-/lodash-4.17.15.tgz",
"integrity": "sha512-w/P33JFeySuhN6JLkysYUK2gEmy9kHHFN7E8ro0tkfmlDOgxBDzWEZ/J8cWA+fHqFevpswDTFZnDx+R9lbL6xw=="
},
"node_modules/@types/lodash-es": {
"version": "4.17.12",
"resolved": "https://registry.npmmirror.com/@types/lodash-es/-/lodash-es-4.17.12.tgz",
"integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==",
"dependencies": {
"@types/lodash": "*"
}
},
"node_modules/@types/mime": { "node_modules/@types/mime": {
"version": "1.3.5", "version": "1.3.5",
"resolved": "https://registry.npmmirror.com/@types/mime/-/mime-1.3.5.tgz", "resolved": "https://registry.npmmirror.com/@types/mime/-/mime-1.3.5.tgz",
@ -2184,6 +2246,11 @@
"@types/node": "*" "@types/node": "*"
} }
}, },
"node_modules/@types/web-bluetooth": {
"version": "0.0.16",
"resolved": "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz",
"integrity": "sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ=="
},
"node_modules/@types/ws": { "node_modules/@types/ws": {
"version": "8.5.14", "version": "8.5.14",
"resolved": "https://registry.npmmirror.com/@types/ws/-/ws-8.5.14.tgz", "resolved": "https://registry.npmmirror.com/@types/ws/-/ws-8.5.14.tgz",
@ -2886,6 +2953,89 @@
"integrity": "sha512-Iu8Tbg3f+emIIMmI2ycSI8QcEuAUgPTgHwesDU1eKMLE4YC/c/sFbGc70QgMq31ijRftV0R7vCm9co6rldCeOA==", "integrity": "sha512-Iu8Tbg3f+emIIMmI2ycSI8QcEuAUgPTgHwesDU1eKMLE4YC/c/sFbGc70QgMq31ijRftV0R7vCm9co6rldCeOA==",
"dev": true "dev": true
}, },
"node_modules/@vueuse/core": {
"version": "9.13.0",
"resolved": "https://registry.npmmirror.com/@vueuse/core/-/core-9.13.0.tgz",
"integrity": "sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==",
"dependencies": {
"@types/web-bluetooth": "^0.0.16",
"@vueuse/metadata": "9.13.0",
"@vueuse/shared": "9.13.0",
"vue-demi": "*"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/@vueuse/core/node_modules/vue-demi": {
"version": "0.14.10",
"resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.10.tgz",
"integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==",
"hasInstallScript": true,
"bin": {
"vue-demi-fix": "bin/vue-demi-fix.js",
"vue-demi-switch": "bin/vue-demi-switch.js"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"@vue/composition-api": "^1.0.0-rc.1",
"vue": "^3.0.0-0 || ^2.6.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
}
}
},
"node_modules/@vueuse/metadata": {
"version": "9.13.0",
"resolved": "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-9.13.0.tgz",
"integrity": "sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ==",
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/@vueuse/shared": {
"version": "9.13.0",
"resolved": "https://registry.npmmirror.com/@vueuse/shared/-/shared-9.13.0.tgz",
"integrity": "sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==",
"dependencies": {
"vue-demi": "*"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/@vueuse/shared/node_modules/vue-demi": {
"version": "0.14.10",
"resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.10.tgz",
"integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==",
"hasInstallScript": true,
"bin": {
"vue-demi-fix": "bin/vue-demi-fix.js",
"vue-demi-switch": "bin/vue-demi-switch.js"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"@vue/composition-api": "^1.0.0-rc.1",
"vue": "^3.0.0-0 || ^2.6.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
}
}
},
"node_modules/@webassemblyjs/ast": { "node_modules/@webassemblyjs/ast": {
"version": "1.14.1", "version": "1.14.1",
"resolved": "https://registry.npmmirror.com/@webassemblyjs/ast/-/ast-1.14.1.tgz", "resolved": "https://registry.npmmirror.com/@webassemblyjs/ast/-/ast-1.14.1.tgz",
@ -3429,6 +3579,11 @@
"node": ">= 0.4" "node": ">= 0.4"
} }
}, },
"node_modules/async-validator": {
"version": "4.2.5",
"resolved": "https://registry.npmmirror.com/async-validator/-/async-validator-4.2.5.tgz",
"integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg=="
},
"node_modules/at-least-node": { "node_modules/at-least-node": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmmirror.com/at-least-node/-/at-least-node-1.0.0.tgz", "resolved": "https://registry.npmmirror.com/at-least-node/-/at-least-node-1.0.0.tgz",
@ -4709,6 +4864,11 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/dayjs": {
"version": "1.11.13",
"resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.13.tgz",
"integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg=="
},
"node_modules/debounce": { "node_modules/debounce": {
"version": "1.2.1", "version": "1.2.1",
"resolved": "https://registry.npmmirror.com/debounce/-/debounce-1.2.1.tgz", "resolved": "https://registry.npmmirror.com/debounce/-/debounce-1.2.1.tgz",
@ -5132,6 +5292,31 @@
"integrity": "sha512-L0ISiQrP/56Acgu4/i/kfPwWSgrzYZUnQrC0+QPFuhqlLP1Ir7qzPPDVS9BcKIyWTRU8+o6CC8dKw38tSWhYIA==", "integrity": "sha512-L0ISiQrP/56Acgu4/i/kfPwWSgrzYZUnQrC0+QPFuhqlLP1Ir7qzPPDVS9BcKIyWTRU8+o6CC8dKw38tSWhYIA==",
"dev": true "dev": true
}, },
"node_modules/element-plus": {
"version": "2.9.4",
"resolved": "https://registry.npmmirror.com/element-plus/-/element-plus-2.9.4.tgz",
"integrity": "sha512-sGnW0wd9zf6lEGixXV2gfwx3X6VTMkP52qTkX7zbURJ2oariyslrKTBh2txt1sdn1pUvj2l0KY3OfSXoZGmDOw==",
"dependencies": {
"@ctrl/tinycolor": "^3.4.1",
"@element-plus/icons-vue": "^2.3.1",
"@floating-ui/dom": "^1.0.1",
"@popperjs/core": "npm:@sxzz/popperjs-es@^2.11.7",
"@types/lodash": "^4.14.182",
"@types/lodash-es": "^4.17.6",
"@vueuse/core": "^9.1.0",
"async-validator": "^4.2.5",
"dayjs": "^1.11.13",
"escape-html": "^1.0.3",
"lodash": "^4.17.21",
"lodash-es": "^4.17.21",
"lodash-unified": "^1.0.2",
"memoize-one": "^6.0.0",
"normalize-wheel-es": "^1.2.0"
},
"peerDependencies": {
"vue": "^3.2.0"
}
},
"node_modules/emoji-regex": { "node_modules/emoji-regex": {
"version": "8.0.0", "version": "8.0.0",
"resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz",
@ -5377,8 +5562,7 @@
"node_modules/escape-html": { "node_modules/escape-html": {
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmmirror.com/escape-html/-/escape-html-1.0.3.tgz", "resolved": "https://registry.npmmirror.com/escape-html/-/escape-html-1.0.3.tgz",
"integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
"dev": true
}, },
"node_modules/escape-string-regexp": { "node_modules/escape-string-regexp": {
"version": "1.0.5", "version": "1.0.5",
@ -8111,8 +8295,22 @@
"node_modules/lodash": { "node_modules/lodash": {
"version": "4.17.21", "version": "4.17.21",
"resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz", "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
"dev": true },
"node_modules/lodash-es": {
"version": "4.17.21",
"resolved": "https://registry.npmmirror.com/lodash-es/-/lodash-es-4.17.21.tgz",
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
},
"node_modules/lodash-unified": {
"version": "1.0.3",
"resolved": "https://registry.npmmirror.com/lodash-unified/-/lodash-unified-1.0.3.tgz",
"integrity": "sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ==",
"peerDependencies": {
"@types/lodash-es": "*",
"lodash": "*",
"lodash-es": "*"
}
}, },
"node_modules/lodash.debounce": { "node_modules/lodash.debounce": {
"version": "4.0.8", "version": "4.0.8",
@ -8387,6 +8585,11 @@
"node": ">= 4.0.0" "node": ">= 4.0.0"
} }
}, },
"node_modules/memoize-one": {
"version": "6.0.0",
"resolved": "https://registry.npmmirror.com/memoize-one/-/memoize-one-6.0.0.tgz",
"integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw=="
},
"node_modules/memory-fs": { "node_modules/memory-fs": {
"version": "0.2.0", "version": "0.2.0",
"resolved": "https://registry.npmmirror.com/memory-fs/-/memory-fs-0.2.0.tgz", "resolved": "https://registry.npmmirror.com/memory-fs/-/memory-fs-0.2.0.tgz",
@ -8805,6 +9008,11 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/normalize-wheel-es": {
"version": "1.2.0",
"resolved": "https://registry.npmmirror.com/normalize-wheel-es/-/normalize-wheel-es-1.2.0.tgz",
"integrity": "sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw=="
},
"node_modules/npm-run-path": { "node_modules/npm-run-path": {
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmmirror.com/npm-run-path/-/npm-run-path-2.0.2.tgz", "resolved": "https://registry.npmmirror.com/npm-run-path/-/npm-run-path-2.0.2.tgz",
@ -14017,12 +14225,23 @@
"@babel/helper-validator-identifier": "^7.25.9" "@babel/helper-validator-identifier": "^7.25.9"
} }
}, },
"@ctrl/tinycolor": {
"version": "3.6.1",
"resolved": "https://registry.npmmirror.com/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz",
"integrity": "sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA=="
},
"@discoveryjs/json-ext": { "@discoveryjs/json-ext": {
"version": "0.5.7", "version": "0.5.7",
"resolved": "https://registry.npmmirror.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", "resolved": "https://registry.npmmirror.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz",
"integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==",
"dev": true "dev": true
}, },
"@element-plus/icons-vue": {
"version": "2.3.1",
"resolved": "https://registry.npmmirror.com/@element-plus/icons-vue/-/icons-vue-2.3.1.tgz",
"integrity": "sha512-XxVUZv48RZAd87ucGS48jPf6pKu0yV5UCg9f4FFwtrYxXOwWuVJo6wOvSLKEoMQKjv8GsX/mhP6UsC1lRwbUWg==",
"requires": {}
},
"@eslint/eslintrc": { "@eslint/eslintrc": {
"version": "0.4.3", "version": "0.4.3",
"resolved": "https://registry.npmmirror.com/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", "resolved": "https://registry.npmmirror.com/@eslint/eslintrc/-/eslintrc-0.4.3.tgz",
@ -14063,6 +14282,28 @@
} }
} }
}, },
"@floating-ui/core": {
"version": "1.6.9",
"resolved": "https://registry.npmmirror.com/@floating-ui/core/-/core-1.6.9.tgz",
"integrity": "sha512-uMXCuQ3BItDUbAMhIXw7UPXRfAlOAvZzdK9BWpE60MCn+Svt3aLn9jsPTi/WNGlRUu2uI0v5S7JiIUsbsvh3fw==",
"requires": {
"@floating-ui/utils": "^0.2.9"
}
},
"@floating-ui/dom": {
"version": "1.6.13",
"resolved": "https://registry.npmmirror.com/@floating-ui/dom/-/dom-1.6.13.tgz",
"integrity": "sha512-umqzocjDgNRGTuO7Q8CU32dkHkECqI8ZdMZ5Swb6QAM0t5rnlrN3lGo1hdpscRd3WS8T6DKYK4ephgIH9iRh3w==",
"requires": {
"@floating-ui/core": "^1.6.0",
"@floating-ui/utils": "^0.2.9"
}
},
"@floating-ui/utils": {
"version": "0.2.9",
"resolved": "https://registry.npmmirror.com/@floating-ui/utils/-/utils-0.2.9.tgz",
"integrity": "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg=="
},
"@hapi/hoek": { "@hapi/hoek": {
"version": "9.3.0", "version": "9.3.0",
"resolved": "https://registry.npmmirror.com/@hapi/hoek/-/hoek-9.3.0.tgz", "resolved": "https://registry.npmmirror.com/@hapi/hoek/-/hoek-9.3.0.tgz",
@ -14199,6 +14440,11 @@
"integrity": "sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==", "integrity": "sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==",
"dev": true "dev": true
}, },
"@popperjs/core": {
"version": "npm:@sxzz/popperjs-es@2.11.7",
"resolved": "https://registry.npmmirror.com/@sxzz/popperjs-es/-/popperjs-es-2.11.7.tgz",
"integrity": "sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ=="
},
"@rtsao/scc": { "@rtsao/scc": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmmirror.com/@rtsao/scc/-/scc-1.1.0.tgz", "resolved": "https://registry.npmmirror.com/@rtsao/scc/-/scc-1.1.0.tgz",
@ -14385,6 +14631,19 @@
"integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
"dev": true "dev": true
}, },
"@types/lodash": {
"version": "4.17.15",
"resolved": "https://registry.npmmirror.com/@types/lodash/-/lodash-4.17.15.tgz",
"integrity": "sha512-w/P33JFeySuhN6JLkysYUK2gEmy9kHHFN7E8ro0tkfmlDOgxBDzWEZ/J8cWA+fHqFevpswDTFZnDx+R9lbL6xw=="
},
"@types/lodash-es": {
"version": "4.17.12",
"resolved": "https://registry.npmmirror.com/@types/lodash-es/-/lodash-es-4.17.12.tgz",
"integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==",
"requires": {
"@types/lodash": "*"
}
},
"@types/mime": { "@types/mime": {
"version": "1.3.5", "version": "1.3.5",
"resolved": "https://registry.npmmirror.com/@types/mime/-/mime-1.3.5.tgz", "resolved": "https://registry.npmmirror.com/@types/mime/-/mime-1.3.5.tgz",
@ -14484,6 +14743,11 @@
"@types/node": "*" "@types/node": "*"
} }
}, },
"@types/web-bluetooth": {
"version": "0.0.16",
"resolved": "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz",
"integrity": "sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ=="
},
"@types/ws": { "@types/ws": {
"version": "8.5.14", "version": "8.5.14",
"resolved": "https://registry.npmmirror.com/@types/ws/-/ws-8.5.14.tgz", "resolved": "https://registry.npmmirror.com/@types/ws/-/ws-8.5.14.tgz",
@ -15028,6 +15292,46 @@
"integrity": "sha512-Iu8Tbg3f+emIIMmI2ycSI8QcEuAUgPTgHwesDU1eKMLE4YC/c/sFbGc70QgMq31ijRftV0R7vCm9co6rldCeOA==", "integrity": "sha512-Iu8Tbg3f+emIIMmI2ycSI8QcEuAUgPTgHwesDU1eKMLE4YC/c/sFbGc70QgMq31ijRftV0R7vCm9co6rldCeOA==",
"dev": true "dev": true
}, },
"@vueuse/core": {
"version": "9.13.0",
"resolved": "https://registry.npmmirror.com/@vueuse/core/-/core-9.13.0.tgz",
"integrity": "sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==",
"requires": {
"@types/web-bluetooth": "^0.0.16",
"@vueuse/metadata": "9.13.0",
"@vueuse/shared": "9.13.0",
"vue-demi": "*"
},
"dependencies": {
"vue-demi": {
"version": "0.14.10",
"resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.10.tgz",
"integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==",
"requires": {}
}
}
},
"@vueuse/metadata": {
"version": "9.13.0",
"resolved": "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-9.13.0.tgz",
"integrity": "sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ=="
},
"@vueuse/shared": {
"version": "9.13.0",
"resolved": "https://registry.npmmirror.com/@vueuse/shared/-/shared-9.13.0.tgz",
"integrity": "sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==",
"requires": {
"vue-demi": "*"
},
"dependencies": {
"vue-demi": {
"version": "0.14.10",
"resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.10.tgz",
"integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==",
"requires": {}
}
}
},
"@webassemblyjs/ast": { "@webassemblyjs/ast": {
"version": "1.14.1", "version": "1.14.1",
"resolved": "https://registry.npmmirror.com/@webassemblyjs/ast/-/ast-1.14.1.tgz", "resolved": "https://registry.npmmirror.com/@webassemblyjs/ast/-/ast-1.14.1.tgz",
@ -15454,6 +15758,11 @@
"integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==",
"dev": true "dev": true
}, },
"async-validator": {
"version": "4.2.5",
"resolved": "https://registry.npmmirror.com/async-validator/-/async-validator-4.2.5.tgz",
"integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg=="
},
"at-least-node": { "at-least-node": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmmirror.com/at-least-node/-/at-least-node-1.0.0.tgz", "resolved": "https://registry.npmmirror.com/at-least-node/-/at-least-node-1.0.0.tgz",
@ -16354,6 +16663,11 @@
"is-data-view": "^1.0.1" "is-data-view": "^1.0.1"
} }
}, },
"dayjs": {
"version": "1.11.13",
"resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.13.tgz",
"integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg=="
},
"debounce": { "debounce": {
"version": "1.2.1", "version": "1.2.1",
"resolved": "https://registry.npmmirror.com/debounce/-/debounce-1.2.1.tgz", "resolved": "https://registry.npmmirror.com/debounce/-/debounce-1.2.1.tgz",
@ -16664,6 +16978,28 @@
"integrity": "sha512-L0ISiQrP/56Acgu4/i/kfPwWSgrzYZUnQrC0+QPFuhqlLP1Ir7qzPPDVS9BcKIyWTRU8+o6CC8dKw38tSWhYIA==", "integrity": "sha512-L0ISiQrP/56Acgu4/i/kfPwWSgrzYZUnQrC0+QPFuhqlLP1Ir7qzPPDVS9BcKIyWTRU8+o6CC8dKw38tSWhYIA==",
"dev": true "dev": true
}, },
"element-plus": {
"version": "2.9.4",
"resolved": "https://registry.npmmirror.com/element-plus/-/element-plus-2.9.4.tgz",
"integrity": "sha512-sGnW0wd9zf6lEGixXV2gfwx3X6VTMkP52qTkX7zbURJ2oariyslrKTBh2txt1sdn1pUvj2l0KY3OfSXoZGmDOw==",
"requires": {
"@ctrl/tinycolor": "^3.4.1",
"@element-plus/icons-vue": "^2.3.1",
"@floating-ui/dom": "^1.0.1",
"@popperjs/core": "npm:@sxzz/popperjs-es@^2.11.7",
"@types/lodash": "^4.14.182",
"@types/lodash-es": "^4.17.6",
"@vueuse/core": "^9.1.0",
"async-validator": "^4.2.5",
"dayjs": "^1.11.13",
"escape-html": "^1.0.3",
"lodash": "^4.17.21",
"lodash-es": "^4.17.21",
"lodash-unified": "^1.0.2",
"memoize-one": "^6.0.0",
"normalize-wheel-es": "^1.2.0"
}
},
"emoji-regex": { "emoji-regex": {
"version": "8.0.0", "version": "8.0.0",
"resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz",
@ -16861,8 +17197,7 @@
"escape-html": { "escape-html": {
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmmirror.com/escape-html/-/escape-html-1.0.3.tgz", "resolved": "https://registry.npmmirror.com/escape-html/-/escape-html-1.0.3.tgz",
"integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
"dev": true
}, },
"escape-string-regexp": { "escape-string-regexp": {
"version": "1.0.5", "version": "1.0.5",
@ -18811,8 +19146,18 @@
"lodash": { "lodash": {
"version": "4.17.21", "version": "4.17.21",
"resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz", "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
"dev": true },
"lodash-es": {
"version": "4.17.21",
"resolved": "https://registry.npmmirror.com/lodash-es/-/lodash-es-4.17.21.tgz",
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
},
"lodash-unified": {
"version": "1.0.3",
"resolved": "https://registry.npmmirror.com/lodash-unified/-/lodash-unified-1.0.3.tgz",
"integrity": "sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ==",
"requires": {}
}, },
"lodash.debounce": { "lodash.debounce": {
"version": "4.0.8", "version": "4.0.8",
@ -19034,6 +19379,11 @@
"fs-monkey": "^1.0.4" "fs-monkey": "^1.0.4"
} }
}, },
"memoize-one": {
"version": "6.0.0",
"resolved": "https://registry.npmmirror.com/memoize-one/-/memoize-one-6.0.0.tgz",
"integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw=="
},
"memory-fs": { "memory-fs": {
"version": "0.2.0", "version": "0.2.0",
"resolved": "https://registry.npmmirror.com/memory-fs/-/memory-fs-0.2.0.tgz", "resolved": "https://registry.npmmirror.com/memory-fs/-/memory-fs-0.2.0.tgz",
@ -19345,6 +19695,11 @@
"integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==",
"dev": true "dev": true
}, },
"normalize-wheel-es": {
"version": "1.2.0",
"resolved": "https://registry.npmmirror.com/normalize-wheel-es/-/normalize-wheel-es-1.2.0.tgz",
"integrity": "sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw=="
},
"npm-run-path": { "npm-run-path": {
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmmirror.com/npm-run-path/-/npm-run-path-2.0.2.tgz", "resolved": "https://registry.npmmirror.com/npm-run-path/-/npm-run-path-2.0.2.tgz",

View File

@ -9,6 +9,7 @@
}, },
"dependencies": { "dependencies": {
"core-js": "^3.8.3", "core-js": "^3.8.3",
"element-plus": "^2.9.4",
"vue": "^3.2.13", "vue": "^3.2.13",
"vue-router": "^4.0.3", "vue-router": "^4.0.3",
"vuex": "^4.0.0" "vuex": "^4.0.0"

View File

@ -1,5 +1,9 @@
<template> <template>
<router-view/> <router-view v-slot="{ Component, route }">
<transition :name="route.meta.transition" mode="out-in">
<component :is="Component" :key="route.path"/>
</transition>
</router-view>
</template> </template>
<style> <style>
@ -23,4 +27,29 @@ nav a {
nav a.router-link-exact-active { nav a.router-link-exact-active {
color: #42b983; color: #42b983;
} }
/* 翻转动画 */
.flip-enter-active,
.flip-leave-active {
transition: all 0.6s ease;
transform-style: preserve-3d;
}
.flip-enter-from .login-box,
.flip-enter-from .register-box {
transform: rotateY(180deg);
}
.flip-leave-to .login-box,
.flip-leave-to .register-box {
transform: rotateY(-180deg);
}
/* 确保卡片有3D效果 */
.login-box,
.register-box {
transition: transform 0.6s ease;
transform-style: preserve-3d;
backface-visibility: hidden;
}
</style> </style>

View File

@ -1,6 +1,12 @@
import { createApp } from 'vue' import { createApp } from 'vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import App from './App.vue' import App from './App.vue'
import router from './router' import router from './router'
import store from './store' import store from './store'
createApp(App).use(store).use(router).mount('#app') const app = createApp(App)
app.use(store)
app.use(router)
app.use(ElementPlus)
app.mount('#app')

View File

@ -14,12 +14,20 @@ const routes = [
{ {
path: '/login', path: '/login',
name: 'Login', name: 'Login',
component: Login component: Login,
meta: {
transition: 'flip',
title: '登录'
}
}, },
{ {
path: '/register', path: '/register',
name: 'Register', name: 'Register',
component: Register component: Register,
meta: {
transition: 'flip',
title: '注册'
}
}, },
{ {
path: '/admin', path: '/admin',
@ -52,5 +60,12 @@ const router = createRouter({
history: createWebHistory(process.env.BASE_URL), history: createWebHistory(process.env.BASE_URL),
routes routes
}) })
router.beforeEach((to, from, next) => {
// 设置页面标题
if (to.meta.title) {
document.title = to.meta.title
}
next()
})
export default router export default router

View File

@ -1,49 +1,106 @@
<template> <template>
<transition name="fade" mode="out-in">
<div class="login-container"> <div class="login-container">
<div class="login-box"> <el-card class="login-box">
<h2>登录系统</h2> <h2>登录系统</h2>
<form @submit.prevent="handleLogin"> <el-form
<div class="form-group"> @submit.prevent="handleLogin"
<label>用户名</label> :model="loginForm"
<input type="text" v-model="username" required> :rules="rules"
</div> ref="loginForm"
<div class="form-group"> >
<label>密码</label> <el-row class="form-item">
<input type="password" v-model="password" required> <el-col :span="6" class="label-col">
</div> <label>用户名</label>
<div class="form-group"> </el-col>
<label>用户类型</label> <el-col :span="14">
<select v-model="userType"> <el-input
<option value="admin">管理员</option> v-model="loginForm.username"
<option value="staff">员工</option> placeholder="请输入用户名"
<option value="customer">顾客</option> @keyup.enter="handleLogin"
</select> ></el-input>
</div> </el-col>
<button type="submit">登录</button> </el-row>
</form> <el-row class="form-item">
<!-- 添加注册链接 --> <el-col :span="6" class="label-col">
<label>密码</label>
</el-col>
<el-col :span="14">
<el-input
type="password"
v-model="loginForm.password"
placeholder="请输入密码"
@keyup.enter="handleLogin"
show-password
></el-input>
</el-col>
</el-row>
<el-button
type="primary"
@click="handleLogin"
class="submit-btn"
:class="{ 'button-loading': loading }"
@mouseenter="buttonHover = true"
@mouseleave="buttonHover = false"
>
<span class="button-text" :class="{ 'text-loading': loading }">
{{ loading ? '登录中...' : '登录' }}
</span>
<span class="button-effect"></span>
</el-button>
</el-form>
<div class="form-footer"> <div class="form-footer">
<p>还没有账号<router-link to="/register">立即注册</router-link></p> <p>还没有账号
</div> <router-link to="/register" class="link-btn">
立即注册
<span class="arrow"></span>
</router-link>
</p>
</div> </div>
</el-card>
</div> </div>
</transition>
</template> </template>
<script> <script>
export default { export default {
// eslint-disable-next-line vue/multi-word-component-names name: 'LoginPage',
name: 'Login',
data () { data () {
return { return {
loginForm: {
username: '', username: '',
password: '', password: ''
userType: 'customer' },
rules: {
username: [
{ required: true, message: '请输入用户名', trigger: 'blur' },
{ min: 3, max: 20, message: '长度在 3 到 20 个字符', trigger: 'blur' }
],
password: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{ min: 6, max: 20, message: '长度在 6 到 20 个字符', trigger: 'blur' }
]
},
loading: false,
buttonHover: false
} }
}, },
methods: { methods: {
handleLogin () { handleLogin () {
// if (this.loading) return
console.log('登录信息:', this.username, this.password, this.userType) this.$refs.loginForm.validate((valid) => {
if (valid) {
this.loading = true
console.log('登录信息:', this.loginForm)
//
setTimeout(() => {
this.loading = false
this.$message.success('登录成功')
}, 2000)
} else {
return false
}
})
} }
} }
} }
@ -55,48 +112,230 @@ export default {
justify-content: center; justify-content: center;
align-items: center; align-items: center;
height: 100vh; height: 100vh;
background-color: #f5f5f5; background: linear-gradient(135deg, #1abc9c 0%, #8e44ad 100%);
position: relative;
overflow: hidden;
}
.login-container::before {
content: '';
position: absolute;
width: 2000px;
height: 2000px;
border-radius: 50%;
background: rgba(255, 255, 255, 0.1);
top: -10%;
right: 48%;
transform: translateY(-50%);
animation: float 6s ease-in-out infinite;
}
.login-container::after {
content: '';
position: absolute;
width: 1500px;
height: 1500px;
border-radius: 50%;
background: rgba(255, 255, 255, 0.1);
top: -10%;
right: 52%;
transform: translateY(-50%);
animation: float 8s ease-in-out infinite;
} }
.login-box { .login-box {
width: 400px; width: 500px;
padding: 20px; backdrop-filter: blur(10px);
background: white; border: 1px solid rgba(255,255,255,0.2);
border-radius: 8px; position: relative;
box-shadow: 0 0 10px rgba(0,0,0,0.1); z-index: 1;
transform-origin: center center;
perspective: 1000px;
} }
.form-group { :deep(.el-card__body) {
margin-bottom: 15px; padding: 30px;
backface-visibility: hidden;
} }
input, select { h2 {
width: 100%; text-align: center;
padding: 8px; margin-bottom: 30px;
margin-top: 5px; color: #2c3e50;
} }
button { .form-item {
width: 100%; margin-bottom: 20px;
padding: 10px; display: flex;
background: #4CAF50; align-items: center;
color: white; position: relative;
}
.label-col {
text-align: right;
padding-right: 20px;
line-height: 40px;
color: #606266;
font-weight: 500;
transition: all 0.3s ease;
}
.form-item:hover .label-col {
color: #409EFF;
}
.submit-btn {
width: 60%;
margin-top: 20px;
position: relative;
overflow: hidden;
transition: all 0.3s ease;
height: 40px;
border: none; border: none;
border-radius: 4px; }
cursor: pointer;
.submit-btn:hover {
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(0,0,0,0.2);
}
.submit-btn:active {
transform: translateY(0);
}
.button-text {
position: relative;
z-index: 1;
transition: all 0.3s ease;
}
.button-effect {
position: absolute;
top: 50%;
left: 50%;
width: 0;
height: 0;
background: rgba(255,255,255,0.2);
border-radius: 50%;
transform: translate(-50%, -50%);
transition: all 0.5s ease;
}
.submit-btn:hover .button-effect {
width: 300px;
height: 300px;
}
.button-loading {
background: #409EFF !important;
cursor: wait;
}
.text-loading {
animation: textLoading 1.5s infinite;
}
@keyframes textLoading {
0% { opacity: 1; }
50% { opacity: 0.5; }
100% { opacity: 1; }
} }
.form-footer { .form-footer {
margin-top: 15px; margin-top: 20px;
text-align: center; text-align: center;
} }
.form-footer a { .form-footer a {
color: #4CAF50; color: #409EFF;
text-decoration: none; text-decoration: none;
position: relative;
padding-right: 24px;
transition: all 0.3s ease;
} }
.form-footer a:hover { .link-btn {
text-decoration: underline; display: inline-flex;
align-items: center;
}
.arrow {
position: absolute;
right: 0;
opacity: 0;
transform: translateX(-8px);
transition: all 0.3s ease;
}
.link-btn:hover {
padding-right: 28px;
}
.link-btn:hover .arrow {
opacity: 1;
transform: translateX(0);
}
@keyframes float {
0% {
transform: translateY(-50%) rotate(0deg);
}
50% {
transform: translateY(-45%) rotate(180deg);
}
100% {
transform: translateY(-50%) rotate(360deg);
}
}
/* 页面过渡动画 */
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.3s ease, transform 0.3s ease;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
transform: translateX(-30px);
}
.fade-enter-to,
.fade-leave-from {
opacity: 1;
transform: translateX(0);
}
.el-input {
transition: all 0.3s ease;
}
.el-input:focus-within {
transform: translateX(5px);
}
/* 添加输入框焦点时的装饰线 */
.el-input:focus-within::after {
content: '';
position: absolute;
left: -10px;
top: 50%;
height: 60%;
width: 3px;
background: #409EFF;
transform: translateY(-50%);
border-radius: 3px;
animation: focusLine 0.3s ease;
}
@keyframes focusLine {
from {
opacity: 0;
transform: translateY(-50%) scaleY(0);
}
to {
opacity: 1;
transform: translateY(-50%) scaleY(1);
}
} }
</style> </style>

View File

@ -1,57 +1,89 @@
<template> <template>
<transition name="fade" mode="out-in">
<div class="register-container"> <div class="register-container">
<div class="register-box"> <el-card class="register-box">
<h2>注册账号</h2> <h2>注册账号</h2>
<form @submit.prevent="handleRegister"> <el-form
<div class="form-group"> @submit.prevent="handleRegister"
<label>用户名</label> :model="registerForm"
<input type="text" v-model="username" required> :rules="rules"
</div> ref="registerForm"
<div class="form-group"> >
<label>密码</label> <el-row class="form-item">
<input type="password" v-model="password" required> <el-col :span="6" class="label-col">
</div> <label>用户名</label>
<div class="form-group"> </el-col>
<label>确认密码</label> <el-col :span="14">
<input type="password" v-model="confirmPassword" required> <el-input v-model="username" placeholder="请输入用户名"></el-input>
</div> </el-col>
<div class="form-group"> </el-row>
<label>用户类型</label> <el-row class="form-item">
<select v-model="userType"> <el-col :span="6" class="label-col">
<option value="customer">顾客</option> <label>密码</label>
<option value="staff">员工</option> </el-col>
</select> <el-col :span="14">
</div> <el-input type="password" v-model="password" placeholder="请输入密码"></el-input>
<button type="submit">注册</button> </el-col>
</form> </el-row>
<!-- 添加登录链接 --> <el-row class="form-item">
<el-col :span="6" class="label-col">
<label>确认密码</label>
</el-col>
<el-col :span="14">
<el-input type="password" v-model="confirmPassword" placeholder="请再次输入密码"></el-input>
</el-col>
</el-row>
<el-button
type="primary"
@click="handleRegister"
class="submit-btn"
:class="{ 'button-loading': loading }"
@mouseenter="buttonHover = true"
@mouseleave="buttonHover = false"
>
<span class="button-text" :class="{ 'text-loading': loading }">
{{ loading ? '注册中...' : '注册' }}
</span>
<span class="button-effect"></span>
</el-button>
</el-form>
<div class="form-footer"> <div class="form-footer">
<p>已有账号<router-link to="/login">立即登录</router-link></p> <p>已有账号
</div> <router-link to="/login" class="link-btn">
立即登录
<span class="arrow"></span>
</router-link>
</p>
</div> </div>
</el-card>
</div> </div>
</transition>
</template> </template>
<script> <script>
export default { export default {
// eslint-disable-next-line vue/multi-word-component-names name: 'RegisterPage',
name: 'Register',
data () { data () {
return { return {
username: '', username: '',
password: '', password: '',
confirmPassword: '', confirmPassword: '',
userType: 'customer' loading: false,
buttonHover: false
} }
}, },
methods: { methods: {
handleRegister () { handleRegister () {
if (this.loading) return
if (this.password !== this.confirmPassword) { if (this.password !== this.confirmPassword) {
alert('两次输入的密码不一致!') this.$message.error('两次输入的密码不一致!')
return return
} }
// this.loading = true
console.log('注册信息:', this.username, this.password, this.userType) console.log('注册信息:', this.username, this.password)
setTimeout(() => {
this.loading = false
}, 2000)
} }
} }
} }
@ -63,48 +95,230 @@ export default {
justify-content: center; justify-content: center;
align-items: center; align-items: center;
height: 100vh; height: 100vh;
background-color: #f5f5f5; background: linear-gradient(135deg, #1abc9c 0%, #8e44ad 100%);
position: relative;
overflow: hidden;
}
.register-container::before {
content: '';
position: absolute;
width: 2000px;
height: 2000px;
border-radius: 50%;
background: rgba(255, 255, 255, 0.1);
top: -10%;
right: 48%;
transform: translateY(-50%);
animation: float 6s ease-in-out infinite;
}
.register-container::after {
content: '';
position: absolute;
width: 1500px;
height: 1500px;
border-radius: 50%;
background: rgba(255, 255, 255, 0.1);
top: -10%;
right: 52%;
transform: translateY(-50%);
animation: float 8s ease-in-out infinite;
} }
.register-box { .register-box {
width: 400px; width: 500px;
padding: 20px; backdrop-filter: blur(10px);
background: white; border: 1px solid rgba(255,255,255,0.2);
border-radius: 8px; position: relative;
box-shadow: 0 0 10px rgba(0,0,0,0.1); z-index: 1;
transform-origin: center center;
perspective: 1000px;
} }
.form-group { :deep(.el-card__body) {
margin-bottom: 15px; padding: 30px;
backface-visibility: hidden;
} }
input, select { h2 {
width: 100%; text-align: center;
padding: 8px; margin-bottom: 30px;
margin-top: 5px; color: #2c3e50;
} }
button { .form-item {
width: 100%; margin-bottom: 20px;
padding: 10px; display: flex;
background: #4CAF50; align-items: center;
color: white; position: relative;
}
.label-col {
text-align: right;
padding-right: 20px;
line-height: 40px;
color: #606266;
font-weight: 500;
transition: all 0.3s ease;
}
.form-item:hover .label-col {
color: #409EFF;
}
.el-input {
transition: all 0.3s ease;
}
.el-input:focus-within {
transform: translateX(5px);
}
/* 添加输入框焦点时的装饰线 */
.el-input:focus-within::after {
content: '';
position: absolute;
left: -10px;
top: 50%;
height: 60%;
width: 3px;
background: #409EFF;
transform: translateY(-50%);
border-radius: 3px;
animation: focusLine 0.3s ease;
}
@keyframes focusLine {
from {
opacity: 0;
transform: translateY(-50%) scaleY(0);
}
to {
opacity: 1;
transform: translateY(-50%) scaleY(1);
}
}
.submit-btn {
width: 60%;
margin-top: 20px;
position: relative;
overflow: hidden;
transition: all 0.3s ease;
height: 40px;
border: none; border: none;
border-radius: 4px; }
cursor: pointer;
.submit-btn:hover {
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(0,0,0,0.2);
}
.submit-btn:active {
transform: translateY(0);
}
.button-text {
position: relative;
z-index: 1;
transition: all 0.3s ease;
}
.button-effect {
position: absolute;
top: 50%;
left: 50%;
width: 0;
height: 0;
background: rgba(255,255,255,0.2);
border-radius: 50%;
transform: translate(-50%, -50%);
transition: all 0.5s ease;
}
.submit-btn:hover .button-effect {
width: 300px;
height: 300px;
}
.button-loading {
background: #409EFF !important;
cursor: wait;
}
.text-loading {
animation: textLoading 1.5s infinite;
}
@keyframes textLoading {
0% { opacity: 1; }
50% { opacity: 0.5; }
100% { opacity: 1; }
} }
.form-footer { .form-footer {
margin-top: 15px; margin-top: 20px;
text-align: center; text-align: center;
} }
.form-footer a { .form-footer a {
color: #4CAF50; color: #409EFF;
text-decoration: none; text-decoration: none;
position: relative;
padding-left: 24px;
transition: all 0.3s ease;
} }
.form-footer a:hover { .link-btn {
text-decoration: underline; display: inline-flex;
align-items: center;
}
.arrow {
position: absolute;
left: 0;
opacity: 0;
transform: translateX(8px);
transition: all 0.3s ease;
}
.link-btn:hover {
padding-left: 28px;
}
.link-btn:hover .arrow {
opacity: 1;
transform: translateX(0);
}
@keyframes float {
0% {
transform: translateY(-50%) rotate(0deg);
}
50% {
transform: translateY(-45%) rotate(180deg);
}
100% {
transform: translateY(-50%) rotate(360deg);
}
}
/* 页面过渡动画 */
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.3s ease, transform 0.3s ease;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
transform: translateX(30px);
}
.fade-enter-to,
.fade-leave-from {
opacity: 1;
transform: translateX(0);
} }
</style> </style>