Files
trade-assistant/docs/CREDIT_SYSTEM.md
T
TradeMate Dev 2a107a42f3 feat: credit-based billing system
- New DB models: credit_packages, subscription_plans, user_credits, credit_consumptions, credit_purchases
- CreditService: balance, deduct, add_credits, grant_free_trial, history
- User API: /api/v1/credits/* (balance/history/packages/purchase/subscribe)
- Admin API: /api/v1/admin/credit-* (CRUD packages/plans, user credits, consumptions)
- PaymentService.create_credit_order + handle_callback for credit purchases
- Credit deduction on: discovery, translate, marketing, ai_chat, followup
- Free trial 30 credits on registration
- Documentation: docs/CREDIT_SYSTEM.md
2026-06-12 10:39:45 +08:00

400 lines
13 KiB
Markdown
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.
# TradeMate Credit System — 信用计费系统设计方案
## 1. 业务模式变更
### 1.1 从工具订阅 → 结果付费
- **旧模式**:按月订阅解锁功能(Free/Pro/Enterprise
- **新模式**:按次付费购买"结果",所有 AI 功能统一消耗信用额度(Credits)
- **核心**:用户不为功能付费,为**产生的价值**(客户线索、分析报告、翻译字符)付费
### 1.2 目标用户群
- **国内**:中国外贸 SOHO/小团队 → 中文界面,¥ 计价
- **海外**:全球跨境小B → 英文界面,$ 计价
- 两端统一产品逻辑,分语言/货币展示
### 1.3 产品定位
| 维度 | 旧 | 新 |
|------|-----|-----|
| 定位 | 外贸工具套装 | 外贸客户发现引擎 |
| Slogan | 外贸小助手 | Customer Discovery Engine / 外贸获客引擎 |
| 核心价值 | 多功能的工具箱 | 输入产品,找到买家 |
| 免费策略 | 限功能免费版 | 注册送 N 次,用完即购 |
| 收费锚点 | 按月付费解锁 | 按产出结果扣次 |
## 2. 信用额度系统(Credits
### 2.1 定义
**1 Credit = 1 次消费单位。** 所有 AI 调用均以 Credits 计价。
用户持有的 Credits 通过两种方式获得:
- **一次性购买(Credit Pack)**:永不过期,用不完的余额留存
- **月订阅(Subscription)**:每月自动到账,月底未用完清零
两种方式的 Credits 统一存放在 `user_credits.balance` 中,消费时按 `source` 记录来源。
### 2.2 消费价格表
所有 AI 相关功能均消耗 Credits,覆盖 API 调用成本:
| 功能 | Credits | 说明 |
|------|---------|------|
| **客户搜索** (lead_search) | 10 | 多源搜索 + AI 匹配 + 联系方式提取 |
| **公司深度分析** (company_analysis) | 5 | 单家公司 AI 分析报告 |
| **市场情报报告** (market_intel) | 20 | 多维度市场研究 |
| **翻译** (translate, 5000 chars) | 5 | 按字符计费,不足按比例折算 |
| **回复建议** (reply_suggest) | 2 | AI 生成 3 条回复建议 |
| **开发信生成** (outreach) | 3 | 单封定制开发信 |
| **营销素材** (marketing_content) | 5 | 多风格营销文案 |
| **竞品分析** (competitor_analysis) | 10 | 多个竞品对比分析 |
| **AI 助手对话** (ai_chat, 10条消息) | 1 | 普通 AI 对话 |
| **信息提取** (info_extract) | 1 | 询盘/邮件信息提取 |
| **报价单生成** (quotation) | 2 | AI 辅助报价 |
| **跟进策略** (followup_scan) | 2 | AI 扫描跟进建议 |
### 2.3 计费规则
- **按次扣减**:功能调用成功后扣减,失败不扣
- **余额不足**:返回 `402 Payment Required` + 当前余额 + 所需额度
- **不足扣减**:如余额不足单次消费,允许扣至负数(欠费模式),欠费部分下次充值自动抵扣
- **日免费额度**:翻译每日免费 1000 字符(防流失),超出部分扣 Credits
- **免费试用**:新用户注册自动赠送 30 Credits(≈ 3 次搜索)
### 2.4 消费记录
每次扣减记录在 `credit_consumptions` 表,包含:
- user_id, result_type(功能类型)
- reference_id(关联业务记录 ID
- credits_change(正数 = 充值,负数 = 消费)
- balance_after(扣减后余额)
- sourcepackage/subscription/admin_grant
- metadata(Jsonb,保存上下文,如搜索关键词、翻译字符数)
## 3. 定价体系
### 3.1 次数包(一次性,永不过期)
| 次数 | 价格(¥) | 次均 | 价格($) |
|------|---------|------|---------|
| 20 | ¥19 | ¥0.95 | $3 |
| 100 | ¥79 | ¥0.79 | $12 |
| 500 | ¥299 | ¥0.60 | $45 |
| 2000 | ¥899 | ¥0.45 | $138 |
### 3.2 订阅套餐(每月重置)
| 套餐 | 月次数 | 月费(¥) | 月费($) | 次均 |
|------|-------|---------|---------|------|
| Starter | 100 | ¥69 | $10 | ¥0.69 |
| Pro | 500 | ¥269 | $40 | ¥0.54 |
| Enterprise | 2000 | ¥699 | $105 | ¥0.35 |
### 3.3 新旧过渡方案
- 现有有效订阅用户 → 按剩余天数折算为 Credits 存入余额
- Pro 剩余 15 天 ≈ 100 × 0.5 ≈ 50 Credits 一次性赠送
- 同时保留原订阅到期日
- 新用户 → 走新信用系统
- 过渡期两种支付方式并存
## 4. 数据库设计
### 4.1 新增表
```sql
-- 次数包定义(一次性购买)
CREATE TABLE credit_packages (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name VARCHAR(100) NOT NULL, -- 中文名
name_en VARCHAR(100) NOT NULL, -- 英文名
credits INTEGER NOT NULL, -- 额定量
price NUMERIC(10,2) NOT NULL, -- 人民币价格
price_usd NUMERIC(10,2), -- 美元价格
original_price NUMERIC(10,2), -- 原价(划线价)
is_active BOOLEAN DEFAULT TRUE,
sort_order INTEGER DEFAULT 0,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
-- 订阅套餐定义(周期性)
CREATE TABLE subscription_plans (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name VARCHAR(100) NOT NULL,
name_en VARCHAR(100) NOT NULL,
credits_per_month INTEGER NOT NULL,
price NUMERIC(10,2) NOT NULL,
price_usd NUMERIC(10,2),
duration_days INTEGER NOT NULL DEFAULT 30,
is_active BOOLEAN DEFAULT TRUE,
sort_order INTEGER DEFAULT 0,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
-- 用户信用余额
CREATE TABLE user_credits (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL UNIQUE REFERENCES users(id),
balance NUMERIC(12,1) NOT NULL DEFAULT 0, -- 当前余额(支持小数)
total_purchased NUMERIC(12,1) NOT NULL DEFAULT 0,
total_used NUMERIC(12,1) NOT NULL DEFAULT 0,
-- 订阅关联
subscription_plan_id UUID REFERENCES subscription_plans(id),
subscription_expires_at TIMESTAMP,
subscription_auto_renew BOOLEAN DEFAULT FALSE,
-- 免费赠送标记
free_trial_used BOOLEAN DEFAULT FALSE,
daily_translate_chars INTEGER DEFAULT 0,
daily_translate_date DATE,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
-- 信用消费日志
CREATE TABLE credit_consumptions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id),
result_type VARCHAR(50) NOT NULL, -- lead_search / translate / outreach / ...
reference_id UUID, -- 关联业务记录
credits_change NUMERIC(10,1) NOT NULL, -- 负=消费,正=充值
balance_after NUMERIC(12,1) NOT NULL,
source VARCHAR(30) NOT NULL, -- package / subscription / admin_grant / free_trial / daily_free
description VARCHAR(500),
metadata JSONB,
created_at TIMESTAMP DEFAULT NOW()
);
-- 次数包购买记录
CREATE TABLE credit_purchases (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id),
package_id UUID REFERENCES credit_packages(id),
subscription_plan_id UUID REFERENCES subscription_plans(id),
credits INTEGER NOT NULL,
amount NUMERIC(10,2) NOT NULL,
currency VARCHAR(3) DEFAULT 'CNY',
payment_method VARCHAR(20), -- alipay / wechat / stripe
status VARCHAR(20) DEFAULT 'pending', -- pending / paid / refunded
payment_transaction_id UUID REFERENCES payment_transactions(id),
created_at TIMESTAMP DEFAULT NOW(),
paid_at TIMESTAMP
);
```
### 4.2 索引
```sql
CREATE INDEX idx_credit_consumptions_user ON credit_consumptions(user_id, created_at DESC);
CREATE INDEX idx_credit_consumptions_type ON credit_consumptions(result_type);
CREATE INDEX idx_credit_purchases_user ON credit_purchases(user_id);
CREATE INDEX idx_credit_purchases_status ON credit_purchases(status);
```
### 4.3 配置项
```json
{
"free_trial_credits": {"value": 30, "desc": "新用户免费赠送次数"},
"daily_free_translate_chars": {"value": 1000, "desc": "每日免费翻译字符数"},
"credit_consumption_rates": {
"value": {
"lead_search": 10,
"company_analysis": 5,
"market_intel": 20,
"translate_per_1000chars": 1,
"reply_suggest": 2,
"outreach": 3,
"marketing_content": 5,
"competitor_analysis": 10,
"ai_chat_per_10msg": 1,
"info_extract": 1,
"quotation": 2,
"followup_scan": 2
},
"desc": "各功能信用消耗速率"
}
}
```
## 5. API 设计
### 5.1 信用系统
```
GET /api/v1/credits/balance → 余额+订阅信息
GET /api/v1/credits/history?page=&size= → 消费历史
POST /api/v1/credits/packages → 购买次数包(走支付网关)
POST /api/v1/credits/subscribe → 开通订阅
POST /api/v1/credits/cancel-subscription → 取消订阅
GET /api/v1/credits/packages → 次数包列表
GET /api/v1/credits/subscription-plans → 订阅套餐列表
GET /api/v1/credits/rates → 各功能消耗速率
```
### 5.2 现有功能增加额度扣减
所有 AI 功能在返回结果后调用 `CreditService.deduct()`
```python
# 在每个 AI 功能服务层中(discovery/discovery.py, translate/translation.py, etc.)
from app.services.credit import CreditService
svc = CreditService(db)
success, balance = await svc.deduct(user_id, "lead_search", reference_id=record_id)
if not success:
raise HTTPException(status_code=402, detail="次数不足")
```
### 5.3 管理端
```
GET /api/v1/admin/credit-packages → CRUD
POST /api/v1/admin/credit-packages
PUT /api/v1/admin/credit-packages/{id}
DELETE /api/v1/admin/credit-packages/{id}
GET /api/v1/admin/subscription-plans → CRUD
POST /api/v1/admin/subscription-plans
PUT /api/v1/admin/subscription-plans/{id}
GET /api/v1/admin/user-credits → 用户余额列表
POST /api/v1/admin/user-credits/adjust → 手动调整余额
GET /api/v1/admin/credit-consumptions → 消费流水
GET /api/v1/admin/credit-stats → 统计数据
```
## 6. 前端改造
### 6.1 导航栏重构
```
新用户侧边栏(按优先级):
【核心】
★ 发现客户 /discovery ← 首页
市场情报 /market-intel ← 新增
我的线索 /my-leads ← 新增(收藏/保存的线索)
【工具(增值)】
客户管理 /customers
产品库 /products
报价单 /quotations
智能翻译 /translate
开发信 /outreach
营销素材 /marketing
【查看】
工作台 /workspace ← 仪表盘(用量统计/最近操作)
团队协作 /team
个人中心 /profile
```
### 6.2 Topbar 改造
顶部始终显示 `余额: X.X 次` 按钮,点击跳转购买页。
```html
<el-button class="credit-balance" @click="$router.push('/credits')">
<el-icon><Coin /></el-icon>
{{ balance }} 次
</el-button>
```
### 6.3 购买页面
替代现有 `/upgrade` 路由为 `/credits`
- Tab1: **次数包** — 多卡片展示(20/100/500/2000次),支付弹窗
- Tab2: **订阅套餐** — Starter/Pro/Enterprise,月付/年付
- Tab3: **消费明细** — 近期消费流水
### 6.4 余额不足引导
所有 AI 功能检测到余额不足时,前端弹窗:
```
"次数不足,当前剩余 X 次,本次操作需要 Y 次
[去购买] [取消]"
```
### 6.5 免费额度提示
新用户注册后首页显示:
```
"欢迎使用 TradeMate!您有 30 次免费搜索额度,用完即止。"
```
## 7. 国际化
### 7.1 第一阶段(核心页面)
| 页面 | 优先级 |
|------|--------|
| 登录/注册 | P0 |
| 导航栏 | P0 |
| 发现客户 | P0 |
| 购买页面 | P0 |
| 工作台 | P1 |
| 翻译 | P1 |
| 个人中心 | P1 |
### 7.2 技术方案
- 使用 vue-i18n + JSON locale files
- `zh-CN.json`(默认)+ `en.json`
- 通过 URL query `?lang=en` 或 Cookie 切换
- 管理后台跟随用户语言偏好
```json
// en.json
{
"nav": {
"discovery": "Find Buyers",
"translate": "Translate",
"customers": "Customers",
"credits": "Buy Credits"
},
"discovery": {
"search_placeholder": "e.g. LED lighting, solar panels...",
"search_button": "Search Buyers",
"credits_cost": "This search costs 10 credits"
}
}
```
## 8. 实施计划
### Phase 1 — 信用系统后端(当前)
1. 数据库模型 + migration
2. CreditService
3. 信用系统 API
4. 管理端 CRUD
### Phase 2 — 功能接入扣次
1. Discovery 接入(搜索/分析/市场报告)
2. Translate 接入
3. Marketing 接入
4. AI Chat / Outreach 接入
### Phase 3 — 前端改造
1. 新导航 + 余额显示
2. 购买/订阅页面
3. 余额不足引导
4. 工作台改仪表盘
### Phase 4 — 国际化 + 定价上线
1. 中英文切换
2. 海外支付(Stripe
3. 定价正式发布
4. 老用户数据迁移
## 9. 关键风险
| 风险 | 缓解 |
|------|------|
| 用户觉得按次付费贵 | 免费 30 次让用户先体验价值;套餐价需低于用户感知价值 |
| 搜索结果质量不稳 | 多搜索源回退(DB → Bing → Google CSE → AI),持续优化 |
| 老用户不满过渡方案 | 老用户按剩余天数高折抵换算,并保留原有套餐期限内权益 |
| 翻译用量大成本高 | 每日免费额兜底 + Credits 定价覆盖 API 成本 |