Compare commits

...

16 Commits
master ... zcsf

Author SHA1 Message Date
时启龙 edfe5a56e2 feat: 增加忘记密码 2025-10-13 17:45:49 +08:00
时启龙 ce41faacc5 fix: modify 2025-09-16 11:17:17 +08:00
TangShanDD 7fb547ea62 Merge branch 'zcsf' of http://23.33.3.13:30000/efc/main-web into zcsf 2025-09-11 21:38:35 +08:00
TangShanDD d62e89b01b fix: 还原 2025-09-11 21:37:57 +08:00
Hoshi 8bb199339f test 2025-09-10 10:20:46 +08:00
TangShanDD 5f90ebef25 fix: 加库 2025-09-10 10:07:12 +08:00
TangShanDD 96dd695a72 fix: 登录、锁屏加验证码 2025-09-09 14:55:00 +08:00
TangShan_DD 0f9f99063e Merge branch 'develop' of http://23.33.3.13:30000/efc/main-web into develop 2025-06-03 09:46:52 +08:00
TangShan_DD acbbbf3b1a fix: 新增报表仪表盘隐藏头部 2025-06-03 09:44:58 +08:00
时启龙 fe12af4284 chore: efc 3.0 修改 2025-05-14 15:35:49 +08:00
时启龙 76e9abb537 docs: modify 2025-05-06 14:51:21 +08:00
时启龙 99f261117f docs: update README.md to specify pnpm version as 7+ 2024-12-17 16:30:59 +08:00
时启龙 01f6ad20ed docs: 更新 README.md,添加环境准备和快速开始指南,修改项目配置说明 2024-12-17 15:06:18 +08:00
时启龙 36d63032e7 feat: 业务和项目标签名称统一从接口取 2024-10-29 17:04:52 +08:00
时启龙 a43e5eadae chore: 修改开发环境协议 2024-04-01 12:19:38 +08:00
时启龙 2d60aa72f1 fix: 修改代理接口 2024-03-14 14:05:43 +08:00
12 changed files with 358 additions and 84 deletions

View File

@ -1,24 +1,45 @@
# vue3.0-tpl
# 博云 CMP Web 前端项目
## Project setup
```
yarn install
## 环境准备
- Node.js 16+
- pnpm 7+
## 快速开始
1. 配置私有 NPM 源
```bash
# 设置 registry
npm config set registry http://223.112.233.194:13011/repository/bocloud-npm/
npm config set _auth Ym9jbG91ZDpjbXBAdjU4Nw==
# npm 相关配置
npm config set auto-install-peers=true
npm config set strict-peer-dependencies=false
npm config set shamefully-hoist=true
npm config set always-auth true
```
### Compiles and hot-reloads for development
```
yarn serve
2. 安装依赖
```bash
pnpm install
```
### Compiles and minifies for production
```
yarn build
3. 本地开发
```bash
pnpm run serve # 推荐:使用 vue-cli-service
```
### Lints and fixes files
```
yarn lint
4. 项目构建
```bash
pnpm run build
```
### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/).
## 注意事项
- 不推荐使用 vite 进行开发,存在兼容性问题
- 建议使用 vue-cli-service serve 进行本地开发

3
components.d.ts vendored
View File

