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

@@ -1,36 +1,66 @@
<script setup lang="ts">
import { ref } from 'vue';
import { computed, ref, watch } from 'vue';
import { useRoute } from 'vue-router';
import { Profile } from '@easyflow/common-ui';
import { useUserStore } from '@easyflow/stores';
import { $t } from '#/locales';
import ProfileBase from './base-setting.vue';
import ProfileNotificationSetting from './notification-setting.vue';
import ProfilePasswordSetting from './password-setting.vue';
import ProfileSecuritySetting from './security-setting.vue';
const route = useRoute();
const userStore = useUserStore();
const tabsValue = ref<string>('basic');
const tabs = ref([
{
label: '基本设置',
value: 'basic',
const forcePasswordChange = computed(() => {
return !!userStore.userInfo?.passwordResetRequired || route.query.force === '1';
});
const tabs = computed(() => {
if (forcePasswordChange.value) {
return [
{
label: $t('settingsConfig.updatePwd'),
value: 'password',
},
];
}
return [
{
label: '基本设置',
value: 'basic',
},
{
label: '安全设置',
value: 'security',
},
{
label: '修改密码',
value: 'password',
},
{
label: '新消息提醒',
value: 'notice',
},
];
});
watch(
() => [route.query.force, route.query.tab, userStore.userInfo?.passwordResetRequired],
() => {
if (forcePasswordChange.value) {
tabsValue.value = 'password';
return;
}
tabsValue.value = (route.query.tab as string) || 'basic';
},
{
label: '安全设置',
value: 'security',
},
{
label: '修改密码',
value: 'password',
},
{
label: '新消息提醒',
value: 'notice',
},
]);
{ immediate: true },
);
</script>
<template>
<Profile

View File

@@ -2,48 +2,75 @@
import type { EasyFlowFormSchema } from '#/adapter/form';
import { computed, ref } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { ProfilePasswordSetting, z } from '@easyflow/common-ui';
import { preferences } from '@easyflow/preferences';
import { useUserStore } from '@easyflow/stores';
import { ElMessage } from 'element-plus';
import { api } from '#/api/request';
import { $t } from '#/locales';
import { useAuthStore } from '#/store';
import { isStrongPassword } from '#/utils/password-policy';
const profilePasswordSettingRef = ref();
const authStore = useAuthStore();
const route = useRoute();
const router = useRouter();
const userStore = useUserStore();
const isForcedPasswordChange = computed(() => {
return !!userStore.userInfo?.passwordResetRequired || route.query.force === '1';
});
const formSchema = computed((): EasyFlowFormSchema[] => {
return [
{
fieldName: 'oldPassword',
label: '旧密码',
fieldName: 'password',
label: $t('sysAccount.oldPwd'),
component: 'EasyFlowInputPassword',
componentProps: {
placeholder: '请输入旧密码',
placeholder: $t('sysAccount.oldPwd') + $t('common.isRequired'),
},
},
{
fieldName: 'newPassword',
label: '新密码',
label: $t('sysAccount.newPwd'),
component: 'EasyFlowInputPassword',
componentProps: {
passwordStrength: true,
placeholder: '请输入新密码',
placeholder: $t('sysAccount.newPwd') + $t('common.isRequired'),
},
renderComponentContent() {
return {
strengthText: () => $t('sysAccount.passwordStrongTip'),
};
},
rules: z
.string({ required_error: $t('sysAccount.newPwd') + $t('common.isRequired') })
.min(1, { message: $t('sysAccount.newPwd') + $t('common.isRequired') })
.refine((value) => isStrongPassword(value), {
message: $t('sysAccount.passwordStrongTip'),
}),
},
{
fieldName: 'confirmPassword',
label: '确认密码',
label: $t('sysAccount.confirmPwd'),
component: 'EasyFlowInputPassword',
componentProps: {
passwordStrength: true,
placeholder: '请再次输入新密码',
placeholder: $t('sysAccount.repeatPwd'),
},
dependencies: {
rules(values) {
const { newPassword } = values;
return z
.string({ required_error: '请再次输入新密码' })
.min(1, { message: '请再次输入新密码' })
.string({ required_error: $t('sysAccount.repeatPwd') })
.min(1, { message: $t('sysAccount.repeatPwd') })
.refine((value) => value === newPassword, {
message: '两次输入的密码不一致',
message: $t('sysAccount.notSamePwd'),
});
},
triggerFields: ['newPassword'],
@@ -52,12 +79,29 @@ const formSchema = computed((): EasyFlowFormSchema[] => {
];
});
function handleSubmit() {
ElMessage.success('密码修改成功');
const updateLoading = ref(false);
async function handleSubmit(values: any) {
updateLoading.value = true;
try {
const res = await api.post('/userCenter/sysAccount/updatePassword', values);
if (res.errorCode === 0) {
ElMessage.success($t('message.success'));
const userInfo = await authStore.fetchUserInfo();
if (isForcedPasswordChange.value) {
await router.replace(
userInfo?.homePath || preferences.app.defaultHomePath || '/',
);
}
}
} finally {
updateLoading.value = false;
}
}
</script>
<template>
<ProfilePasswordSetting
:button-loading="updateLoading"
:button-text="$t('button.update')"
ref="profilePasswordSettingRef"
class="w-1/3"
:form-schema="formSchema"