613 lines
17 KiB
TypeScript
613 lines
17 KiB
TypeScript
/**
|
|
* 用户信息组件
|
|
* 包含用户头像、昵称、会员等级等信息
|
|
*/
|
|
|
|
/**
|
|
* 获取用户信息组件的 HTML 内容
|
|
* 只包含用户详情下拉面板,不包含触发按钮
|
|
*/
|
|
export function getUserInfoComponentContent(): string {
|
|
return `
|
|
<div class="user-info-wrapper">
|
|
<!-- 用户详情下拉面板 -->
|
|
<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"/>
|
|
</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>
|
|
<!-- 升级到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="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>
|
|
`;
|
|
}
|
|
|
|
/**
|
|
* 获取用户信息组件的 CSS 样式
|
|
*/
|
|
export function getUserInfoComponentStyles(): string {
|
|
return `
|
|
.user-info-wrapper {
|
|
position: relative;
|
|
}
|
|
|
|
/* 用户详情下拉面板 */
|
|
.user-detail-dropdown {
|
|
display: none;
|
|
position: absolute;
|
|
top: calc(100% + 8px);
|
|
right: 0;
|
|
z-index: 10000;
|
|
min-width: 250px;
|
|
max-width: 320px;
|
|
}
|
|
|
|
.user-detail-dropdown.active {
|
|
display: block;
|
|
animation: dropdownSlideIn 0.2s ease-out;
|
|
}
|
|
|
|
@keyframes dropdownSlideIn {
|
|
from {
|
|
opacity: 0;
|
|
transform: translateY(-10px);
|
|
}
|
|
to {
|
|
opacity: 1;
|
|
transform: translateY(0);
|
|
}
|
|
}
|
|
|
|
.user-detail-content {
|
|
background: var(--vscode-sideBar-background);
|
|
border: 1px solid var(--vscode-widget-border);
|
|
border-radius: 8px;
|
|
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
|
|
overflow: hidden;
|
|
}
|
|
|
|
.user-detail-header {
|
|
padding: 16px;
|
|
display: flex;
|
|
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;
|
|
flex-shrink: 0;
|
|
background: linear-gradient(135deg, #007acc 0%, #58a6ff 100%);
|
|
border-radius: 50%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
box-shadow: 0 2px 8px rgba(0, 122, 204, 0.3);
|
|
transition: all 0.2s ease;
|
|
}
|
|
|
|
.user-avatar-small.clickable {
|
|
cursor: pointer;
|
|
}
|
|
|
|
.user-avatar-small.clickable:hover {
|
|
transform: scale(1.1);
|
|
box-shadow: 0 4px 12px rgba(0, 122, 204, 0.5);
|
|
}
|
|
|
|
.user-avatar-small svg {
|
|
width: 18px;
|
|
height: 18px;
|
|
color: #ffffff;
|
|
}
|
|
|
|
.user-name-tier {
|
|
flex: 1;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
}
|
|
|
|
.user-detail-name {
|
|
font-size: 14px;
|
|
font-weight: 600;
|
|
color: var(--vscode-foreground);
|
|
transition: all 0.2s ease;
|
|
}
|
|
|
|
.user-detail-name.clickable {
|
|
cursor: pointer;
|
|
}
|
|
|
|
.user-detail-name.clickable:hover {
|
|
color: #007acc;
|
|
text-decoration: underline;
|
|
}
|
|
|
|
.tier-icon-inline {
|
|
height: 26px;
|
|
object-fit: contain;
|
|
}
|
|
|
|
.user-detail-body {
|
|
padding: 12px;
|
|
background: var(--vscode-sideBar-background);
|
|
}
|
|
|
|
.user-detail-item {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding: 10px 12px;
|
|
margin-bottom: 6px;
|
|
background: var(--vscode-editor-background);
|
|
border-radius: 6px;
|
|
border: 1px solid var(--vscode-widget-border);
|
|
transition: all 0.2s ease;
|
|
}
|
|
|
|
.user-detail-item:hover {
|
|
background: var(--vscode-list-hoverBackground);
|
|
border-color: rgba(0, 122, 204, 0.3);
|
|
}
|
|
|
|
.user-detail-item:last-child {
|
|
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;
|
|
color: var(--vscode-descriptionForeground);
|
|
opacity: 0.8;
|
|
}
|
|
|
|
.detail-value {
|
|
font-size: 12px;
|
|
font-weight: 500;
|
|
color: var(--vscode-foreground);
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
}
|
|
|
|
.logout-link {
|
|
color: var(--vscode-foreground);
|
|
transition: color 0.2s ease;
|
|
}
|
|
|
|
.tier-icon-large {
|
|
height: 20px;
|
|
object-fit: contain;
|
|
}
|
|
|
|
.tier-icon {
|
|
width: 110px;
|
|
height: 35px;
|
|
flex-shrink: 0;
|
|
object-fit: contain;
|
|
border-radius: 4px;
|
|
}
|
|
|
|
.upgrade-pro-wrapper {
|
|
margin-top: 8px;
|
|
}
|
|
|
|
.upgrade-pro-btn {
|
|
width: 100%;
|
|
padding: 6px 12px;
|
|
background: linear-gradient(135deg, #007acc 0%, #58a6ff 100%);
|
|
color: #ffffff;
|
|
border: none;
|
|
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-cancel-btn {
|
|
background: var(--vscode-button-secondaryBackground);
|
|
color: var(--vscode-button-secondaryForeground);
|
|
}
|
|
|
|
.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);
|
|
}
|
|
`;
|
|
}
|
|
|
|
/**
|
|
* 获取用户信息组件的 JavaScript 脚本
|
|
*/
|
|
export function getUserInfoComponentScript(): string {
|
|
return `
|
|
// 用户信息数据
|
|
let currentUserInfo = null;
|
|
|
|
// 切换用户详情下拉面板
|
|
function openUserDetailModal() {
|
|
const dropdown = document.getElementById('userDetailDropdown');
|
|
const userButton = document.getElementById('userAvatarIconButton');
|
|
|
|
if (dropdown) {
|
|
const isActive = dropdown.classList.contains('active');
|
|
if (isActive) {
|
|
dropdown.classList.remove('active');
|
|
if (userButton) {
|
|
userButton.classList.remove('active');
|
|
}
|
|
} else {
|
|
dropdown.classList.add('active');
|
|
if (userButton) {
|
|
userButton.classList.add('active');
|
|
}
|
|
// 更新下拉面板中的用户信息
|
|
updateUserDetailModal();
|
|
}
|
|
}
|
|
}
|
|
|
|
// 退出登录
|
|
function logout() {
|
|
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 官网
|
|
function openICCoder() {
|
|
console.log("跳转到 IC Coder 官网");
|
|
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');
|
|
const userButton = document.getElementById('userAvatarIconButton');
|
|
|
|
if (dropdown) {
|
|
dropdown.classList.remove('active');
|
|
}
|
|
if (userButton) {
|
|
userButton.classList.remove('active');
|
|
}
|
|
}
|
|
|
|
// 更新用户详情下拉面板内容
|
|
function updateUserDetailModal() {
|
|
if (!currentUserInfo) {
|
|
return;
|
|
}
|
|
|
|
// 更新用户名
|
|
const userDetailName = document.getElementById('userDetailName');
|
|
if (userDetailName) {
|
|
userDetailName.textContent = currentUserInfo.nickname || '未知用户';
|
|
}
|
|
|
|
// 更新会员等级图标(显示在用户名旁边)
|
|
const tierIconInline = document.getElementById('tierIconInline');
|
|
if (tierIconInline && currentUserInfo.tierIconUrl) {
|
|
tierIconInline.src = currentUserInfo.tierIconUrl;
|
|
tierIconInline.style.display = 'block';
|
|
} else if (tierIconInline) {
|
|
tierIconInline.style.display = 'none';
|
|
}
|
|
|
|
// 更新剩余 Credits
|
|
const creditsDetail = document.getElementById('creditsDetail');
|
|
console.log('[UserInfoComponent] 更新 Credits 显示');
|
|
console.log('[UserInfoComponent] currentUserInfo.credits:', currentUserInfo.credits);
|
|
console.log('[UserInfoComponent] creditsDetail 元素:', creditsDetail);
|
|
if (creditsDetail) {
|
|
const creditsText = currentUserInfo.credits !== undefined ? currentUserInfo.credits.toString() : '-';
|
|
creditsDetail.textContent = creditsText;
|
|
console.log('[UserInfoComponent] Credits 已更新为:', creditsText);
|
|
} 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 元素未找到');
|
|
}
|
|
}
|
|
|
|
// 更新用户信息显示
|
|
function updateUserInfoDisplay(userInfo) {
|
|
currentUserInfo = userInfo;
|
|
console.log('[UserInfoComponent] 更新用户信息:', userInfo);
|
|
// 如果下拉面板已打开,立即更新显示
|
|
const dropdown = document.getElementById('userDetailDropdown');
|
|
if (dropdown && dropdown.classList.contains('active')) {
|
|
updateUserDetailModal();
|
|
}
|
|
}
|
|
|
|
// 绑定下拉面板事件
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
// 绑定退出登录卡片点击事件
|
|
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) {
|
|
userAvatar.addEventListener('click', (e) => {
|
|
e.stopPropagation();
|
|
openICCoder();
|
|
});
|
|
}
|
|
|
|
// 绑定用户名点击事件
|
|
const userName = document.getElementById('userDetailName');
|
|
if (userName) {
|
|
userName.addEventListener('click', (e) => {
|
|
e.stopPropagation();
|
|
openICCoder();
|
|
});
|
|
}
|
|
|
|
// 点击页面其他地方关闭下拉面板
|
|
document.addEventListener('click', (e) => {
|
|
const dropdown = document.getElementById('userDetailDropdown');
|
|
const userButton = document.getElementById('userAvatarIconButton');
|
|
|
|
if (dropdown && dropdown.classList.contains('active')) {
|
|
// 如果点击的不是用户按钮和下拉面板内容,则关闭
|
|
if (!userButton?.contains(e.target) && !dropdown.contains(e.target)) {
|
|
closeUserDetailModal();
|
|
}
|
|
}
|
|
});
|
|
|
|
// 阻止下拉面板内容点击事件冒泡
|
|
const dropdownContent = document.querySelector('.user-detail-content');
|
|
if (dropdownContent) {
|
|
dropdownContent.addEventListener('click', (e) => {
|
|
e.stopPropagation();
|
|
});
|
|
}
|
|
});
|
|
`;
|
|
}
|