Files
IC-Coder-Plugin/src/views/invitationModal.ts

458 lines
12 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 邀请码验证弹窗
*/
/**
* 获取邀请码弹窗的 HTML 内容
*/
export function getInvitationModalContent(
qrCodeUri?: string,
logoUri?: string,
): string {
return `
<!-- 邀请码验证弹窗 -->
<div id="invitationModal" class="invitation-modal" style="display: none;">
<div class="invitation-modal-overlay"></div>
<div class="invitation-modal-content">
${logoUri ? `<img src="${logoUri}" class="invitation-logo-corner" alt="IC Coder" />` : ""}
<button id="invitationCloseBtn" class="invitation-close-btn" title="关闭">
<svg width="14" height="14" viewBox="0 0 14 14" fill="none">
<path d="M1 1L13 13M13 1L1 13" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
</svg>
</button>
<div class="invitation-modal-header">
<!-- <div class="invitation-icon">🔐</div> -->
<h2>欢迎使用 IC Coder</h2>
<p class="invitation-modal-subtitle">目前IC Coder插件端仅供企业端付费用户使用2026年3月起会逐步开放给所有用户使用~</p>
</div>
<div class="invitation-modal-body">
<div class="invitation-qrcode-section">
<div class="invitation-qrcode-wrapper">
<img src="${qrCodeUri}" alt="微信二维码" class="invitation-qrcode-image" />
</div>
<p class="invitation-qrcode-text">欢迎扫码添加微信,填写《企业试用申请表》获取邀请码,与我们一起加速芯片设计与验证吧!</p>
</div>
<div class="invitation-divider">
</div>
<div class="invitation-input-section">
<label class="invitation-input-label">邀请码</label>
<input
type="text"
id="invitationCodeInput"
class="invitation-code-input"
placeholder="请输入您的邀请码"
maxlength="20"
/>
<div id="invitationError" class="invitation-error" style="display: none;"></div>
<button id="invitationSubmitBtn" class="invitation-btn invitation-btn-primary">
<span>立即验证</span>
<svg width="16" height="16" viewBox="0 0 16 16" fill="none">
<path d="M6 3L11 8L6 13" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</button>
</div>
</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;
padding: 20px;
font-family: var(--vscode-font-family, "Segoe UI", Tahoma, Geneva, Verdana, sans-serif);
}
.invitation-modal-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.7);
backdrop-filter: blur(5px);
animation: fadeIn 0.3s ease-out;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
.invitation-modal-content {
position: relative;
background: var(--vscode-editor-background);
border: 1px solid var(--vscode-widget-border);
border-radius: 12px;
width: 100%;
max-width: 420px;
box-shadow: 0 16px 48px rgba(0, 0, 0, 0.5);
animation: modalSlideIn 0.3s cubic-bezier(0.2, 0.8, 0.2, 1);
overflow: hidden;
display: flex;
flex-direction: column;
}
.invitation-close-btn {
position: absolute;
top: 16px;
right: 16px;
width: 32px;
height: 32px;
border: none;
background: transparent;
color: var(--vscode-descriptionForeground);
cursor: pointer;
border-radius: 6px;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s;
z-index: 10;
}
.invitation-logo-corner {
position: absolute;
top: 16px;
left: 24px;
height: 40px;
width: auto;
opacity: 0.9;
z-index: 10;
}
.invitation-close-btn:hover {
background: var(--vscode-toolbar-hoverBackground);
color: var(--vscode-foreground);
}
.invitation-close-btn:active {
transform: scale(0.95);
}
@keyframes modalSlideIn {
from {
opacity: 0;
transform: translateY(20px) scale(0.98);
}
to {
opacity: 1;
transform: translateY(0) scale(1);
}
}
.invitation-modal-header {
padding: 60px 32px 20px;
text-align: center;
}
.invitation-modal-header h2 {
margin: 0 0 12px;
font-size: 20px;
font-weight: 600;
color: var(--vscode-foreground);
}
.invitation-modal-subtitle {
margin: 0;
font-size: 13px;
color: var(--vscode-descriptionForeground);
line-height: 1.5;
}
.invitation-modal-body {
padding: 0 32px 32px;
}
.invitation-qrcode-section {
text-align: center;
margin-bottom: 24px;
background: var(--vscode-editor-inactiveSelectionBackground);
padding: 20px;
border-radius: 8px;
margin-top: 10px;
}
.invitation-qrcode-wrapper {
display: inline-block;
padding: 8px;
background: #fff;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
}
.invitation-qrcode-image {
width: 150px;
height: 150px;
display: block;
}
.invitation-qrcode-text {
margin-top: 12px;
font-size: 12px;
color: var(--vscode-descriptionForeground);
line-height: 1.5;
}
.invitation-divider {
display: flex;
align-items: center;
margin: 20px 0;
color: var(--vscode-descriptionForeground);
font-size: 12px;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.invitation-divider::before,
.invitation-divider::after {
content: '';
flex: 1;
height: 1px;
background: var(--vscode-widget-border);
opacity: 0.5;
}
.invitation-divider span {
padding: 0 12px;
}
.invitation-input-section {
display: flex;
flex-direction: column;
gap: 12px;
}
.invitation-input-label {
font-size: 13px;
font-weight: 600;
color: var(--vscode-foreground);
}
.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: 6px;
outline: none;
box-sizing: border-box;
transition: border-color 0.2s;
}
.invitation-code-input:focus {
border-color: var(--vscode-focusBorder);
/* box-shadow: 0 0 0 2px var(--vscode-focusBorder); */
}
.invitation-code-input::placeholder {
color: var(--vscode-input-placeholderForeground);
}
.invitation-error {
padding: 8px 12px;
font-size: 12px;
color: var(--vscode-errorForeground);
background: var(--vscode-inputValidation-errorBackground);
border: 1px solid var(--vscode-inputValidation-errorBorder);
border-radius: 6px;
animation: shakeError 0.4s ease-in-out;
}
@keyframes shakeError {
0%, 100% { transform: translateX(0); }
25% { transform: translateX(-6px); }
75% { transform: translateX(6px); }
}
.invitation-btn {
width: 100%;
padding: 10px 16px;
font-size: 14px;
font-weight: 600;
border: none;
border-radius: 6px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
background: var(--vscode-button-background);
color: var(--vscode-button-foreground);
transition: all 0.2s;
}
.invitation-btn:hover {
background: var(--vscode-button-hoverBackground);
transform: translateY(-1px);
box-shadow: 0 2px 8px rgba(0,0,0,0.2);
}
.invitation-btn:active {
transform: translateY(0);
}
.invitation-btn:disabled {
opacity: 0.5;
cursor: not-allowed;
transform: none;
box-shadow: none;
}
.invitation-btn svg {
width: 16px;
height: 16px;
}
`;
}
/**
* 获取邀请码弹窗的 JavaScript 逻辑
*/
export function getInvitationModalScript(): string {
return `
// 邀请码弹窗逻辑
(function() {
const modal = document.getElementById('invitationModal');
const input = document.getElementById('invitationCodeInput');
const submitBtn = document.getElementById('invitationSubmitBtn');
const closeBtn = document.getElementById('invitationCloseBtn');
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);
// 点击关闭按钮
if (closeBtn) {
closeBtn.addEventListener('click', function(e) {
console.log('[InvitationModal] Close button clicked');
e.preventDefault();
e.stopPropagation();
hideInvitationModal();
});
}
// 回车键提交
input.addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
submitInvitationCode();
}
});
// 点击遮罩层关闭弹窗
document.querySelector('.invitation-modal-overlay').addEventListener('click', function() {
hideInvitationModal();
});
// 阻止点击弹窗内容时关闭
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 || '验证失败,请重试');
}
}
});
})();
`;
}