feat: 从JWT解析userId并添加资源点余额提醒

- 新增 jwtUtils.ts 解析JWT token获取user_id
- dialogService 从登录session获取真实userId
- 添加 credit_update 事件处理
- 余额低于5点时弹窗提醒用户充值
- settings.ts 登录URL改为可配置
This commit is contained in:
XiaoFeng
2026-01-09 15:53:54 +08:00
parent 4037e9e2d7
commit 178f3a7498
6 changed files with 136 additions and 7 deletions

73
src/utils/jwtUtils.ts Normal file
View File

@ -0,0 +1,73 @@
/**
* JWT 工具函数
*/
/**
* JWT Payload 接口
*/
export interface JwtPayload {
sub?: string; // subject (通常是 userId)
userId?: number; // 用户ID (驼峰命名)
user_id?: number; // 用户ID (下划线命名)
exp?: number; // 过期时间
iat?: number; // 签发时间
[key: string]: unknown;
}
/**
* 解析 JWT token 的 payload
* @param token JWT token
* @returns 解析后的 payload解析失败返回 null
*/
export function parseJwtPayload(token: string): JwtPayload | null {
try {
const parts = token.split('.');
if (parts.length !== 3) {
console.warn('[JWT] token 格式不正确期望3部分实际:', parts.length);
return null;
}
// payload 是第二部分base64url 编码
const payload = parts[1];
// base64url 转 base64
const base64 = payload.replace(/-/g, '+').replace(/_/g, '/');
// 解码
const jsonStr = Buffer.from(base64, 'base64').toString('utf-8');
const parsed = JSON.parse(jsonStr);
console.log('[JWT] 解析成功, payload 字段:', Object.keys(parsed));
console.log('[JWT] payload 内容:', JSON.stringify(parsed));
return parsed;
} catch (error) {
console.error('[JWT] 解析失败:', error);
return null;
}
}
/**
* 从 JWT token 中获取用户ID
* @param token JWT token
* @returns 用户ID字符串获取失败返回 null
*/
export function getUserIdFromToken(token: string): string | null {
const payload = parseJwtPayload(token);
if (!payload) {
return null;
}
// 支持多种字段名user_id, userId, sub
if (payload.user_id !== undefined) {
return String(payload.user_id);
}
if (payload.userId !== undefined) {
return String(payload.userId);
}
if (payload.sub !== undefined) {
return String(payload.sub);
}
console.warn('[JWT] payload 中没有 user_id, userId 或 sub 字段');
return null;
}