Compare commits
15 Commits
4b2da8244f
...
21a8abd5cf
| Author | SHA1 | Date | |
|---|---|---|---|
| 21a8abd5cf | |||
| 58113fb109 | |||
| 25966bc1e2 | |||
| 3c93c07afd | |||
| 85a37b546c | |||
| 341b6540fa | |||
| 1d074e5a94 | |||
| 43189e144a | |||
| d08f9a7366 | |||
| faa7b63aee | |||
| e440dd2773 | |||
| a3fd5df8e8 | |||
| d44b316c9a | |||
| 939768986c | |||
| 1e99f3cb20 |
@ -1,29 +0,0 @@
|
|||||||
# 排除开发文件
|
|
||||||
.vscode/**
|
|
||||||
.git/**
|
|
||||||
.gitignore
|
|
||||||
node_modules/**
|
|
||||||
src/**
|
|
||||||
**/*.ts
|
|
||||||
**/*.map
|
|
||||||
|
|
||||||
# 排除测试文件
|
|
||||||
test/**
|
|
||||||
**/*.test.js
|
|
||||||
|
|
||||||
# 排除文档
|
|
||||||
*.md
|
|
||||||
!README.md
|
|
||||||
|
|
||||||
# 排除 waveform_trace Python 源码(只保留 exe)
|
|
||||||
tools/waveform_trace/src/**
|
|
||||||
tools/waveform_trace/build/**
|
|
||||||
tools/waveform_trace/dist/**
|
|
||||||
tools/waveform_trace/build.bat
|
|
||||||
tools/waveform_trace/build.sh
|
|
||||||
|
|
||||||
# 排除打包临时文件
|
|
||||||
**/__pycache__/**
|
|
||||||
**/*.pyc
|
|
||||||
**/*.pyo
|
|
||||||
**/*.spec
|
|
||||||
@ -180,3 +180,8 @@ export const userQuestionIconSvg = `<svg t="1767869230062" class="icon" viewBox=
|
|||||||
* 用户头像图标 SVG
|
* 用户头像图标 SVG
|
||||||
*/
|
*/
|
||||||
export const userAvatarIconSvg = `<svg t="1767947405083" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4661" width="16" height="16"><path d="M515.541449 7.082899c-280.359429 0-508.458551 228.120391-508.458551 508.458551s228.120391 508.458551 508.458551 508.458551 508.458551-228.120391 508.458551-508.458551S795.900879 7.082899 515.541449 7.082899zM515.541449 981.864196c-257.132626 0-466.301477-209.190121-466.301477-466.322747 0-257.132626 209.168851-466.322747 466.301477-466.322747s466.301477 209.190121 466.301477 466.322747S772.674075 981.864196 515.541449 981.864196zM614.574414 524.177056 614.574414 524.177056c47.751075-31.96876 79.230625-86.398604 79.230625-148.187857 0-98.437405-79.804915-178.24232-178.24232-178.24232-98.437405 0-178.24232 79.804915-178.24232 178.24232 0 61.810523 31.479551 116.219097 79.251895 148.187857-100.266622 39.519598-171.244501 137.170014-171.244501 251.453545 0 0.23397 0 0.446669 0.02127 0.659369 0 0.04254-0.02127 0.10635-0.02127 0.14889 0 15.612155 12.65563 28.246516 28.267786 28.246516 15.590885 0 21.886796-12.63436 21.886796-28.246516 0-0.340319-0.08508-0.659369-0.10635-1.020958 0.10635-118.005774 102.159649-219.995264 220.207964-219.995264 118.112124 0 220.207964 102.095839 220.207964 220.207964 0 0.14889-1.467628 29.054774 21.971875 29.054774 15.505806 0 28.076356-12.57055 28.076356-28.055086 0-0.06381-0.02127-0.12762-0.02127-0.2127 0-0.25524 0.02127-0.510479 0.02127-0.786989C785.797645 661.34707 714.798496 563.696654 614.574414 524.177056zM515.541449 510.734437c-74.402343 0-134.723968-60.321625-134.723968-134.723968 0-74.423613 60.321625-134.723968 134.723968-134.723968 74.423613 0 134.723968 60.321625 134.723968 134.723968S589.943792 510.734437 515.541449 510.734437z" fill="currentColor" p-id="4662"></path></svg>`;
|
export const userAvatarIconSvg = `<svg t="1767947405083" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4661" width="16" height="16"><path d="M515.541449 7.082899c-280.359429 0-508.458551 228.120391-508.458551 508.458551s228.120391 508.458551 508.458551 508.458551 508.458551-228.120391 508.458551-508.458551S795.900879 7.082899 515.541449 7.082899zM515.541449 981.864196c-257.132626 0-466.301477-209.190121-466.301477-466.322747 0-257.132626 209.168851-466.322747 466.301477-466.322747s466.301477 209.190121 466.301477 466.322747S772.674075 981.864196 515.541449 981.864196zM614.574414 524.177056 614.574414 524.177056c47.751075-31.96876 79.230625-86.398604 79.230625-148.187857 0-98.437405-79.804915-178.24232-178.24232-178.24232-98.437405 0-178.24232 79.804915-178.24232 178.24232 0 61.810523 31.479551 116.219097 79.251895 148.187857-100.266622 39.519598-171.244501 137.170014-171.244501 251.453545 0 0.23397 0 0.446669 0.02127 0.659369 0 0.04254-0.02127 0.10635-0.02127 0.14889 0 15.612155 12.65563 28.246516 28.267786 28.246516 15.590885 0 21.886796-12.63436 21.886796-28.246516 0-0.340319-0.08508-0.659369-0.10635-1.020958 0.10635-118.005774 102.159649-219.995264 220.207964-219.995264 118.112124 0 220.207964 102.095839 220.207964 220.207964 0 0.14889-1.467628 29.054774 21.971875 29.054774 15.505806 0 28.076356-12.57055 28.076356-28.055086 0-0.06381-0.02127-0.12762-0.02127-0.2127 0-0.25524 0.02127-0.510479 0.02127-0.786989C785.797645 661.34707 714.798496 563.696654 614.574414 524.177056zM515.541449 510.734437c-74.402343 0-134.723968-60.321625-134.723968-134.723968 0-74.423613 60.321625-134.723968 134.723968-134.723968 74.423613 0 134.723968 60.321625 134.723968 134.723968S589.943792 510.734437 515.541449 510.734437z" fill="currentColor" p-id="4662"></path></svg>`;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新阶段图标 SVG
|
||||||
|
*/
|
||||||
|
export const updateStageIconSvg = `<svg t="1768188846282" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7848" width="14" height="14"><path d="M83.712 1024c-0.256 0-0.768 0-1.024-0.256-17.408-0.512-31.488-14.848-31.488-32.512V32.512C51.2 14.592 65.792 0 83.712 0h745.472c17.92 0 32.512 14.592 32.512 32.512v280.576c0 18.432-14.592 33.28-32.512 33.28-1.536 0-3.072 0-4.608-0.256-16.128-2.304-27.648-15.872-27.648-32V77.056c0-6.912-5.632-12.288-12.288-12.288H128.256c-6.912 0-12.288 5.632-12.288 12.288v869.632c0 6.912 5.632 12.288 12.288 12.288h238.08c9.728 0 18.944 4.096 25.344 11.52 6.144 7.168 8.96 16.384 7.68 25.6-2.304 16.128-15.872 27.648-32 27.648H83.712v0.256zM534.784 1024c-6.144 0-12.032-2.816-15.616-7.424-3.84-4.352-5.376-10.496-4.352-16.64l27.648-147.968c0-0.512 0.512-1.024 0.768-1.536L867.84 558.336c11.52-11.264 26.624-17.664 42.24-17.664 16.384 0 31.488 6.4 42.752 17.664l53.76 53.504c23.296 23.04 23.552 60.928 0.768 84.736l-0.768 0.768-323.584 294.912c-2.816 2.56-6.4 4.352-9.984 5.12l-134.656 26.368c-0.512 0-2.048 0.256-3.584 0.256z m95.488-182.528c-1.024 0-1.792 0.256-2.56 1.024L590.848 875.52c-0.512 0.512-1.024 1.28-1.28 2.048l-15.104 81.152c-0.256 1.792 0.768 3.072 0.768 3.072 0.768 0.768 1.792 1.28 2.816 1.28H578.816l73.984-14.336c0.768-0.256 1.28-0.512 1.792-0.768l38.4-34.816c0.768-0.768 1.024-1.536 1.024-2.56s-0.256-2.304-1.024-3.072l-60.416-64.768-0.256-0.256c0-0.512-1.024-1.024-2.048-1.024z m217.088-194.56c-1.024 0-1.792 0.256-2.56 1.024l-172.8 155.392c-0.768 0.768-1.28 1.536-1.28 2.816 0 1.024 0.256 2.048 1.024 2.56l60.16 64.768c0.768 0.768 1.792 1.28 2.816 1.28s1.792-0.256 2.56-1.024l173.568-157.952c0.768-0.768 1.024-1.536 1.024-2.56s-0.256-2.048-1.28-3.072L849.92 647.936c-0.512-0.256-1.536-1.024-2.56-1.024z m101.376 28.928c0.768 0.768 1.536 1.024 2.816 1.024 1.024 0 1.792-0.256 2.56-1.024l16.384-14.848 0.512-0.512c3.072-3.584 2.816-8.704-0.512-12.032L916.48 594.944c-1.536-1.536-4.096-2.56-6.144-2.56-2.56 0-4.864 1.024-6.4 2.56-0.256 0.256-0.512 0.512-0.768 0.512l-17.664 15.872 63.232 64.512z" p-id="7849" fill="#8a8a8a"></path><path d="M212.48 419.584h118.016v39.424H212.48v-39.424z m137.472-118.016h118.016v39.424h-118.016v-39.424z m137.728-118.016h196.608v39.424h-196.608V183.552z m0 0" fill="#8a8a8a" p-id="7850"></path><path d="M664.576 242.688h-157.184c-11.776 0-19.712 7.936-19.712 19.712v98.304h-118.016c-11.776 0-19.712 7.936-19.712 19.712V478.72h-117.76c-11.776 0-19.712 7.936-19.712 19.712v118.016c0 11.776 7.936 19.712 19.712 19.712h432.384c11.776 0 19.712-7.936 19.712-19.712V262.144c-0.256-11.776-7.936-19.456-19.712-19.456zM369.664 576.768h-117.76v-39.424h118.016v39.424z m137.728-118.016h-118.016v-39.424h118.016v39.424z m137.472-117.76h-118.016v-39.424h118.016v39.424z m0 0" fill="#8a8a8a" p-id="7851"></path></svg>`;
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import { ChatHistoryManager } from "./utils/chatHistoryManager";
|
|||||||
import { ICCoderAuthenticationProvider } from "./services/icCoderAuthProvider";
|
import { ICCoderAuthenticationProvider } from "./services/icCoderAuthProvider";
|
||||||
import { VCDFileServer } from "./services/vcdFileServer";
|
import { VCDFileServer } from "./services/vcdFileServer";
|
||||||
import { initUserService } from "./services/userService";
|
import { initUserService } from "./services/userService";
|
||||||
|
import { initCreditsService } from "./services/creditsService";
|
||||||
|
|
||||||
export function activate(context: vscode.ExtensionContext) {
|
export function activate(context: vscode.ExtensionContext) {
|
||||||
console.log("🎉 IC Coder 插件已激活!");
|
console.log("🎉 IC Coder 插件已激活!");
|
||||||
@ -13,6 +14,9 @@ export function activate(context: vscode.ExtensionContext) {
|
|||||||
// 初始化用户服务
|
// 初始化用户服务
|
||||||
initUserService(context);
|
initUserService(context);
|
||||||
|
|
||||||
|
// 初始化 Credits 服务
|
||||||
|
initCreditsService(context);
|
||||||
|
|
||||||
// 初始化 VCD 文件服务器
|
// 初始化 VCD 文件服务器
|
||||||
const vcdFileServer = new VCDFileServer(context.extensionUri);
|
const vcdFileServer = new VCDFileServer(context.extensionUri);
|
||||||
vcdFileServer.start().then((port) => {
|
vcdFileServer.start().then((port) => {
|
||||||
|
|||||||
@ -147,16 +147,20 @@ export async function showICHelperPanel(
|
|||||||
if (userInfo) {
|
if (userInfo) {
|
||||||
// 使用缓存的用户信息
|
// 使用缓存的用户信息
|
||||||
console.log('[ICHelperPanel] 使用缓存的用户信息:', userInfo);
|
console.log('[ICHelperPanel] 使用缓存的用户信息:', userInfo);
|
||||||
|
console.log('[ICHelperPanel] Credits 余额:', userInfo.credits);
|
||||||
const tierIconUrl = getTierIconUri(panel.webview, context, userInfo.membership?.tierCode);
|
const tierIconUrl = getTierIconUri(panel.webview, context, userInfo.membership?.tierCode);
|
||||||
panel.webview.postMessage({
|
const messageData = {
|
||||||
command: 'updateUserInfo',
|
command: 'updateUserInfo',
|
||||||
userInfo: {
|
userInfo: {
|
||||||
userId: userInfo.userId,
|
userId: userInfo.userId,
|
||||||
nickname: userInfo.nickname,
|
nickname: userInfo.nickname,
|
||||||
username: userInfo.username
|
username: userInfo.username,
|
||||||
|
credits: userInfo.credits
|
||||||
},
|
},
|
||||||
tierIconUrl: tierIconUrl
|
tierIconUrl: tierIconUrl
|
||||||
});
|
};
|
||||||
|
console.log('[ICHelperPanel] 发送用户信息到前端:', messageData);
|
||||||
|
panel.webview.postMessage(messageData);
|
||||||
} else {
|
} else {
|
||||||
// 如果没有缓存,从 session 中获取
|
// 如果没有缓存,从 session 中获取
|
||||||
const session = await vscode.authentication.getSession("iccoder", [], {
|
const session = await vscode.authentication.getSession("iccoder", [], {
|
||||||
|
|||||||
@ -22,6 +22,33 @@ let lastUpdateTime: number = 0;
|
|||||||
/** 缓存有效期(5分钟) */
|
/** 缓存有效期(5分钟) */
|
||||||
const CACHE_TTL_MS = 5 * 60 * 1000;
|
const CACHE_TTL_MS = 5 * 60 * 1000;
|
||||||
|
|
||||||
|
/** ExtensionContext 用于持久化存储 */
|
||||||
|
let extensionContext: vscode.ExtensionContext | null = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化 Credits 服务(设置 context)
|
||||||
|
*/
|
||||||
|
export function initCreditsService(context: vscode.ExtensionContext): void {
|
||||||
|
extensionContext = context;
|
||||||
|
// 从持久化存储加载余额
|
||||||
|
const savedBalance = extensionContext.globalState.get<number>('icCoderCreditsBalance');
|
||||||
|
if (savedBalance !== undefined) {
|
||||||
|
cachedBalance = savedBalance;
|
||||||
|
lastUpdateTime = Date.now();
|
||||||
|
console.log('[CreditsService] 从持久化存储加载余额:', savedBalance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存余额到持久化存储
|
||||||
|
*/
|
||||||
|
async function saveBalance(balance: number): Promise<void> {
|
||||||
|
if (extensionContext) {
|
||||||
|
await extensionContext.globalState.update('icCoderCreditsBalance', balance);
|
||||||
|
console.log('[CreditsService] 余额已保存到持久化存储:', balance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新缓存的余额(从 SSE credit_update 事件调用)
|
* 更新缓存的余额(从 SSE credit_update 事件调用)
|
||||||
*/
|
*/
|
||||||
@ -29,6 +56,10 @@ export function updateCachedBalance(balance: number): void {
|
|||||||
cachedBalance = balance;
|
cachedBalance = balance;
|
||||||
lastUpdateTime = Date.now();
|
lastUpdateTime = Date.now();
|
||||||
console.log('[CreditsService] 余额已更新:', balance);
|
console.log('[CreditsService] 余额已更新:', balance);
|
||||||
|
// 异步保存到持久化存储
|
||||||
|
saveBalance(balance).catch(err => {
|
||||||
|
console.error('[CreditsService] 保存余额失败:', err);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -203,8 +234,11 @@ export async function checkBalanceBeforeSend(): Promise<{
|
|||||||
/**
|
/**
|
||||||
* 清除缓存(登出时调用)
|
* 清除缓存(登出时调用)
|
||||||
*/
|
*/
|
||||||
export function clearBalanceCache(): void {
|
export async function clearBalanceCache(): Promise<void> {
|
||||||
cachedBalance = null;
|
cachedBalance = null;
|
||||||
lastUpdateTime = 0;
|
lastUpdateTime = 0;
|
||||||
|
if (extensionContext) {
|
||||||
|
await extensionContext.globalState.update('icCoderCreditsBalance', undefined);
|
||||||
|
}
|
||||||
console.log('[CreditsService] 余额缓存已清除');
|
console.log('[CreditsService] 余额缓存已清除');
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import { URL } from 'url';
|
|||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
import { getStrangeLoopApiUrl, getConfig } from '../config/settings';
|
import { getStrangeLoopApiUrl, getConfig } from '../config/settings';
|
||||||
import type { UserInfoResponse, MembershipResponse, MultiMembershipVO, MembershipItemVO } from '../types/api';
|
import type { UserInfoResponse, MembershipResponse, MultiMembershipVO, MembershipItemVO } from '../types/api';
|
||||||
|
import { fetchBalance, getCachedBalance } from './creditsService';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* HTTP 请求选项
|
* HTTP 请求选项
|
||||||
@ -114,6 +115,8 @@ export interface UserInfo {
|
|||||||
remainingDays?: number;
|
remainingDays?: number;
|
||||||
monthlyCredits?: number;
|
monthlyCredits?: number;
|
||||||
};
|
};
|
||||||
|
// Credits 余额
|
||||||
|
credits?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -221,12 +224,13 @@ function getHighestTierMembership(allMemberships?: MembershipItemVO[]): Membersh
|
|||||||
*/
|
*/
|
||||||
export async function onTokenReceived(token: string): Promise<UserInfo | null> {
|
export async function onTokenReceived(token: string): Promise<UserInfo | null> {
|
||||||
try {
|
try {
|
||||||
console.log('[UserService] Token 已获取,正在获取用户信息和会员信息...');
|
console.log('[UserService] Token 已获取,正在获取用户信息、会员信息和余额...');
|
||||||
|
|
||||||
// 并行获取用户信息和会员信息
|
// 并行获取用户信息、会员信息和余额
|
||||||
const [userInfo, membershipInfo] = await Promise.all([
|
const [userInfo, membershipInfo, credits] = await Promise.all([
|
||||||
getUserInfo(token),
|
getUserInfo(token),
|
||||||
getMembershipInfo(token)
|
getMembershipInfo(token),
|
||||||
|
fetchBalance()
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (!userInfo) {
|
if (!userInfo) {
|
||||||
@ -234,6 +238,15 @@ export async function onTokenReceived(token: string): Promise<UserInfo | null> {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 添加 Credits 余额到用户信息
|
||||||
|
console.log('[UserService] 获取到的 Credits 余额:', credits);
|
||||||
|
if (credits !== null) {
|
||||||
|
userInfo.credits = credits;
|
||||||
|
console.log('[UserService] Credits 已添加到用户信息');
|
||||||
|
} else {
|
||||||
|
console.warn('[UserService] Credits 余额为 null,未添加到用户信息');
|
||||||
|
}
|
||||||
|
|
||||||
// 打印用户信息到控制台
|
// 打印用户信息到控制台
|
||||||
console.log('='.repeat(60));
|
console.log('='.repeat(60));
|
||||||
console.log('用户信息详情:');
|
console.log('用户信息详情:');
|
||||||
@ -286,6 +299,15 @@ export async function onTokenReceived(token: string): Promise<UserInfo | null> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 打印 Credits 余额
|
||||||
|
console.log('');
|
||||||
|
console.log('资源点余额:');
|
||||||
|
if (userInfo.credits !== undefined) {
|
||||||
|
console.log(`当前余额: ${userInfo.credits} Credits`);
|
||||||
|
} else {
|
||||||
|
console.log('当前余额: 未获取到余额信息');
|
||||||
|
}
|
||||||
|
|
||||||
console.log('='.repeat(60));
|
console.log('='.repeat(60));
|
||||||
|
|
||||||
// 保存到持久化存储
|
// 保存到持久化存储
|
||||||
@ -329,7 +351,18 @@ export function getCachedUserInfo(): UserInfo | null {
|
|||||||
console.warn('[UserService] ExtensionContext 未初始化');
|
console.warn('[UserService] ExtensionContext 未初始化');
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return extensionContext.globalState.get<UserInfo>('icCoderUserInfo') || null;
|
const userInfo = extensionContext.globalState.get<UserInfo>('icCoderUserInfo') || null;
|
||||||
|
|
||||||
|
// 从 creditsService 加载余额并合并到用户信息中
|
||||||
|
if (userInfo) {
|
||||||
|
const cachedCredits = getCachedBalance();
|
||||||
|
if (cachedCredits !== null) {
|
||||||
|
userInfo.credits = cachedCredits;
|
||||||
|
console.log('[UserService] 从 creditsService 加载余额:', cachedCredits);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return userInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -18,7 +18,10 @@ import { ChatHistoryManager } from "./chatHistoryManager";
|
|||||||
import { dialogManager, DialogSession } from "../services/dialogService";
|
import { dialogManager, DialogSession } from "../services/dialogService";
|
||||||
import { userInteractionManager } from "../services/userInteraction";
|
import { userInteractionManager } from "../services/userInteraction";
|
||||||
import { healthCheck } from "../services/apiClient";
|
import { healthCheck } from "../services/apiClient";
|
||||||
import { checkBalanceBeforeSend } from "../services/creditsService";
|
import {
|
||||||
|
checkBalanceBeforeSend,
|
||||||
|
fetchBalance,
|
||||||
|
} from "../services/creditsService";
|
||||||
|
|
||||||
import type { RunMode, ServiceTier } from "../types/api";
|
import type { RunMode, ServiceTier } from "../types/api";
|
||||||
|
|
||||||
@ -78,7 +81,9 @@ export async function handleUserMessage(
|
|||||||
"去充值"
|
"去充值"
|
||||||
);
|
);
|
||||||
if (selection === "去充值") {
|
if (selection === "去充值") {
|
||||||
vscode.env.openExternal(vscode.Uri.parse("https://iccoder.com/recharge"));
|
vscode.env.openExternal(
|
||||||
|
vscode.Uri.parse("https://iccoder.com/memberCenter")
|
||||||
|
);
|
||||||
}
|
}
|
||||||
// 恢复输入状态
|
// 恢复输入状态
|
||||||
panel.webview.postMessage({
|
panel.webview.postMessage({
|
||||||
@ -92,7 +97,14 @@ export async function handleUserMessage(
|
|||||||
// 尝试使用后端服务
|
// 尝试使用后端服务
|
||||||
if (useBackendService && extensionPath) {
|
if (useBackendService && extensionPath) {
|
||||||
try {
|
try {
|
||||||
await handleUserMessageWithBackend(panel, text, extensionPath, mode, undefined, serviceTier);
|
await handleUserMessageWithBackend(
|
||||||
|
panel,
|
||||||
|
text,
|
||||||
|
extensionPath,
|
||||||
|
mode,
|
||||||
|
undefined,
|
||||||
|
serviceTier
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("后端服务不可用:", error);
|
console.error("后端服务不可用:", error);
|
||||||
@ -137,10 +149,18 @@ async function handleUserMessageWithBackend(
|
|||||||
const taskIdToUse = reuseTaskId || historyManager.getCurrentTaskId();
|
const taskIdToUse = reuseTaskId || historyManager.getCurrentTaskId();
|
||||||
|
|
||||||
// 创建会话(dialogManager 会自动处理旧会话的中止)
|
// 创建会话(dialogManager 会自动处理旧会话的中止)
|
||||||
currentSession = dialogManager.createSession(extensionPath, taskIdToUse || undefined);
|
currentSession = dialogManager.createSession(
|
||||||
|
extensionPath,
|
||||||
|
taskIdToUse || undefined
|
||||||
|
);
|
||||||
// 保存 taskId 用于后续操作(如压缩)
|
// 保存 taskId 用于后续操作(如压缩)
|
||||||
lastTaskId = currentSession.getTaskId();
|
lastTaskId = currentSession.getTaskId();
|
||||||
console.log("[MessageHandler] 创建会话: taskId=", lastTaskId, "来源=", taskIdToUse ? "historyManager" : "新生成");
|
console.log(
|
||||||
|
"[MessageHandler] 创建会话: taskId=",
|
||||||
|
lastTaskId,
|
||||||
|
"来源=",
|
||||||
|
taskIdToUse ? "historyManager" : "新生成"
|
||||||
|
);
|
||||||
|
|
||||||
// 显示状态栏
|
// 显示状态栏
|
||||||
panel.webview.postMessage({
|
panel.webview.postMessage({
|
||||||
@ -200,6 +220,17 @@ async function handleUserMessageWithBackend(
|
|||||||
// 最后一次发送完整的段落
|
// 最后一次发送完整的段落
|
||||||
console.log("[MessageHandler] 对话完成, 段落数:", segments.length);
|
console.log("[MessageHandler] 对话完成, 段落数:", segments.length);
|
||||||
|
|
||||||
|
// 对话完成后重新获取余额(因为已经消耗了 Credits)
|
||||||
|
try {
|
||||||
|
console.log("[MessageHandler] 对话完成,重新获取余额...");
|
||||||
|
const newBalance = await fetchBalance();
|
||||||
|
if (newBalance !== null) {
|
||||||
|
console.log("[MessageHandler] 余额已更新:", newBalance);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("[MessageHandler] 获取余额失败:", error);
|
||||||
|
}
|
||||||
|
|
||||||
const result = await panel.webview.postMessage({
|
const result = await panel.webview.postMessage({
|
||||||
command: "updateSegments",
|
command: "updateSegments",
|
||||||
segments: segments,
|
segments: segments,
|
||||||
@ -369,7 +400,14 @@ export async function handlePlanAction(
|
|||||||
extensionPath: string,
|
extensionPath: string,
|
||||||
serviceTier?: ServiceTier
|
serviceTier?: ServiceTier
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
console.log("[handlePlanAction] action:", action, "planTitle:", planTitle, "serviceTier:", serviceTier);
|
console.log(
|
||||||
|
"[handlePlanAction] action:",
|
||||||
|
action,
|
||||||
|
"planTitle:",
|
||||||
|
planTitle,
|
||||||
|
"serviceTier:",
|
||||||
|
serviceTier
|
||||||
|
);
|
||||||
|
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case "confirm":
|
case "confirm":
|
||||||
|
|||||||
@ -14,9 +14,7 @@ export function getContextButtonContent(): string {
|
|||||||
<path d="M469.333333 469.333333V170.666667h85.333334v298.666666h298.666666v85.333334h-298.666666v298.666666h-85.333334v-298.666666H170.666667v-85.333334h298.666666z" fill="#8a8a8a" p-id="4995"></path>
|
<path d="M469.333333 469.333333V170.666667h85.333334v298.666666h298.666666v85.333334h-298.666666v298.666666h-85.333334v-298.666666H170.666667v-85.333334h298.666666z" fill="#8a8a8a" p-id="4995"></path>
|
||||||
</svg>
|
</svg>
|
||||||
<span class="add-context-label">添加上下文</span>
|
<span class="add-context-label">添加上下文</span>
|
||||||
<svg class="dropdown-arrow" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path d="M512 714.666667L213.333333 416l42.666667-42.666667L512 629.333333l256-256 42.666667 42.666667z" fill="currentColor"/>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
<span class="tooltiptext">添加文件、文件夹、图片或文档作为上下文</span>
|
<span class="tooltiptext">添加文件、文件夹、图片或文档作为上下文</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
216
src/views/exampleShowcase.ts
Normal file
216
src/views/exampleShowcase.ts
Normal file
@ -0,0 +1,216 @@
|
|||||||
|
/**
|
||||||
|
* 获取展示区域的 HTML 内容
|
||||||
|
*/
|
||||||
|
export function getExampleShowcaseContent(): string {
|
||||||
|
return `
|
||||||
|
<div class="example-showcase" id="exampleShowcase">
|
||||||
|
<div class="showcase-title">展示</div>
|
||||||
|
<div class="example-cards">
|
||||||
|
<div class="example-card" onclick="fillExample(0)">
|
||||||
|
<div class="example-icon">📝</div>
|
||||||
|
<div class="example-content">
|
||||||
|
<div class="example-title">代码生成</div>
|
||||||
|
<div class="example-desc">生成一个 8 位全加器的 Verilog 代码</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="example-card" onclick="fillExample(1)">
|
||||||
|
<div class="example-icon">🔍</div>
|
||||||
|
<div class="example-content">
|
||||||
|
<div class="example-title">代码分析</div>
|
||||||
|
<div class="example-desc">分析当前项目中的时序逻辑设计</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="web-link">
|
||||||
|
<a href="https://iccoder.com" target="_blank" class="web-link-button">
|
||||||
|
<span class="link-icon">🌐</span>
|
||||||
|
<span>IC Coder Web端</span>
|
||||||
|
<span class="link-arrow">→</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取展示区域的样式
|
||||||
|
*/
|
||||||
|
export function getExampleShowcaseStyles(): string {
|
||||||
|
return `
|
||||||
|
.example-showcase {
|
||||||
|
margin-top: 24px;
|
||||||
|
padding: 0;
|
||||||
|
opacity: 1;
|
||||||
|
transition: opacity 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.example-showcase.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.showcase-title {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--vscode-foreground);
|
||||||
|
margin-bottom: 12px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.example-cards {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
gap: 12px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.example-card {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
background: var(--vscode-input-background);
|
||||||
|
border: 1px solid var(--vscode-input-border);
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 14px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.example-card:hover {
|
||||||
|
border-color: var(--vscode-focusBorder);
|
||||||
|
background: var(--vscode-list-hoverBackground);
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.example-icon {
|
||||||
|
font-size: 28px;
|
||||||
|
line-height: 1;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.example-content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 4px;
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.example-title {
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--vscode-foreground);
|
||||||
|
}
|
||||||
|
|
||||||
|
.example-desc {
|
||||||
|
font-size: 11px;
|
||||||
|
color: var(--vscode-descriptionForeground);
|
||||||
|
line-height: 1.4;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
}
|
||||||
|
|
||||||
|
.web-link {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
padding-top: 20px;
|
||||||
|
border-top: 1px solid var(--vscode-panel-border);
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.web-link-button {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
padding: 10px 20px;
|
||||||
|
background: transparent;
|
||||||
|
border: none;
|
||||||
|
text-decoration: none;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 600;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 50%, #a855f7 100%);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
background-clip: text;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.web-link-button:focus {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.web-link-button:hover {
|
||||||
|
transform: translateY(-1px);
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link-icon {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link-arrow {
|
||||||
|
font-size: 16px;
|
||||||
|
transition: transform 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.web-link-button:hover .link-arrow {
|
||||||
|
transform: translateX(3px);
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取展示区域的脚本
|
||||||
|
*/
|
||||||
|
export function getExampleShowcaseScript(): string {
|
||||||
|
return `
|
||||||
|
// 示例文本数组
|
||||||
|
const exampleTexts = [
|
||||||
|
'生成一个 8 位全加器的 Verilog 代码',
|
||||||
|
'分析当前项目中的时序逻辑设计'
|
||||||
|
];
|
||||||
|
|
||||||
|
// 填充示例到输入框
|
||||||
|
function fillExample(index) {
|
||||||
|
const messageInput = document.getElementById('messageInput');
|
||||||
|
if (messageInput && exampleTexts[index]) {
|
||||||
|
messageInput.value = exampleTexts[index];
|
||||||
|
messageInput.focus();
|
||||||
|
// 触发自动调整高度
|
||||||
|
if (typeof autoResizeTextarea === 'function') {
|
||||||
|
autoResizeTextarea();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 监听消息变化,自动隐藏/显示展示区域
|
||||||
|
function updateShowcaseVisibility() {
|
||||||
|
const showcase = document.getElementById('exampleShowcase');
|
||||||
|
if (showcase) {
|
||||||
|
if (hasMessages) {
|
||||||
|
showcase.classList.add('hidden');
|
||||||
|
} else {
|
||||||
|
showcase.classList.remove('hidden');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 扩展原有的布局更新函数
|
||||||
|
const originalUpdateInputAreaLayout = updateInputAreaLayout;
|
||||||
|
updateInputAreaLayout = function() {
|
||||||
|
if (originalUpdateInputAreaLayout) {
|
||||||
|
originalUpdateInputAreaLayout();
|
||||||
|
}
|
||||||
|
updateShowcaseVisibility();
|
||||||
|
};
|
||||||
|
`;
|
||||||
|
}
|
||||||
@ -29,16 +29,21 @@ import {
|
|||||||
getOptimizeButtonStyles,
|
getOptimizeButtonStyles,
|
||||||
getOptimizeButtonScript,
|
getOptimizeButtonScript,
|
||||||
} from "./optimizeButton";
|
} from "./optimizeButton";
|
||||||
|
import {
|
||||||
|
getExampleShowcaseContent,
|
||||||
|
getExampleShowcaseStyles,
|
||||||
|
getExampleShowcaseScript,
|
||||||
|
} from "./exampleShowcase";
|
||||||
import { sendIconSvg, stopIconSvg } from "../constants/toolIcons";
|
import { sendIconSvg, stopIconSvg } from "../constants/toolIcons";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取输入区域的 HTML 内容
|
* 获取输入区域的 HTML 内容
|
||||||
*/
|
*/
|
||||||
export function getInputAreaContent(
|
export function getInputAreaContent(
|
||||||
autoIcon: string = '',
|
autoIcon: string = "",
|
||||||
liteIcon: string = '',
|
liteIcon: string = "",
|
||||||
syIcon: string = '',
|
syIcon: string = "",
|
||||||
maxIcon: string = ''
|
maxIcon: string = ""
|
||||||
): string {
|
): string {
|
||||||
return `
|
return `
|
||||||
<div class="input-area centered" id="inputArea">
|
<div class="input-area centered" id="inputArea">
|
||||||
@ -71,6 +76,8 @@ export function getInputAreaContent(
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- 展示区域:案例和 Web 端链接 -->
|
||||||
|
${getExampleShowcaseContent()}
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
@ -86,6 +93,7 @@ export function getInputAreaStyles(): string {
|
|||||||
${getContextDisplayStyles()}
|
${getContextDisplayStyles()}
|
||||||
${getContextCompressStyles()}
|
${getContextCompressStyles()}
|
||||||
${getOptimizeButtonStyles()}
|
${getOptimizeButtonStyles()}
|
||||||
|
${getExampleShowcaseStyles()}
|
||||||
.input-area {
|
.input-area {
|
||||||
border-top: 1px solid var(--vscode-panel-border);
|
border-top: 1px solid var(--vscode-panel-border);
|
||||||
padding-top: 15px;
|
padding-top: 15px;
|
||||||
@ -95,7 +103,7 @@ export function getInputAreaStyles(): string {
|
|||||||
/* 居中模式:未发起对话时 */
|
/* 居中模式:未发起对话时 */
|
||||||
.input-area.centered {
|
.input-area.centered {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 50%;
|
top: 55%;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
transform: translate(-50%, -50%);
|
transform: translate(-50%, -50%);
|
||||||
width: calc(100% - 40px);
|
width: calc(100% - 40px);
|
||||||
@ -292,6 +300,7 @@ export function getInputAreaScript(): string {
|
|||||||
${getContextDisplayScript()}
|
${getContextDisplayScript()}
|
||||||
${getContextCompressScript()}
|
${getContextCompressScript()}
|
||||||
${getOptimizeButtonScript()}
|
${getOptimizeButtonScript()}
|
||||||
|
${getExampleShowcaseScript()}
|
||||||
|
|
||||||
// 对话状态管理
|
// 对话状态管理
|
||||||
let isConversationActive = false;
|
let isConversationActive = false;
|
||||||
|
|||||||
@ -24,6 +24,7 @@ import {
|
|||||||
knowledgeLoadIconSvg,
|
knowledgeLoadIconSvg,
|
||||||
stateTransitionIconSvg,
|
stateTransitionIconSvg,
|
||||||
userQuestionIconSvg,
|
userQuestionIconSvg,
|
||||||
|
updateStageIconSvg,
|
||||||
} from "../constants/toolIcons";
|
} from "../constants/toolIcons";
|
||||||
import {
|
import {
|
||||||
getWaveformPreviewContent,
|
getWaveformPreviewContent,
|
||||||
@ -670,6 +671,7 @@ export function getMessageAreaScript(): string {
|
|||||||
const knowledgeLoadIconSvg = \`${knowledgeLoadIconSvg}\`;
|
const knowledgeLoadIconSvg = \`${knowledgeLoadIconSvg}\`;
|
||||||
const stateTransitionIconSvg = \`${stateTransitionIconSvg}\`;
|
const stateTransitionIconSvg = \`${stateTransitionIconSvg}\`;
|
||||||
const userQuestionIconSvg = \`${userQuestionIconSvg}\`;
|
const userQuestionIconSvg = \`${userQuestionIconSvg}\`;
|
||||||
|
const updateStageIconSvg = \`${updateStageIconSvg}\`;
|
||||||
|
|
||||||
${getAgentCardScript()}
|
${getAgentCardScript()}
|
||||||
|
|
||||||
@ -724,6 +726,7 @@ export function getMessageAreaScript(): string {
|
|||||||
'updateNode': fileWriteIconSvg,
|
'updateNode': fileWriteIconSvg,
|
||||||
'addStateTransition': stateTransitionIconSvg,
|
'addStateTransition': stateTransitionIconSvg,
|
||||||
'askUser': userQuestionIconSvg,
|
'askUser': userQuestionIconSvg,
|
||||||
|
'updatePhase': updateStageIconSvg,
|
||||||
};
|
};
|
||||||
return iconMap[toolName] || '';
|
return iconMap[toolName] || '';
|
||||||
}
|
}
|
||||||
@ -756,6 +759,8 @@ export function getMessageAreaScript(): string {
|
|||||||
'spawnExplorer': '代码探索',
|
'spawnExplorer': '代码探索',
|
||||||
'spawnDebugger': '波形调试',
|
'spawnDebugger': '波形调试',
|
||||||
'askUser': '用户提问',
|
'askUser': '用户提问',
|
||||||
|
'updatePhase': '已更新阶段',
|
||||||
|
'iverilog': '已完成编译',
|
||||||
};
|
};
|
||||||
return toolNameMap[toolName] || toolName;
|
return toolNameMap[toolName] || toolName;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -62,9 +62,9 @@ export function getPlanCardStyles(): string {
|
|||||||
.plan-summary p { margin: 8px 0; }
|
.plan-summary p { margin: 8px 0; }
|
||||||
.plan-summary ul, .plan-summary ol {
|
.plan-summary ul, .plan-summary ol {
|
||||||
margin: 8px 0;
|
margin: 8px 0;
|
||||||
padding-left: 24px;
|
padding-left: 0;
|
||||||
}
|
}
|
||||||
.plan-summary li { margin: 4px 0; }
|
.plan-summary li { margin: 4px 0 4px 27px; }
|
||||||
.plan-summary code {
|
.plan-summary code {
|
||||||
background: var(--vscode-textCodeBlock-background);
|
background: var(--vscode-textCodeBlock-background);
|
||||||
padding: 2px 6px;
|
padding: 2px 6px;
|
||||||
@ -403,6 +403,12 @@ export function getPlanCardScript(): string {
|
|||||||
.replace(/</g, '<')
|
.replace(/</g, '<')
|
||||||
.replace(/>/g, '>');
|
.replace(/>/g, '>');
|
||||||
|
|
||||||
|
// 标题(必须在转义之后、其他处理之前)
|
||||||
|
html = html.replace(/^#### (.+)$/gm, '<h4>$1</h4>');
|
||||||
|
html = html.replace(/^### (.+)$/gm, '<h3>$1</h3>');
|
||||||
|
html = html.replace(/^## (.+)$/gm, '<h2>$1</h2>');
|
||||||
|
html = html.replace(/^# (.+)$/gm, '<h1>$1</h1>');
|
||||||
|
|
||||||
// 代码块 (\`\`\`code\`\`\`)
|
// 代码块 (\`\`\`code\`\`\`)
|
||||||
html = html.replace(/\\x60\\x60\\x60([\\s\\S]*?)\\x60\\x60\\x60/g, '<pre><code>$1</code></pre>');
|
html = html.replace(/\\x60\\x60\\x60([\\s\\S]*?)\\x60\\x60\\x60/g, '<pre><code>$1</code></pre>');
|
||||||
|
|
||||||
@ -428,12 +434,6 @@ export function getPlanCardScript(): string {
|
|||||||
return table;
|
return table;
|
||||||
});
|
});
|
||||||
|
|
||||||
// 标题
|
|
||||||
html = html.replace(/^#### (.+)$/gm, '<h4>$1</h4>');
|
|
||||||
html = html.replace(/^### (.+)$/gm, '<h3>$1</h3>');
|
|
||||||
html = html.replace(/^## (.+)$/gm, '<h2>$1</h2>');
|
|
||||||
html = html.replace(/^# (.+)$/gm, '<h1>$1</h1>');
|
|
||||||
|
|
||||||
// 粗体和斜体
|
// 粗体和斜体
|
||||||
html = html.replace(/\\*\\*(.+?)\\*\\*/g, '<strong>$1</strong>');
|
html = html.replace(/\\*\\*(.+?)\\*\\*/g, '<strong>$1</strong>');
|
||||||
html = html.replace(/\\*(.+?)\\*/g, '<em>$1</em>');
|
html = html.replace(/\\*(.+?)\\*/g, '<em>$1</em>');
|
||||||
|
|||||||
@ -250,14 +250,27 @@ export function getUserInfoComponentScript(): string {
|
|||||||
|
|
||||||
// 更新剩余 Credits
|
// 更新剩余 Credits
|
||||||
const creditsDetail = document.getElementById('creditsDetail');
|
const creditsDetail = document.getElementById('creditsDetail');
|
||||||
|
console.log('[UserInfoComponent] 更新 Credits 显示');
|
||||||
|
console.log('[UserInfoComponent] currentUserInfo.credits:', currentUserInfo.credits);
|
||||||
|
console.log('[UserInfoComponent] creditsDetail 元素:', creditsDetail);
|
||||||
if (creditsDetail) {
|
if (creditsDetail) {
|
||||||
creditsDetail.textContent = currentUserInfo.credits !== undefined ? currentUserInfo.credits.toString() : '-';
|
const creditsText = currentUserInfo.credits !== undefined ? currentUserInfo.credits.toString() : '-';
|
||||||
|
creditsDetail.textContent = creditsText;
|
||||||
|
console.log('[UserInfoComponent] Credits 已更新为:', creditsText);
|
||||||
|
} else {
|
||||||
|
console.warn('[UserInfoComponent] creditsDetail 元素未找到');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新用户信息显示
|
// 更新用户信息显示
|
||||||
function updateUserInfoDisplay(userInfo) {
|
function updateUserInfoDisplay(userInfo) {
|
||||||
currentUserInfo = userInfo;
|
currentUserInfo = userInfo;
|
||||||
|
console.log('[UserInfoComponent] 更新用户信息:', userInfo);
|
||||||
|
// 如果下拉面板已打开,立即更新显示
|
||||||
|
const dropdown = document.getElementById('userDetailDropdown');
|
||||||
|
if (dropdown && dropdown.classList.contains('active')) {
|
||||||
|
updateUserDetailModal();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 绑定下拉面板事件
|
// 绑定下拉面板事件
|
||||||
|
|||||||
@ -174,7 +174,7 @@ export function getWaveformPreviewScript(): string {
|
|||||||
const content = document.createElement('div');
|
const content = document.createElement('div');
|
||||||
content.className = 'waveform-preview-content';
|
content.className = 'waveform-preview-content';
|
||||||
|
|
||||||
const miniViewerId = 'waveform-mini-' + Date.now();
|
const miniViewerId = 'waveform-mini-' + Date.now() + '-' + Math.random().toString(36).substr(2, 9);
|
||||||
const miniViewer = document.createElement('div');
|
const miniViewer = document.createElement('div');
|
||||||
miniViewer.id = miniViewerId;
|
miniViewer.id = miniViewerId;
|
||||||
miniViewer.className = 'waveform-mini-viewer';
|
miniViewer.className = 'waveform-mini-viewer';
|
||||||
|
|||||||
@ -588,20 +588,25 @@ export function getWebviewContent(
|
|||||||
case 'updateUserInfo':
|
case 'updateUserInfo':
|
||||||
// 更新用户信息
|
// 更新用户信息
|
||||||
console.log('[WebView] 收到用户信息:', message.userInfo);
|
console.log('[WebView] 收到用户信息:', message.userInfo);
|
||||||
|
console.log('[WebView] Credits 字段值:', message.userInfo?.credits);
|
||||||
if (message.userInfo) {
|
if (message.userInfo) {
|
||||||
const userInfoData = {
|
const userInfoData = {
|
||||||
nickname: message.userInfo.nickname || message.userInfo.username || '用户',
|
nickname: message.userInfo.nickname || message.userInfo.username || '用户',
|
||||||
userId: message.userInfo.userId || message.userInfo.id,
|
userId: message.userInfo.userId || message.userInfo.id,
|
||||||
tierName: message.userInfo.tierName,
|
tierName: message.userInfo.tierName,
|
||||||
tierIconUrl: message.tierIconUrl,
|
tierIconUrl: message.tierIconUrl,
|
||||||
registerTime: message.userInfo.registerTime || message.userInfo.createdAt
|
registerTime: message.userInfo.registerTime || message.userInfo.createdAt,
|
||||||
|
credits: message.userInfo.credits
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log('[WebView] 显示用户信息:', userInfoData);
|
console.log('[WebView] 显示用户信息:', userInfoData);
|
||||||
|
console.log('[WebView] userInfoData.credits:', userInfoData.credits);
|
||||||
|
|
||||||
// 调用更新用户头像图标按钮的函数
|
// 调用更新用户头像图标按钮的函数
|
||||||
if (typeof updateUserAvatarIconButton === 'function') {
|
if (typeof updateUserAvatarIconButton === 'function') {
|
||||||
updateUserAvatarIconButton(userInfoData);
|
updateUserAvatarIconButton(userInfoData);
|
||||||
|
} else {
|
||||||
|
console.warn('[WebView] updateUserAvatarIconButton 函数不存在');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
Reference in New Issue
Block a user