From a04a896f53b22984ca015be349e402f89727451f Mon Sep 17 00:00:00 2001 From: Feynman Date: Wed, 17 Jun 2026 11:43:03 +0800 Subject: [PATCH] feat: add password strength indicators and validation to user form --- apps/daas/src/i18n/langs/en.js | 3 + apps/daas/src/i18n/langs/zh-CN.js | 3 + apps/daas/src/i18n/langs/zh-TW.js | 3 + apps/daas/src/views/user/List.vue | 109 ++++++++++++++++++++++++++++++ 4 files changed, 118 insertions(+) diff --git a/apps/daas/src/i18n/langs/en.js b/apps/daas/src/i18n/langs/en.js index b2317d91b..ca9127c35 100644 --- a/apps/daas/src/i18n/langs/en.js +++ b/apps/daas/src/i18n/langs/en.js @@ -888,6 +888,9 @@ export default { 'The length of the password cannot be less than 5 and greater than 32', user_form_password_not_cn: 'Password only allows English, numbers and English punctuation', + user_password_strength_weak: 'Weak', + user_password_strength_medium: 'Medium', + user_password_strength_strong: 'Strong', user_form_activation_code: 'Access Code', user_form_status: 'Status', cluster_name: 'Monitor Name', diff --git a/apps/daas/src/i18n/langs/zh-CN.js b/apps/daas/src/i18n/langs/zh-CN.js index 6a91bbac9..083eb0c99 100644 --- a/apps/daas/src/i18n/langs/zh-CN.js +++ b/apps/daas/src/i18n/langs/zh-CN.js @@ -837,6 +837,9 @@ export default { user_form_password_null: '请输入密码, 长度为 5 ~ 32 个字符', user_form_pass_hint: '密码长度不能小于5大于32', user_form_password_not_cn: '密码仅允许英文、数字和英文标点符号', + user_password_strength_weak: '弱', + user_password_strength_medium: '中', + user_password_strength_strong: '强', user_form_activation_code: '访问码', user_form_status: '状态', cluster_name: '监控名称', diff --git a/apps/daas/src/i18n/langs/zh-TW.js b/apps/daas/src/i18n/langs/zh-TW.js index 4dbdcd377..9b591745a 100644 --- a/apps/daas/src/i18n/langs/zh-TW.js +++ b/apps/daas/src/i18n/langs/zh-TW.js @@ -833,6 +833,9 @@ export default { user_form_password_null: '請輸入密碼, 長度為 5 ~ 32 個字符', user_form_pass_hint: '密碼長度不能小於5大於32', user_form_password_not_cn: '密碼僅允許英文、數字和英文標點符號', + user_password_strength_weak: '弱', + user_password_strength_medium: '中', + user_password_strength_strong: '強', user_form_activation_code: '訪問碼', user_form_status: '狀態', cluster_name: '監控名稱', diff --git a/apps/daas/src/views/user/List.vue b/apps/daas/src/views/user/List.vue index fa8a8aa55..881c0f0e3 100644 --- a/apps/daas/src/views/user/List.vue +++ b/apps/daas/src/views/user/List.vue @@ -191,6 +191,30 @@ export default { message: this.$t('account_user_null'), }, ], + password: [ + { + required: true, + validator: (rule, v, callback) => { + if ( + this.createForm.id && // 编辑时密码选填,但填了就要校验 + !v + ) + return callback() + if (!v || !v.trim()) { + return callback(new Error(this.$t('user_form_password_null'))) + } else if (v.length < 5 || v.length > 32) { + return callback(new Error(this.$t('user_form_pass_hint'))) + } else if (/[\s\u4E00-\u9FA5]/.test(v)) { + return callback( + new Error(this.$t('user_form_password_not_cn')), + ) + } else { + return callback() + } + }, + trigger: ['blur', 'change'], + }, + ], email: [ { required: true, @@ -220,6 +244,19 @@ export default { table() { return this.$refs.table }, + passwordStrength() { + const v = this.createForm.password + if (!v) return 0 + let score = 0 + if (v.length >= 5) score++ + if (v.length >= 8) score++ + if (/[A-Z]/.test(v)) score++ + if (/\d/.test(v)) score++ + if (/[^A-Z0-9]/i.test(v)) score++ + if (score <= 1) return 1 // 弱 + if (score <= 3) return 2 // 中 + return 3 // 强 + }, }, watch: { '$route.query': function () { @@ -1092,6 +1129,28 @@ export default { maxlength="32" show-password /> +
+
+ +
+ + {{ + [ + $t('user_password_strength_weak'), + $t('user_password_strength_medium'), + $t('user_password_strength_strong'), + ][passwordStrength - 1] + }} + +
@@ -1240,4 +1299,54 @@ export default { } } } + +.password-strength { + display: flex; + align-items: center; + gap: 8px; + width: 100%; + line-height: 20px; + + &__bars { + display: flex; + gap: 4px; + flex: 1; + } + + &__bar { + flex: 1; + height: 4px; + border-radius: 2px; + transition: background-color 0.3s; + + &--empty { + background-color: var(--el-border-color); + } + &--weak { + background-color: #f56c6c; + } + &--medium { + background-color: #e6a23c; + } + &--strong { + background-color: #67c23a; + } + } + + &__label { + font-size: 12px; + min-width: 16px; + text-align: right; + + &--weak { + color: #f56c6c; + } + &--medium { + color: #e6a23c; + } + &--strong { + color: #67c23a; + } + } +}