@ -26,6 +26,9 @@ declare module 'vue' {
ASwitch: typeof import('ant-design-vue/es')['Switch']
ATextarea: typeof import('ant-design-vue/es')['Textarea']
ATooltip: typeof import('ant-design-vue/es')['Tooltip']
ElButton: typeof import('element-plus/es')['ElButton']
ElDialog: typeof import('element-plus/es')['ElDialog']
ElInput: typeof import('element-plus/es')['ElInput']
ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
Empty: typeof import('./src/components/empty/Empty.vue')['default']
ImageCropper: typeof import('./src/components/image-cropper/index.vue')['default']

View File

@ -1,4 +1,4 @@
lockfileVersion: 5.3
lockfileVersion: 5.4
specifiers:
'@ant-design/icons-vue': ^6.0.1
@ -76,8 +76,8 @@ devDependencies:
'@types/qs': 6.9.7
'@vitejs/plugin-vue': 2.2.0_vite@2.8.3+vue@3.2.31
'@vitejs/plugin-vue-jsx': 1.3.7
'@vue/eslint-config-prettier': 7.0.0_eslint@8.9.0+prettier@2.5.1
'@vue/eslint-config-typescript': 10.0.0_cd100ca74b8c3cfb64acbb3ff997764b
'@vue/eslint-config-prettier': 7.0.0_o3yyxvqqntu2psyhklvnrymevm
'@vue/eslint-config-typescript': 10.0.0_zuiazj2lrq6pwzfmxm77tf3wjm
'@vue/tsconfig': 0.1.3_@types+node@16.11.25
eslint: 8.9.0
eslint-plugin-vue: 8.4.1_eslint@8.9.0
@ -315,7 +315,6 @@ packages:
/@babel/helper-validator-identifier/7.16.7:
resolution: {integrity: sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==}
engines: {node: '>=6.9.0'}
dev: true
/@babel/helper-validator-option/7.16.7:
resolution: {integrity: sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==}
@ -346,6 +345,8 @@ packages:
resolution: {integrity: sha512-7yJPvPV+ESz2IUTPbOL+YkIGyCqOyNIzdguKQuJGnH7bg1WTIifuM21YqokFt/THWh1AkCRn9IgoykTRCBVpzA==}
engines: {node: '>=6.0.0'}
hasBin: true
dependencies:
'@babel/types': 7.17.0
/@babel/plugin-syntax-import-meta/7.10.4_@babel+core@7.17.5:
resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==}
@ -429,7 +430,6 @@ packages:
dependencies:
'@babel/helper-validator-identifier': 7.16.7
to-fast-properties: 2.0.0
dev: true
/@commitlint/cli/11.0.0:
resolution: {integrity: sha512-YWZWg1DuqqO5Zjh7vUOeSX76vm0FFyz4y0cpGMFhrhvUi5unc4IVfCXZ6337R9zxuBtmveiRuuhQqnRRer+13g==}
@ -691,8 +691,10 @@ packages:
zen-observable:
optional: true
dependencies:
any-observable: 0.3.0
any-observable: 0.3.0_rxjs@6.6.7
rxjs: 6.6.7
transitivePeerDependencies:
- zenObservable
dev: true
/@simonwep/pickr/1.8.2:
@ -758,7 +760,7 @@ packages:
resolution: {integrity: sha512-5eQEtSCoESnh2FsiLTxE121IiE60hnMqcb435fShf4bpLRjEu1Eoekht23y6zXS9Ts3l+Szu3TARnTsA0GkOkQ==}
dev: true
/@typescript-eslint/eslint-plugin/5.12.0_c467cf9bb49b295941e83ce479a578b7:
/@typescript-eslint/eslint-plugin/5.12.0_yrt47g5utmuvsqpihtshtjlyw4:
resolution: {integrity: sha512-fwCMkDimwHVeIOKeBHiZhRUfJXU8n6xW1FL9diDxAyGAFvKcH4csy0v7twivOQdQdA0KC8TDr7GGRd3L4Lv0rQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
@ -769,10 +771,10 @@ packages:
typescript:
optional: true
dependencies:
'@typescript-eslint/parser': 5.12.0_eslint@8.9.0+typescript@4.5.5
'@typescript-eslint/parser': 5.12.0_fhzmdq77bspfhxkfuzq4fbrdsy
'@typescript-eslint/scope-manager': 5.12.0
'@typescript-eslint/type-utils': 5.12.0_eslint@8.9.0+typescript@4.5.5
'@typescript-eslint/utils': 5.12.0_eslint@8.9.0+typescript@4.5.5
'@typescript-eslint/type-utils': 5.12.0_fhzmdq77bspfhxkfuzq4fbrdsy
'@typescript-eslint/utils': 5.12.0_fhzmdq77bspfhxkfuzq4fbrdsy
debug: 4.3.3
eslint: 8.9.0
functional-red-black-tree: 1.0.1
@ -785,7 +787,7 @@ packages:
- supports-color
dev: true
/@typescript-eslint/parser/5.12.0_eslint@8.9.0+typescript@4.5.5:
/@typescript-eslint/parser/5.12.0_fhzmdq77bspfhxkfuzq4fbrdsy:
resolution: {integrity: sha512-MfSwg9JMBojMUoGjUmX+D2stoQj1CBYTCP0qnnVtu9A+YQXVKNtLjasYh+jozOcrb/wau8TCfWOkQTiOAruBog==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
@ -813,7 +815,7 @@ packages:
'@typescript-eslint/visitor-keys': 5.12.0
dev: true
/@typescript-eslint/type-utils/5.12.0_eslint@8.9.0+typescript@4.5.5:
/@typescript-eslint/type-utils/5.12.0_fhzmdq77bspfhxkfuzq4fbrdsy:
resolution: {integrity: sha512-9j9rli3zEBV+ae7rlbBOotJcI6zfc6SHFMdKI9M3Nc0sy458LJ79Os+TPWeBBL96J9/e36rdJOfCuyRSgFAA0Q==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
@ -823,7 +825,7 @@ packages:
typescript:
optional: true
dependencies:
'@typescript-eslint/utils': 5.12.0_eslint@8.9.0+typescript@4.5.5
'@typescript-eslint/utils': 5.12.0_fhzmdq77bspfhxkfuzq4fbrdsy
debug: 4.3.3
eslint: 8.9.0
tsutils: 3.21.0_typescript@4.5.5
@ -858,7 +860,7 @@ packages:
- supports-color
dev: true
/@typescript-eslint/utils/5.12.0_eslint@8.9.0+typescript@4.5.5:
/@typescript-eslint/utils/5.12.0_fhzmdq77bspfhxkfuzq4fbrdsy:
resolution: {integrity: sha512-k4J2WovnMPGI4PzKgDtQdNrCnmBHpMUFy21qjX2CoPdoBcSBIMvVBr9P2YDP8jOqZOeK3ThOL6VO/sy6jtnvzw==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
@ -1019,20 +1021,18 @@ packages:
magic-string: 0.25.7
postcss: 8.4.6
source-map: 0.6.1
dev: false
/@vue/compiler-ssr/3.2.31:
resolution: {integrity: sha512-mjN0rqig+A8TVDnsGPYJM5dpbjlXeHUm2oZHZwGyMYiGT/F4fhJf/cXy8QpjnLQK4Y9Et4GWzHn9PS8AHUnSkw==}
dependencies:
'@vue/compiler-dom': 3.2.31
'@vue/shared': 3.2.31
dev: false
/@vue/devtools-api/6.0.12:
resolution: {integrity: sha512-iO/4FIezHKXhiDBdKySCvJVh8/mZPxHpiQrTy+PXVqJZgpTPTdHy4q8GXulaY+UKEagdkBb0onxNQZ0LNiqVhw==}
dev: false
/@vue/eslint-config-prettier/7.0.0_eslint@8.9.0+prettier@2.5.1:
/@vue/eslint-config-prettier/7.0.0_o3yyxvqqntu2psyhklvnrymevm:
resolution: {integrity: sha512-/CTc6ML3Wta1tCe1gUeO0EYnVXfo3nJXsIhZ8WJr3sov+cGASr6yuiibJTL6lmIBm7GobopToOuB3B6AWyV0Iw==}
peerDependencies:
eslint: '>= 7.28.0'
@ -1040,25 +1040,29 @@ packages:
dependencies:
eslint: 8.9.0
eslint-config-prettier: 8.3.0_eslint@8.9.0
eslint-plugin-prettier: 4.0.0_07b422646bb75d3db791621d4fdbc992
eslint-plugin-prettier: 4.0.0_a62cezdlw5ot3n4rmiou7w6jsi
prettier: 2.5.1
dev: true
/@vue/eslint-config-typescript/10.0.0_cd100ca74b8c3cfb64acbb3ff997764b:
/@vue/eslint-config-typescript/10.0.0_zuiazj2lrq6pwzfmxm77tf3wjm:
resolution: {integrity: sha512-F94cL8ug3FaYXlCfU5/wiGjk1qeadmoBpRGAOBq+qre3Smdupa59dd6ZJrsfRODpsMPyTG7330juMDsUvpZ3Rw==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
eslint: ^6.2.0 || ^7.0.0 || ^8.0.0
eslint-plugin-vue: ^8.0.1
typescript: '*'
peerDependenciesMeta:
typescript:
optional: true
dependencies:
'@typescript-eslint/eslint-plugin': 5.12.0_c467cf9bb49b295941e83ce479a578b7
'@typescript-eslint/parser': 5.12.0_eslint@8.9.0+typescript@4.5.5
'@typescript-eslint/eslint-plugin': 5.12.0_yrt47g5utmuvsqpihtshtjlyw4
'@typescript-eslint/parser': 5.12.0_fhzmdq77bspfhxkfuzq4fbrdsy
eslint: 8.9.0
eslint-plugin-vue: 8.4.1_eslint@8.9.0
typescript: 4.5.5
vue-eslint-parser: 8.2.0_eslint@8.9.0
transitivePeerDependencies:
- supports-color
- typescript
dev: true
/@vue/reactivity-transform/3.2.31:
@ -1069,7 +1073,6 @@ packages:
'@vue/shared': 3.2.31
estree-walker: 2.0.2
magic-string: 0.25.7
dev: false
/@vue/reactivity/3.2.31:
resolution: {integrity: sha512-HVr0l211gbhpEKYr2hYe7hRsV91uIVGFYNHj73njbARVGHQvIojkImKMaZNDdoDZOIkMsBc9a1sMqR+WZwfSCw==}
@ -1081,7 +1084,6 @@ packages:
dependencies:
'@vue/reactivity': 3.2.31
'@vue/shared': 3.2.31
dev: false
/@vue/runtime-dom/3.2.31:
resolution: {integrity: sha512-N+o0sICVLScUjfLG7u9u5XCjvmsexAiPt17GNnaWHJUfsKed5e85/A3SWgKxzlxx2SW/Hw7RQxzxbXez9PtY3g==}
@ -1089,7 +1091,6 @@ packages:
'@vue/runtime-core': 3.2.31
'@vue/shared': 3.2.31
csstype: 2.6.19
dev: false
/@vue/server-renderer/3.2.31_vue@3.2.31:
resolution: {integrity: sha512-8CN3Zj2HyR2LQQBHZ61HexF5NReqngLT3oahyiVRfSSvak+oAvVmu8iNLSu6XR77Ili2AOpnAt1y8ywjjqtmkg==}
@ -1099,7 +1100,6 @@ packages:
'@vue/compiler-ssr': 3.2.31
'@vue/shared': 3.2.31
vue: 3.2.31
dev: false
/@vue/shared/3.2.31:
resolution: {integrity: sha512-ymN2pj6zEjiKJZbrf98UM2pfDd6F2H7ksKw7NDt/ZZ1fh5Ei39X5tABugtT03ZRlWd9imccoK0hE8hpjpU7irQ==}
@ -1247,9 +1247,19 @@ packages:
warning: 4.0.3
dev: false
/any-observable/0.3.0:
/any-observable/0.3.0_rxjs@6.6.7:
resolution: {integrity: sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog==}
engines: {node: '>=6'}
peerDependencies:
rxjs: '*'
zenObservable: '*'
peerDependenciesMeta:
rxjs:
optional: true
zenObservable:
optional: true
dependencies:
rxjs: 6.6.7
dev: true
/anymatch/3.1.2:
@ -1422,6 +1432,8 @@ packages:
snapdragon-node: 2.1.1
split-string: 3.1.0
to-regex: 3.0.2
transitivePeerDependencies:
- supports-color
dev: true
/braces/3.0.2:
@ -1753,8 +1765,8 @@ packages:
engines: {node: '>=10'}
hasBin: true
dependencies:
is-text-path: 1.0.1
JSONStream: 1.3.5
is-text-path: 1.0.1
lodash: 4.17.21
meow: 8.1.2
split2: 3.2.2
@ -1867,7 +1879,6 @@ packages:
/csstype/2.6.19:
resolution: {integrity: sha512-ZVxXaNy28/k3kJg0Fou5MiYpp88j7H9hLZp8PDC3jV0WFjfH5E9xHb56L0W59cPbKbcHXeP4qyT8PrHp8t6LcQ==}
dev: false
/dargs/7.0.0:
resolution: {integrity: sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==}
@ -1884,12 +1895,22 @@ packages:
/debug/2.6.9:
resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==}
peerDependencies:
supports-color: '*'
peerDependenciesMeta:
supports-color:
optional: true
dependencies:
ms: 2.0.0
dev: true
/debug/3.2.7:
resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==}
peerDependencies:
supports-color: '*'
peerDependenciesMeta:
supports-color:
optional: true
dependencies:
ms: 2.1.3
dev: true
@ -2374,7 +2395,7 @@ packages:
eslint: 8.9.0
dev: true
/eslint-plugin-prettier/4.0.0_07b422646bb75d3db791621d4fdbc992:
/eslint-plugin-prettier/4.0.0_a62cezdlw5ot3n4rmiou7w6jsi:
resolution: {integrity: sha512-98MqmCJ7vJodoQK359bqQWaxOE0CS8paAz/GgjaZLyex4TTk3g9HugoO89EqWCrFiOqn9EVvcoo7gZzONCWVwQ==}
engines: {node: '>=6.0.0'}
peerDependencies:
@ -2562,6 +2583,8 @@ packages:
regex-not: 1.0.2
snapdragon: 0.8.2
to-regex: 3.0.2
transitivePeerDependencies:
- supports-color
dev: true
/extend-shallow/2.0.1:
@ -2591,6 +2614,8 @@ packages:
regex-not: 1.0.2
snapdragon: 0.8.2
to-regex: 3.0.2
transitivePeerDependencies:
- supports-color
dev: true
/fast-deep-equal/3.1.3:
@ -3518,6 +3543,8 @@ packages:
mime: 1.6.0
needle: 2.9.1
source-map: 0.6.1
transitivePeerDependencies:
- supports-color
dev: true
/levn/0.4.1:
@ -3563,6 +3590,7 @@ packages:
transitivePeerDependencies:
- supports-color
- zen-observable
- zenObservable
dev: true
/listr-silent-renderer/1.1.1:
@ -3612,6 +3640,7 @@ packages:
rxjs: 6.6.7
transitivePeerDependencies:
- zen-observable
- zenObservable
dev: true
/loader-utils/1.4.0:
@ -3802,6 +3831,8 @@ packages:
regex-not: 1.0.2
snapdragon: 0.8.2
to-regex: 3.0.2
transitivePeerDependencies:
- supports-color
dev: true
/micromatch/3.1.10:
@ -3821,6 +3852,8 @@ packages:
regex-not: 1.0.2
snapdragon: 0.8.2
to-regex: 3.0.2
transitivePeerDependencies:
- supports-color
dev: true
/micromatch/4.0.4:
@ -3916,6 +3949,8 @@ packages:
regex-not: 1.0.2
snapdragon: 0.8.2
to-regex: 3.0.2
transitivePeerDependencies:
- supports-color
dev: true
/nanopop/2.1.0:
@ -3935,6 +3970,8 @@ packages:
debug: 3.2.7
iconv-lite: 0.4.24
sax: 1.2.4
transitivePeerDependencies:
- supports-color
dev: true
optional: true
@ -4907,6 +4944,8 @@ packages:
source-map: 0.5.7
source-map-resolve: 0.5.3
use: 3.1.1
transitivePeerDependencies:
- supports-color
dev: true
/source-map-js/1.0.2:
@ -5123,6 +5162,8 @@ packages:
deepmerge: 1.3.2
mitt: 1.1.2
svg-baker: 1.7.0
transitivePeerDependencies:
- supports-color
dev: true
/svg-baker/1.7.0:
@ -5141,6 +5182,8 @@ packages:
posthtml-svg-mode: 1.0.3
query-string: 4.3.4
traverse: 0.6.6
transitivePeerDependencies:
- supports-color
dev: true
/svg-sprite-loader/6.0.11:
@ -5155,6 +5198,8 @@ packages:
svg-baker: 1.7.0
svg-baker-runtime: 1.4.7
url-slug: 2.0.0
transitivePeerDependencies:
- supports-color
dev: true
/svg-tags/1.0.0:
@ -5210,7 +5255,6 @@ packages:
/to-fast-properties/2.0.0:
resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==}
engines: {node: '>=4'}
dev: true
/to-object-path/0.3.0:
resolution: {integrity: sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==}
@ -5697,7 +5741,6 @@ packages:
'@vue/runtime-dom': 3.2.31
'@vue/server-renderer': 3.2.31_vue@3.2.31
'@vue/shared': 3.2.31
dev: false
/vuex/4.0.2_vue@3.2.31:
resolution: {integrity: sha512-M6r8uxELjZIK8kTKDGgZTYX/ahzblnzC4isU1tpmEuOIIKmV+TRdc+H4s8ds2NuZ7wpUTdGRzJRtoj+lI+pc0Q==}

View File

@ -1,6 +1,6 @@
/** * Created by HaijunZhang on 2019/12/18. */
<template>
<a-layout-header class="common-header" :style="style">
<a-layout-header class="common-header" :style="style" v-if="$route.name !== 'Designer'">
<div class="header-logo">
<img :src="pageConfigs.headerLogo" alt="" class="pull-left" />
</div>
@ -26,7 +26,7 @@ export default defineComponent({
RightContent,
Divider,
HeaderMenu,
HomeOutlined,
HomeOutlined
},
setup() {
const store = useStore()
@ -34,14 +34,14 @@ export default defineComponent({
const style = computed(() => {
return {
backgroundColor: pageConfigs.value.headerBgColour,
color: pageConfigs.value.headerFontColour,
color: pageConfigs.value.headerFontColour
}
})
return {
pageConfigs,
style,
style
}
}
},
})
</script>

View File

@ -74,7 +74,7 @@ export default {
}
//
const isShow = () => {
return !['/sms-web/resource_dashboard', '/screen/list', '/redirect'].includes(route.path)
return !['/sms-web/resource_dashboard', '/screen/list', '/redirect', '/report/designer'].includes(route.path)
}
const getFixTags = (routes) => {
const tags = []

View File

@ -21,12 +21,12 @@ export function logout() {
}
export function getConfig(params) {
return request.get('/sms/v1/logo', {
params: wrapperParams(params),
params: wrapperParams(params)
})
}
export function getDict(data) {
return request.get('/dict/children', {
params: wrapperParams(data),
params: wrapperParams(data)
})
}
export function getSysconf() {
@ -48,7 +48,7 @@ export function getPortal(params) {
}
export function getServiceQuota(tenantId, data) {
return request.get(`/cos/v1/tenants/${tenantId}/quotas`, {
params: wrapperParams(data),
params: wrapperParams(data)
})
}
export function replaceToken(params) {
@ -69,10 +69,18 @@ export function getSystemTreeConfigs(params) {
// 更新系统配置信息
export function updateSystemConfigs(params) {
return request.put('/sms/v1/system-configs', params, {
headers: { 'Content-Type': 'multipart/form-data', BsmAjaxHeader: true, options: { noSeri: true } },
headers: { 'Content-Type': 'multipart/form-data', BsmAjaxHeader: true, options: { noSeri: true } }
})
}
// 测试连接
export function testLinkApi(category) {
return request.get('/sms/v1/configs/test', { params: { category } })
}
export function getVertifyCode(params) {
return request.post('/sms/v1/users/code', wrapperParams(params))
}
// 忘记密码
export function forgetPassword(params) {
return request.post('/sms/v1/users/forget', params)
}

View File

@ -10,7 +10,7 @@ const state = {
isCollapsed: false,
sideMenuData: [],
pageConfig: {},
systemConfig: {},
systemConfig: JSON.parse(localStorage.getItem('systemConfig')) || {},
userData: null,
operateTime: '',
basePath: '',
@ -66,6 +66,10 @@ const mutations = {
state.pageConfig = data
},
SETTING_SYSTEM_CONFIG(state, data) {
// 为什么不用 csc 的方式 管理端父传子是异步方式 可能导致表格列渲染完成后接口还没返回
data.projectConfigLabel = data.projectConfigLabel || '项目'
data.serviceConfigLabel = data.serviceConfigLabel || '业务'
localStorage.setItem('systemConfig', JSON.stringify(data))
state.systemConfig = data
}
}
@ -102,7 +106,7 @@ const actions = {
}
},
async GetSystemConfigs({ commit }) {
const data = await getSystemConfigs({ codes: 'pwdStrength,lockScreenTime' })
const data = await getSystemConfigs({ codes: 'pwdStrength,lockScreenTime,serviceConfigLabel,projectConfigLabel' })
if (data.success) {
commit('SETTING_SYSTEM_CONFIG', data.data)
}

View File

@ -46,9 +46,9 @@ export default defineComponent({
setup() {
const state = reactive({
loginForm: {
password: '',
password: ''
},
loading: false,
loading: false
})
let timer: any = 0
const store = useStore()
@ -56,14 +56,14 @@ export default defineComponent({
//
const currentTime = ref({
time: '',
date: '',
date: ''
})
function setTimer() {
const getTime = () => {
const time = dayjs()
currentTime.value = {
time: time.format('HH:mm:ss'),
date: `${time.format('MM月DD日')}, ${time.format('dddd')}`,
date: `${time.format('MM月DD日')}, ${time.format('dddd')}`
}
}
getTime()
@ -73,7 +73,7 @@ export default defineComponent({
}
let lockData = {
isLock: false,
path: '',
path: ''
}
onMounted(() => {
const lockDataItem = localStorage.getItem('lockData')
@ -83,7 +83,7 @@ export default defineComponent({
'lockData',
JSON.stringify({
...lockData,
isLock: true,
isLock: true
})
)
setTimer()
@ -103,7 +103,7 @@ export default defineComponent({
const res = await login({
account: userData.value.account,
password: encrypt(values.password),
isManager: true,
isManager: true
})
if (res.success) {
setLoginData(res.data)
@ -113,7 +113,7 @@ export default defineComponent({
'lockData',
JSON.stringify({
...lockData,
isLock: false,
isLock: false
})
)
}
@ -129,9 +129,9 @@ export default defineComponent({
loginFormRef,
required,
switchUser,
handleLogin,
handleLogin
}
}
},
})
</script>

View File

@ -26,31 +26,72 @@
</a-input-password>
</a-form-item>
</a-tooltip>
<a-form-item v-if="needSmsVerify" class="login-form-item" name="verify" :rules="[{ ...required, message: '请输入验证码' }]">
<a-input placeholder="请输入验证码" autocomplete="off" v-model:value="loginForm.verify" style="width: 67%; vertical-align: middle">
<template #prefix>
<LockOutlined />
</template>
</a-input>
<a-button style="height: 60px; width: 31%; margin-left: 2%" @click="getVertify" :loading="verifyLoading" :disabled="isCountingDown || !loginForm.account.trim()">
{{ isCountingDown ? `${countdown}s后重新获取` : '获取验证码' }}
</a-button>
</a-form-item>
<a-form-item class="login-form-item">
<div class="operate-region">
<span class="remember">
<a-switch v-model:checked="remember"></a-switch>
<span class="m-l-xs">记住密码</span>
</span>
<a :href="`mailto:${configs.helpInformationLink}`" type="text" class="text-info pull-right help-info" :title="configs.helpInformationContent">{{ configs.helpInformationContent }}</a>
<a :href="`mailto:${configs.helpInformationLink}`" type="text" class="text-info help-info" :title="configs.helpInformationContent">{{ configs.helpInformationContent }}</a>
<a type="text" class="m-l text-info forgot-password" @click="openForgotPasswordDialog"></a>
</div>
</a-form-item>
<a-button class="login-btn" type="primary" size="medium" :loading="loading" @click="handleLogin"></a-button>
</a-form>
</div>
<div class="copyright-info">{{ configs.copyrightInformation }}</div>
<!-- 忘记密码弹窗 -->
<a-modal title="忘记密码" v-model:visible="showForgotPasswordDialog" width="600px" :confirm-loading="forgotPasswordLoading" @ok="handleForgotPassword" :close-on-click-modal="false">
<a-form :model="forgotPasswordForm" ref="forgotPasswordFormRef" label-position="left" :labelCol="{ style: { width: '80px' } }">
<a-form-item label="用户名" name="account" :rules="[{ ...required, message: '请输入用户名' }]">
<a-input class="w-lg" v-model:value="forgotPasswordForm.account" placeholder="请输入用户名"></a-input>
</a-form-item>
<a-form-item label="新密码" name="password" :rules="[{ ...required, message: '请输入密码' }]">
<a-input class="w-lg" v-model:value="forgotPasswordForm.password" type="password" placeholder="请输入新密码" show-password></a-input>
</a-form-item>
<a-form-item label="确认密码" name="confirmPassword" :rules="[{ ...required, message: '请输入密码' }]">
<a-input class="w-lg" v-model:value="forgotPasswordForm.confirmPassword" type="password" placeholder="请再次输入新密码" show-password></a-input>
</a-form-item>
<a-form-item label="验证码" name="verificationCode" :rules="[{ ...required, message: '请输入验证码' }]">
<div class="verification-code-input">
<a-input class="w-lg m-r" v-model:value="forgotPasswordForm.verificationCode" placeholder="请输入验证码"></a-input>
<a-button type="primary" :disabled="codeCountdown > 0" @click="getVerificationCode" :loading="codeLoading">
{{ codeCountdown > 0 ? `${codeCountdown}s后重新获取` : '获取验证码' }}
</a-button>
</div>
</a-form-item>
</a-form>
<template #footer>
<div class="dialog-footer">
<a-button @click="showForgotPasswordDialog = false">取消</a-button>
<a-button type="primary" :loading="forgotPasswordLoading" @click="handleForgotPassword"></a-button>
</div>
</template>
</a-modal>
</div>
</template>
<script>
import { decrypt, encrypt } from 'utils/crypto'
import { login } from 'services'
import { reactive, toRefs, ref, computed } from 'vue'
import { reactive, toRefs, ref, computed, watch } from 'vue'
import { UserOutlined, LockOutlined } from '@ant-design/icons-vue'
import { useStore } from 'vuex'
import { useRouter, useRoute } from 'vue-router'
import setLoginData from './tools'
import { required } from '@/validate'
import { getVertifyCode, forgetPassword } from '@/services'
import { message, Modal } from 'ant-design-vue'
export default {
components: { UserOutlined, LockOutlined },
@ -59,14 +100,55 @@ export default {
remember: false,
loginForm: {
account: '',
password: '',
password: ''
},
loading: false,
capsTooltip: false,
verifyLoading: false,
countdown: 0,
isCountingDown: false,
needSmsVerify: true,
showForgotPasswordDialog: false,
forgotPasswordForm: {
account: '',
password: '',
confirmPassword: '',
verificationCode: ''
},
forgotPasswordLoading: false,
codeCountdown: 0,
codeLoading: false
})
const store = useStore()
const pwdRule = computed(() => store.state.app.systemConfig.pwdStrength + ',pswNoSpace' + ',required')
const configs = computed(() => store.getters.pageConfig)
const loginFormRef = ref(null)
const forgotPasswordFormRef = ref(null)
let countdownTimer = null
//
const startCountdown = () => {
state.countdown = 60
state.isCountingDown = true
countdownTimer = setInterval(() => {
state.countdown--
if (state.countdown <= 0) {
clearInterval(countdownTimer)
state.isCountingDown = false
state.countdown = 0
}
}, 1000)
}
//
const resetCountdown = () => {
if (countdownTimer) {
clearInterval(countdownTimer)
countdownTimer = null
}
state.isCountingDown = false
state.countdown = 0
}
const init = () => {
const local = localStorage.getItem('cmcLoginData')
if (local) {
@ -79,12 +161,51 @@ export default {
init()
const router = useRouter()
const route = useRoute()
// accountneedSmsVerify
watch(
() => state.loginForm.account,
(newAccount) => {
if (!newAccount.trim()) {
state.needSmsVerify = true
resetCountdown() //
}
}
)
const getVertify = () => {
if (state.isCountingDown) return //
if (!state.loginForm.account.trim()) {
// 使 message
return //
}
state.verifyLoading = true
getVertifyCode({ account: state.loginForm.account })
.then((res) => {
if (res.success) {
state.verifyLoading = false
state.hasVertify = res.data
message.success(res.message)
//
if (res.message && res.message.includes('无需短信验证码校验')) {
state.needSmsVerify = false
} else {
state.needSmsVerify = true
startCountdown() //
}
}
})
.finally(() => {
state.verifyLoading = false
})
}
function goLogin(data) {
setLoginData(data)
if (state.remember) {
const obj = {
account: state.loginForm.account,
password: encrypt(state.loginForm.password),
password: encrypt(state.loginForm.password)
}
localStorage.setItem('cmcLoginData', JSON.stringify(obj))
} else {
@ -100,16 +221,23 @@ export default {
try {
state.loading = true
const values = await loginFormRef.value.validate()
const { account, password } = values
const res = await login({
const { account, password, verify } = values
const loginData = {
account,
password: encrypt(password),
isManager: true,
})
isManager: true
}
// code
if (state.needSmsVerify) {
loginData.code = verify
}
const res = await login(loginData)
if (res.success) {
goLogin(res.data)
}
} catch (error) {}
} catch (error) {
console.error('登录失败:', error)
}
state.loading = false
}
@ -125,6 +253,58 @@ export default {
state.capsTooltip = false
}
}
function getVerificationCode() {
if (!state.forgotPasswordForm.account) {
message.error('请先输入用户名')
return
}
state.codeLoading = true
getVertifyCode({ account: state.forgotPasswordForm.account })
.then((res) => {
if (res.success) {
message.success('验证码已发送')
state.codeCountdown = 60
const timer = setInterval(() => {
state.codeCountdown--
if (state.codeCountdown <= 0) {
clearInterval(timer)
}
}, 1000)
}
})
.finally(() => {
state.codeLoading = false
})
}
function openForgotPasswordDialog() {
//
state.forgotPasswordForm.account = state.loginForm.account
state.showForgotPasswordDialog = true
}
function handleForgotPassword() {
forgotPasswordFormRef.value.validate().then(() => {
const { account, password, confirmPassword, verificationCode } = state.forgotPasswordForm
if (confirmPassword !== password) return message.error('两次输入的密码不相同')
state.forgotPasswordLoading = true
forgetPassword({
account,
password: encrypt(password),
code: verificationCode
})
.then((res) => {
if (res.success) {
message.success(res.message)
state.showForgotPasswordDialog = false
}
})
.finally(() => {
state.forgotPasswordLoading = false
})
})
}
return {
...toRefs(state),
required,
@ -132,8 +312,16 @@ export default {
loginFormRef,
handleLogin,
checkCapslock,
getVertify,
startCountdown,
resetCountdown,
forgotPasswordFormRef,
getVerificationCode,
openForgotPasswordDialog,
handleForgotPassword,
pwdRule
}
}
},
}
</script>
@ -225,6 +413,14 @@ export default {
}
}
}
//
.ant-btn:disabled {
background-color: #f5f5f5;
border-color: #d9d9d9;
color: #999;
cursor: not-allowed;
}
}
}
.copyright-info {

View File

@ -5,6 +5,7 @@
"baseUrl": ".",
"allowJs": true,
"skipLibCheck": true,
"lib": ["ES2018", "DOM", "DOM.Iterable"],
"paths": {
"@/*": ["./src/*"],
"services/*": ["src/services/*"],
@ -20,7 +21,5 @@
"path": "./tsconfig.vite-config.json"
}
],
"exclude": [
"node_modules"
]
"exclude": ["node_modules"]
}

View File

@ -12,7 +12,7 @@ function resolve(dir: string) {
}
const httpType = 'https://'
const proxyUrl = 'develop.cmp56.com:60006/' // 代理地址设置
const proxyUrl = '10.10.33.173:60006' // 中车代理地址
// https://vitejs.dev/config/
export default defineConfig({