Files
medical-mall/docs/AUTH_ID_MAPPING_FIX.md
2026-06-12 10:16:27 +08:00

8.1 KiB
Raw Blame History

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

数据库映射关系

-- 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

修改前

const session = supa.getSession()
const workerId = session != null && session.user != null ? session.user.getString('id') : ''

修改后

import { getCurrentAkUserId } from '@/utils/akUserMapping.uts'

const workerId = await getCurrentAkUserId()

原因:签到预校验 RPC 需要业务用户 ID不是 Supabase Auth ID

pages/user/login.uvue

新增

import { loadCurrentAkUser } from '@/utils/akUserMapping.uts'

// 登录成功后
await loadCurrentAkUser()

原因:登录后立即加载 ak_users 映射,存储到本地缓存

pages/mall/delivery/orders/checkin.uvue

新增

import { debugCurrentUser } from '@/utils/akUserMapping.uts'

// 预校验前
debugCurrentUser()

原因:调试输出当前 ak_user 信息,方便排查问题

types/delivery.uts

新增字段

export type DeliveryOrderType = {
  // ... existing fields ...
  acceptedBy: string      // 接单人员 ID业务用户 ID
  acceptedByName: string  // 接单人员姓名
  // ... existing fields ...
}

api/delivery.uts

修改:在 mapRpcOrderItemCompat 函数中添加接单人员信息提取:

// 从 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

新增:订单卡片上显示接单人员

<text v-if="item.acceptedByName != ''" class="meta-text accepted-by"
  >接单人:{{ item.acceptedByName }}</text
>

pages/mall/delivery/orders/detail.uvue

新增:服务人员信息卡片

<view class="card">
  <text class="section-title">服务人员</text>
  <text class="row-text">配送员:{{ order.deliveryStaffName }}</text>
  <text v-if="order.acceptedByName != ''" class="row-text"
    >接单人:{{ order.acceptedByName }} (ID: {{ order.acceptedBy }})</text
  >
  <text v-if="order.acceptTime != ''" class="row-text"
    >接单时间:{{ formatDateTime(order.acceptTime) }}</text
  >
</view>

数据流

登录流程

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_idak_user_id2a97a39f...
  • 后端返回 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.id311860b5...
    • 正确: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. 回滚代码:

    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. 重新编译