# Supabase Auth ID 与业务用户 ID 映射修复 ## 问题根因 前端和后端混用了两套 ID: | ID 类型 | 来源 | 示例 | 用途 | | -------------------- | -------------------------------- | -------------------------------------- | ----------------- | | **Supabase Auth ID** | `session.user.id` / `auth.uid()` | `311860b5-d99f-478f-b1ac-3ef1cc55ae07` | Supabase 认证系统 | | **业务用户 ID** | `public.ak_users.id` | `2a97a39f-4efc-40c6-a065-55a2484e3784` | 所有业务表 | **所有业务表都应该使用业务用户 ID**: - `ec_care_tasks.assigned_to` - `hc_dispatch_assignments.worker_id` - `hc_worker_locations.worker_id` - `hc_evidence_files.uploader_id` - `hss_service_orders.current_staff_id` ## 数据库映射关系 ```sql -- ak_users 表结构 SELECT id, auth_id, username, email, role, user_type, status FROM public.ak_users; -- 示例数据 -- id: 2a97a39f-4efc-40c6-a065-55a2484e3784 (业务用户 ID) -- auth_id: 311860b5-d99f-478f-b1ac-3ef1cc55ae07 (Supabase Auth ID) -- username: 居家服务员 -- email: homecare_worker@test.com -- role: delivery ``` ## 修改文件清单 ### 1. 新增文件 #### `utils/akUserMapping.uts` - **作用**:管理 Supabase Auth ID 到业务用户 ID 的映射 - **核心函数**: - `loadCurrentAkUser()` - 登录后加载 ak_users 映射 - `getCurrentAkUserId()` - 获取当前业务用户 ID - `getCurrentAkUser()` - 获取当前业务用户完整信息 - `getCurrentAuthUserId()` - 获取当前 Supabase Auth ID - `debugCurrentUser()` - 调试输出当前用户信息 ### 2. 修改文件 #### `utils/homecareAuth.uts` **修改前**: ```uts const session = supa.getSession() const workerId = session != null && session.user != null ? session.user.getString('id') : '' ``` **修改后**: ```uts import { getCurrentAkUserId } from '@/utils/akUserMapping.uts' const workerId = await getCurrentAkUserId() ``` **原因**:签到预校验 RPC 需要业务用户 ID,不是 Supabase Auth ID #### `pages/user/login.uvue` **新增**: ```uts import { loadCurrentAkUser } from '@/utils/akUserMapping.uts' // 登录成功后 await loadCurrentAkUser() ``` **原因**:登录后立即加载 ak_users 映射,存储到本地缓存 #### `pages/mall/delivery/orders/checkin.uvue` **新增**: ```uts import { debugCurrentUser } from '@/utils/akUserMapping.uts' // 预校验前 debugCurrentUser() ``` **原因**:调试输出当前 ak_user 信息,方便排查问题 #### `types/delivery.uts` **新增字段**: ```uts export type DeliveryOrderType = { // ... existing fields ... acceptedBy: string // 接单人员 ID(业务用户 ID) acceptedByName: string // 接单人员姓名 // ... existing fields ... } ``` #### `api/delivery.uts` **修改**:在 `mapRpcOrderItemCompat` 函数中添加接单人员信息提取: ```uts // 从 statusLog 中提取接单人员信息 order.acceptedBy = '' order.acceptedByName = '' const statusLog = order.statusLog for (let i = 0; i < statusLog.length; i++) { if (statusLog[i].toStatus == 'accepted' || statusLog[i].toStatus == 'pending_accept') { order.acceptedBy = statusLog[i].operatorId != '' ? statusLog[i].operatorId : order.deliveryStaffId order.acceptedByName = statusLog[i].operatorRole != '' ? statusLog[i].operatorRole : order.deliveryStaffName break } } ``` #### `pages/mall/delivery/orders/index.uvue` **新增**:订单卡片上显示接单人员 ```html 接单人:{{ item.acceptedByName }} ``` #### `pages/mall/delivery/orders/detail.uvue` **新增**:服务人员信息卡片 ```html 服务人员 配送员:{{ order.deliveryStaffName }} 接单人:{{ order.acceptedByName }} (ID: {{ order.acceptedBy }}) 接单时间:{{ formatDateTime(order.acceptTime) }} ``` ## 数据流 ### 登录流程 ``` 1. 用户输入邮箱/密码登录 ↓ 2. Supabase Auth 验证,返回 session (authUserId = 311860b5...) ↓ 3. 调用 loginDelivery() 获取 token 和用户信息 ↓ 4. 调用 loadCurrentAkUser(): - 从 session 获取 authUserId - 查询 ak_users WHERE auth_id = authUserId - 获取业务用户 ID (akUserId = 2a97a39f...) - 存储到本地缓存 ↓ 5. 登录完成 ``` ### 签到流程 ``` 1. 用户点击"距离预校验" ↓ 2. checkinPrecheck() 调用 getCurrentAkUserId() - 从缓存读取 akUserId - 如果缓存不存在,自动加载 ↓ 3. 调用 RPC rpc_homecare_checkin_precheck: p_worker_id = akUserId (2a97a39f...) ↓ 4. 后端验证: - 查询 ec_care_tasks WHERE id = workOrderId - 检查 assigned_to = p_worker_id - 如果匹配,返回 canCheckin = true ↓ 5. 签到成功 ``` ## 测试步骤 ### 1. 清除旧缓存 在微信开发者工具中: ``` 控制台 -> Storage -> 清除所有缓存 ``` ### 2. 重新登录 1. 打开配送端 2. 使用测试账号登录: - 账号:`homecare_worker@test.com` - 密码:`Homecare123!` 3. 登录成功后,控制台应该显示: ``` [akUserMapping] 加载业务用户成功: { authUserId: '311860b5-d99f-478f-b1ac-3ef1cc55ae07', akUserId: '2a97a39f-4efc-40c6-a065-55a2484e3784', username: '居家服务员', role: 'delivery' } ``` ### 3. 测试签到 1. 进入"待接单"列表 2. 点击任意订单接单 3. 进入订单详情 4. 点击"到达签到" 5. 点击"距离预校验" 6. 控制台应该显示: ``` [akUserMapping] ========== 当前用户调试信息 ========== [akUserMapping] authUserId: 311860b5-d99f-478f-b1ac-3ef1cc55ae07 [akUserMapping] akUserId: 2a97a39f-4efc-40c6-a065-55a2484e3784 [akUserMapping] profile: { id: '2a97a39f...', ... } [akUserMapping] ====================================== [CHECKIN RPC] workerId (ak_user_id): 2a97a39f-4efc-40c6-a065-55a2484e3784 ``` 7. 如果 `workerId` 显示的是 `2a97a39f...` 而不是 `311860b5...`,说明修复成功 ### 4. 验证订单列表 1. 订单卡片上应该显示接单人员姓名 2. 例如:`接单人:居家服务员` ## 验收标准 - [ ] 登录后 storage 中同时存在: - `auth_user_id` = `311860b5...` - `ak_user_id` = `2a97a39f...` - [ ] `checkin.uvue` 获取定位时使用 gcj02 - [ ] precheck 调用时 `p_worker_id` 传 `ak_user_id`(2a97a39f...) - [ ] 后端返回 `reasonCode` 不再是 `WORKER_NOT_MATCHED` - [ ] 数据库 `hc_worker_locations.worker_id` 写入的是 `2a97a39f...`,不是 `311860b5...` - [ ] 正式签到 submit 成功后,`hc_work_order_confirmations` 生成 ARRIVAL / PENDING 记录 - [ ] 现场图片 `hc_evidence_files.uploader_id` 使用 `ak_users.id` - [ ] 订单列表显示接单人员姓名 ## 注意事项 1. **不要使用 `session.user.id` 作为业务用户 ID** - 错误:`session.user.id` → `311860b5...` - 正确:`getCurrentAkUserId()` → `2a97a39f...` 2. **所有业务表都使用业务用户 ID** - `ec_care_tasks.assigned_to` = `2a97a39f...` - `hc_dispatch_assignments.worker_id` = `2a97a39f...` 3. **如果 ak_users 映射加载失败** - 不影响登录流程 - 但签到功能会失败 - 需要联系管理员在 `ak_users.auth_id` 字段绑定 Supabase Auth ID 4. **配送员 vs 居家服务员** - 配送员:负责配送医药商城的药品、器械 - 居家服务员:负责居家医疗服务 - 当前 `ak_users` 中 username 是"居家服务员",role = delivery 只是 delivery 端角色 - 不等于商城配送员 ## 回滚方案 如果修复后出现问题,可以: 1. 清除本地缓存: ``` 微信开发者工具 -> Storage -> 清除所有缓存 ``` 2. 回滚代码: ```bash git checkout HEAD -- utils/akUserMapping.uts git checkout HEAD -- utils/homecareAuth.uts git checkout HEAD -- pages/user/login.uvue git checkout HEAD -- pages/mall/delivery/orders/checkin.uvue ``` 3. 重新编译