diff --git a/dashboard/src/assets/mdi-subset/materialdesignicons-subset.css b/dashboard/src/assets/mdi-subset/materialdesignicons-subset.css index fcb8c2c09..a84d730fa 100644 --- a/dashboard/src/assets/mdi-subset/materialdesignicons-subset.css +++ b/dashboard/src/assets/mdi-subset/materialdesignicons-subset.css @@ -1,4 +1,4 @@ -/* Auto-generated MDI subset – 274 icons */ +/* Auto-generated MDI subset – 260 icons */ /* Do not edit manually. Run: pnpm run subset-icons */ @font-face { @@ -220,6 +220,10 @@ content: "\F0765"; } +.mdi-circle-outline::before { + content: "\F0766"; +} + .mdi-circle-small::before { content: "\F09DF"; } @@ -244,10 +248,6 @@ content: "\F0167"; } -.mdi-code-braces::before { - content: "\F0169"; -} - .mdi-code-json::before { content: "\F0626"; } @@ -416,10 +416,6 @@ content: "\F022E"; } -.mdi-file-delimited-outline::before { - content: "\F0EA5"; -} - .mdi-file-document::before { content: "\F0219"; } @@ -440,10 +436,6 @@ content: "\F021C"; } -.mdi-file-music-outline::before { - content: "\F0E2A"; -} - .mdi-file-outline::before { content: "\F0224"; } @@ -464,14 +456,6 @@ content: "\F0A4D"; } -.mdi-file-upload-outline::before { - content: "\F0A4E"; -} - -.mdi-file-video-outline::before { - content: "\F0E2C"; -} - .mdi-file-word-box::before { content: "\F022D"; } @@ -484,14 +468,6 @@ content: "\F0236"; } -.mdi-flash::before { - content: "\F0241"; -} - -.mdi-flash-off::before { - content: "\F0243"; -} - .mdi-folder::before { content: "\F024B"; } @@ -616,38 +592,10 @@ content: "\F0318"; } -.mdi-language-css3::before { - content: "\F031C"; -} - -.mdi-language-html5::before { - content: "\F031D"; -} - -.mdi-language-java::before { - content: "\F0B37"; -} - -.mdi-language-javascript::before { - content: "\F031E"; -} - .mdi-language-markdown::before { content: "\F0354"; } -.mdi-language-markdown-outline::before { - content: "\F0F5B"; -} - -.mdi-language-python::before { - content: "\F0320"; -} - -.mdi-language-typescript::before { - content: "\F06E6"; -} - .mdi-layers-outline::before { content: "\F09FE"; } @@ -908,10 +856,6 @@ content: "\F167A"; } -.mdi-send::before { - content: "\F048A"; -} - .mdi-server::before { content: "\F048B"; } diff --git a/dashboard/src/assets/mdi-subset/materialdesignicons-webfont-subset.woff b/dashboard/src/assets/mdi-subset/materialdesignicons-webfont-subset.woff index bb66f5225..b80b14d06 100644 Binary files a/dashboard/src/assets/mdi-subset/materialdesignicons-webfont-subset.woff and b/dashboard/src/assets/mdi-subset/materialdesignicons-webfont-subset.woff differ diff --git a/dashboard/src/assets/mdi-subset/materialdesignicons-webfont-subset.woff2 b/dashboard/src/assets/mdi-subset/materialdesignicons-webfont-subset.woff2 index a2e49e099..aa231a921 100644 Binary files a/dashboard/src/assets/mdi-subset/materialdesignicons-webfont-subset.woff2 and b/dashboard/src/assets/mdi-subset/materialdesignicons-webfont-subset.woff2 differ diff --git a/dashboard/src/i18n/locales/en-US/core/header.json b/dashboard/src/i18n/locales/en-US/core/header.json index 7dfe59fd2..7bec66c27 100644 --- a/dashboard/src/i18n/locales/en-US/core/header.json +++ b/dashboard/src/i18n/locales/en-US/core/header.json @@ -100,7 +100,11 @@ "passwordLowercase": "Password must include at least one lowercase letter", "passwordDigit": "Password must include at least one digit", "passwordMatch": "Passwords do not match", - "usernameMinLength": "Username must be at least 3 characters" + "usernameMinLength": "Username must be at least 3 characters", + "strengthWeak": "Weak", + "strengthFair": "Fair", + "strengthGood": "Good", + "strengthStrong": "Strong" }, "actions": { "save": "Save Changes", diff --git a/dashboard/src/i18n/locales/zh-CN/core/header.json b/dashboard/src/i18n/locales/zh-CN/core/header.json index a38a0740b..2c7dfce22 100644 --- a/dashboard/src/i18n/locales/zh-CN/core/header.json +++ b/dashboard/src/i18n/locales/zh-CN/core/header.json @@ -100,7 +100,11 @@ "passwordLowercase": "密码必须包含至少一个小写字母", "passwordDigit": "密码必须包含至少一个数字", "passwordMatch": "两次输入的密码不一致", - "usernameMinLength": "用户名长度至少3位" + "usernameMinLength": "用户名长度至少3位", + "strengthWeak": "弱", + "strengthFair": "一般", + "strengthGood": "好", + "strengthStrong": "强" }, "actions": { "save": "保存修改", diff --git a/dashboard/src/layouts/full/vertical-header/VerticalHeader.vue b/dashboard/src/layouts/full/vertical-header/VerticalHeader.vue index ed684f43b..11a26da10 100644 --- a/dashboard/src/layouts/full/vertical-header/VerticalHeader.vue +++ b/dashboard/src/layouts/full/vertical-header/VerticalHeader.vue @@ -145,6 +145,48 @@ const usernameRules = computed(() => [ t("core.header.accountDialog.validation.usernameMinLength"), ]); +// 密码强度校验 +const passwordChecks = computed(() => [ + { + key: "minLength", + label: t("core.header.accountDialog.validation.passwordMinLength"), + pass: newPassword.value.length >= 12, + }, + { + key: "uppercase", + label: t("core.header.accountDialog.validation.passwordUppercase"), + pass: /[A-Z]/.test(newPassword.value), + }, + { + key: "lowercase", + label: t("core.header.accountDialog.validation.passwordLowercase"), + pass: /[a-z]/.test(newPassword.value), + }, + { + key: "digit", + label: t("core.header.accountDialog.validation.passwordDigit"), + pass: /\d/.test(newPassword.value), + }, +]); +const passwordStrengthPercent = computed(() => { + const passed = passwordChecks.value.filter((c) => c.pass).length; + return (passed / passwordChecks.value.length) * 100; +}); +const passwordStrengthColor = computed(() => { + const pct = passwordStrengthPercent.value; + if (pct <= 25) return "error"; + if (pct <= 50) return "warning"; + if (pct <= 75) return "info"; + return "success"; +}); +const passwordStrengthText = computed(() => { + const pct = passwordStrengthPercent.value; + if (pct <= 25) return t("core.header.accountDialog.validation.strengthWeak"); + if (pct <= 50) return t("core.header.accountDialog.validation.strengthFair"); + if (pct <= 75) return t("core.header.accountDialog.validation.strengthGood"); + return t("core.header.accountDialog.validation.strengthStrong"); +}); + // 显示密码相关 const showPassword = ref(false); const showNewPassword = ref(false); @@ -1179,6 +1221,40 @@ const isChristmas = computed(() => { @click:append-inner="showNewPassword = !showNewPassword" /> + +
+ +
+ + {{ passwordStrengthText }} + +
+
+
+ + {{ check.label }} +
+
+
+