refactor: switch to free-trial/private-deploy/buyout pricing, fix feature gaps, add SEO landing + deploy config

This commit is contained in:
TradeMate Dev
2026-07-12 08:09:28 +08:00
parent 9ca5d79d8a
commit 04924e3bc4
36 changed files with 1026 additions and 975 deletions
+7
View File
@@ -136,3 +136,10 @@ export async function generateKeywords(productName, description, count = 10) {
body: { product_name: productName, description, count, language: 'en' },
});
}
/** Extract structured customer info from pasted text */
export async function extractInfo(text, extractType = 'auto') {
return request('/api/v1/translate/extract', {
body: { text, extract_type: extractType },
});
}
+27 -12
View File
@@ -42,6 +42,7 @@
<button class="tab" data-tab="reply">回复</button>
<button class="tab" data-tab="discovery">发现</button>
<button class="tab" data-tab="marketing">营销</button>
<button class="tab" data-tab="extract">客户</button>
</div>
<!-- Tab: Translate -->
@@ -86,19 +87,33 @@
</div>
<!-- Tab: Marketing -->
<div id="tab-marketing" class="tab-content">
<input type="text" id="marketing-name" placeholder="产品名称" />
<textarea id="marketing-desc" rows="3" placeholder="产品描述..."></textarea>
<div class="row">
<select id="marketing-style">
<option value="professional">专业</option>
<option value="friendly">友好</option>
<option value="luxury">高端</option>
</select>
<button id="marketing-btn" class="btn btn-primary">生成文案</button>
<div id="tab-marketing" class="tab-content">
<input type="text" id="marketing-name" placeholder="产品名称" />
<textarea id="marketing-desc" rows="3" placeholder="产品描述..."></textarea>
<div class="row">
<select id="marketing-style">
<option value="professional">专业</option>
<option value="friendly">友好</option>
<option value="luxury">高端</option>
</select>
<button id="marketing-btn" class="btn btn-primary">生成文案</button>
</div>
<div id="marketing-result" class="result-box"></div>
</div>
<!-- Tab: Extract customer info -->
<div id="tab-extract" class="tab-content">
<textarea id="extract-input" rows="5" placeholder="粘贴客户名片 / 邮件签名 / 网页介绍,自动提取姓名、公司、邮箱、电话、国家等"></textarea>
<div class="row">
<select id="extract-type">
<option value="auto">自动识别</option>
<option value="contact">联系人</option>
<option value="company">公司</option>
</select>
<button id="extract-btn" class="btn btn-primary">提取客户</button>
</div>
<div id="extract-result" class="result-box"></div>
</div>
<div id="marketing-result" class="result-box"></div>
</div>
</div>
<!-- Footer -->
+30 -2
View File
@@ -7,6 +7,7 @@ import {
generateReply,
searchLeads,
generateMarketing,
extractInfo,
getBalance,
getSubscriptionPlans,
getCreditPackages,
@@ -53,6 +54,11 @@ const marketingStyle = $('marketing-style');
const marketingBtn = $('marketing-btn');
const marketingResult = $('marketing-result');
const extractInput = $('extract-input');
const extractType = $('extract-type');
const extractBtn = $('extract-btn');
const extractResult = $('extract-result');
const creditsDisplay = $('credits-display');
const btnSettings = $('btn-settings');
const upgradeBanner = $('upgrade-banner');
@@ -215,7 +221,7 @@ function setupUpgradeUI() {
// Open backend payment page or settings page
// For now, open the workspace credits page
chrome.tabs.create({
url: `${settingsUrl.value?.replace(/\/+$/, '') || 'https://trade.yuzhiran.com'}/workspace/credits`,
url: `${settingsUrl.value?.replace(/\/+$/, '') || 'https://trade.yuzhiran.com'}/workspace/upgrade`,
});
hideUpgradeModal();
});
@@ -225,7 +231,7 @@ function setupUpgradeUI() {
btn.addEventListener('click', () => {
const pkg = btn.dataset.pkg;
chrome.tabs.create({
url: `${settingsUrl.value?.replace(/\/+$/, '') || 'https://trade.yuzhiran.com'}/workspace/credits`,
url: `${settingsUrl.value?.replace(/\/+$/, '') || 'https://trade.yuzhiran.com'}/workspace/upgrade`,
});
hidePackageModal();
});
@@ -465,6 +471,28 @@ function setupActions() {
}
});
});
// Extract customer info
extractBtn.addEventListener('click', async () => {
const text = extractInput.value.trim();
if (!text) return;
setLoading(extractBtn, true);
showResult(extractResult, '<div class="loading"><span class="spinner"></span>提取中...</div>');
try {
const result = await extractInfo(text, extractType.value);
const info = result.extracted || {};
const rows = Object.entries(info)
.filter(([, v]) => v !== null && v !== undefined && v !== '')
.map(([k, v]) => `<div class="item"><div class="item-label">${escapeHtml(k)}</div><div>${escapeHtml(String(Array.isArray(v) ? v.join(', ') : v))}</div></div>`)
.join('');
showResult(extractResult, rows || '(无提取结果)');
refreshCredits();
} catch (err) {
handleApiError(extractResult, err);
} finally {
setLoading(extractBtn, false);
}
});
}
// Auto-init on load