feat(web): 实现能源站监控与运行管理系统的登录功能

- 新增登录页面组件 LoginView.vue
- 添加全局样式和布局调整
- 实现用户登录逻辑,包括表单验证、验证码校验和 token 存储
- 集成 ant-design-vue 组件库
- 添加请求拦截器和错误处理
This commit is contained in:
zhoumengru
2025-08-29 12:28:33 +08:00
parent 5e559f8d36
commit 390ea73d7d
11 changed files with 629 additions and 168 deletions

116
web/package-lock.json generated
View File

@@ -9,7 +9,9 @@
"version": "0.1.0", "version": "0.1.0",
"dependencies": { "dependencies": {
"ant-design-vue": "^4.2.6", "ant-design-vue": "^4.2.6",
"axios": "^1.11.0",
"core-js": "^3.8.3", "core-js": "^3.8.3",
"moment": "^2.30.1",
"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"
@@ -3903,6 +3905,12 @@
"integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==", "integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
"license": "MIT"
},
"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",
@@ -3951,6 +3959,17 @@
"postcss": "^8.1.0" "postcss": "^8.1.0"
} }
}, },
"node_modules/axios": {
"version": "1.11.0",
"resolved": "https://registry.npmmirror.com/axios/-/axios-1.11.0.tgz",
"integrity": "sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==",
"license": "MIT",
"dependencies": {
"follow-redirects": "^1.15.6",
"form-data": "^4.0.4",
"proxy-from-env": "^1.1.0"
}
},
"node_modules/babel-loader": { "node_modules/babel-loader": {
"version": "8.4.1", "version": "8.4.1",
"resolved": "https://registry.npmmirror.com/babel-loader/-/babel-loader-8.4.1.tgz", "resolved": "https://registry.npmmirror.com/babel-loader/-/babel-loader-8.4.1.tgz",
@@ -4297,7 +4316,6 @@
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmmirror.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", "resolved": "https://registry.npmmirror.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"es-errors": "^1.3.0", "es-errors": "^1.3.0",
@@ -4632,6 +4650,18 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"license": "MIT",
"dependencies": {
"delayed-stream": "~1.0.0"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/commander": { "node_modules/commander": {
"version": "8.3.0", "version": "8.3.0",
"resolved": "https://registry.npmmirror.com/commander/-/commander-8.3.0.tgz", "resolved": "https://registry.npmmirror.com/commander/-/commander-8.3.0.tgz",
@@ -5462,6 +5492,15 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
"license": "MIT",
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/depd": { "node_modules/depd": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmmirror.com/depd/-/depd-2.0.0.tgz", "resolved": "https://registry.npmmirror.com/depd/-/depd-2.0.0.tgz",
@@ -5666,7 +5705,6 @@
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmmirror.com/dunder-proto/-/dunder-proto-1.0.1.tgz", "resolved": "https://registry.npmmirror.com/dunder-proto/-/dunder-proto-1.0.1.tgz",
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"call-bind-apply-helpers": "^1.0.1", "call-bind-apply-helpers": "^1.0.1",
@@ -5809,7 +5847,6 @@
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.1.tgz", "resolved": "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.1.tgz",
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">= 0.4" "node": ">= 0.4"
@@ -5819,7 +5856,6 @@
"version": "1.3.0", "version": "1.3.0",
"resolved": "https://registry.npmmirror.com/es-errors/-/es-errors-1.3.0.tgz", "resolved": "https://registry.npmmirror.com/es-errors/-/es-errors-1.3.0.tgz",
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">= 0.4" "node": ">= 0.4"
@@ -5836,7 +5872,6 @@
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmmirror.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz", "resolved": "https://registry.npmmirror.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"es-errors": "^1.3.0" "es-errors": "^1.3.0"
@@ -5845,6 +5880,21 @@
"node": ">= 0.4" "node": ">= 0.4"
} }
}, },
"node_modules/es-set-tostringtag": {
"version": "2.1.0",
"resolved": "https://registry.npmmirror.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
"integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
"get-intrinsic": "^1.2.6",
"has-tostringtag": "^1.0.2",
"hasown": "^2.0.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/escalade": { "node_modules/escalade": {
"version": "3.2.0", "version": "3.2.0",
"resolved": "https://registry.npmmirror.com/escalade/-/escalade-3.2.0.tgz", "resolved": "https://registry.npmmirror.com/escalade/-/escalade-3.2.0.tgz",
@@ -6807,7 +6857,6 @@
"version": "1.15.11", "version": "1.15.11",
"resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.11.tgz", "resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.11.tgz",
"integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==",
"dev": true,
"funding": [ "funding": [
{ {
"type": "individual", "type": "individual",
@@ -6824,6 +6873,22 @@
} }
} }
}, },
"node_modules/form-data": {
"version": "4.0.4",
"resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.4.tgz",
"integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==",
"license": "MIT",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"es-set-tostringtag": "^2.1.0",
"hasown": "^2.0.2",
"mime-types": "^2.1.12"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/forwarded": { "node_modules/forwarded": {
"version": "0.2.0", "version": "0.2.0",
"resolved": "https://registry.npmmirror.com/forwarded/-/forwarded-0.2.0.tgz", "resolved": "https://registry.npmmirror.com/forwarded/-/forwarded-0.2.0.tgz",
@@ -6907,7 +6972,6 @@
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz", "resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz",
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
"dev": true,
"license": "MIT", "license": "MIT",
"funding": { "funding": {
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
@@ -6944,7 +7008,6 @@
"version": "1.3.0", "version": "1.3.0",
"resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz", "resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"call-bind-apply-helpers": "^1.0.2", "call-bind-apply-helpers": "^1.0.2",
@@ -6969,7 +7032,6 @@
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmmirror.com/get-proto/-/get-proto-1.0.1.tgz", "resolved": "https://registry.npmmirror.com/get-proto/-/get-proto-1.0.1.tgz",
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"dunder-proto": "^1.0.1", "dunder-proto": "^1.0.1",
@@ -7088,7 +7150,6 @@
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmmirror.com/gopd/-/gopd-1.2.0.tgz", "resolved": "https://registry.npmmirror.com/gopd/-/gopd-1.2.0.tgz",
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">= 0.4" "node": ">= 0.4"
@@ -7154,7 +7215,6 @@
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.1.0.tgz", "resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.1.0.tgz",
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">= 0.4" "node": ">= 0.4"
@@ -7163,6 +7223,21 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/has-tostringtag": {
"version": "1.0.2",
"resolved": "https://registry.npmmirror.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
"license": "MIT",
"dependencies": {
"has-symbols": "^1.0.3"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/hash-sum": { "node_modules/hash-sum": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmmirror.com/hash-sum/-/hash-sum-2.0.0.tgz", "resolved": "https://registry.npmmirror.com/hash-sum/-/hash-sum-2.0.0.tgz",
@@ -7174,7 +7249,6 @@
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmmirror.com/hasown/-/hasown-2.0.2.tgz", "resolved": "https://registry.npmmirror.com/hasown/-/hasown-2.0.2.tgz",
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"function-bind": "^1.1.2" "function-bind": "^1.1.2"
@@ -8368,7 +8442,6 @@
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmmirror.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz", "resolved": "https://registry.npmmirror.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">= 0.4" "node": ">= 0.4"
@@ -8482,7 +8555,6 @@
"version": "1.52.0", "version": "1.52.0",
"resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz", "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">= 0.6" "node": ">= 0.6"
@@ -8492,7 +8564,6 @@
"version": "2.1.35", "version": "2.1.35",
"resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz", "resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"mime-db": "1.52.0" "mime-db": "1.52.0"
@@ -8646,6 +8717,15 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/moment": {
"version": "2.30.1",
"resolved": "https://registry.npmmirror.com/moment/-/moment-2.30.1.tgz",
"integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==",
"license": "MIT",
"engines": {
"node": "*"
}
},
"node_modules/mrmime": { "node_modules/mrmime": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmmirror.com/mrmime/-/mrmime-2.0.1.tgz", "resolved": "https://registry.npmmirror.com/mrmime/-/mrmime-2.0.1.tgz",
@@ -10116,6 +10196,12 @@
"node": ">= 0.10" "node": ">= 0.10"
} }
}, },
"node_modules/proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
"license": "MIT"
},
"node_modules/pseudomap": { "node_modules/pseudomap": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmmirror.com/pseudomap/-/pseudomap-1.0.2.tgz", "resolved": "https://registry.npmmirror.com/pseudomap/-/pseudomap-1.0.2.tgz",

View File

@@ -9,7 +9,9 @@
}, },
"dependencies": { "dependencies": {
"ant-design-vue": "^4.2.6", "ant-design-vue": "^4.2.6",
"axios": "^1.11.0",
"core-js": "^3.8.3", "core-js": "^3.8.3",
"moment": "^2.30.1",
"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,8 +1,4 @@
<template> <template>
<nav>
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link>
</nav>
<router-view /> <router-view />
</template> </template>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

View File

@@ -1,130 +0,0 @@
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<p>
For a guide and recipes on how to configure / customize this project,<br />
check out the
<a href="https://cli.vuejs.org" target="_blank" rel="noopener"
>vue-cli documentation</a
>.
</p>
<h3>Installed CLI Plugins</h3>
<ul>
<li>
<a
href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel"
target="_blank"
rel="noopener"
>babel</a
>
</li>
<li>
<a
href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-router"
target="_blank"
rel="noopener"
>router</a
>
</li>
<li>
<a
href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-vuex"
target="_blank"
rel="noopener"
>vuex</a
>
</li>
<li>
<a
href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint"
target="_blank"
rel="noopener"
>eslint</a
>
</li>
</ul>
<h3>Essential Links</h3>
<ul>
<li>
<a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a>
</li>
<li>
<a href="https://forum.vuejs.org" target="_blank" rel="noopener"
>Forum</a
>
</li>
<li>
<a href="https://chat.vuejs.org" target="_blank" rel="noopener"
>Community Chat</a
>
</li>
<li>
<a href="https://twitter.com/vuejs" target="_blank" rel="noopener"
>Twitter</a
>
</li>
<li>
<a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a>
</li>
</ul>
<h3>Ecosystem</h3>
<ul>
<li>
<a href="https://router.vuejs.org" target="_blank" rel="noopener"
>vue-router</a
>
</li>
<li>
<a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a>
</li>
<li>
<a
href="https://github.com/vuejs/vue-devtools#vue-devtools"
target="_blank"
rel="noopener"
>vue-devtools</a
>
</li>
<li>
<a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener"
>vue-loader</a
>
</li>
<li>
<a
href="https://github.com/vuejs/awesome-vue"
target="_blank"
rel="noopener"
>awesome-vue</a
>
</li>
</ul>
</div>
</template>
<script>
export default {
name: "HelloWorld",
props: {
msg: String,
},
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>

16
web/src/request/api.js Normal file
View File

@@ -0,0 +1,16 @@
import request from "@/request/index.js";
export function postReq(data, url) {
return request({
method: "post",
url,
data,
});
}
export function getReq(data, url) {
// const query = qs.stringify(data, { indices: false })
return request({
method: "get",
url: url + "?" + data,
});
}

61
web/src/request/index.js Normal file
View File

@@ -0,0 +1,61 @@
import axios from "axios";
// import openNotification from "../utils/notification";
// let { config } = window;
// let { baseUrl } = config;
const service = axios.create({
// baseURL: baseUrl,
baseURL: "",
timeout: 120000,
});
service.interceptors.request.use((config) => {
const webConfig = config;
// if (!["/user/login", "/config/getConfig"].includes(config.url)) {
// if (localStorage.getItem("token")) {
// webConfig.headers = {
// Authorization: localStorage.getItem("token"),
// };
// }
// }
return webConfig;
});
service.interceptors.response.use(
(response) => {
// 排除以下接口的错误提示
const { url } = response.config;
const urls = ["/light/", "/serve/delete", "/user/checkRandom"];
const urlFlag = urls.map((item) => {
return url.includes(item);
});
const res = response.data;
if (res.code !== 200) {
if (res.code == 401 || res.tip == "校验token过期") {
setTimeout(() => {
window.$wujie?.props.jump({ path: "/login" });
}, 1000);
} else if (urlFlag.every((item) => item === false)) {
// openNotification({
// status: "error",
// desc: res.tip,
// });
}
}
return res;
},
(error) => {
// console.log(error, 'error 此处添加监控超时处理')
if (
error.name === "AxiosError" &&
error.message === "timeout of 120000ms exceeded" &&
error.code === "ECONNABORTED"
) {
return error;
}
}
);
export default service;

View File

@@ -21,7 +21,7 @@ const routes = [
]; ];
const router = createRouter({ const router = createRouter({
history: createWebHistory(process.env.BASE_URL), history: createWebHistory(""),
routes, routes,
}); });

View File

@@ -1,5 +1,441 @@
<template> <template>
<div class="about"> <a-config-provider
<h1>login</h1> :theme="{
</div> token: {
colorPrimary: '#065758',
},
}"
>
<div class="login">
<div class="main-title">能源站监控与运行管理系统</div>
<div class="login-content">
<div class="title" style="">账号登录</div>
<a-form ref="ruleForm" :model="form" :rules="rules">
<a-form-item label="" name="user">
<a-input
:bordered="false"
v-model:value="form.user"
placeholder="请输入账号"
autocomplete
>
<template #prefix>
<span class="iconfont icon-a-xingzhuangjiehe1x"></span>
</template>
</a-input>
</a-form-item>
<a-form-item label="" name="passwd">
<a-input-password
:bordered="false"
v-model:value="form.passwd"
placeholder="请输入密码"
autocomplete
@pressEnter="login"
style="background-color: #fff; margin-top: 6px"
>
<template #prefix>
<span class="iconfont icon-a-xingzhuangjiehe1x1"></span>
</template>
</a-input-password>
</a-form-item>
</a-form>
<a-button class="login-btn" @click="login" :loading="loading"
>登录
</a-button>
</div>
</div>
</a-config-provider>
</template> </template>
<script>
import { getReq, postReq } from "@/request/api.js";
// import { sm2Encrypt, sm2Decrypt } from "@c/utils/sm2Utils.js";
// import { getSysConfig } from "@/utils/index.js";
// import { copyRight } from "@c/utils/config.js";
import // EyeInvisibleOutlined,
// EyeTwoTone,
// LockOutlined,
// UserOutlined,
"@ant-design/icons-vue";
// import moment from "moment";
// import { themeColor } from "@c/utils/config.js";
export default {
name: "loginView",
// components: { EyeTwoTone, EyeInvisibleOutlined },
props: {},
data() {
return {
copyRight: "",
loading: false,
companyName: "",
publickey: "",
form: {},
rules: {
user: [{ required: true, message: "请输入用户名", trigger: "blur" }],
passwd: [
{ required: true, message: "请输入登录密码", trigger: "blur" },
],
code: [{ required: true, message: "请输入验证码", trigger: "blur" }],
},
// rules: {
// user: [{ validator: this.checkUser, trigger: 'blur' }],
// passwd: [{ validator: this.checkPasswd, trigger: 'blur' }],
// code: [
// { required: true, message: '请输入验证码', trigger: 'blur' },
// // { validator: this.asynCheckRandom, },
// ]
// },
codeId: Math.random(),
codeString: "", // 验证码字符串
};
},
async mounted() {
// await this.getRandom();
// this.companyName = await getSysConfig("app-name");
// this.copyRight = await getSysConfig("app-version");
// this.publickey = await getSysConfig("secret-pub-key");
document.title = this.companyName;
},
methods: {
// 验证码校验
async asynCheckRandom(code) {
const res = await getReq({ id: this.codeId, code }, "/user/checkRandom");
if (res.code == 200 && res.data) {
return Promise.resolve({ success: true, msg: "" });
} else {
return Promise.resolve({ success: false, msg: "验证码输入错误" });
}
},
// })
// 登录后首次判断主题色
// async changeTheme() {
// const res = await getSysConfig("app-map-center");
// const theme = localStorage.getItem("theme");
// if (!theme) {
// const { sunriseSunset } = JSON.parse(res).weather;
// const sunrise = sunriseSunset.sunrise.trim().split(/\s+/)[1] || "04:00";
// const sunset = sunriseSunset.sunset.trim().split(/\s+/)[1] || "20:00";
// const current = moment().locale("zh-cn").format("HH:mm");
// if (sunrise < current && current < sunset) {
// localStorage.setItem("theme", "light");
// Object.keys(themeColor).forEach((key) => {
// document.documentElement.style.setProperty(
// key,
// themeColor[key].light
// );
// });
// } else {
// localStorage.setItem("theme", "dark");
// Object.keys(themeColor).forEach((key) => {
// document.documentElement.style.setProperty(
// key,
// themeColor[key].dark
// );
// });
// }
// } else {
// Object.keys(themeColor).forEach((key) => {
// document.documentElement.style.setProperty(
// key,
// themeColor[key][theme]
// );
// });
// }
// },
// 填充密码
async fillPassword() {
let userName = localStorage.getItem("userName");
if (userName) {
// this.form.user = localStorage.getItem('userName')
// const key = await getSysConfig('secret-pub-key')
// this.form.passwd = sm2Decrypt(localStorage.getItem('passwd'), key)
this.form.remember = true;
}
},
// 获取验证码
async getRandom() {
const res = await getReq({ id: this.codeId }, "/user/getRandom");
if (res.code == 200) {
this.codeString = res.data;
} else {
this.codeString = "获取失败";
}
},
async login() {
this.$refs.ruleForm
.validate()
.then((res) => {
if (res) {
this.asynCheckRandom(res.code).then((res) => {
if (!res.success) {
this.$openNotification({
name: "",
type: "",
status: "error",
desc: res.msg,
});
this.form.code = "";
} else {
this.submitLoginForm();
}
});
}
})
.catch((err) => {
console.log(err);
});
},
async submitLoginForm() {
// let newPsdSM2 = sm2Encrypt(this.form.passwd, this.publickey);
// if (newPsdSM2) {
let paramsDate = {
user: this.form.user,
// passwd: newPsdSM2,
};
if (this.form.remember) {
localStorage.setItem("userName", this.form.user);
// localStorage.setItem("passwd", newPsdSM2);
}
try {
const res = await postReq(paramsDate, "/user/login");
// 记住密码
if (res.code == 200) {
const { token, user } = res.data;
this.$openNotification({
name: "",
type: "",
status: "success",
desc: "登录成功",
});
localStorage.setItem("token", token);
localStorage.setItem("showNotice", true);
// this.changeTheme();
this.getUserRoute(user);
} else {
this.loading = false;
throw new Error(res);
}
} catch (error) {
this.loading = false;
this.form.code = "";
this.getRandom();
}
// }
},
async getUserRoute(user) {
const { userExtend } = user;
const { role } = userExtend;
localStorage.setItem("user", JSON.stringify(user));
if (role && role.permissionList.length > 0) {
const allMenus = [];
role.permissionList.forEach((item) => {
allMenus.push(...item.menusList);
});
const uniqueArray = [
...new Map(allMenus.map((item) => [item.id, item])).values(),
];
const treeMunes = this.buildTree(uniqueArray);
const pcMunes = treeMunes.filter((item) => item.type == 0);
localStorage.setItem("menuList", JSON.stringify(pcMunes));
}
setTimeout(() => {
this.loading = false;
this.$router.push("/");
}, 1000);
this.loading = false;
},
buildTree(items, parentId = null) {
const result = [];
const itemMap = {}; // 用于存储id和对应节点的映射方便快速查找父节点
items.forEach((item) => {
if (!itemMap[item.id]) {
itemMap[item.id] = { ...item, children: [] };
}
const node = itemMap[item.id];
if (item.parentId === parentId || item.parentId == 0) {
result.push(node);
} else {
if (!itemMap[item.parentId]) {
itemMap[item.parentId] = { children: [] };
}
itemMap[item.parentId].children.push(node);
}
});
result.sort((a, b) => a.seq - b.seq);
result.forEach((item) => {
if (item.children.length == 0) {
delete item.children;
}
});
return result;
},
onChange() {},
forgetPassword() {
this.$openNotification({
name: "",
type: "",
status: "warning",
desc: "请联系平台管理员",
});
},
},
};
</script>
<style lang="scss" scoped>
.login {
position: relative;
display: flex;
justify-content: center;
align-items: center;
min-width: 1440px;
min-height: 900px;
width: 100%;
height: 100%;
background-image: url("@/assets/images/loginBg.png");
background-size: cover;
background-repeat: no-repeat;
background-position: center;
.main-title {
background: linear-gradient(
180deg,
rgba(255, 255, 255, 1) 0%,
rgba(40, 235, 231, 1) 100%
);
color: transparent;
-webkit-background-clip: text;
background-clip: text;
font-size: 50px;
font-weight: 400;
letter-spacing: 5px;
line-height: 53px;
}
.login-content {
width: 390px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 0 40px;
.title {
margin-bottom: 10px;
color: #fff;
font-size: 20px;
}
:deep(.ant-input-prefix) {
color: #217575;
}
:deep(.ant-form-item) {
margin-bottom: 20px !important;
}
:deep(.ant-form-item-explain-error) {
font-size: 12px;
}
.iconfont {
margin: 0 10px 0 5px;
}
}
.yanzhengma {
width: 60px;
font-family: yanzhengma;
font-size: 23px;
cursor: pointer;
}
.rememberPass {
font-size: 14px;
color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: space-around;
align-items: center;
width: 290px;
.ant-checkbox-wrapper,
span {
color: rgba(0, 0, 0, 0.5);
cursor: pointer;
}
.ant-checkbox-wrapper:hover {
color: #065758;
}
span:hover {
color: #065758;
}
}
.login-btn {
width: 335px;
height: 45px;
border-radius: 4px;
background: #2a82e4;
font-size: 16px;
margin-top: 20px;
.btn-text {
}
}
.copyright {
position: absolute;
bottom: 5px;
left: 50%;
transform: translateX(-50%);
color: #fff;
font-weight: 700;
font-size: 20px;
}
}
:deep(.ant-input) {
&::placeholder {
// font-size: 12px !important;
// line-height: 12px;
// line-height: 100px !important;
// height: 40px !important;
// line-height: 40px !important;
}
}
:deep(span.ant-input-affix-wrapper) {
height: 40px !important;
background: #eceff4 !important;
color: #065758 !important;
border: none !important;
border-radius: 8px !important;
.ant-input {
// height: 40px !important;
border-radius: 0 !important;
background: #eceff4 !important;
}
&:hover {
border-color: #0caf60 !important;
}
&:focus {
border: none !important;
background-color: #eceff4;
}
}
:deep(.ant-input-affix-wrapper) {
padding: 0 10px !important;
}
// 输入框自动填充后的背景改色
input:-internal-autofill-previewed,
input:-internal-autofill-selected {
-webkit-text-fill-color: #000000 !important;
transition: background-color 500s ease-out 0.5s;
}
</style>

View File

@@ -7,12 +7,9 @@
<script> <script>
// @ is an alias to /src // @ is an alias to /src
import HelloWorld from "@/components/HelloWorld.vue";
export default { export default {
name: "HomeView", name: "HomeView",
components: { components: {},
HelloWorld,
},
}; };
</script> </script>

View File

@@ -43,7 +43,15 @@ module.exports = defineConfig({
chunkFilename: `css/.[contenthash:8].chunk.css`, chunkFilename: `css/.[contenthash:8].chunk.css`,
}, },
}, },
// webpack相关配置
configureWebpack: { configureWebpack: {
// 自定义打包入口
entry: "./src/main.js",
// 扩展 webpack 配置
plugins: [
// 添加插件
],
resolve: { resolve: {
alias: { alias: {
"@": path.join(__dirname, "src"), "@": path.join(__dirname, "src"),
@@ -60,17 +68,6 @@ module.exports = defineConfig({
// 生产环境的 source map // 生产环境的 source map
productionSourceMap: true, productionSourceMap: true,
// webpack相关配置
configureWebpack: {
// 自定义打包入口
entry: "./src/main.js",
// 扩展 webpack 配置
plugins: [
// 添加插件
],
},
// 第三方插件配置 // 第三方插件配置
pluginOptions: { pluginOptions: {
// ... // ...