feat:实现BASIC用户显示升级到Pro的按钮 + 修改退出登录的展现形式 + 退出登录的再次确认
This commit is contained in:
@ -162,7 +162,8 @@ export async function showICHelperPanel(
|
|||||||
userId: userInfo.userId,
|
userId: userInfo.userId,
|
||||||
nickname: userInfo.nickname,
|
nickname: userInfo.nickname,
|
||||||
username: userInfo.username,
|
username: userInfo.username,
|
||||||
credits: userInfo.credits
|
credits: userInfo.credits,
|
||||||
|
membership: userInfo.membership
|
||||||
},
|
},
|
||||||
tierIconUrl: tierIconUrl
|
tierIconUrl: tierIconUrl
|
||||||
};
|
};
|
||||||
@ -511,6 +512,20 @@ export async function showICHelperPanel(
|
|||||||
hasWorkspace: hasWorkspace,
|
hasWorkspace: hasWorkspace,
|
||||||
});
|
});
|
||||||
break;
|
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,
|
undefined,
|
||||||
|
|||||||
@ -217,6 +217,17 @@ export class ICViewProvider implements vscode.WebviewViewProvider {
|
|||||||
vscode.commands.executeCommand("ic-coder.openChat");
|
vscode.commands.executeCommand("ic-coder.openChat");
|
||||||
} else if (message.command === "login") {
|
} else if (message.command === "login") {
|
||||||
vscode.commands.executeCommand("ic-coder.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,
|
undefined,
|
||||||
|
|||||||
@ -14,14 +14,20 @@ export function getUserInfoComponentContent(): string {
|
|||||||
<div class="user-detail-dropdown" id="userDetailDropdown">
|
<div class="user-detail-dropdown" id="userDetailDropdown">
|
||||||
<div class="user-detail-content">
|
<div class="user-detail-content">
|
||||||
<div class="user-detail-header">
|
<div class="user-detail-header">
|
||||||
<div class="user-avatar-small clickable" id="userAvatarClickable">
|
<div class="user-info-row">
|
||||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
<div class="user-avatar-small clickable" id="userAvatarClickable">
|
||||||
<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"/>
|
<svg 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"/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div class="user-name-tier">
|
||||||
|
<div class="user-detail-name clickable" id="userDetailName">加载中...</div>
|
||||||
|
<img class="tier-icon-inline" id="tierIconInline" style="display: none;" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="user-name-tier">
|
<!-- 升级到Pro按钮 (仅BASIC会员显示) -->
|
||||||
<div class="user-detail-name clickable" id="userDetailName">加载中...</div>
|
<div class="upgrade-pro-wrapper" id="upgradeProWrapper" style="display: none;">
|
||||||
<img class="tier-icon-inline" id="tierIconInline" style="display: none;" />
|
<button class="upgrade-pro-btn" id="upgradeProBtn">升级到 Pro</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -30,13 +36,31 @@ export function getUserInfoComponentContent(): string {
|
|||||||
<span class="detail-label">剩余 Credits</span>
|
<span class="detail-label">剩余 Credits</span>
|
||||||
<span class="detail-value" id="creditsDetail">-</span>
|
<span class="detail-value" id="creditsDetail">-</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="logout">
|
<div class="user-detail-item logout-item" id="logoutItem">
|
||||||
<button class="logout-btn" id="logoutBtn">退出登录</button>
|
<span class="detail-label">账户管理</span>
|
||||||
|
<span class="detail-value logout-link">退出登录</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</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 {
|
.user-detail-header {
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
flex-direction: column;
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
background: linear-gradient(135deg, rgba(0, 122, 204, 0.1) 0%, rgba(88, 166, 255, 0.05) 100%);
|
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);
|
border-bottom: 1px solid var(--vscode-widget-border);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.user-info-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
.user-avatar-small {
|
.user-avatar-small {
|
||||||
width: 26px;
|
width: 26px;
|
||||||
height: 26px;
|
height: 26px;
|
||||||
@ -175,6 +205,19 @@ export function getUserInfoComponentStyles(): string {
|
|||||||
margin-bottom: 0;
|
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 {
|
.detail-label {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
@ -191,6 +234,11 @@ export function getUserInfoComponentStyles(): string {
|
|||||||
gap: 6px;
|
gap: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.logout-link {
|
||||||
|
color: var(--vscode-foreground);
|
||||||
|
transition: color 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
.tier-icon-large {
|
.tier-icon-large {
|
||||||
height: 20px;
|
height: 20px;
|
||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
@ -204,28 +252,133 @@ export function getUserInfoComponentStyles(): string {
|
|||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.logout {
|
.upgrade-pro-wrapper {
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.logout-btn {
|
.upgrade-pro-btn {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 8px 12px;
|
padding: 6px 12px;
|
||||||
background: var(--vscode-button-background);
|
background: linear-gradient(135deg, #007acc 0%, #58a6ff 100%);
|
||||||
color: var(--vscode-button-foreground);
|
color: #ffffff;
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: 6px;
|
border-radius: 4px;
|
||||||
cursor: pointer;
|
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-size: 12px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
|
cursor: pointer;
|
||||||
transition: all 0.2s ease;
|
transition: all 0.2s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.logout-btn:hover {
|
.logout-cancel-btn {
|
||||||
background: var(--vscode-button-hoverBackground);
|
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);
|
transform: scale(0.98);
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@ -264,8 +417,28 @@ export function getUserInfoComponentScript(): string {
|
|||||||
|
|
||||||
// 退出登录
|
// 退出登录
|
||||||
function logout() {
|
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' });
|
vscode.postMessage({ command: 'logout' });
|
||||||
|
// 关闭确认对话框
|
||||||
|
closeLogoutConfirmModal();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭退出登录确认对话框
|
||||||
|
function closeLogoutConfirmModal() {
|
||||||
|
const modal = document.getElementById('logoutConfirmModal');
|
||||||
|
if (modal) {
|
||||||
|
modal.classList.remove('active');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 跳转到 IC Coder 官网
|
// 跳转到 IC Coder 官网
|
||||||
@ -274,6 +447,12 @@ export function getUserInfoComponentScript(): string {
|
|||||||
vscode.postMessage({ command: 'openICCoder' });
|
vscode.postMessage({ command: 'openICCoder' });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 升级到Pro
|
||||||
|
function upgradeToPro() {
|
||||||
|
console.log("升级到 Pro - 跳转到 IC Coder 官网");
|
||||||
|
vscode.postMessage({ command: 'openExternalUrl', url: 'https://www.iccoder.com' });
|
||||||
|
}
|
||||||
|
|
||||||
// 关闭用户详情下拉面板
|
// 关闭用户详情下拉面板
|
||||||
function closeUserDetailModal() {
|
function closeUserDetailModal() {
|
||||||
const dropdown = document.getElementById('userDetailDropdown');
|
const dropdown = document.getElementById('userDetailDropdown');
|
||||||
@ -320,6 +499,19 @@ export function getUserInfoComponentScript(): string {
|
|||||||
} else {
|
} else {
|
||||||
console.warn('[UserInfoComponent] creditsDetail 元素未找到');
|
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', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
// 绑定退出登录按钮
|
// 绑定退出登录卡片点击事件
|
||||||
const logoutBtn = document.getElementById('logoutBtn');
|
const logoutItem = document.getElementById('logoutItem');
|
||||||
if (logoutBtn) {
|
if (logoutItem) {
|
||||||
logoutBtn.addEventListener('click', () => {
|
logoutItem.addEventListener('click', () => {
|
||||||
logout();
|
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');
|
const userAvatar = document.getElementById('userAvatarClickable');
|
||||||
if (userAvatar) {
|
if (userAvatar) {
|
||||||
|
|||||||
@ -607,11 +607,13 @@ export function getWebviewContent(
|
|||||||
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
|
credits: message.userInfo.credits,
|
||||||
|
membership: message.userInfo.membership
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log('[WebView] 显示用户信息:', userInfoData);
|
console.log('[WebView] 显示用户信息:', userInfoData);
|
||||||
console.log('[WebView] userInfoData.credits:', userInfoData.credits);
|
console.log('[WebView] userInfoData.credits:', userInfoData.credits);
|
||||||
|
console.log('[WebView] userInfoData.membership:', userInfoData.membership);
|
||||||
|
|
||||||
// 调用更新用户头像图标按钮的函数
|
// 调用更新用户头像图标按钮的函数
|
||||||
if (typeof updateUserAvatarIconButton === 'function') {
|
if (typeof updateUserAvatarIconButton === 'function') {
|
||||||
|
|||||||
Reference in New Issue
Block a user