feat(i18n): 剩余15页全量接入中英(登录/注册/扫码/绑定/佩戴/扫描/治疗/订阅/帮助等)
- 3 个并行 agent 各管 5 页,互不重叠命名空间 - 全 App 18 页均 i18n.bind,22 命名空间/400 键中英对齐 - 动态文案(时长/天数/价格/区域)JS 内 i18n.t 计算;区域标签复用 common.regions
这个提交包含在:
@@ -1,4 +1,5 @@
|
||||
var api = require('../../utils/api')
|
||||
var i18n = require('../../i18n/index')
|
||||
|
||||
Page({
|
||||
data: {
|
||||
@@ -8,6 +9,7 @@ Page({
|
||||
purchasing: false,
|
||||
subscription: null,
|
||||
subRemaining: 0,
|
||||
subRemainingText: '',
|
||||
loadingPlans: true
|
||||
},
|
||||
|
||||
@@ -25,10 +27,18 @@ Page({
|
||||
},
|
||||
|
||||
onShow: function () {
|
||||
i18n.bind(this)
|
||||
this.loadPlans()
|
||||
this.loadSubscription()
|
||||
},
|
||||
|
||||
planName: function (key) {
|
||||
if (key === 'trial') return i18n.t('subPlans.planTrial')
|
||||
if (key === 'monthly') return i18n.t('subPlans.planMonthly')
|
||||
if (key === 'yearly') return i18n.t('subPlans.planYearly')
|
||||
return key
|
||||
},
|
||||
|
||||
loadPlans: function () {
|
||||
var self = this
|
||||
self.setData({ loadingPlans: true })
|
||||
@@ -41,16 +51,16 @@ Page({
|
||||
var plans = serverPlans.map(function (p) {
|
||||
var daily = p.days > 0 ? (p.price / p.days).toFixed(1) : 0
|
||||
var desc = ''
|
||||
if (p.key === 'trial') desc = p.days + '天免费体验'
|
||||
else if (p.key === 'yearly') desc = '省¥' + Math.round(monthlyPrice * 12 - p.price)
|
||||
else desc = '约' + daily + '元/天'
|
||||
if (p.key === 'trial') desc = i18n.t('subPlans.descTrial', { days: p.days })
|
||||
else if (p.key === 'yearly') desc = i18n.t('subPlans.descSave', { amount: Math.round(monthlyPrice * 12 - p.price) })
|
||||
else desc = i18n.t('subPlans.descDaily', { price: daily })
|
||||
return {
|
||||
key: p.key,
|
||||
name: p.name,
|
||||
name: self.planName(p.key),
|
||||
price: p.price,
|
||||
priceLabel: p.key === 'trial' ? '免费' : '¥' + p.price,
|
||||
priceLabel: p.key === 'trial' ? i18n.t('subPlans.free') : '¥' + p.price,
|
||||
desc: desc,
|
||||
tag: p.key === 'yearly' ? '推荐' : '',
|
||||
tag: p.key === 'yearly' ? i18n.t('subPlans.tagRecommend') : '',
|
||||
disabled: false
|
||||
}
|
||||
})
|
||||
@@ -61,9 +71,9 @@ Page({
|
||||
self.setData({
|
||||
loadingPlans: false,
|
||||
plans: [
|
||||
{ key: 'trial', name: '试用', price: 0, priceLabel: '免费', desc: '7天免费体验', disabled: false },
|
||||
{ key: 'monthly', name: '月卡', price: 99, priceLabel: '¥99', desc: '约3.3元/天' },
|
||||
{ key: 'yearly', name: '年卡', price: 899, priceLabel: '¥899', desc: '省¥289', tag: '推荐' }
|
||||
{ key: 'trial', name: self.planName('trial'), price: 0, priceLabel: i18n.t('subPlans.free'), desc: i18n.t('subPlans.descTrial', { days: 7 }), disabled: false },
|
||||
{ key: 'monthly', name: self.planName('monthly'), price: 99, priceLabel: '¥99', desc: i18n.t('subPlans.descDaily', { price: '3.3' }) },
|
||||
{ key: 'yearly', name: self.planName('yearly'), price: 899, priceLabel: '¥899', desc: i18n.t('subPlans.descSave', { amount: 289 }), tag: i18n.t('subPlans.tagRecommend') }
|
||||
]
|
||||
})
|
||||
self.checkTrialUsed()
|
||||
@@ -75,7 +85,7 @@ Page({
|
||||
var sub = self.data.subscription
|
||||
if (sub && sub.trial_used) {
|
||||
var plans = self.data.plans.map(function (p) {
|
||||
if (p.key === 'trial') return Object.assign({}, p, { disabled: true, tag: '已使用' })
|
||||
if (p.key === 'trial') return Object.assign({}, p, { disabled: true, tag: i18n.t('subPlans.tagUsed') })
|
||||
return p
|
||||
})
|
||||
self.setData({ plans: plans })
|
||||
@@ -86,16 +96,18 @@ Page({
|
||||
loadSubscription: function () {
|
||||
var self = this
|
||||
api.getSubscription().then(function (sub) {
|
||||
var remaining = sub.remaining_days || 0
|
||||
self.setData({
|
||||
subscription: sub,
|
||||
subRemaining: sub.remaining_days || 0
|
||||
subRemaining: remaining,
|
||||
subRemainingText: i18n.t('subPlans.daysValue', { days: remaining })
|
||||
})
|
||||
self.checkTrialUsed()
|
||||
}).catch(function () {})
|
||||
},
|
||||
|
||||
onAgreement: function () {
|
||||
wx.showModal({ title: '提示', content: '订阅协议内容建设中', showCancel: false })
|
||||
wx.showModal({ title: i18n.t('subPlans.tipTitle'), content: i18n.t('subPlans.agreementBuilding'), showCancel: false })
|
||||
},
|
||||
|
||||
onSelect: function (e) {
|
||||
@@ -116,8 +128,8 @@ Page({
|
||||
|
||||
if (plan.key === 'trial') {
|
||||
wx.showModal({
|
||||
title: '激活试用',
|
||||
content: '免费试用 ' + plan.desc + '?',
|
||||
title: i18n.t('subPlans.activateTrialTitle'),
|
||||
content: i18n.t('subPlans.activateTrialConfirm', { desc: plan.desc }),
|
||||
success: function (res) {
|
||||
if (res.confirm) self.doActivateTrial()
|
||||
}
|
||||
@@ -127,10 +139,10 @@ Page({
|
||||
|
||||
var isRenew = self.data.subscription && self.data.subscription.status === 'active' && self.data.subRemaining > 0
|
||||
var planDays = plan.key === 'yearly' ? 365 : 30
|
||||
var title = isRenew ? '确认续费' : '确认支付'
|
||||
var title = isRenew ? i18n.t('subPlans.confirmRenewTitle') : i18n.t('subPlans.confirmPayTitle')
|
||||
var content = isRenew
|
||||
? '在现有订阅基础上延长' + planDays + '天,支付 ¥' + plan.price
|
||||
: '支付 ¥' + plan.price
|
||||
? i18n.t('subPlans.renewContent', { days: planDays, price: plan.price })
|
||||
: i18n.t('subPlans.payContent', { price: plan.price })
|
||||
|
||||
wx.showModal({
|
||||
title: title,
|
||||
@@ -148,13 +160,13 @@ Page({
|
||||
self.setData({ purchasing: true })
|
||||
api.activateTrial().then(function () {
|
||||
self.setData({ purchasing: false })
|
||||
wx.showToast({ title: '试用已激活', icon: 'success' })
|
||||
wx.showToast({ title: i18n.t('subPlans.trialActivated'), icon: 'success' })
|
||||
setTimeout(function () {
|
||||
wx.redirectTo({ url: '/pages/subscribe-success/subscribe-success?plan=trial' })
|
||||
}, 1000)
|
||||
}).catch(function (err) {
|
||||
self.setData({ purchasing: false })
|
||||
wx.showToast({ title: err.message || '激活失败', icon: 'none' })
|
||||
wx.showToast({ title: err.message || i18n.t('subPlans.activateFailed'), icon: 'none' })
|
||||
})
|
||||
},
|
||||
|
||||
@@ -164,7 +176,7 @@ Page({
|
||||
api.purchase(plan.key).then(function (data) {
|
||||
if (!data.payment_params) {
|
||||
self.setData({ purchasing: false })
|
||||
wx.showToast({ title: '支付服务暂不可用', icon: 'none' })
|
||||
wx.showToast({ title: i18n.t('subPlans.payUnavailable'), icon: 'none' })
|
||||
return
|
||||
}
|
||||
|
||||
@@ -182,13 +194,13 @@ Page({
|
||||
},
|
||||
fail: function (err) {
|
||||
self.setData({ purchasing: false })
|
||||
var msg = (err.errMsg || '').indexOf('cancel') > -1 ? '已取消支付' : '支付失败'
|
||||
var msg = (err.errMsg || '').indexOf('cancel') > -1 ? i18n.t('subPlans.payCancelled') : i18n.t('subPlans.payFailed')
|
||||
wx.showToast({ title: msg, icon: 'none' })
|
||||
}
|
||||
})
|
||||
}).catch(function (err) {
|
||||
self.setData({ purchasing: false })
|
||||
wx.showToast({ title: err.message || '创建订单失败', icon: 'none' })
|
||||
wx.showToast({ title: err.message || i18n.t('subPlans.createOrderFailed'), icon: 'none' })
|
||||
})
|
||||
},
|
||||
|
||||
@@ -201,7 +213,7 @@ Page({
|
||||
api.syncPaymentOrder(orderId).then(function (result) {
|
||||
if (result.status === 'paid') {
|
||||
self.setData({ purchasing: false })
|
||||
wx.showToast({ title: '支付成功', icon: 'success' })
|
||||
wx.showToast({ title: i18n.t('subPlans.paySuccess'), icon: 'success' })
|
||||
setTimeout(function () {
|
||||
wx.redirectTo({ url: '/pages/subscribe-success/subscribe-success?plan=' + planKey })
|
||||
}, 1000)
|
||||
@@ -210,7 +222,7 @@ Page({
|
||||
setTimeout(pollSync, 2000)
|
||||
} else {
|
||||
self.setData({ purchasing: false })
|
||||
wx.showToast({ title: '支付处理中,请稍后在订阅页查看', icon: 'none' })
|
||||
wx.showToast({ title: i18n.t('subPlans.payProcessing'), icon: 'none' })
|
||||
}
|
||||
}).catch(function () {
|
||||
if (retryCount < maxRetries) {
|
||||
@@ -218,7 +230,7 @@ Page({
|
||||
setTimeout(pollSync, 2000)
|
||||
} else {
|
||||
self.setData({ purchasing: false })
|
||||
wx.showToast({ title: '支付处理中,请稍后在订阅页查看', icon: 'none' })
|
||||
wx.showToast({ title: i18n.t('subPlans.payProcessing'), icon: 'none' })
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,35 +1,35 @@
|
||||
<view class="page">
|
||||
<view class="page-header page-header-gold" style="padding-top: {{statusBarHeight + 24}}px;">
|
||||
<view class="nav-back" bindtap="onBack">‹ 返回</view>
|
||||
<view class="page-header-title">订阅服务</view>
|
||||
<view class="page-header-subtitle">解锁智能模式</view>
|
||||
<view class="nav-back" bindtap="onBack">‹ {{i18n.common.back}}</view>
|
||||
<view class="page-header-title">{{i18n.subPlans.title}}</view>
|
||||
<view class="page-header-subtitle">{{i18n.subPlans.subtitle}}</view>
|
||||
</view>
|
||||
|
||||
<view class="page-content">
|
||||
<!-- Current subscription status -->
|
||||
<view class="current-sub" wx:if="{{subscription && subscription.status === 'active' && subRemaining > 0}}">
|
||||
<view class="current-sub-row">
|
||||
<text class="current-sub-label">当前套餐</text>
|
||||
<text class="current-sub-value">{{subscription.plan === 'trial' ? '试用' : subscription.plan === 'monthly' ? '月卡' : subscription.plan === 'yearly' ? '年卡' : subscription.plan}}</text>
|
||||
<text class="current-sub-label">{{i18n.subPlans.currentPlanLabel}}</text>
|
||||
<text class="current-sub-value">{{subscription.plan === 'trial' ? i18n.subPlans.planTrial : subscription.plan === 'monthly' ? i18n.subPlans.planMonthly : subscription.plan === 'yearly' ? i18n.subPlans.planYearly : subscription.plan}}</text>
|
||||
</view>
|
||||
<view class="current-sub-row">
|
||||
<text class="current-sub-label">剩余天数</text>
|
||||
<text class="current-sub-value">{{subRemaining}}天</text>
|
||||
<text class="current-sub-label">{{i18n.subPlans.remainDaysLabel}}</text>
|
||||
<text class="current-sub-value">{{subRemainingText}}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="page-title">选择订阅套餐</view>
|
||||
<view class="page-title">{{i18n.subPlans.choosePlan}}</view>
|
||||
|
||||
<view class="loading-plans" wx:if="{{loadingPlans}}">
|
||||
<view class="loading-spinner"></view>
|
||||
<text class="loading-text">加载套餐中...</text>
|
||||
<text class="loading-text">{{i18n.subPlans.loadingPlans}}</text>
|
||||
</view>
|
||||
|
||||
<view class="service-card" wx:if="{{!loadingPlans}}">
|
||||
<view class="service-icon">✨</view>
|
||||
<view class="service-info">
|
||||
<view class="service-name">智能模式</view>
|
||||
<view class="service-desc">智能自动调节</view>
|
||||
<view class="service-name">{{i18n.subPlans.smartMode}}</view>
|
||||
<view class="service-desc">{{i18n.subPlans.smartModeDesc}}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -44,9 +44,9 @@
|
||||
|
||||
<block wx:if="{{!loadingPlans}}">
|
||||
<button class="btn-primary btn-primary-gold" bindtap="onPurchase" disabled="{{purchasing}}" loading="{{purchasing}}">
|
||||
{{subscription && subscription.status === 'active' && subRemaining > 0 ? '续费' : '确认支付'}}
|
||||
{{subscription && subscription.status === 'active' && subRemaining > 0 ? i18n.subPlans.renew : i18n.subPlans.confirmPay}}
|
||||
</button>
|
||||
<view class="agreement" bindtap="onAgreement">支付即表示同意《订阅协议》</view>
|
||||
<view class="agreement" bindtap="onAgreement">{{i18n.subPlans.agreement}}</view>
|
||||
</block>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
在新工单中引用
屏蔽一个用户