From 25ee6ab0bda364f8ec9fac35babb17d32f444aae Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Fri, 2 Oct 2026 14:13:30 +0800 Subject: [PATCH] =?UTF-8?q?feat(gerp):=20=E6=A1=A3=E6=A1=88=E9=A1=B5?= =?UTF-8?q?=E8=BA=AB=E4=BB=BD=E8=AF=81=E5=8F=B7=E4=BA=8C=E6=AC=A1=E5=AF=86?= =?UTF-8?q?=E7=A0=81=E8=A7=A3=E9=94=81=E6=9F=A5=E7=9C=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 档案管理页新增「查看身份证」按钮:输入当前登录账号密码解锁 - 解锁成功后刷新列表,10 分钟内切换他人档案同样可查看(解锁态后端按登录用户维护) - api/form.ts 新增 ehrmIdCardApi(unlock/status) --- src/api/form.ts | 17 +++++++ src/views/ehrm/Profile.vue | 94 +++++++++++++++++++++++++++++++++++++- 2 files changed, 109 insertions(+), 2 deletions(-) diff --git a/src/api/form.ts b/src/api/form.ts index 50a6076..8cebbf2 100644 --- a/src/api/form.ts +++ b/src/api/form.ts @@ -91,3 +91,20 @@ export const formApi = { return post('/API/FormAPI/BatchPositions', data) }, } + +/** + * eHRM 员工档案身份证:二次密码验证 + * + * 身份证号为敏感字段,未解锁时后端返回空值(完全隐藏)。 + * 输入当前登录用户密码后开启 10 分钟查看窗口,解锁态按登录用户维度共享, + * 因此窗口内切换到其他员工档案也能查看。 + */ +export const ehrmIdCardApi = { + /** 校验当前登录用户密码,开启 10 分钟身份证查看窗口 */ + unlock: (password: string): Promise<{ unlocked: boolean; expiresIn: number }> => + post<{ unlocked: boolean; expiresIn: number }>('/API/Ehrm/UnlockIdCard', { Password: password }), + + /** 查询当前登录用户是否处于解锁窗口内 */ + status: (): Promise<{ unlocked: boolean }> => + get<{ unlocked: boolean }>('/API/Ehrm/IdCardStatus'), +} diff --git a/src/views/ehrm/Profile.vue b/src/views/ehrm/Profile.vue index 4e1bcbf..388b4d9 100644 --- a/src/views/ehrm/Profile.vue +++ b/src/views/ehrm/Profile.vue @@ -3,23 +3,76 @@ * 档案管理(eHRM 人力资源管理扩展) * * 员工档案表:工号 / 部门 / 入职日期 / 职务 / 学历 / 紧急联系人 / 地址等。 + * + * 身份证号(IdCard)为敏感列:未二次验证时后端返回空值(完全隐藏), + * 需在此页点「查看身份证」输入**当前登录账号**密码解锁;解锁后 10 分钟内在 + * 任意员工档案(含切换到别人)都能查看——解锁态由后端按登录用户维度维护。 */ -import { computed } from 'vue' +import { computed, onMounted, ref } from 'vue' +import { ElMessage } from 'element-plus' import CrudTable from '@/components/CrudTable.vue' import AdminBadge from '@/components/AdminBadge.vue' import { useUserStore } from '@/stores/user' import { setPageTitle } from '@/utils/serverScope' +import { ehrmIdCardApi } from '@/api/form' const userStore = useUserStore() setPageTitle('档案管理') const isAdmin = computed(() => userStore.isAdmin) + +// ===== 身份证二次密码验证 ===== +// 解锁窗口(10 分钟)由后端记录,前端只负责触发解锁并在成功后刷新列表取明文 +const tableRef = ref() +const idCardUnlocked = ref(false) +const unlockDialogVisible = ref(false) +const unlockPassword = ref('') +const unlocking = ref(false) + +/** 查询当前登录用户是否已处于解锁窗口内(页面刷新后恢复按钮状态) */ +async function loadIdCardStatus(): Promise { + try { + const res = await ehrmIdCardApi.status() + idCardUnlocked.value = !!res?.unlocked + } catch { + idCardUnlocked.value = false + } +} + +function openUnlockDialog(): void { + unlockPassword.value = '' + unlockDialogVisible.value = true +} + +/** 提交密码:成功后刷新列表(此时后端才会在 EmployeeProfile 记录里返回身份证明文) */ +async function submitUnlock(): Promise { + if (!unlockPassword.value) { + ElMessage.warning('请输入密码') + return + } + unlocking.value = true + try { + await ehrmIdCardApi.unlock(unlockPassword.value) + idCardUnlocked.value = true + unlockDialogVisible.value = false + unlockPassword.value = '' + ElMessage.success('验证成功,10 分钟内可查看身份证号') + await tableRef.value?.refresh?.() + } catch { + // 失败提示由响应拦截器统一弹出(如「密码错误」),弹窗保留供重试 + } finally { + unlocking.value = false + } +} + +onMounted(loadIdCardStatus) @@ -39,4 +122,11 @@ const isAdmin = computed(() => userStore.isAdmin) flex-direction: column; box-sizing: border-box; } + +.idcard-tip { + margin: 0 0 12px; + font-size: 13px; + line-height: 1.6; + color: var(--el-text-color-secondary); +}