diff --git a/docs/BRD_IMPLEMENTATION_AUDIT.md b/docs/BRD_IMPLEMENTATION_AUDIT.md index 37af8919..8865b4db 100644 --- a/docs/BRD_IMPLEMENTATION_AUDIT.md +++ b/docs/BRD_IMPLEMENTATION_AUDIT.md @@ -26,7 +26,7 @@ | 缺口 | BRD依据 | 当前事实 | 下一步 | |---|---|---|---| -| 正式主管身份、项目范围和数据权限 | 5.4、L1-B、G3 | 代码已有 `aihr_org_snapshot`、岗位/项目过滤和主管接口;生产快照当前为 22 条 active、2 个项目,但手机号关联为 0/22;生产环境当前未配置 `AIHR_ORG_SYNC_*` 组织同步凭据;移动端角色查询失败已改为安全降级员工端,线上视觉测试不能替代真实主管身份验证;组织覆盖写入现在会拒绝被跳过、手机号不完整、脱敏手机号或疑似乱码的快照,除非显式传 `allowPartialReplace=true`;重复 `ext_party_id` 无论是否允许部分覆盖都直接拒绝,避免唯一键折叠不同员工身份 | 由业务/运维提供正式组织接口配置后先做 dry-run,核对项目、岗位、`ext_party_id`、手机号;补齐手机号映射并确认主管身份后,才执行正式同步和主管数据权限验收 | +| 正式主管身份、项目范围和数据权限 | 5.4、L1-B、G3 | 代码已有 `aihr_org_snapshot`、岗位/项目过滤和主管接口;生产快照当前为 22 条 active、2 个项目,但手机号关联为 0/22;生产环境当前未配置 `AIHR_ORG_SYNC_*` 组织同步凭据;移动端角色查询失败已改为安全降级员工端,员工登录/路由现在通过认证的 `/api/aihr/mobile/me` 刷新官方岗位,只有组织未映射时才保留本地演示岗位回退;线上视觉测试不能替代真实主管身份验证;组织覆盖写入现在会拒绝被跳过、手机号不完整、脱敏手机号或疑似乱码的快照,除非显式传 `allowPartialReplace=true`;重复 `ext_party_id` 无论是否允许部分覆盖都直接拒绝,避免唯一键折叠不同员工身份 | 由业务/运维提供正式组织接口配置后先做 dry-run,核对项目、岗位、`ext_party_id`、手机号;补齐手机号映射并确认主管身份后,才执行正式同步和主管数据权限验收 | | 管理端/后端生产发布证据 | 6.3、12.1、L1-C | 2026-07-14 已核实并发布:生产根站点 `https://peilian.njzhmj.top/`、Caddy `/prod-api`、systemd `wygj-aihr.service` 和后端 jar 均可核查;管理端静态包、后端 jar 已与本地构建 hash 对齐,租户接口和移动端首页 API 返回 200 | 发布证据已具备;后续仍需把正式发布命令、回滚脚本和生产部署凭据纳入运维交接,不能把“服务可访问”直接等同于正式试点通过 | | M5 正式试点证据 | L1-B/C/D、G1/G3/G4 | 已补员工训练后 1–5 分满意度和可选意见采集,意见脱敏后写入 `aihr_practice_session`,CSV/严格门禁可读满意度响应数与平均分;但本地样本不能代表正式窗口,仍不能用 seed/烟测数据替代,尚无法证明“满意度 ≥4/5” | 固定 1–2 个住宅项目和窗口,按唯一在职身份采集训练、人工校准、SOP 评审、完训率和满意度;严格门禁要求满意度有真实响应且平均分 ≥4.0/5 | | AI 分数与人工复核边界 | 4.1、4.5、G1/G2 | 面试和对练已有人工复核/校准入口;正式试点 CSV 已补明细级 AI 分、人工校准分、校准人、校准时间和最终采用分;正式试点仍需用真实窗口验证人工可否决证据 | 在正式试点报告中抽查校准记录与最终采用值,确认人工分可覆盖 AI 建议且不直接挂钩绩效/晋升 | diff --git a/mobile-uni/src/services/position.ts b/mobile-uni/src/services/position.ts index 320aabfd..50d158ee 100644 --- a/mobile-uni/src/services/position.ts +++ b/mobile-uni/src/services/position.ts @@ -1,7 +1,6 @@ -import type { MobileIdentity, OrgSnapshotResponse, RoleKey } from '@/types/api'; +import type { MobileIdentity, RoleKey } from '@/types/api'; import { apiRequest } from './api'; import { - getAuth, hasSelectedPosition, normalizePosition, roleKey, @@ -56,18 +55,15 @@ export const goToMobileTarget = (url: string) => { uni.redirectTo({ url }); }; -export const hydratePositionFromOrg = async (phone = getAuth().phone): Promise => { - const keyword = phone.trim(); - if (!keyword) return ''; +export const hydratePositionFromOrg = async (): Promise => { try { - const snapshot = await apiRequest({ - url: `/api/aihr/org/snapshot?keyword=${encodeURIComponent(keyword)}&status=active&pageSize=1`, + const identity = await apiRequest({ + url: '/api/aihr/mobile/me', method: 'GET', timeout: 15000, clearAuthOnUnauthorized: false }); - const officialPosition = snapshot.rows?.[0]?.positionName || ''; - return saveSelectedPosition(officialPosition); + return saveSelectedPosition(identity.positionName); } catch { return ''; } @@ -77,9 +73,10 @@ export const nextUserRouteAfterLogin = async (redirect: string) => { const role = await hydrateMobileRole(); const roleRoute = routeForMobileRole(role, redirect); if (roleRoute !== redirect) return roleRoute; - if (!isUserRoute(redirect) || hasSelectedPosition()) return redirect; + if (!isUserRoute(redirect)) return redirect; const officialPosition = await hydratePositionFromOrg(); - return normalizePosition(officialPosition) ? redirect : positionSetupUrl(redirect); + if (normalizePosition(officialPosition) || hasSelectedPosition()) return redirect; + return positionSetupUrl(redirect); }; export const ensureEmployeePosition = async (redirect: string) => { diff --git a/scripts/demo-check.sh b/scripts/demo-check.sh index 3bfe0d47..76833a06 100755 --- a/scripts/demo-check.sh +++ b/scripts/demo-check.sh @@ -314,6 +314,7 @@ contains mobile-uni/src/pages/user/sop/index.vue "没解决" contains mobile-uni/src/services/knowledge.ts "/api/knowledge/summary-card" contains mobile-uni/src/services/knowledge.ts "/api/knowledge/position-sop" contains mobile-uni/src/services/position.ts "removeStorageSync(roleKey)" +contains mobile-uni/src/services/position.ts "/api/aihr/mobile/me" contains mobile-uni/src/services/case.ts "/api/knowledge/case/upload" contains mobile-uni/src/services/candidate.ts "/api/recruit/interview/start" contains mobile-uni/src/services/candidate.ts "/api/aihr/mobile/candidate/materials"