feat: 实现试用用户欢迎引导和过期检测功能
- 新增试用用户首次登录欢迎弹窗,展示使用教程 - 新增试用期过期检测服务和过期提醒弹窗 - 从 JWT token 中提取 ispluginTrial 标识判断用户类型 - 试用用户跳过邀请码验证流程 - 在消息发送前检查试用期是否过期 - 新增 ExpiredPanel 和 WelcomePanel 面板组件 - 新增 expiredModal 和 welcomeModal 视图组件 - 优化用户登录流程,根据用户类型显示不同引导
This commit is contained in:
@ -9,6 +9,8 @@ import * as vscode from 'vscode';
|
||||
import { getStrangeLoopApiUrl, getConfig } from '../config/settings';
|
||||
import type { UserInfoResponse, MembershipResponse, MultiMembershipVO, MembershipItemVO } from '../types/api';
|
||||
import { fetchBalanceWithToken, getCachedBalance } from './creditsService';
|
||||
import { getIsPluginTrialFromToken } from '../utils/jwtUtils';
|
||||
// 移除 WelcomePanel 导入,改用消息通知方式
|
||||
|
||||
/**
|
||||
* HTTP 请求选项
|
||||
@ -117,6 +119,10 @@ export interface UserInfo {
|
||||
};
|
||||
// Credits 余额
|
||||
credits?: number;
|
||||
// 插件试用用户标识(从 JWT token 中提取)
|
||||
isPluginTrial?: boolean;
|
||||
// 试用到期时间(毫秒时间戳)
|
||||
pluginTrialExpiresAt?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -226,6 +232,10 @@ export async function onTokenReceived(token: string): Promise<UserInfo | null> {
|
||||
try {
|
||||
console.log('[UserService] Token 已获取,正在获取用户信息、会员信息和余额...');
|
||||
|
||||
// 从 token 中提取 ispluginTrial 标识
|
||||
const isPluginTrial = getIsPluginTrialFromToken(token);
|
||||
console.log('[UserService] 从 token 中提取 ispluginTrial:', isPluginTrial);
|
||||
|
||||
// 并行获取用户信息、会员信息和余额
|
||||
const [userInfo, membershipInfo, credits] = await Promise.all([
|
||||
getUserInfo(token),
|
||||
@ -238,6 +248,12 @@ export async function onTokenReceived(token: string): Promise<UserInfo | null> {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 将 token 中的 ispluginTrial 标识添加到用户信息
|
||||
if (isPluginTrial !== null) {
|
||||
userInfo.isPluginTrial = isPluginTrial;
|
||||
console.log('[UserService] 已将 ispluginTrial 添加到用户信息:', isPluginTrial);
|
||||
}
|
||||
|
||||
// 添加 Credits 余额到用户信息
|
||||
console.log('[UserService] 获取到的 Credits 余额:', credits);
|
||||
if (credits !== null) {
|
||||
@ -313,6 +329,34 @@ export async function onTokenReceived(token: string): Promise<UserInfo | null> {
|
||||
// 保存到持久化存储
|
||||
await saveUserInfo(userInfo);
|
||||
|
||||
// 判断是否是插件试用用户
|
||||
console.log('[UserService] 检查用户类型,isPluginTrial:', userInfo.isPluginTrial);
|
||||
console.log('[UserService] extensionContext 是否存在:', !!extensionContext);
|
||||
|
||||
if (userInfo.isPluginTrial === true) {
|
||||
// 插件试用用户:标记需要显示欢迎弹窗
|
||||
const hasWelcomed = extensionContext?.globalState.get('pluginTrialWelcomed');
|
||||
console.log('[UserService] 是否已显示过欢迎弹窗:', hasWelcomed);
|
||||
|
||||
if (!hasWelcomed && extensionContext) {
|
||||
// 设置标记,让聊天面板显示欢迎弹窗
|
||||
await extensionContext.globalState.update('showWelcomeModal', true);
|
||||
await extensionContext.globalState.update('pluginTrialWelcomed', true);
|
||||
console.log('[UserService] ✅ 已设置欢迎弹窗标记 showWelcomeModal=true');
|
||||
|
||||
// 验证标记是否设置成功
|
||||
const checkMark = extensionContext.globalState.get('showWelcomeModal');
|
||||
console.log('[UserService] 验证标记:', checkMark);
|
||||
} else if (!extensionContext) {
|
||||
console.error('[UserService] ❌ extensionContext 为 null,无法设置标记');
|
||||
} else {
|
||||
console.log('[UserService] 已经显示过欢迎弹窗,跳过');
|
||||
}
|
||||
} else {
|
||||
// 正式用户:显示邀请码弹窗(现有逻辑)
|
||||
console.log('[UserService] 正式用户登录,将在面板中检查邀请码');
|
||||
}
|
||||
|
||||
return userInfo;
|
||||
} catch (error) {
|
||||
console.error('[UserService] 获取用户信息失败:', error);
|
||||
|
||||
Reference in New Issue
Block a user