diff --git a/.trae/documents/fix-login-infinite-loop.md b/.trae/documents/fix-login-infinite-loop.md new file mode 100644 index 0000000..e46d1d5 --- /dev/null +++ b/.trae/documents/fix-login-infinite-loop.md @@ -0,0 +1,51 @@ +# 修复登录无限循环(登录成功后弹回登录页) + +## Context(问题与证据链) + +用户反馈:登录成功后又回到登录界面,无限循环。排查已确认(含用户亲证): + +**用户确认的现象** +- 登录页地址栏为 `api.yunzer.cn`(远程线上认证中心,非本地 9000) +- 登录后见过「选择要进入的企业」界面(hero920103 绑定 2 家企业),**选完企业后又弹回登录页** + +**数据库证据(go-platform 库)** +- hero920103 = identity_id 2(李志强),绑定两家企业(tid=1、tid=2)→ 登录必走"待选企业"分支 +- `yz_auth_session`:18:09~18:12 连续 4 条会话被踢(revoked=1, revoke_reason='kicked');最新会话 id=386(18:18:29,tid=2,client_id 为空) +- 18:24:42 登录日志(id=218,user_id=1)与 hero920103 实际 identity_id=2 不符 → **该日志由远程旧版代码写入**(字段语义不同),且 IP=127.0.0.1/::1 符合"远程 nginx 反代回环"特征 + +**代码机制(go/services/auth/session.go L61-134)** +- `CreateSession` 按 identity_id **全局**统计活跃会话,超 MaxSession 即踢最旧会话(kicked),不区分 tid/client/服务实例 +- 登录 → 远程建会话 → 企业选择 → 新会话又创建 → 互踢 → authorize 发现会话已吊销 → 送回登录页 → 再登录 → **无限循环** +- 远程为旧版代码(字段错位可证),其企业选择后的会话处理存在缺陷,无法本地修复 + +## 修复方案 + +### 第一步:本地开发认证切换到本地 9000 实例(核心修复) + +修改 `backend/.env.development`: + +``` +VITE_AUTH_BASE='http://127.0.0.1:9000/auth' +``` + +本地 9000 已注册全套认证端点(/auth/login、/auth/authorize、/auth/token、/auth/userinfo、/auth/switch-tenant,见 `go/routers/auth/auth.go`),且为最新代码(企业选择、cookie、PKCE 逻辑完整)。 + +### 第二步:配套校验与清理 + +1. 核对 `yz_auth_client` 表 yz-backend 的 redirect_uris 白名单包含 `http://127.0.0.1:4401/auth-callback.html`(不匹配则用 MySQL MCP 补登) +2. 清理脏数据:将 hero920103(identity_id=2)名下 revoked=0 的旧会话标记 revoked=1(reason='cleanup'),避免旧会话占用互踢名额 +3. 重启 Vite dev server 使 env 生效 +4. 验证本地登录页 HTML 表单嵌入 client_id(curl 抓取确认,防止空 client 会话再现) + +### 第三步:端到端验证 + +1. 无痕窗口(避免残留 localStorage token/userInfo)访问 `http://127.0.0.1:4401` +2. 完整走:跳本地登录页 → 输入 hero920103 → 企业选择(展示 2 家)→ 选 tid=2 → 回跳 auth-callback → 进入工作台,无循环 +3. MySQL MCP 复查 `yz_auth_session` 无异常互踢 +4. 登录恢复后,验证原任务功能:apps/oa/schedule 日历按 hero920103 排班显示上班(绿)/休息(橙)背景(后端 `/backend/oa/scheduling/my` 已就绪) + +## 涉及文件 + +- `backend/.env.development`(唯一代码修改:VITE_AUTH_BASE 指向本地) +- 数据库:`yz_auth_client`(白名单核对)、`yz_auth_session`(脏数据清理) +- 不改 Go 代码(互踢规则是合理安全设计;根因是开发环境认证指向了旧版远程中心) diff --git a/backend/src/api/oaScheduling.js b/backend/src/api/oaScheduling.js index 0ff0ff7..7c82280 100644 --- a/backend/src/api/oaScheduling.js +++ b/backend/src/api/oaScheduling.js @@ -34,6 +34,11 @@ export function getScheduleBoard(params) { return request({ url: '/backend/oa/scheduling/board', method: 'get', params }) } +// 当前登录用户的排班(按账号匹配员工档案),供日程日历显示上班/休息背景 +export function getMyScheduleBoard(params) { + return request({ url: '/backend/oa/scheduling/my', method: 'get', params }) +} + // 批量按格子编辑排班:cells 为排班板多选的「员工 × 日期」任意组合 // shift_id>0 设为该班次(有排班=调班,无排班=新增);shift_id=0 清除(休息/请假) export function saveScheduleEntryCells(data) { diff --git a/backend/src/views/apps/oa/schedule/index.vue b/backend/src/views/apps/oa/schedule/index.vue index 2c4251d..d94077d 100644 --- a/backend/src/views/apps/oa/schedule/index.vue +++ b/backend/src/views/apps/oa/schedule/index.vue @@ -78,6 +78,12 @@ > 今天 + 当前账号暂无排班
@@ -94,7 +100,9 @@ selected: cell.date === selectedDate, 'has-items': cell.items.length > 0, 'is-off': cell.tag === 'off', - 'is-work': cell.tag === 'work' + 'is-work': cell.tag === 'work', + 'is-my-work': cell.myTag === 'work', + 'is-my-rest': cell.myTag === 'rest' }" @click="selectedDate = cell.date" @dblclick="openCreate(cell.date)" @@ -109,6 +117,13 @@ {{ cell.month }}月 + {{ cell.myEntry.short_name || cell.myEntry.shift_name }}
{{ cell.holidayName }} @@ -164,6 +179,28 @@ 周末 + + {{ selectedMyEntry.short_name || selectedMyEntry.shift_name }} + {{ selectedMyEntry.work_start }}-{{ + selectedMyEntry.work_end + }} + + 休息
{{ selectedItems.length }} 项日程