输入文件:
- 租赁任务考核_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>
4.4 KiB
4.4 KiB
用户权限校验实现计划
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.ts—POST /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.ts—filterByPermission<T>(items, user)通用过滤函数
后端修改
src/server/index.ts— 挂载 auth 路由和中间件src/server/routes/mileage/vehicle-info.ts— SQL 添加c.bd AS manager_idsrc/server/routes/mileage/types.ts— CachedVehicle 添加managerId: number | nullsrc/server/routes/mileage/cache.ts— 传递 managerIdsrc/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— 认证状态 hooksrc/auth/api-client.ts— 全局 fetchJson,自动附加 Authorization headersrc/auth/UnauthorizedPage.tsx— 未授权页面(图标 + 提示文字)
前端修改
src/App.tsx— 包裹 AuthProvider,条件渲染 Shell / UnauthorizedPagesrc/modules/mileage/api.ts— fetchJson 改用 auth/api-clientsrc/modules/assets/api.ts— fetchJson 改用 auth/api-client
环境配置
.env添加JWT_SECRET、EXTERNAL_API_BASEpackage.json添加jsonwebtoken、@types/jsonwebtoken
关键设计决策
- 缓存全局,请求时过滤 — 监控缓存保持全量数据,每次请求根据用户权限过滤,筛选选项也从过滤后数据重算
- jumpToken 交换走后端代理 — 避免前端 CORS 问题,外部 API 调用全部在服务端
- 用 managerId(数字ID)匹配而非 userName — 避免重名问题
- JWT 存 sessionStorage — 刷新页面不丢失,关闭标签页自动清除
- filterByPermission 泛型函数 — 同时适配 Vehicle 和 CachedVehicle 类型
实施顺序
- 安装依赖 (
jsonwebtoken) - 后端 auth 模块(types → login → middleware → permissions)
- 数据模型添加 managerId(vehicle-info → types → cache)
- 挂载中间件到 server/index.ts
- 集成权限过滤到各路由(vehicles.ts, monitoring, targets, trend)
- 前端 auth 模块(AuthProvider, useAuth, api-client, UnauthorizedPage)
- 前端 API 模块切换到 auth fetch
- App.tsx 添加认证网关
- 端到端测试三个权限级别
验证方式
- 无 jumpToken 访问 → 显示"未授权访问"页面
- 带有效 jumpToken 访问 → 正常进入,检查 JWT 签发
- full 角色用户 → 看到全部 1004 辆车数据
- department 角色用户 → 仅看到自己部门的车辆
- personal 用户 → 仅看到自己负责的车辆
- JWT 过期后请求 → 返回 401,前端显示未授权
- 全屏监控筛选选项 → 仅显示用户权限范围内的部门/客户