feat: 实现邀请码验证功能
## 功能概述 - 用户首次使用需验证邀请码才能发起对话 - 在输入框聚焦和点击示例时触发验证检查 - 使用弹窗形式展示邀请码输入界面,包含企业端用户提示和微信二维码 ## 主要变更 ### 新增文件 - `services/invitationService.ts`: 邀请码验证服务,处理验证逻辑和状态管理 - `views/invitationModal.ts`: 邀请码验证弹窗组件(HTML/CSS/JS) - `docs/invitation-code-design.md`: 邀请码功能设计文档 ### 修改文件 - `extension.ts`: 添加更换邀请码命令,退出登录时清除验证状态 - `panels/ICHelperPanel.ts`: 添加邀请码验证状态检查和验证消息处理 - `services/apiClient.ts`: 添加邀请码验证接口调用 - `types/api.ts`: 添加邀请码相关类型定义 - `views/inputArea.ts`: 输入框聚焦时触发邀请码验证检查 - `views/exampleShowcase.ts`: 点击示例时先检查邀请码验证状态 - `views/webviewContent.ts`: 集成邀请码弹窗到主界面 ## 技术实现 - 验证状态保存在 ExtensionContext.globalState 中 - 使用后端接口 POST /api/invitation/verify 进行验证 - 弹窗样式适配 VS Code 主题 - 支持回车键提交验证
This commit is contained in:
@ -9,6 +9,7 @@ import { initUserService } from "./services/userService";
|
||||
import { initCreditsService } from "./services/creditsService";
|
||||
import { isTokenExpired } from "./utils/jwtUtils";
|
||||
import { NotificationService } from "./services/notificationService";
|
||||
import { InvitationService } from "./services/invitationService";
|
||||
|
||||
export async function activate(context: vscode.ExtensionContext) {
|
||||
console.log("🎉 IC Coder 插件已激活!");
|
||||
@ -187,6 +188,8 @@ export async function activate(context: vscode.ExtensionContext) {
|
||||
if (session) {
|
||||
// 调用 authProvider 的 removeSession 方法
|
||||
await authProvider.removeSession(session.id);
|
||||
// 清除邀请码验证状态
|
||||
await InvitationService.clearVerificationStatus(context);
|
||||
} else {
|
||||
vscode.window.showInformationMessage("当前未登录");
|
||||
}
|
||||
@ -196,6 +199,23 @@ export async function activate(context: vscode.ExtensionContext) {
|
||||
}
|
||||
);
|
||||
|
||||
// 注册命令:更换邀请码
|
||||
const changeInvitationCodeCommand = vscode.commands.registerCommand(
|
||||
"ic-coder.changeInvitationCode",
|
||||
async () => {
|
||||
const confirm = await vscode.window.showWarningMessage(
|
||||
'确定要更换邀请码吗?',
|
||||
'确定',
|
||||
'取消'
|
||||
);
|
||||
|
||||
if (confirm === '确定') {
|
||||
await InvitationService.clearVerificationStatus(context);
|
||||
vscode.window.showInformationMessage('已清除邀请码,请重新验证');
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// 注册命令:测试系统通知
|
||||
const testNotificationCommand = vscode.commands.registerCommand(
|
||||
"ic-coder.testNotification",
|
||||
@ -283,6 +303,7 @@ export async function activate(context: vscode.ExtensionContext) {
|
||||
openVCDViewerInBrowserCommand,
|
||||
loginCommand,
|
||||
logoutCommand,
|
||||
changeInvitationCodeCommand,
|
||||
testNotificationCommand,
|
||||
// TODO: 等待重新实现这些命令
|
||||
// viewHistoryCommand,
|
||||
|
||||
@ -396,6 +396,40 @@ export async function showICHelperPanel(
|
||||
// 退出登录
|
||||
vscode.commands.executeCommand("ic-coder.logout");
|
||||
break;
|
||||
case "checkInvitationCode":
|
||||
// 检查邀请码验证状态
|
||||
{
|
||||
const { InvitationService } = require("../services/invitationService");
|
||||
const isVerified = await InvitationService.isVerified(context);
|
||||
panel.webview.postMessage({
|
||||
command: "invitationCodeStatus",
|
||||
verified: isVerified
|
||||
});
|
||||
}
|
||||
break;
|
||||
case "verifyInvitationCode":
|
||||
// 验证邀请码
|
||||
{
|
||||
const { InvitationService } = require("../services/invitationService");
|
||||
const result = await InvitationService.verifyCode(message.code);
|
||||
|
||||
if (result.success) {
|
||||
// 验证成功,保存状态
|
||||
await InvitationService.saveVerificationStatus(context, message.code);
|
||||
panel.webview.postMessage({
|
||||
command: "invitationCodeVerified",
|
||||
success: true
|
||||
});
|
||||
} else {
|
||||
// 验证失败,返回错误信息
|
||||
panel.webview.postMessage({
|
||||
command: "invitationCodeVerified",
|
||||
success: false,
|
||||
message: result.message
|
||||
});
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "openICCoder":
|
||||
// 跳转到 IC Coder 官网
|
||||
vscode.env.openExternal(vscode.Uri.parse("https://www.iccoder.com"));
|
||||
|
||||
@ -7,7 +7,7 @@ import * as https from 'https';
|
||||
import * as http from 'http';
|
||||
import { URL } from 'url';
|
||||
import { getApiUrl, getConfig } from '../config/settings';
|
||||
import type { ToolCallResult, AnswerRequest, ToolResultResponse, AnswerResponse, ToolConfirmResponse, UserInfoResponse } from '../types/api';
|
||||
import type { ToolCallResult, AnswerRequest, ToolResultResponse, AnswerResponse, ToolConfirmResponse, UserInfoResponse, InvitationVerifyRequest, InvitationVerifyResponse, InvitationStatusResponse } from '../types/api';
|
||||
|
||||
/**
|
||||
* HTTP 请求选项
|
||||
@ -260,3 +260,27 @@ export async function getCreditBalance(userId: string): Promise<CreditBalanceRes
|
||||
timeout: 5000
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证邀请码
|
||||
* POST /api/invitation/verify
|
||||
*/
|
||||
export async function verifyInvitationCode(code: string): Promise<InvitationVerifyResponse> {
|
||||
console.log('[API] 验证邀请码');
|
||||
const body: InvitationVerifyRequest = { code };
|
||||
return request<InvitationVerifyResponse>('/api/invitation/verify', {
|
||||
method: 'POST',
|
||||
body
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询邀请码验证状态
|
||||
* GET /api/invitation/status
|
||||
*/
|
||||
export async function checkInvitationStatus(): Promise<InvitationStatusResponse> {
|
||||
console.log('[API] 查询邀请码验证状态');
|
||||
return request<InvitationStatusResponse>('/api/invitation/status', {
|
||||
method: 'GET'
|
||||
});
|
||||
}
|
||||
|
||||
91
src/services/invitationService.ts
Normal file
91
src/services/invitationService.ts
Normal file
@ -0,0 +1,91 @@
|
||||
/**
|
||||
* 邀请码验证服务
|
||||
*/
|
||||
import * as vscode from 'vscode';
|
||||
import { verifyInvitationCode, checkInvitationStatus } from './apiClient';
|
||||
|
||||
/**
|
||||
* 邀请码验证服务类
|
||||
*/
|
||||
export class InvitationService {
|
||||
/**
|
||||
* 检查用户是否已验证邀请码
|
||||
*/
|
||||
static async isVerified(context: vscode.ExtensionContext): Promise<boolean> {
|
||||
// 【临时】使用本地验证,不调用后端
|
||||
const localVerified = context.globalState.get<boolean>('invitationCodeVerified');
|
||||
return localVerified || false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证邀请码
|
||||
*/
|
||||
static async verifyCode(code: string): Promise<{ success: boolean; message: string }> {
|
||||
try {
|
||||
console.log('[InvitationService] 验证邀请码:', code);
|
||||
const response = await verifyInvitationCode(code);
|
||||
|
||||
if (response.code === 200 && response.data?.verified) {
|
||||
return {
|
||||
success: true,
|
||||
message: response.msg || '验证成功'
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
success: false,
|
||||
message: response.msg || '验证失败'
|
||||
};
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error('[InvitationService] 验证邀请码失败:', error);
|
||||
return {
|
||||
success: false,
|
||||
message: error.message || '网络连接失败,请检查网络后重试'
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存验证状态到本地
|
||||
*/
|
||||
static async saveVerificationStatus(
|
||||
context: vscode.ExtensionContext,
|
||||
code: string,
|
||||
verifiedTime?: string
|
||||
): Promise<void> {
|
||||
await context.globalState.update('invitationCodeVerified', true);
|
||||
await context.globalState.update('invitationCode', code);
|
||||
await context.globalState.update('invitationVerifiedTime', verifiedTime || new Date().toISOString());
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除验证状态(用于退出登录或更换邀请码)
|
||||
*/
|
||||
static async clearVerificationStatus(context: vscode.ExtensionContext): Promise<void> {
|
||||
await context.globalState.update('invitationCodeVerified', undefined);
|
||||
await context.globalState.update('invitationCode', undefined);
|
||||
await context.globalState.update('invitationVerifiedTime', undefined);
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示邀请码输入弹窗
|
||||
*/
|
||||
static async showInputDialog(): Promise<string | undefined> {
|
||||
const code = await vscode.window.showInputBox({
|
||||
prompt: '请输入邀请码以继续使用 IC Coder',
|
||||
placeHolder: '例如:INVITE2024ABC',
|
||||
ignoreFocusOut: true,
|
||||
validateInput: (value) => {
|
||||
if (!value || value.trim().length === 0) {
|
||||
return '邀请码不能为空';
|
||||
}
|
||||
if (value.trim().length < 6) {
|
||||
return '邀请码格式不正确';
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
return code?.trim();
|
||||
}
|
||||
}
|
||||
@ -581,3 +581,49 @@ export type ToolArgs =
|
||||
| WaveformTraceArgs
|
||||
| KnowledgeSaveArgs
|
||||
| KnowledgeLoadArgs;
|
||||
|
||||
// ============== 邀请码验证 ==============
|
||||
|
||||
/**
|
||||
* 邀请码验证请求
|
||||
* POST /api/invitation/verify
|
||||
*/
|
||||
export interface InvitationVerifyRequest {
|
||||
/** 邀请码 */
|
||||
code: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 邀请码验证响应
|
||||
*/
|
||||
export interface InvitationVerifyResponse {
|
||||
/** 响应代码 */
|
||||
code: number;
|
||||
/** 响应消息 */
|
||||
msg: string;
|
||||
/** 验证结果数据 */
|
||||
data?: {
|
||||
/** 是否验证成功 */
|
||||
verified: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 邀请码状态响应
|
||||
* GET /api/invitation/status
|
||||
*/
|
||||
export interface InvitationStatusResponse {
|
||||
/** 响应代码 */
|
||||
code: number;
|
||||
/** 响应消息 */
|
||||
msg?: string;
|
||||
/** 状态数据 */
|
||||
data?: {
|
||||
/** 是否已验证 */
|
||||
verified: boolean;
|
||||
/** 使用的邀请码 */
|
||||
invitationCode?: string;
|
||||
/** 验证时间 */
|
||||
verifiedTime?: string;
|
||||
};
|
||||
}
|
||||
|
||||
@ -231,10 +231,10 @@ export function getExampleShowcaseScript(): string {
|
||||
|
||||
// 直接发送示例消息
|
||||
function sendExample(index) {
|
||||
// 先检查工作区
|
||||
// 先检查邀请码验证状态
|
||||
pendingExampleIndex = index;
|
||||
vscode.postMessage({
|
||||
command: 'checkWorkspace'
|
||||
command: 'checkInvitationCode'
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -339,12 +339,14 @@ export function getInputAreaScript(): string {
|
||||
if (messageInput) {
|
||||
messageInput.addEventListener('input', autoResizeTextarea);
|
||||
|
||||
// 监听点击事件,检测工作区状态
|
||||
// 监听点击事件,检测工作区状态和邀请码验证状态
|
||||
messageInput.addEventListener('focus', () => {
|
||||
if (!hasCheckedWorkspace) {
|
||||
hasCheckedWorkspace = true;
|
||||
vscode.postMessage({ command: 'checkWorkspace' });
|
||||
}
|
||||
// 检查邀请码验证状态
|
||||
vscode.postMessage({ command: 'checkInvitationCode' });
|
||||
});
|
||||
|
||||
// 初始化时调整一次高度
|
||||
|
||||
321
src/views/invitationModal.ts
Normal file
321
src/views/invitationModal.ts
Normal file
@ -0,0 +1,321 @@
|
||||
/**
|
||||
* 邀请码验证弹窗
|
||||
*/
|
||||
|
||||
/**
|
||||
* 获取邀请码弹窗的 HTML 内容
|
||||
*/
|
||||
export function getInvitationModalContent(qrCodeUri?: string): string {
|
||||
return `
|
||||
<!-- 邀请码验证弹窗 -->
|
||||
<div id="invitationModal" class="invitation-modal" style="display: none;">
|
||||
<div class="invitation-modal-overlay"></div>
|
||||
<div class="invitation-modal-content">
|
||||
<div class="invitation-modal-header">
|
||||
<h2>验证邀请码</h2>
|
||||
<p class="invitation-modal-subtitle">仅供企业端用户和内部人员使用</p>
|
||||
</div>
|
||||
<div class="invitation-modal-body">
|
||||
<div class="invitation-qrcode-section">
|
||||
<p class="invitation-qrcode-text">欢迎企业端用户扫码添加微信获取邀请码</p>
|
||||
<img src="${qrCodeUri}" alt="微信二维码" class="invitation-qrcode-image" />
|
||||
</div>
|
||||
<div class="invitation-input-section">
|
||||
<input
|
||||
type="text"
|
||||
id="invitationCodeInput"
|
||||
class="invitation-code-input"
|
||||
placeholder="请输入邀请码"
|
||||
maxlength="20"
|
||||
/>
|
||||
<div id="invitationError" class="invitation-error" style="display: none;"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="invitation-modal-footer">
|
||||
<button id="invitationSubmitBtn" class="invitation-btn invitation-btn-primary">
|
||||
验证
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取邀请码弹窗的 CSS 样式
|
||||
*/
|
||||
export function getInvitationModalStyles(): string {
|
||||
return `
|
||||
/* 邀请码弹窗样式 */
|
||||
.invitation-modal {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 10000;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.invitation-modal-overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
backdrop-filter: blur(4px);
|
||||
}
|
||||
|
||||
.invitation-modal-content {
|
||||
position: relative;
|
||||
background: var(--vscode-editor-background);
|
||||
border: 1px solid var(--vscode-panel-border);
|
||||
border-radius: 8px;
|
||||
width: 90%;
|
||||
max-width: 400px;
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
|
||||
animation: modalSlideIn 0.3s ease-out;
|
||||
}
|
||||
|
||||
@keyframes modalSlideIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-20px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.invitation-modal-header {
|
||||
padding: 24px 24px 16px;
|
||||
border-bottom: 1px solid var(--vscode-panel-border);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.invitation-modal-header h2 {
|
||||
margin: 0;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: var(--vscode-foreground);
|
||||
}
|
||||
|
||||
.invitation-modal-subtitle {
|
||||
margin: 8px 0 0;
|
||||
font-size: 13px;
|
||||
color: var(--vscode-descriptionForeground);
|
||||
}
|
||||
|
||||
.invitation-modal-body {
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
.invitation-qrcode-section {
|
||||
text-align: center;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.invitation-qrcode-text {
|
||||
margin: 0 0 16px;
|
||||
font-size: 13px;
|
||||
color: var(--vscode-foreground);
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.invitation-qrcode-image {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
border: 1px solid var(--vscode-panel-border);
|
||||
border-radius: 8px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.invitation-input-section {
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
.invitation-code-input {
|
||||
width: 100%;
|
||||
padding: 10px 12px;
|
||||
font-size: 14px;
|
||||
border: 1px solid var(--vscode-input-border);
|
||||
background: var(--vscode-input-background);
|
||||
color: var(--vscode-input-foreground);
|
||||
border-radius: 4px;
|
||||
outline: none;
|
||||
transition: border-color 0.2s;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.invitation-code-input:focus {
|
||||
border-color: var(--vscode-focusBorder);
|
||||
}
|
||||
|
||||
.invitation-code-input::placeholder {
|
||||
color: var(--vscode-input-placeholderForeground);
|
||||
}
|
||||
|
||||
.invitation-error {
|
||||
margin-top: 12px;
|
||||
padding: 8px 12px;
|
||||
font-size: 13px;
|
||||
color: var(--vscode-errorForeground);
|
||||
background: var(--vscode-inputValidation-errorBackground);
|
||||
border: 1px solid var(--vscode-inputValidation-errorBorder);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.invitation-modal-footer {
|
||||
padding: 16px 24px;
|
||||
border-top: 1px solid var(--vscode-panel-border);
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.invitation-btn {
|
||||
padding: 8px 20px;
|
||||
font-size: 13px;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.invitation-btn-primary {
|
||||
background: var(--vscode-button-background);
|
||||
color: var(--vscode-button-foreground);
|
||||
}
|
||||
|
||||
.invitation-btn-primary:hover {
|
||||
background: var(--vscode-button-hoverBackground);
|
||||
}
|
||||
|
||||
.invitation-btn-primary:active {
|
||||
transform: scale(0.98);
|
||||
}
|
||||
|
||||
.invitation-btn-primary:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取邀请码弹窗的 JavaScript 逻辑
|
||||
*/
|
||||
export function getInvitationModalScript(): string {
|
||||
return `
|
||||
// 邀请码弹窗逻辑
|
||||
(function() {
|
||||
const modal = document.getElementById('invitationModal');
|
||||
const input = document.getElementById('invitationCodeInput');
|
||||
const submitBtn = document.getElementById('invitationSubmitBtn');
|
||||
const errorDiv = document.getElementById('invitationError');
|
||||
|
||||
// 显示邀请码弹窗
|
||||
window.showInvitationModal = function() {
|
||||
modal.style.display = 'flex';
|
||||
setTimeout(() => {
|
||||
input.focus();
|
||||
}, 100);
|
||||
};
|
||||
|
||||
// 隐藏邀请码弹窗
|
||||
window.hideInvitationModal = function() {
|
||||
modal.style.display = 'none';
|
||||
input.value = '';
|
||||
errorDiv.style.display = 'none';
|
||||
errorDiv.textContent = '';
|
||||
submitBtn.disabled = false;
|
||||
};
|
||||
|
||||
// 显示错误信息
|
||||
window.showInvitationError = function(message) {
|
||||
errorDiv.textContent = message;
|
||||
errorDiv.style.display = 'block';
|
||||
submitBtn.disabled = false;
|
||||
};
|
||||
|
||||
// 提交邀请码
|
||||
function submitInvitationCode() {
|
||||
const code = input.value.trim();
|
||||
|
||||
if (!code) {
|
||||
showInvitationError('邀请码不能为空');
|
||||
return;
|
||||
}
|
||||
|
||||
if (code.length < 6) {
|
||||
showInvitationError('邀请码格式不正确');
|
||||
return;
|
||||
}
|
||||
|
||||
// 禁用按钮,防止重复提交
|
||||
submitBtn.disabled = true;
|
||||
errorDiv.style.display = 'none';
|
||||
|
||||
// 发送验证请求到后端
|
||||
vscode.postMessage({
|
||||
command: 'verifyInvitationCode',
|
||||
code: code
|
||||
});
|
||||
}
|
||||
|
||||
// 点击提交按钮
|
||||
submitBtn.addEventListener('click', submitInvitationCode);
|
||||
|
||||
// 回车键提交
|
||||
input.addEventListener('keypress', function(e) {
|
||||
if (e.key === 'Enter') {
|
||||
submitInvitationCode();
|
||||
}
|
||||
});
|
||||
|
||||
// 阻止点击弹窗内容时关闭
|
||||
document.querySelector('.invitation-modal-content').addEventListener('click', function(e) {
|
||||
e.stopPropagation();
|
||||
});
|
||||
|
||||
// 监听来自后端的消息
|
||||
window.addEventListener('message', function(event) {
|
||||
const message = event.data;
|
||||
|
||||
// 处理邀请码验证状态
|
||||
if (message.command === 'invitationCodeStatus') {
|
||||
if (!message.verified) {
|
||||
// 未验证,显示弹窗
|
||||
showInvitationModal();
|
||||
} else {
|
||||
// 已验证,继续执行待处理的操作
|
||||
if (typeof pendingExampleIndex !== 'undefined' && pendingExampleIndex >= 0) {
|
||||
// 如果有待发送的示例,先检查工作区
|
||||
vscode.postMessage({ command: 'checkWorkspace' });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 处理邀请码验证结果
|
||||
if (message.command === 'invitationCodeVerified') {
|
||||
if (message.success) {
|
||||
// 验证成功,隐藏弹窗
|
||||
hideInvitationModal();
|
||||
// 继续执行待处理的操作
|
||||
if (typeof pendingExampleIndex !== 'undefined' && pendingExampleIndex >= 0) {
|
||||
// 如果有待发送的示例,先检查工作区
|
||||
vscode.postMessage({ command: 'checkWorkspace' });
|
||||
}
|
||||
} else {
|
||||
// 验证失败,显示错误信息
|
||||
showInvitationError(message.message || '验证失败,请重试');
|
||||
}
|
||||
}
|
||||
});
|
||||
})();
|
||||
`;
|
||||
}
|
||||
@ -25,6 +25,11 @@ import {
|
||||
} from "./progressBar";
|
||||
import { getHighlightJsLinks } from "../components/codeHighlight";
|
||||
import { getCurrentEnv } from "../config/settings";
|
||||
import {
|
||||
getInvitationModalContent,
|
||||
getInvitationModalStyles,
|
||||
getInvitationModalScript,
|
||||
} from "./invitationModal";
|
||||
/**
|
||||
* 获取 WebView 面板的 HTML 内容
|
||||
*/
|
||||
@ -93,6 +98,7 @@ export function getWebviewContent(
|
||||
${getConversationHistoryBarStyles()}
|
||||
${getProgressBarStyles()}
|
||||
${getInputAreaStyles()}
|
||||
${getInvitationModalStyles()}
|
||||
|
||||
.file-editor-section {
|
||||
margin-bottom: 15px;
|
||||
@ -398,6 +404,7 @@ export function getWebviewContent(
|
||||
<body>
|
||||
${getConversationHistoryBarContent()}
|
||||
${getProgressBarContent()}
|
||||
${getInvitationModalContent(qrCodeUri)}
|
||||
<div class="header">
|
||||
<div style="display: flex; align-items: center; justify-content: center; gap: 15px;">
|
||||
<img src="${iconUri}" alt="IC Coder" style="width: 48px; height: 48px;" />
|
||||
@ -802,6 +809,7 @@ export function getWebviewContent(
|
||||
${getConversationHistoryBarScript()}
|
||||
${getProgressBarScript()}
|
||||
${getInputAreaScript()}
|
||||
${getInvitationModalScript()}
|
||||
</script></body>
|
||||
</html>`;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user