refactor: switch to free-trial/private-deploy/buyout pricing, fix feature gaps, add SEO landing + deploy config
This commit is contained in:
+10
-10
@@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0, viewport-fit=cover" />
|
||||
<meta name="description" content="TradeMate 外贸小助手 - AI 驱动的外贸智能工作台。智能翻译、客户管理、营销文案、报价单生成、WhatsApp 集成,专为外贸 SOHO 和小团队打造。" />
|
||||
<meta name="description" content="TradeMate 外贸小助手 - AI 驱动的外贸智能工作台。智能翻译、客户管理、营销文案、报价单生成、AI 数字员工,支持免费试用、私有化部署与买断源码,专为外贸 SOHO 和小团队打造。" />
|
||||
<meta name="keywords" content="外贸小助手,TradeMate,外贸AI工具,智能翻译,客户管理,营销文案,报价单,WhatsApp集成,外贸SOHO,外贸工具" />
|
||||
<meta name="author" content="北京宇之然科技中心" />
|
||||
<meta name="robots" content="index, follow" />
|
||||
@@ -18,11 +18,11 @@
|
||||
<meta property="og:description" content="专为外贸 SOHO 和小团队打造的 AI 智能工作台。集成智能翻译、客户管理、营销文案、报价单、WhatsApp 沟通于一体。" />
|
||||
<meta property="og:url" content="https://trade.yuzhiran.com/app/" />
|
||||
<meta property="og:site_name" content="TradeMate" />
|
||||
<meta property="og:image" content="https://trade.yuzhiran.com/og-image.png" />
|
||||
<meta property="og:image" content="https://trade.yuzhiran.com/app/static/images/yzr/yuzhiran.jpg" />
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<meta name="twitter:title" content="TradeMate 外贸小助手" />
|
||||
<meta name="twitter:description" content="AI 驱动的外贸智能工作台" />
|
||||
<meta name="twitter:image" content="https://trade.yuzhiran.com/og-image.png" />
|
||||
<meta name="twitter:description" content="AI 驱动的外贸智能工作台,支持免费试用、私有化部署与买断源码" />
|
||||
<meta name="twitter:image" content="https://trade.yuzhiran.com/app/static/images/yzr/yuzhiran.jpg" />
|
||||
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />
|
||||
@@ -39,12 +39,12 @@
|
||||
"url": "https://trade.yuzhiran.com/app/",
|
||||
"applicationCategory": "BusinessApplication",
|
||||
"operatingSystem": "Web, iOS, Android",
|
||||
"description": "AI 驱动的外贸智能工作台,专为外贸 SOHO 和小团队打造",
|
||||
"offers": {
|
||||
"@type": "Offer",
|
||||
"price": "0",
|
||||
"priceCurrency": "CNY"
|
||||
},
|
||||
"description": "AI 驱动的外贸智能工作台,专为外贸 SOHO 和小团队打造,支持免费试用、私有化部署与买断源码",
|
||||
"offers": [
|
||||
{ "@type": "Offer", "name": "免费试用", "price": "0", "priceCurrency": "CNY" },
|
||||
{ "@type": "Offer", "name": "私有化部署", "price": "39800", "priceCurrency": "CNY", "description": "年付授权,独立部署到客户自有服务器" },
|
||||
{ "@type": "Offer", "name": "买断源码", "price": "98000", "priceCurrency": "CNY", "description": "一次性买断完整前后端源码,可二次开发" }
|
||||
],
|
||||
"aggregateRating": {
|
||||
"@type": "AggregateRating",
|
||||
"ratingValue": "4.8",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<view class="container">
|
||||
<view class="header">
|
||||
<text class="page-title">升级会员</text>
|
||||
<text class="page-title">选择方案</text>
|
||||
<text class="current-plan" v-if="currentPlan">当前: {{ planLabel(currentPlan) }}</text>
|
||||
</view>
|
||||
|
||||
@@ -16,8 +16,7 @@
|
||||
<text class="plan-name">{{ plan.name }}</text>
|
||||
<text class="plan-price">
|
||||
<text class="price-num">¥{{ plan.price }}</text>
|
||||
<text class="price-unit" v-if="plan.price > 0">/月</text>
|
||||
<text class="price-unit" v-else>免费</text>
|
||||
<text class="price-unit">{{ plan.unit }}</text>
|
||||
</text>
|
||||
<view class="plan-features">
|
||||
<text class="feature" v-for="(f, i) in plan.features" :key="i">• {{ f }}</text>
|
||||
@@ -26,92 +25,87 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<button
|
||||
class="upgrade-btn"
|
||||
@click="handleUpgrade"
|
||||
:disabled="!selected || selected === currentPlan || loading"
|
||||
>
|
||||
{{ loading ? '处理中...' : (selected === currentPlan ? '当前方案' : '立即升级') }}
|
||||
<button class="upgrade-btn" @click="handleSelect" :disabled="!selected || loading">
|
||||
{{ loading ? '处理中...' : actionText }}
|
||||
</button>
|
||||
|
||||
<!-- H5 Native 支付:显示二维码 -->
|
||||
<view class="qr-modal" v-if="showQr">
|
||||
<!-- Enterprise contact popup -->
|
||||
<view class="qr-modal" v-if="showContact">
|
||||
<view class="qr-box">
|
||||
<text class="qr-title">请使用微信扫码支付</text>
|
||||
<image class="qr-img" :src="qrCodeUrl" mode="widthFix" />
|
||||
<text class="qr-hint">打开微信扫一扫完成支付</text>
|
||||
<text class="qr-close" @click="showQr = false">关闭</text>
|
||||
<text class="qr-title">{{ contactTitle }}</text>
|
||||
<input class="c-input" v-model="form.name" placeholder="您的称呼" />
|
||||
<input class="c-input" v-model="form.company" placeholder="公司名称(选填)" />
|
||||
<input class="c-input" v-model="form.phone" placeholder="手机号(必填)" />
|
||||
<textarea class="c-area" v-model="form.message" placeholder="部署规模 / 定制需求(选填)" />
|
||||
<button class="c-submit" :disabled="contactLoading" @click="submitContact">提交申请</button>
|
||||
<text class="qr-close" @click="showContact = false">关闭</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { ref, computed } from 'vue'
|
||||
import { onShow } from '@dcloudio/uni-app'
|
||||
import { paymentApi } from '@/utils/api.js'
|
||||
import { leadApi } from '@/utils/api.js'
|
||||
|
||||
const plans = ref([])
|
||||
const PRICING = [
|
||||
{ id: 'free', name: '免费试用', price: '0', unit: '', features: ['30 积分(一次性)', '每日 1000 字免费翻译', '网页端 / 插件通用'], action: 'trial' },
|
||||
{ id: 'private', name: '私有化部署', price: '39,800', unit: '/年', features: ['独立部署、数据私有', '不限账号与调用量', '对接自有 AI 模型', '一年技术支持'], action: 'contact' },
|
||||
{ id: 'buyout', name: '买断源码', price: '98,000', unit: '/一次性', features: ['完整前后端源码', '可二次开发', '永久授权', '文档与社区支持'], action: 'contact' },
|
||||
]
|
||||
|
||||
const plans = ref(PRICING)
|
||||
const currentPlan = ref('free')
|
||||
const selected = ref('')
|
||||
const loading = ref(false)
|
||||
const showQr = ref(false)
|
||||
const qrCodeUrl = ref('')
|
||||
|
||||
onShow(async () => {
|
||||
try {
|
||||
const [planRes, subRes] = await Promise.all([
|
||||
paymentApi.plans(),
|
||||
paymentApi.subscription(),
|
||||
])
|
||||
plans.value = planRes.plans || []
|
||||
currentPlan.value = subRes.plan || 'free'
|
||||
} catch (_) {}
|
||||
const showContact = ref(false)
|
||||
const contactLoading = ref(false)
|
||||
const contactType = ref('private')
|
||||
const form = ref({ name: '', company: '', phone: '', message: '' })
|
||||
|
||||
const contactTitle = computed(() => contactType.value === 'private' ? '申请私有化部署' : '咨询源码买断')
|
||||
const actionText = computed(() => {
|
||||
const p = plans.value.find(x => x.id === selected.value)
|
||||
if (!p) return '请选择方案'
|
||||
if (p.action === 'trial') return '免费使用'
|
||||
return contactType.value === 'private' ? '申请私有化部署' : '咨询源码买断'
|
||||
})
|
||||
|
||||
onShow(() => { currentPlan.value = 'free' })
|
||||
|
||||
const planLabel = (id) => {
|
||||
const map = { free: '免费版', pro: 'Pro 版', enterprise: '企业版' }
|
||||
const map = { free: '免费版', private: '私有化部署', buyout: '买断源码' }
|
||||
return map[id] || id
|
||||
}
|
||||
|
||||
const handleUpgrade = async () => {
|
||||
if (!selected.value || selected.value === currentPlan.value) return
|
||||
loading.value = true
|
||||
const handleSelect = () => {
|
||||
const p = plans.value.find(x => x.id === selected.value)
|
||||
if (!p) return
|
||||
if (p.action === 'trial') {
|
||||
uni.showToast({ title: '已使用免费版', icon: 'success' })
|
||||
return
|
||||
}
|
||||
contactType.value = p.id
|
||||
form.value = { name: '', company: '', phone: '', message: '' }
|
||||
showContact.value = true
|
||||
}
|
||||
|
||||
const submitContact = async () => {
|
||||
if (!form.value.name.trim() || !form.value.phone.trim()) {
|
||||
uni.showToast({ title: '请填写称呼与手机号', icon: 'none' })
|
||||
return
|
||||
}
|
||||
contactLoading.value = true
|
||||
try {
|
||||
// #ifdef MP-WEIXIN
|
||||
const payType = 'jsapi'
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
const payType = 'native'
|
||||
// #endif
|
||||
const res = await paymentApi.createOrder(selected.value, payType)
|
||||
|
||||
if (res.amount === 0) {
|
||||
uni.showToast({ title: '已切换为免费版', icon: 'success' })
|
||||
currentPlan.value = selected.value
|
||||
return
|
||||
}
|
||||
|
||||
if (res.pay_type === 'jsapi' && res.pay_params) {
|
||||
uni.requestPayment({
|
||||
provider: 'wxpay',
|
||||
...res.pay_params,
|
||||
success: () => {
|
||||
uni.showToast({ title: '支付成功', icon: 'success' })
|
||||
currentPlan.value = selected.value
|
||||
},
|
||||
fail: (err) => {
|
||||
uni.showToast({ title: err.errMsg || '支付失败', icon: 'none' })
|
||||
},
|
||||
})
|
||||
} else if (res.pay_type === 'native' && res.code_url) {
|
||||
qrCodeUrl.value = `https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=${encodeURIComponent(res.code_url)}`
|
||||
showQr.value = true
|
||||
}
|
||||
await leadApi.create({ type: contactType.value, ...form.value })
|
||||
uni.showToast({ title: '提交成功,商务会联系您', icon: 'success' })
|
||||
showContact.value = false
|
||||
} catch (err) {
|
||||
uni.showToast({ title: err.message || '操作失败', icon: 'none' })
|
||||
uni.showToast({ title: err.message || '提交失败', icon: 'none' })
|
||||
} finally {
|
||||
loading.value = false
|
||||
contactLoading.value = false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -136,9 +130,10 @@ const handleUpgrade = async () => {
|
||||
.upgrade-btn[disabled] { background: #a0cfff; }
|
||||
|
||||
.qr-modal { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.6); z-index: 999; display: flex; align-items: center; justify-content: center; }
|
||||
.qr-box { background: #fff; border-radius: 20rpx; padding: 50rpx; text-align: center; width: 500rpx; }
|
||||
.qr-title { font-size: 30rpx; font-weight: 600; color: #333; margin-bottom: 30rpx; display: block; }
|
||||
.qr-img { width: 300rpx; height: 300rpx; display: block; margin: 0 auto 30rpx; }
|
||||
.qr-hint { font-size: 24rpx; color: #999; display: block; margin-bottom: 20rpx; }
|
||||
.qr-close { font-size: 26rpx; color: #1890ff; display: block; }
|
||||
.qr-box { background: #fff; border-radius: 20rpx; padding: 40rpx; width: 560rpx; }
|
||||
.qr-title { font-size: 30rpx; font-weight: 600; color: #333; margin-bottom: 24rpx; display: block; text-align: center; }
|
||||
.c-input { border: 2rpx solid #e8e8e8; border-radius: 10rpx; padding: 16rpx; font-size: 26rpx; margin-bottom: 16rpx; width: 100%; box-sizing: border-box; }
|
||||
.c-area { border: 2rpx solid #e8e8e8; border-radius: 10rpx; padding: 16rpx; font-size: 26rpx; margin-bottom: 16rpx; width: 100%; box-sizing: border-box; height: 120rpx; }
|
||||
.c-submit { width: 100%; height: 80rpx; background: #1890ff; color: #fff; border: none; border-radius: 10rpx; font-size: 28rpx; margin-bottom: 12rpx; }
|
||||
.qr-close { font-size: 26rpx; color: #1890ff; display: block; text-align: center; }
|
||||
</style>
|
||||
|
||||
@@ -259,6 +259,10 @@ export const paymentApi = {
|
||||
request('/payment/create-order', 'POST', { plan, pay_type: payType }),
|
||||
}
|
||||
|
||||
export const leadApi = {
|
||||
create: (data) => request('/leads', 'POST', data),
|
||||
}
|
||||
|
||||
export const creditApi = {
|
||||
balance: () => request('/credits/balance'),
|
||||
history: (page = 1, size = 20) => request(`/credits/history?page=${page}&size=${size}`),
|
||||
|
||||
Reference in New Issue
Block a user