Files
mileage-bonus/.claude_plans/tranquil-sniffing-babbage.md
kkfluous 573f8397a6 chore: 添加输入输出文件 + .claude记忆和计划
输入文件:
- 租赁任务考核_2026年{1,2,3}月.xlsx (考核源数据)
- {1,2}月.xlsx (客户盈亏表)
- 车辆里程考核与奖金发放规则(V.1.2).docx

输出文件:
- 里程任务考核_{1,2,3}月核算.xlsx (月度核算结果)
- 里程任务考核_Q1汇总.xlsx (含车辆台账)
- 3月客户盈亏表(待填写).xlsx (模版)

.claude_memory: 项目记忆(规则/偏好/架构/测试车辆)
.claude_plans: 历次计划文件

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 14:09:24 +08:00

4.4 KiB
Raw Blame History

用户权限校验实现计划

Context

当前系统零认证,所有 API 完全开放。需要接入公司现有的 jumpToken 认证体系,并根据用户角色实现数据权限过滤。用户从资产管理平台跳转进入本系统,携带 jumpToken。

认证流程

用户带 jumpToken 访问 → 前端提取 jumpToken
  → 后端代理调用外部API换取 sessionToken
  → 后端调用外部API获取用户信息(roles, depCode)
  → 后端签发 JWT 返回前端
  → 前端所有请求带 JWT → 后端中间件验证

三级权限模型

级别 角色条件 数据范围
full roleName 含 "所有权限" / "数智中心" / "BI-Leader" 全部数据
department roleName 含 "BI-Leader-Dep" 自己部门的全部数据
personal 无以上角色 仅自己负责的车辆bd=userId

部门匹配:用户 depCode → 查 tab_department 得 dep_name → 过滤车辆数据中的 department 字段 个人匹配:添加 managerId 字段c.bd按 userId 精确匹配(不用 userName 避免重名)

新增/修改文件

后端新增

  • src/server/auth/types.ts — AuthUser、PermissionLevel、JwtPayload 类型
  • src/server/auth/login.tsPOST /api/auth/login接收外部token调外部API获取用户信息签发JWT+ GET /api/auth/exchange(代理 jumpToken 换取 sessionToken避免前端 CORS 问题)
  • src/server/auth/middleware.ts — Hono 中间件,验证 JWT跳过 /api/health 和 /api/auth/*
  • src/server/auth/permissions.tsfilterByPermission<T>(items, user) 通用过滤函数

后端修改

  • src/server/index.ts — 挂载 auth 路由和中间件
  • src/server/routes/mileage/vehicle-info.ts — SQL 添加 c.bd AS manager_id
  • src/server/routes/mileage/types.ts — CachedVehicle 添加 managerId: number | null
  • src/server/routes/mileage/cache.ts — 传递 managerId
  • src/server/routes/mileage/monitoring.ts — 请求时 filterByPermission + 重算筛选选项
  • src/server/routes/mileage/targets.ts — 按权限过滤
  • src/server/routes/mileage/trend.ts — 按权限限定车牌范围
  • src/server/routes/vehicles.ts — 所有端点用 getVehiclesForUser(c) 替代 getVehicles()
  • src/server/types.ts — Vehicle 类型添加 managerId

前端新增

  • src/auth/AuthProvider.tsx — 认证上下文,管理 jumpToken 交换和 JWT 存储
  • src/auth/useAuth.ts — 认证状态 hook
  • src/auth/api-client.ts — 全局 fetchJson自动附加 Authorization header
  • src/auth/UnauthorizedPage.tsx — 未授权页面(图标 + 提示文字)

前端修改

  • src/App.tsx — 包裹 AuthProvider条件渲染 Shell / UnauthorizedPage
  • src/modules/mileage/api.ts — fetchJson 改用 auth/api-client
  • src/modules/assets/api.ts — fetchJson 改用 auth/api-client

环境配置

  • .env 添加 JWT_SECRETEXTERNAL_API_BASE
  • package.json 添加 jsonwebtoken@types/jsonwebtoken

关键设计决策

  1. 缓存全局,请求时过滤 — 监控缓存保持全量数据,每次请求根据用户权限过滤,筛选选项也从过滤后数据重算
  2. jumpToken 交换走后端代理 — 避免前端 CORS 问题,外部 API 调用全部在服务端
  3. 用 managerId数字ID匹配而非 userName — 避免重名问题
  4. JWT 存 sessionStorage — 刷新页面不丢失,关闭标签页自动清除
  5. filterByPermission 泛型函数 — 同时适配 Vehicle 和 CachedVehicle 类型

实施顺序

  1. 安装依赖 (jsonwebtoken)
  2. 后端 auth 模块types → login → middleware → permissions
  3. 数据模型添加 managerIdvehicle-info → types → cache
  4. 挂载中间件到 server/index.ts
  5. 集成权限过滤到各路由vehicles.ts, monitoring, targets, trend
  6. 前端 auth 模块AuthProvider, useAuth, api-client, UnauthorizedPage
  7. 前端 API 模块切换到 auth fetch
  8. App.tsx 添加认证网关
  9. 端到端测试三个权限级别

验证方式

  1. 无 jumpToken 访问 → 显示"未授权访问"页面
  2. 带有效 jumpToken 访问 → 正常进入,检查 JWT 签发
  3. full 角色用户 → 看到全部 1004 辆车数据
  4. department 角色用户 → 仅看到自己部门的车辆
  5. personal 用户 → 仅看到自己负责的车辆
  6. JWT 过期后请求 → 返回 401前端显示未授权
  7. 全屏监控筛选选项 → 仅显示用户权限范围内的部门/客户