feat:实现BASIC用户显示升级到Pro的按钮 + 修改退出登录的展现形式 + 退出登录的再次确认

This commit is contained in:
Roe-xin
2026-01-19 10:52:39 +08:00
parent d90cca7cef
commit 50eacdafde
4 changed files with 280 additions and 26 deletions

View File

@ -162,7 +162,8 @@ export async function showICHelperPanel(
userId: userInfo.userId,
nickname: userInfo.nickname,
username: userInfo.username,
credits: userInfo.credits
credits: userInfo.credits,
membership: userInfo.membership
},
tierIconUrl: tierIconUrl
};
@ -511,6 +512,20 @@ export async function showICHelperPanel(
hasWorkspace: hasWorkspace,
});
break;
case "openExternalUrl":
// 打开外部链接
if (message.url) {
vscode.env.openExternal(vscode.Uri.parse(message.url));
}
break;
case "openICCoder":
// 打开 IC Coder 官网
vscode.env.openExternal(vscode.Uri.parse('https://www.iccoder.com'));
break;
case "logout":
// 退出登录(前端已有确认对话框)
vscode.commands.executeCommand('iccoder.logout');
break;
}
},
undefined,

View File

@ -217,6 +217,17 @@ export class ICViewProvider implements vscode.WebviewViewProvider {
vscode.commands.executeCommand("ic-coder.openChat");
} else if (message.command === "login") {
vscode.commands.executeCommand("ic-coder.login");
} else if (message.command === "logout") {
// 退出登录(前端已有确认对话框)
vscode.commands.executeCommand('iccoder.logout');
} else if (message.command === "openICCoder") {
// 打开 IC Coder 官网
vscode.env.openExternal(vscode.Uri.parse('https://www.iccoder.com'));
} else if (message.command === "openExternalUrl") {
// 打开外部链接
if (message.url) {
vscode.env.openExternal(vscode.Uri.parse(message.url));
}
}
},
undefined,

View File

