feat/获取用户信息+展示用户名称
This commit is contained in:
@ -17,6 +17,8 @@ export type ServiceTier = "lite" | "syntaxic" | "max" | "auto";
|
|||||||
export interface IccoderConfig {
|
export interface IccoderConfig {
|
||||||
/** 后端服务地址 */
|
/** 后端服务地址 */
|
||||||
backendUrl: string;
|
backendUrl: string;
|
||||||
|
/** 后端服务地址(strangeLoop) */
|
||||||
|
backendUrlStrongeLoop: string;
|
||||||
/** 请求超时时间(毫秒) */
|
/** 请求超时时间(毫秒) */
|
||||||
timeout: number;
|
timeout: number;
|
||||||
/** 用户ID(临时使用,后续对接认证) */
|
/** 用户ID(临时使用,后续对接认证) */
|
||||||
@ -30,6 +32,7 @@ const ENV_CONFIG: Record<Environment, IccoderConfig> = {
|
|||||||
/** 本地开发环境 */
|
/** 本地开发环境 */
|
||||||
dev: {
|
dev: {
|
||||||
backendUrl: "http://localhost:2233",
|
backendUrl: "http://localhost:2233",
|
||||||
|
backendUrlStrongeLoop: "http://192.168.1.108:2029",
|
||||||
timeout: 300000,
|
timeout: 300000,
|
||||||
userId: "default-user",
|
userId: "default-user",
|
||||||
serviceTier: "max", // 默认使用 max
|
serviceTier: "max", // 默认使用 max
|
||||||
@ -37,6 +40,7 @@ const ENV_CONFIG: Record<Environment, IccoderConfig> = {
|
|||||||
/** 测试服务器环境 */
|
/** 测试服务器环境 */
|
||||||
test: {
|
test: {
|
||||||
backendUrl: "http://192.168.1.108:2233",
|
backendUrl: "http://192.168.1.108:2233",
|
||||||
|
backendUrlStrongeLoop: "http://192.168.1.108:2029",
|
||||||
timeout: 60000,
|
timeout: 60000,
|
||||||
userId: "default-user",
|
userId: "default-user",
|
||||||
serviceTier: "max",
|
serviceTier: "max",
|
||||||
@ -44,6 +48,7 @@ const ENV_CONFIG: Record<Environment, IccoderConfig> = {
|
|||||||
/** 生产环境 */
|
/** 生产环境 */
|
||||||
prod: {
|
prod: {
|
||||||
backendUrl: "https://api.iccoder.com",
|
backendUrl: "https://api.iccoder.com",
|
||||||
|
backendUrlStrongeLoop: "http://api.iccoder.com:2029",
|
||||||
timeout: 60000,
|
timeout: 60000,
|
||||||
userId: "default-user",
|
userId: "default-user",
|
||||||
serviceTier: "auto",
|
serviceTier: "auto",
|
||||||
@ -75,3 +80,15 @@ export function getApiUrl(path: string): string {
|
|||||||
const apiPath = path.startsWith("/") ? path : `/${path}`;
|
const apiPath = path.startsWith("/") ? path : `/${path}`;
|
||||||
return `${baseUrl}${apiPath}`;
|
return `${baseUrl}${apiPath}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 StrangeLoop 服务 API 地址(用于用户信息等)
|
||||||
|
*/
|
||||||
|
export function getStrangeLoopApiUrl(path: string): string {
|
||||||
|
const { backendUrlStrongeLoop } = getConfig();
|
||||||
|
const baseUrl = backendUrlStrongeLoop.endsWith("/")
|
||||||
|
? backendUrlStrongeLoop.slice(0, -1)
|
||||||
|
: backendUrlStrongeLoop;
|
||||||
|
const apiPath = path.startsWith("/") ? path : `/${path}`;
|
||||||
|
return `${baseUrl}${apiPath}`;
|
||||||
|
}
|
||||||
|
|||||||
@ -5,10 +5,14 @@ import { VCDViewerPanel, VCDViewerEditorProvider } from "./panels/VCDViewerPanel
|
|||||||
import { ChatHistoryManager } from "./utils/chatHistoryManager";
|
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";
|
||||||
|
|
||||||
export function activate(context: vscode.ExtensionContext) {
|
export function activate(context: vscode.ExtensionContext) {
|
||||||
console.log("🎉 IC Coder 插件已激活!");
|
console.log("🎉 IC Coder 插件已激活!");
|
||||||
|
|
||||||
|
// 初始化用户服务
|
||||||
|
initUserService(context);
|
||||||
|
|
||||||
// 初始化 VCD 文件服务器
|
// 初始化 VCD 文件服务器
|
||||||
const vcdFileServer = new VCDFileServer();
|
const vcdFileServer = new VCDFileServer();
|
||||||
vcdFileServer.start().then((port) => {
|
vcdFileServer.start().then((port) => {
|
||||||
|
|||||||
@ -18,6 +18,7 @@ import { compactDialog } from "../services/apiClient";
|
|||||||
import { VCDViewerPanel } from "./VCDViewerPanel";
|
import { VCDViewerPanel } from "./VCDViewerPanel";
|
||||||
import { ChatHistoryManager } from "../utils/chatHistoryManager";
|
import { ChatHistoryManager } from "../utils/chatHistoryManager";
|
||||||
import { MessageType } from "../types/chatHistory";
|
import { MessageType } from "../types/chatHistory";
|
||||||
|
import { getCachedUserInfo } from "../services/userService";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建并显示 IC 助手面板
|
* 创建并显示 IC 助手面板
|
||||||
@ -108,6 +109,43 @@ export async function showICHelperPanel(
|
|||||||
maxIconUri.toString()
|
maxIconUri.toString()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// 获取并发送用户信息到 webview
|
||||||
|
try {
|
||||||
|
// 优先使用缓存的用户信息
|
||||||
|
let userInfo = getCachedUserInfo();
|
||||||
|
|
||||||
|
if (userInfo) {
|
||||||
|
// 使用缓存的用户信息
|
||||||
|
console.log('[ICHelperPanel] 使用缓存的用户信息:', userInfo);
|
||||||
|
panel.webview.postMessage({
|
||||||
|
command: 'updateUserInfo',
|
||||||
|
userInfo: {
|
||||||
|
userId: userInfo.userId,
|
||||||
|
nickname: userInfo.nickname,
|
||||||
|
username: userInfo.username
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// 如果没有缓存,从 session 中获取
|
||||||
|
const session = await vscode.authentication.getSession("iccoder", [], {
|
||||||
|
createIfNone: false,
|
||||||
|
});
|
||||||
|
if (session) {
|
||||||
|
console.log('[ICHelperPanel] 从 session 获取用户信息, account:', session.account);
|
||||||
|
panel.webview.postMessage({
|
||||||
|
command: 'updateUserInfo',
|
||||||
|
userInfo: {
|
||||||
|
userId: session.account.id,
|
||||||
|
nickname: session.account.label,
|
||||||
|
username: session.account.label
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[ICHelperPanel] 获取用户信息失败:', error);
|
||||||
|
}
|
||||||
|
|
||||||
// 处理消息
|
// 处理消息
|
||||||
panel.webview.onDidReceiveMessage(
|
panel.webview.onDidReceiveMessage(
|
||||||
async (message) => {
|
async (message) => {
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import * as https from 'https';
|
|||||||
import * as http from 'http';
|
import * as http from 'http';
|
||||||
import { URL } from 'url';
|
import { URL } from 'url';
|
||||||
import { getApiUrl, getConfig } from '../config/settings';
|
import { getApiUrl, getConfig } from '../config/settings';
|
||||||
import type { ToolCallResult, AnswerRequest, ToolResultResponse, AnswerResponse, ToolConfirmResponse } from '../types/api';
|
import type { ToolCallResult, AnswerRequest, ToolResultResponse, AnswerResponse, ToolConfirmResponse, UserInfoResponse } from '../types/api';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* HTTP 请求选项
|
* HTTP 请求选项
|
||||||
@ -213,3 +213,14 @@ export function createSystemErrorResult(id: number, code: number, message: strin
|
|||||||
error: { code, message }
|
error: { code, message }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取用户信息
|
||||||
|
* GET /system/user/getInfo
|
||||||
|
*/
|
||||||
|
export async function getUserInfo(): Promise<UserInfoResponse> {
|
||||||
|
console.log('[API] 获取用户信息');
|
||||||
|
return request<UserInfoResponse>('/system/user/getInfo', {
|
||||||
|
method: 'GET'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import * as vscode from "vscode";
|
|||||||
import * as http from "http";
|
import * as http from "http";
|
||||||
import * as path from "path";
|
import * as path from "path";
|
||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
|
import { onTokenReceived, type UserInfo, clearUserInfo } from "./userService";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IC Coder Authentication Provider
|
* IC Coder Authentication Provider
|
||||||
@ -62,13 +63,16 @@ export class ICCoderAuthenticationProvider
|
|||||||
try {
|
try {
|
||||||
const token = await this.login();
|
const token = await this.login();
|
||||||
|
|
||||||
|
// 获取到 token 后立即调用用户信息接口
|
||||||
|
const userInfo = await onTokenReceived(token);
|
||||||
|
|
||||||
// 创建会话
|
// 创建会话
|
||||||
const session: vscode.AuthenticationSession = {
|
const session: vscode.AuthenticationSession = {
|
||||||
id: this.generateSessionId(),
|
id: this.generateSessionId(),
|
||||||
accessToken: token,
|
accessToken: token,
|
||||||
account: {
|
account: {
|
||||||
id: "iccoder-user",
|
id: userInfo?.userId || "iccoder-user",
|
||||||
label: "IC Coder 用户",
|
label: userInfo?.nickname || userInfo?.username || "IC Coder 用户",
|
||||||
},
|
},
|
||||||
scopes: [...scopes],
|
scopes: [...scopes],
|
||||||
};
|
};
|
||||||
@ -109,6 +113,9 @@ export class ICCoderAuthenticationProvider
|
|||||||
this._sessions.splice(sessionIndex, 1);
|
this._sessions.splice(sessionIndex, 1);
|
||||||
await this.saveSessions();
|
await this.saveSessions();
|
||||||
|
|
||||||
|
// 清除用户信息缓存
|
||||||
|
await clearUserInfo();
|
||||||
|
|
||||||
// 触发会话变化事件
|
// 触发会话变化事件
|
||||||
this._onDidChangeSessions.fire({
|
this._onDidChangeSessions.fire({
|
||||||
added: [],
|
added: [],
|
||||||
|
|||||||
251
src/services/userService.ts
Normal file
251
src/services/userService.ts
Normal file
@ -0,0 +1,251 @@
|
|||||||
|
/**
|
||||||
|
* 用户服务
|
||||||
|
* 管理用户信息和认证相关的 API 调用
|
||||||
|
*/
|
||||||
|
import * as https from 'https';
|
||||||
|
import * as http from 'http';
|
||||||
|
import { URL } from 'url';
|
||||||
|
import * as vscode from 'vscode';
|
||||||
|
import { getStrangeLoopApiUrl, getConfig } from '../config/settings';
|
||||||
|
import type { UserInfoResponse } from '../types/api';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HTTP 请求选项
|
||||||
|
*/
|
||||||
|
interface RequestOptions {
|
||||||
|
method: 'GET' | 'POST' | 'PUT' | 'DELETE';
|
||||||
|
headers?: Record<string, string>;
|
||||||
|
body?: unknown;
|
||||||
|
timeout?: number;
|
||||||
|
token?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送 HTTP 请求(带 token)
|
||||||
|
*/
|
||||||
|
async function request<T>(path: string, options: RequestOptions): Promise<T> {
|
||||||
|
const url = new URL(getStrangeLoopApiUrl(path));
|
||||||
|
const { timeout } = getConfig();
|
||||||
|
|
||||||
|
const isHttps = url.protocol === 'https:';
|
||||||
|
const httpModule = isHttps ? https : http;
|
||||||
|
|
||||||
|
const headers: Record<string, string> = {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
...options.headers
|
||||||
|
};
|
||||||
|
|
||||||
|
// 如果有 token,添加到请求头
|
||||||
|
if (options.token) {
|
||||||
|
headers['Authorization'] = `Bearer ${options.token}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const requestOptions: http.RequestOptions = {
|
||||||
|
hostname: url.hostname,
|
||||||
|
port: url.port || (isHttps ? 443 : 80),
|
||||||
|
path: url.pathname + url.search,
|
||||||
|
method: options.method,
|
||||||
|
headers,
|
||||||
|
timeout: options.timeout || timeout
|
||||||
|
};
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const req = httpModule.request(requestOptions, (res) => {
|
||||||
|
let data = '';
|
||||||
|
|
||||||
|
res.on('data', (chunk) => {
|
||||||
|
data += chunk;
|
||||||
|
});
|
||||||
|
|
||||||
|
res.on('end', () => {
|
||||||
|
console.log(`[HTTP] 响应状态码: ${res.statusCode}`);
|
||||||
|
console.log(`[HTTP] 响应内容: ${data}`);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const json = JSON.parse(data);
|
||||||
|
if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {
|
||||||
|
resolve(json as T);
|
||||||
|
} else {
|
||||||
|
reject(new Error(json.error || json.message || json.msg || `HTTP ${res.statusCode}`));
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
// 如果不是 JSON,直接返回原始内容
|
||||||
|
reject(new Error(`解析响应失败 (${res.statusCode}): ${data}`));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
req.on('error', (error) => {
|
||||||
|
reject(error);
|
||||||
|
});
|
||||||
|
|
||||||
|
req.on('timeout', () => {
|
||||||
|
req.destroy();
|
||||||
|
reject(new Error('请求超时'));
|
||||||
|
});
|
||||||
|
|
||||||
|
if (options.body) {
|
||||||
|
req.write(JSON.stringify(options.body));
|
||||||
|
}
|
||||||
|
|
||||||
|
req.end();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户信息数据结构(实际返回的数据)
|
||||||
|
*/
|
||||||
|
export interface UserInfo {
|
||||||
|
userId: string;
|
||||||
|
username: string;
|
||||||
|
nickname: string;
|
||||||
|
email?: string;
|
||||||
|
phonenumber?: string;
|
||||||
|
avatar?: string;
|
||||||
|
roles?: string[];
|
||||||
|
permissions?: string[];
|
||||||
|
createTime?: string;
|
||||||
|
loginDate?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取用户信息
|
||||||
|
* GET /system/user/getInfo
|
||||||
|
*/
|
||||||
|
export async function getUserInfo(token: string): Promise<UserInfo | null> {
|
||||||
|
const apiPath = '/system/user/getInfo';
|
||||||
|
const fullUrl = getStrangeLoopApiUrl(apiPath);
|
||||||
|
console.log('[UserService] 获取用户信息');
|
||||||
|
console.log('[UserService] 请求地址:', fullUrl);
|
||||||
|
console.log('[UserService] Token:', token ? '已提供' : '未提供');
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await request<UserInfoResponse>(apiPath, {
|
||||||
|
method: 'GET',
|
||||||
|
token
|
||||||
|
});
|
||||||
|
|
||||||
|
// 处理响应数据 - 检查 code 是否为 200
|
||||||
|
if (response.code === 200 && response.user) {
|
||||||
|
const user = response.user;
|
||||||
|
return {
|
||||||
|
userId: String(user.userId),
|
||||||
|
username: user.userName,
|
||||||
|
nickname: user.nickName,
|
||||||
|
email: user.email,
|
||||||
|
phonenumber: user.phonenumber,
|
||||||
|
avatar: user.avatar,
|
||||||
|
roles: response.roles,
|
||||||
|
permissions: response.permissions,
|
||||||
|
createTime: user.createTime,
|
||||||
|
loginDate: user.loginDate
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
console.error('[UserService] 获取用户信息失败:', response);
|
||||||
|
return null;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[UserService] 请求失败:', error);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当获取到 token 时自动调用此函数
|
||||||
|
* 用于在登录成功后立即获取用户信息
|
||||||
|
*/
|
||||||
|
export async function onTokenReceived(token: string): Promise<UserInfo | null> {
|
||||||
|
try {
|
||||||
|
console.log('[UserService] Token 已获取,正在获取用户信息...');
|
||||||
|
const userInfo = await getUserInfo(token);
|
||||||
|
|
||||||
|
if (!userInfo) {
|
||||||
|
console.warn('[UserService] 未能获取到用户信息');
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 打印用户信息到控制台
|
||||||
|
console.log('='.repeat(60));
|
||||||
|
console.log('用户信息详情:');
|
||||||
|
console.log('='.repeat(60));
|
||||||
|
console.log(`用户ID: ${userInfo.userId}`);
|
||||||
|
console.log(`用户名: ${userInfo.username}`);
|
||||||
|
console.log(`昵称: ${userInfo.nickname}`);
|
||||||
|
if (userInfo.email) {
|
||||||
|
console.log(`邮箱: ${userInfo.email}`);
|
||||||
|
}
|
||||||
|
if (userInfo.phonenumber) {
|
||||||
|
console.log(`手机号: ${userInfo.phonenumber}`);
|
||||||
|
}
|
||||||
|
if (userInfo.avatar) {
|
||||||
|
console.log(`头像: ${userInfo.avatar}`);
|
||||||
|
}
|
||||||
|
if (userInfo.roles && userInfo.roles.length > 0) {
|
||||||
|
console.log(`角色: ${userInfo.roles.join(', ')}`);
|
||||||
|
}
|
||||||
|
if (userInfo.permissions && userInfo.permissions.length > 0) {
|
||||||
|
console.log(`权限: ${userInfo.permissions.join(', ')}`);
|
||||||
|
}
|
||||||
|
if (userInfo.createTime) {
|
||||||
|
console.log(`创建时间: ${userInfo.createTime}`);
|
||||||
|
}
|
||||||
|
if (userInfo.loginDate) {
|
||||||
|
console.log(`最后登录: ${userInfo.loginDate}`);
|
||||||
|
}
|
||||||
|
console.log('='.repeat(60));
|
||||||
|
|
||||||
|
// 保存到持久化存储
|
||||||
|
await saveUserInfo(userInfo);
|
||||||
|
|
||||||
|
return userInfo;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[UserService] 获取用户信息失败:', error);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============== 持久化存储 ==============
|
||||||
|
|
||||||
|
let extensionContext: vscode.ExtensionContext | null = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化用户服务(设置 context)
|
||||||
|
*/
|
||||||
|
export function initUserService(context: vscode.ExtensionContext): void {
|
||||||
|
extensionContext = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存用户信息到持久化存储
|
||||||
|
*/
|
||||||
|
export async function saveUserInfo(userInfo: UserInfo): Promise<void> {
|
||||||
|
if (!extensionContext) {
|
||||||
|
console.warn('[UserService] ExtensionContext 未初始化');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await extensionContext.globalState.update('icCoderUserInfo', userInfo);
|
||||||
|
console.log('[UserService] 用户信息已保存到持久化存储');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从持久化存储获取用户信息
|
||||||
|
*/
|
||||||
|
export function getCachedUserInfo(): UserInfo | null {
|
||||||
|
if (!extensionContext) {
|
||||||
|
console.warn('[UserService] ExtensionContext 未初始化');
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return extensionContext.globalState.get<UserInfo>('icCoderUserInfo') || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清除持久化存储的用户信息
|
||||||
|
*/
|
||||||
|
export async function clearUserInfo(): Promise<void> {
|
||||||
|
if (!extensionContext) {
|
||||||
|
console.warn('[UserService] ExtensionContext 未初始化');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await extensionContext.globalState.update('icCoderUserInfo', undefined);
|
||||||
|
console.log('[UserService] 用户信息已清除');
|
||||||
|
}
|
||||||
@ -310,6 +310,41 @@ export interface ToolConfirmResponse {
|
|||||||
approved: boolean;
|
approved: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ============== 用户信息 ==============
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户信息响应
|
||||||
|
* GET /system/user/getInfo
|
||||||
|
*/
|
||||||
|
export interface UserInfoResponse {
|
||||||
|
/** 响应消息 */
|
||||||
|
msg: string;
|
||||||
|
/** 响应代码 (200 表示成功) */
|
||||||
|
code: number;
|
||||||
|
/** 权限列表 */
|
||||||
|
permissions: string[];
|
||||||
|
/** 角色列表 */
|
||||||
|
roles: string[];
|
||||||
|
/** 是否默认修改密码 */
|
||||||
|
isDefaultModifyPwd: boolean;
|
||||||
|
/** 密码是否过期 */
|
||||||
|
isPasswordExpired: boolean;
|
||||||
|
/** 用户信息 */
|
||||||
|
user: {
|
||||||
|
userId: number;
|
||||||
|
userName: string;
|
||||||
|
nickName: string;
|
||||||
|
email?: string;
|
||||||
|
phonenumber?: string;
|
||||||
|
sex?: string;
|
||||||
|
avatar?: string;
|
||||||
|
status?: string;
|
||||||
|
createTime?: string;
|
||||||
|
loginDate?: string;
|
||||||
|
[key: string]: any;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// ============== 辅助类型 ==============
|
// ============== 辅助类型 ==============
|
||||||
|
|
||||||
/** 后端工具名称 */
|
/** 后端工具名称 */
|
||||||
|
|||||||
@ -19,11 +19,20 @@ export function getConversationHistoryBarContent(): string {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button class="new-conversation-button" onclick="createNewConversation()" title="新建对话">
|
<div class="right-actions">
|
||||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
<div class="user-info" id="userInfo" style="display: none;">
|
||||||
<path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z" fill="currentColor"/>
|
<svg class="user-icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||||
</svg>
|
<path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z" fill="currentColor"/>
|
||||||
</button>
|
</svg>
|
||||||
|
<span class="user-nickname" id="userNickname">加载中...</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button class="new-conversation-button" onclick="createNewConversation()" title="新建对话">
|
||||||
|
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z" fill="currentColor"/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
@ -49,6 +58,36 @@ export function getConversationHistoryBarStyles(): string {
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.right-actions {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-info {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
padding: 6px 10px;
|
||||||
|
background: var(--vscode-button-secondaryBackground);
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 13px;
|
||||||
|
color: var(--vscode-button-secondaryForeground);
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-icon {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-nickname {
|
||||||
|
white-space: nowrap;
|
||||||
|
max-width: 120px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
.history-dropdown-button {
|
.history-dropdown-button {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|||||||
@ -585,6 +585,19 @@ export function getWebviewContent(
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'updateUserInfo':
|
||||||
|
// 更新用户信息
|
||||||
|
console.log('[WebView] 收到用户信息:', message.userInfo);
|
||||||
|
const userInfo = document.getElementById('userInfo');
|
||||||
|
const userNickname = document.getElementById('userNickname');
|
||||||
|
if (userInfo && userNickname && message.userInfo) {
|
||||||
|
const displayName = message.userInfo.nickname || message.userInfo.username || '用户';
|
||||||
|
console.log('[WebView] 显示用户名:', displayName);
|
||||||
|
userNickname.textContent = displayName;
|
||||||
|
userInfo.style.display = 'flex';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case 'resetSegmentedMessage':
|
case 'resetSegmentedMessage':
|
||||||
// 重置分段消息容器(停止对话时调用)
|
// 重置分段消息容器(停止对话时调用)
|
||||||
console.log('[WebView] 重置分段消息容器');
|
console.log('[WebView] 重置分段消息容器');
|
||||||
|
|||||||
Reference in New Issue
Block a user