feat(users): 统一员工密码策略并修复新增员工表单残留

This commit is contained in:
yelan
2026-09-30 09:58:15 +08:00
parent 0db94b22bf
commit 3ad95cc795
4 changed files with 143 additions and 17 deletions
@@ -0,0 +1,49 @@
<script setup lang="ts">
import { computed } from 'vue'
import { PASSWORD_POLICY_RULES, checkPasswordPolicy } from '@/utils/password-policy'
const props = defineProps<{ password: string }>()
const checks = computed(() => checkPasswordPolicy(props.password))
</script>
<template>
<ul class="password-hints" aria-label="密码规则">
<li v-for="rule in PASSWORD_POLICY_RULES" :key="rule.key" :class="{ 'is-ok': checks[rule.key] }">
<span class="password-hints__mark" aria-hidden="true">
{{ checks[rule.key] ? '✓' : '○' }}
</span>
<span>{{ rule.label }}</span>
</li>
</ul>
</template>
<style scoped>
.password-hints {
display: grid;
gap: 3px;
padding: 0;
margin: 0;
color: var(--mut);
font-size: 11px;
font-weight: 400;
line-height: 1.5;
list-style: none;
}
.password-hints li {
display: flex;
gap: 6px;
align-items: center;
}
.password-hints__mark {
color: #b3c3ca;
}
.password-hints li.is-ok,
.password-hints li.is-ok .password-hints__mark {
color: var(--brand);
}
</style>
@@ -2,7 +2,13 @@
import { computed, reactive, watch } from 'vue'
import type { CampusRecord, DepartmentRecord, RoleRecord } from '@/api/management/types'
import {
PASSWORD_MIN_LENGTH,
firstPasswordPolicyIssue,
isPasswordPolicySatisfied,
} from '@/utils/password-policy'
import PasswordPolicyHints from './PasswordPolicyHints.vue'
import type { UserEditorForm } from '../types'
const props = defineProps<{
@@ -51,16 +57,22 @@ function createEmptyForm(): UserEditorForm {
}
function resetForm() {
Object.assign(
form,
props.initial
? {
...props.initial,
roleIds: [...props.initial.roleIds],
roleLabels: [...(props.initial.roleLabels ?? [])],
}
: createEmptyForm(),
)
const next: UserEditorForm = props.initial
? {
...createEmptyForm(),
...props.initial,
roleIds: [...props.initial.roleIds],
roleLabels: [...(props.initial.roleLabels ?? [])],
}
: createEmptyForm()
// 先清空全部字段再写入:编辑态会带入 id / employeeId / version / phoneMasked 等键,
// 若只做增量合并,这些键会残留到「新增员工」表单,使新增被误判为编辑态并提交成更新。
const mutableForm = form as unknown as Record<string, unknown>
for (const key of Object.keys(mutableForm)) {
delete mutableForm[key]
}
Object.assign(form, next)
error.message = ''
}
@@ -98,8 +110,8 @@ function submit() {
return
}
if (!isEditing.value && form.password.length < 8) {
error.message = '初始密码至少需要 8 位'
if (!isEditing.value && !isPasswordPolicySatisfied(form.password)) {
error.message = firstPasswordPolicyIssue(form.password) ?? '初始密码不符合安全要求'
return
}
@@ -201,8 +213,10 @@ watch(
v-model="form.password"
type="password"
autocomplete="new-password"
:minlength="PASSWORD_MIN_LENGTH"
placeholder="请输入初始密码"
/>
<PasswordPolicyHints :password="form.password" />
</label>
<label>
<span>工号 <em>*</em></span>
@@ -1,6 +1,14 @@
<script setup lang="ts">
import { reactive, watch } from 'vue'
import {
PASSWORD_MIN_LENGTH,
firstPasswordPolicyIssue,
isPasswordPolicySatisfied,
} from '@/utils/password-policy'
import PasswordPolicyHints from './PasswordPolicyHints.vue'
const props = defineProps<{
visible: boolean
userName: string
@@ -33,8 +41,8 @@ function resetForm() {
function submit() {
error.message = ''
if (form.newPassword.length < 12) {
error.message = '新密码至少需要 12 位'
if (!isPasswordPolicySatisfied(form.newPassword)) {
error.message = firstPasswordPolicyIssue(form.newPassword) ?? '新密码不符合安全要求'
return
}
@@ -97,9 +105,10 @@ watch(
v-model="form.newPassword"
type="password"
autocomplete="new-password"
minlength="12"
placeholder="至少 12 位"
:minlength="PASSWORD_MIN_LENGTH"
placeholder="至少 12 位,含大小写字母"
/>
<PasswordPolicyHints :password="form.newPassword" />
</label>
<label>
<span>确认新密码 <em>*</em></span>
@@ -107,7 +116,7 @@ watch(
v-model="form.confirmPassword"
type="password"
autocomplete="new-password"
minlength="12"
:minlength="PASSWORD_MIN_LENGTH"
placeholder="再次输入新密码"
/>
</label>