@ -14,6 +14,7 @@ export function getUserInfoComponentContent(): string {
<div class="user-detail-dropdown" id="userDetailDropdown">
<div class="user-detail-content">
<div class="user-detail-header">
<div class="user-info-row">
<div class="user-avatar-small clickable" id="userAvatarClickable">
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/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"/>
@ -24,19 +25,42 @@ export function getUserInfoComponentContent(): string {
<img class="tier-icon-inline" id="tierIconInline" style="display: none;" />
</div>
</div>
<!-- 升级到Pro按钮 (仅BASIC会员显示) -->
<div class="upgrade-pro-wrapper" id="upgradeProWrapper" style="display: none;">
<button class="upgrade-pro-btn" id="upgradeProBtn">升级到 Pro</button>
</div>
</div>
<div class="user-detail-body">
<div class="user-detail-item">
<span class="detail-label">剩余 Credits</span>
<span class="detail-value" id="creditsDetail">-</span>
</div>
<div class="logout">
<button class="logout-btn" id="logoutBtn">退出登录</button>
<div class="user-detail-item logout-item" id="logoutItem">
<span class="detail-label">账户管理</span>
<span class="detail-value logout-link">退出登录</span>
</div>
</div>
</div>
</div>
</div>
<!-- 退出登录确认对话框 -->
<div class="logout-confirm-modal" id="logoutConfirmModal">
<div class="logout-confirm-overlay"></div>
<div class="logout-confirm-content">
<div class="logout-confirm-header">
<h3>确认退出</h3>
</div>
<div class="logout-confirm-body">
<p>确定要退出登录吗?</p>
</div>
<div class="logout-confirm-footer">
<button class="logout-confirm-btn logout-cancel-btn" id="logoutCancelBtn">取消</button>
<button class="logout-confirm-btn logout-ok-btn" id="logoutOkBtn">确定</button>
</div>
</div>
</div>
`;
}
@ -87,12 +111,18 @@ export function getUserInfoComponentStyles(): string {
.user-detail-header {
padding: 16px;
display: flex;
align-items: center;
flex-direction: column;
gap: 12px;
background: linear-gradient(135deg, rgba(0, 122, 204, 0.1) 0%, rgba(88, 166, 255, 0.05) 100%);
border-bottom: 1px solid var(--vscode-widget-border);
}
.user-info-row {
display: flex;
align-items: center;
gap: 12px;
}
.user-avatar-small {
width: 26px;
height: 26px;
@ -175,6 +205,19 @@ export function getUserInfoComponentStyles(): string {
margin-bottom: 0;
}
.logout-item {
cursor: pointer;
}
.logout-item:hover {
background: var(--vscode-list-hoverBackground);
border-color: rgba(204, 0, 0, 0.3);
}
.logout-item:hover .logout-link {
color: #f48771;
}
.detail-label {
font-size: 12px;
font-weight: 500;
@ -191,6 +234,11 @@ export function getUserInfoComponentStyles(): string {
gap: 6px;
}
.logout-link {
color: var(--vscode-foreground);
transition: color 0.2s ease;
}
.tier-icon-large {
height: 20px;
object-fit: contain;
@ -204,28 +252,133 @@ export function getUserInfoComponentStyles(): string {
border-radius: 4px;
}
.logout {
.upgrade-pro-wrapper {
margin-top: 8px;
}
.logout-btn {
.upgrade-pro-btn {
width: 100%;
padding: 8px 12px;
background: var(--vscode-button-background);
color: var(--vscode-button-foreground);
padding: 6px 12px;
background: linear-gradient(135deg, #007acc 0%, #58a6ff 100%);
color: #ffffff;
border: none;
border-radius: 6px;
border-radius: 4px;
cursor: pointer;
font-size: 11px;
font-weight: 600;
transition: all 0.2s ease;
box-shadow: 0 1px 4px rgba(0, 122, 204, 0.2);
letter-spacing: 0.3px;
}
.upgrade-pro-btn:hover {
background: linear-gradient(135deg, #0098ff 0%, #6bb6ff 100%);
box-shadow: 0 2px 8px rgba(0, 122, 204, 0.4);
transform: translateY(-1px);
}
.upgrade-pro-btn:active {
transform: translateY(0) scale(0.98);
box-shadow: 0 1px 4px rgba(0, 122, 204, 0.3);
}
/* 退出登录确认对话框 */
.logout-confirm-modal {
display: none;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 20000;
}
.logout-confirm-modal.active {
display: block;
}
.logout-confirm-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
}
.logout-confirm-content {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: var(--vscode-editor-background);
border: 1px solid var(--vscode-widget-border);
border-radius: 8px;
min-width: 320px;
max-width: 400px;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
}
.logout-confirm-header {
padding: 16px 20px;
border-bottom: 1px solid var(--vscode-widget-border);
}
.logout-confirm-header h3 {
margin: 0;
font-size: 14px;
font-weight: 600;
color: var(--vscode-foreground);
}
.logout-confirm-body {
padding: 20px;
}
.logout-confirm-body p {
margin: 0;
font-size: 13px;
color: var(--vscode-foreground);
line-height: 1.5;
}
.logout-confirm-footer {
padding: 12px 20px;
display: flex;
justify-content: flex-end;
gap: 8px;
border-top: 1px solid var(--vscode-widget-border);
}
.logout-confirm-btn {
padding: 6px 16px;
border: none;
border-radius: 4px;
font-size: 12px;
font-weight: 500;
cursor: pointer;
transition: all 0.2s ease;
}
.logout-btn:hover {
background: var(--vscode-button-hoverBackground);
.logout-cancel-btn {
background: var(--vscode-button-secondaryBackground);
color: var(--vscode-button-secondaryForeground);
}
.logout-btn:active {
.logout-cancel-btn:hover {
background: var(--vscode-button-secondaryHoverBackground);
}
.logout-ok-btn {
background: #f48771;
color: #ffffff;
}
.logout-ok-btn:hover {
background: #e67361;
}
.logout-confirm-btn:active {
transform: scale(0.98);
}
`;
@ -264,8 +417,28 @@ export function getUserInfoComponentScript(): string {
// 退出登录
function logout() {
console.log("退出登录");
console.log("显示退出登录确认对话框");
// 显示确认对话框
const modal = document.getElementById('logoutConfirmModal');
if (modal) {
modal.classList.add('active');
}
}
// 确认退出登录
function confirmLogout() {
console.log("确认退出登录");
vscode.postMessage({ command: 'logout' });
// 关闭确认对话框
closeLogoutConfirmModal();
}
// 关闭退出登录确认对话框
function closeLogoutConfirmModal() {
const modal = document.getElementById('logoutConfirmModal');
if (modal) {
modal.classList.remove('active');
}
}
// 跳转到 IC Coder 官网
@ -274,6 +447,12 @@ export function getUserInfoComponentScript(): string {
vscode.postMessage({ command: 'openICCoder' });
}
// 升级到Pro
function upgradeToPro() {
console.log("升级到 Pro - 跳转到 IC Coder 官网");
vscode.postMessage({ command: 'openExternalUrl', url: 'https://www.iccoder.com' });
}
// 关闭用户详情下拉面板
function closeUserDetailModal() {
const dropdown = document.getElementById('userDetailDropdown');
@ -320,6 +499,19 @@ export function getUserInfoComponentScript(): string {
} else {
console.warn('[UserInfoComponent] creditsDetail 元素未找到');
}
// 显示或隐藏升级到Pro按钮 (仅BASIC会员显示)
const upgradeProWrapper = document.getElementById('upgradeProWrapper');
const tierCode = currentUserInfo.membership?.tierCode;
if (upgradeProWrapper) {
if (tierCode === 'BASIC') {
upgradeProWrapper.style.display = 'block';
} else {
upgradeProWrapper.style.display = 'none';
}
} else {
console.warn('[UserInfoComponent] upgradeProWrapper 元素未找到');
}
}
// 更新用户信息显示
@ -335,14 +527,48 @@ export function getUserInfoComponentScript(): string {
// 绑定下拉面板事件
document.addEventListener('DOMContentLoaded', () => {
// 绑定退出登录按钮
const logoutBtn = document.getElementById('logoutBtn');
if (logoutBtn) {
logoutBtn.addEventListener('click', () => {
// 绑定退出登录卡片点击事件
const logoutItem = document.getElementById('logoutItem');
if (logoutItem) {
logoutItem.addEventListener('click', () => {
logout();
});
}
// 绑定退出登录确认对话框按钮
const logoutOkBtn = document.getElementById('logoutOkBtn');
if (logoutOkBtn) {
logoutOkBtn.addEventListener('click', () => {
confirmLogout();
});
}
const logoutCancelBtn = document.getElementById('logoutCancelBtn');
if (logoutCancelBtn) {
logoutCancelBtn.addEventListener('click', () => {
closeLogoutConfirmModal();
});
}
// 点击遮罩层关闭对话框
const logoutConfirmModal = document.getElementById('logoutConfirmModal');
if (logoutConfirmModal) {
const overlay = logoutConfirmModal.querySelector('.logout-confirm-overlay');
if (overlay) {
overlay.addEventListener('click', () => {
closeLogoutConfirmModal();
});
}
}
// 绑定升级到Pro按钮
const upgradeProBtn = document.getElementById('upgradeProBtn');
if (upgradeProBtn) {
upgradeProBtn.addEventListener('click', () => {
upgradeToPro();
});
}
// 绑定头像点击事件
const userAvatar = document.getElementById('userAvatarClickable');
if (userAvatar) {

View File

@ -607,11 +607,13 @@ export function getWebviewContent(
tierName: message.userInfo.tierName,
tierIconUrl: message.tierIconUrl,
registerTime: message.userInfo.registerTime || message.userInfo.createdAt,
credits: message.userInfo.credits
credits: message.userInfo.credits,
membership: message.userInfo.membership
};
console.log('[WebView] 显示用户信息:', userInfoData);
console.log('[WebView] userInfoData.credits:', userInfoData.credits);
console.log('[WebView] userInfoData.membership:', userInfoData.membership);
// 调用更新用户头像图标按钮的函数
if (typeof updateUserAvatarIconButton === 'function') {