feat: 支持账号导入与强制改密

- 新增账号导入模板下载、导入校验和默认密码重置标记

- 支持管理员重置密码并在登录后强制跳转修改密码

- 管理端与用户中心接入强密码校验和密码重置流程
This commit is contained in:
2026-03-18 21:56:05 +08:00
parent 14c78d54f5
commit 5d3c7d8692
40 changed files with 1720 additions and 142 deletions

View File

@@ -0,0 +1,6 @@
export const strongPasswordPattern =
/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^A-Za-z\d]).{8,}$/;
export function isStrongPassword(value?: string) {
return !!value && strongPasswordPattern.test(value);
}

View File

@@ -0,0 +1,52 @@
import type { Router } from 'vue-router';
import { ElMessage } from 'element-plus';
import { $t } from '#/locales';
const FORCE_PASSWORD_NOTICE_INTERVAL = 1500;
let lastForcePasswordNoticeAt = 0;
export function buildForcePasswordRoute() {
return {
name: 'Profile',
query: {
force: '1',
tab: 'password',
},
};
}
export function isForcePasswordRoute(
route: Pick<{ name?: string | symbol | null; query?: Record<string, any> }, 'name' | 'query'>,
) {
return route.name === 'Profile' && route.query?.tab === 'password';
}
export function shouldForcePasswordChange(
userInfo?: null | Record<string, any>,
forceChangePassword?: boolean,
) {
return !!forceChangePassword || !!userInfo?.passwordResetRequired;
}
export function resolveForcePasswordPath(router: Router) {
return router.resolve(buildForcePasswordRoute()).fullPath;
}
export function notifyForcePasswordChange() {
const now = Date.now();
if (now - lastForcePasswordNoticeAt < FORCE_PASSWORD_NOTICE_INTERVAL) {
return;
}
lastForcePasswordNoticeAt = now;
ElMessage({
message: $t('sysAccount.forceChangePasswordNavigateTip'),
type: 'warning',
duration: 2200,
grouping: true,
plain: true,
showClose: true,
});
}