Billing菜单及页面实现多语言支持
This commit is contained in:
parent
2a350e93ce
commit
d911a973eb
@ -178,7 +178,7 @@ export default {
|
||||
disabled: enforce2FA,
|
||||
},
|
||||
{
|
||||
name: '账单',
|
||||
name: this.$t('Billing'),
|
||||
icon: () => h(WalletCards),
|
||||
route: '/billing',
|
||||
isActive: routeName.startsWith('Billing'),
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<Dialog v-model="show" :options="{ title: '余额充值' }">
|
||||
<Dialog v-model="show" :options="{ title: $t('Account Recharge') }">
|
||||
<template #body-content>
|
||||
<div
|
||||
v-if="showMessage"
|
||||
@ -7,7 +7,7 @@
|
||||
>
|
||||
<FeatherIcon class="h-4" name="info" />
|
||||
<span>
|
||||
在更改支付方式之前,请先为您的账户充值余额。
|
||||
{{ $t('Please recharge your account balance before changing payment method.') }}
|
||||
</span>
|
||||
</div>
|
||||
<PrepaidCreditsForm
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
v-model="billingInformation.billing_name"
|
||||
type="text"
|
||||
name="billing_name"
|
||||
label="账单名称"
|
||||
:label="$t('Billing Name')"
|
||||
:required="true"
|
||||
/>
|
||||
<NewAddressForm
|
||||
@ -18,7 +18,7 @@
|
||||
<Button
|
||||
class="w-full"
|
||||
variant="solid"
|
||||
label="更新账单信息"
|
||||
:label="$t('Update Billing Information')"
|
||||
:loading="addressFormRef.updateBillingInformation.loading"
|
||||
@click="updateBillingInformation"
|
||||
/>
|
||||
@ -27,7 +27,7 @@
|
||||
<script setup>
|
||||
import NewAddressForm from './NewAddressForm.vue';
|
||||
import { FormControl, ErrorMessage, Button, createResource } from 'jingrow-ui';
|
||||
import { reactive, ref, inject } from 'vue';
|
||||
import { reactive, ref, inject, getCurrentInstance } from 'vue';
|
||||
|
||||
const emit = defineEmits(['success']);
|
||||
|
||||
@ -70,15 +70,16 @@ createResource({
|
||||
const errorMessage = ref('');
|
||||
|
||||
function updateBillingInformation() {
|
||||
const { $t } = getCurrentInstance().appContext.config.globalProperties;
|
||||
if (!billingInformation.billing_name) {
|
||||
errorMessage.value = '账单名称为必填项';
|
||||
errorMessage.value = $t('Billing name is required');
|
||||
return;
|
||||
}
|
||||
const billing_name = billingInformation.billing_name.trim();
|
||||
const billingNameRegex = /^[a-zA-Z0-9\-\'\,\.\s]+$/;
|
||||
const billingNameValid = billingNameRegex.test(billing_name);
|
||||
if (!billingNameValid) {
|
||||
errorMessage.value = '账单名称包含无效字符';
|
||||
errorMessage.value = $t('Billing name contains invalid characters');
|
||||
return;
|
||||
}
|
||||
billingInformation.billing_name = billing_name;
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
<template>
|
||||
<Dialog v-model="show" :options="{ title: '账单详情' }">
|
||||
<Dialog v-model="show" :options="{ title: $t('Billing Details') }">
|
||||
<template #body-content>
|
||||
<div
|
||||
v-if="showMessage"
|
||||
class="mb-5 inline-flex gap-1.5 text-base text-gray-700"
|
||||
>
|
||||
<FeatherIcon class="h-4" name="info" />
|
||||
<span> 在继续之前,请为您的账户添加账单详情。</span>
|
||||
<span> {{ $t('Please add billing details to your account before continuing.') }}</span>
|
||||
</div>
|
||||
<BillingDetails
|
||||
ref="billingRef"
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
</template>
|
||||
<script setup>
|
||||
import { FormControl, ErrorMessage, createResource } from 'jingrow-ui';
|
||||
import { ref, computed, inject, watch, onMounted } from 'vue';
|
||||
import { ref, computed, inject, watch, onMounted, getCurrentInstance } from 'vue';
|
||||
import { toast } from 'vue-sonner';
|
||||
import { DashboardError } from '../../utils/error';
|
||||
import { countryNameMap, chinaStates } from '@/utils/billing';
|
||||
@ -70,7 +70,9 @@ const updateBillingInformation = createResource({
|
||||
if (error) throw new DashboardError(error);
|
||||
},
|
||||
onSuccess: () => {
|
||||
toast.success('账单信息已更新');
|
||||
const instance = getCurrentInstance();
|
||||
const $t = instance?.appContext.config.globalProperties.$t || ((key) => key);
|
||||
toast.success($t('Billing information updated'));
|
||||
emit('success');
|
||||
},
|
||||
});
|
||||
@ -92,8 +94,11 @@ const codeToNameMap = computed(() => {
|
||||
|
||||
// 国家选择列表 - 包含英文代码映射到中文显示
|
||||
const countryList = computed(() => {
|
||||
const instance = getCurrentInstance();
|
||||
const $t = instance?.appContext.config.globalProperties.$t || ((key) => key);
|
||||
|
||||
// 由于后端限制,目前只提供中国选项
|
||||
return [{ label: '中国', value: 'China' }];
|
||||
return [{ label: $t('China'), value: 'China' }];
|
||||
|
||||
// 如果未来允许其他国家,可以恢复这个:
|
||||
// return Object.entries({
|
||||
@ -114,14 +119,17 @@ const stateOptions = computed(() => {
|
||||
});
|
||||
|
||||
const sections = computed(() => {
|
||||
const instance = getCurrentInstance();
|
||||
const $t = instance?.appContext.config.globalProperties.$t || ((key) => key);
|
||||
|
||||
return [
|
||||
{
|
||||
name: '国家和城市',
|
||||
name: $t('Country and City'),
|
||||
columns: 2,
|
||||
fields: [
|
||||
{
|
||||
fieldtype: 'Select',
|
||||
label: '国家',
|
||||
label: $t('Country'),
|
||||
fieldname: 'country',
|
||||
options: countryList.value,
|
||||
required: true,
|
||||
@ -129,32 +137,32 @@ const sections = computed(() => {
|
||||
},
|
||||
{
|
||||
fieldtype: 'Data',
|
||||
label: '城市',
|
||||
label: $t('City'),
|
||||
fieldname: 'city',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: '地址',
|
||||
name: $t('Address'),
|
||||
columns: 1,
|
||||
fields: [
|
||||
{
|
||||
fieldtype: 'Data',
|
||||
label: '地址',
|
||||
label: $t('Address'),
|
||||
fieldname: 'address',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: '州和邮政编码',
|
||||
name: $t('State and Postal Code'),
|
||||
columns: 2,
|
||||
fields: [
|
||||
{
|
||||
fieldtype:
|
||||
billingInformation.value.country === 'China' ? 'Select' : 'Data',
|
||||
label: '州/省/地区',
|
||||
label: $t('State/Province/Region'),
|
||||
fieldname: 'state',
|
||||
required: true,
|
||||
options:
|
||||
@ -164,7 +172,7 @@ const sections = computed(() => {
|
||||
},
|
||||
{
|
||||
fieldtype: 'Data',
|
||||
label: '邮政编码',
|
||||
label: $t('Postal Code'),
|
||||
fieldname: 'postal_code',
|
||||
required: true,
|
||||
},
|
||||
@ -186,10 +194,13 @@ function getInputType(field) {
|
||||
}
|
||||
|
||||
async function validate() {
|
||||
const instance = getCurrentInstance();
|
||||
const $t = instance?.appContext.config.globalProperties.$t || ((key) => key);
|
||||
|
||||
// 验证必填字段
|
||||
for (let field of sections.value.flatMap((s) => s.fields)) {
|
||||
if (field.required && !billingInformation.value[field.fieldname]) {
|
||||
return `${field.label} 是必填项`;
|
||||
return $t('{field} is required', { field: field.label });
|
||||
}
|
||||
}
|
||||
return null; // 返回null表示没有错误
|
||||
|
||||
@ -3,14 +3,14 @@
|
||||
<div class="flex flex-col">
|
||||
<div class="flex items-center justify-between text-base text-gray-900">
|
||||
<div class="flex flex-col gap-1.5">
|
||||
<div class="text-lg font-semibold text-gray-900">账户余额</div>
|
||||
<div class="text-lg font-semibold text-gray-900">{{ $t('Account Balance') }}</div>
|
||||
<div class="text-2xl font-bold text-blue-600 py-6">
|
||||
{{ availableCredits || currency + ' 0.00' }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="shrink-0">
|
||||
<Button
|
||||
:label="'充值'"
|
||||
:label="$t('Recharge')"
|
||||
@click="
|
||||
() => {
|
||||
showMessage = false;
|
||||
@ -27,15 +27,15 @@
|
||||
<div class="my-3 h-px bg-gray-100" />
|
||||
<div class="flex items-center justify-between text-base text-gray-900">
|
||||
<div class="flex flex-col gap-1.5">
|
||||
<div class="font-medium">账单地址</div>
|
||||
<div class="font-medium">{{ $t('Billing Address') }}</div>
|
||||
<div v-if="billingDetailsSummary" class="leading-5 text-gray-700">
|
||||
{{ billingDetailsSummary }}
|
||||
</div>
|
||||
<div v-else class="text-gray-700">无地址</div>
|
||||
<div v-else class="text-gray-700">{{ $t('No address') }}</div>
|
||||
</div>
|
||||
<div class="shrink-0">
|
||||
<Button
|
||||
:label="billingDetailsSummary ? '编辑' : '添加账单地址'"
|
||||
:label="billingDetailsSummary ? $t('Edit') : $t('Add Billing Address')"
|
||||
@click="
|
||||
() => {
|
||||
showMessage = false;
|
||||
@ -73,7 +73,7 @@ import {
|
||||
confirmDialog,
|
||||
renderDialog,
|
||||
} from '../../utils/components';
|
||||
import { computed, ref, inject, h, defineAsyncComponent, onMounted, nextTick } from 'vue';
|
||||
import { computed, ref, inject, h, defineAsyncComponent, onMounted, nextTick, getCurrentInstance } from 'vue';
|
||||
import router from '../../router';
|
||||
|
||||
// 英文国家名到中文的映射
|
||||
@ -83,6 +83,9 @@ const countryToZh = {
|
||||
// 可以根据需要添加更多国家
|
||||
};
|
||||
|
||||
const instance = getCurrentInstance();
|
||||
const $t = instance?.appContext.config.globalProperties.$t || ((key) => key);
|
||||
|
||||
const team = inject('team');
|
||||
const {
|
||||
availableCredits,
|
||||
@ -146,31 +149,31 @@ const billingDetailsSummary = computed(() => {
|
||||
|
||||
const paymentModeOptions = [
|
||||
{
|
||||
label: '余额支付',
|
||||
label: $t('Prepaid Credits'),
|
||||
value: 'Prepaid Credits',
|
||||
description: '您的每月账单费用将从账户余额中扣除',
|
||||
description: $t('Your monthly billing charges will be deducted from your account balance'),
|
||||
component: () =>
|
||||
h(DropdownItem, {
|
||||
label: '余额支付',
|
||||
label: $t('Prepaid Credits'),
|
||||
active: team.pg.payment_mode === 'Prepaid Credits',
|
||||
onClick: () => updatePaymentMode('Prepaid Credits'),
|
||||
}),
|
||||
},
|
||||
{
|
||||
label: '由合作伙伴支付',
|
||||
label: $t('Paid By Partner'),
|
||||
value: 'Paid By Partner',
|
||||
condition: () => team.pg.partner_email,
|
||||
description: '您的合作伙伴将为您支付每月订阅费用',
|
||||
description: $t('Your partner will pay your monthly subscription fees'),
|
||||
component: () =>
|
||||
h(DropdownItem, {
|
||||
label: '由合作伙伴支付',
|
||||
label: $t('Paid By Partner'),
|
||||
active: team.pg.payment_mode === 'Paid by Partner',
|
||||
onClick: () =>
|
||||
confirmDialog({
|
||||
title: '确认支付方式',
|
||||
message: `通过将支付方式更改为<strong>由合作伙伴支付</strong>,以下详细信息将与您的合作伙伴共享:<br><br><li>站点/服务器名称</li> <li>计划名称</li><li>站点/服务器激活天数</li><br>您确定要继续吗?`,
|
||||
title: $t('Confirm Payment Method'),
|
||||
message: $t('By changing the payment method to <strong>Paid By Partner</strong>, the following details will be shared with your partner:<br><br><li>Site/Server Name</li> <li>Plan Name</li><li>Site/Server Active Days</li><br>Are you sure you want to continue?'),
|
||||
primaryAction: {
|
||||
label: '更改支付方式',
|
||||
label: $t('Change Payment Method'),
|
||||
variant: 'solid',
|
||||
onClick: ({ hide }) => {
|
||||
updatePaymentMode('Paid By Partner');
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<div class="sticky top-0 z-10 shrink-0">
|
||||
<Header>
|
||||
<FBreadcrumbs
|
||||
:items="[{ label: '账单', route: { name: 'Billing' } }]"
|
||||
:items="[{ label: $t('Billing'), route: { name: 'Billing' } }]"
|
||||
/>
|
||||
</Header>
|
||||
<TabsWithRouter
|
||||
@ -14,7 +14,7 @@
|
||||
class="mx-auto mt-60 w-fit rounded border border-dashed px-12 py-8 text-center text-gray-600"
|
||||
>
|
||||
<i-lucide-alert-triangle class="mx-auto mb-4 h-6 w-6 text-red-600" />
|
||||
<ErrorMessage message="您无权查看账单页面" />
|
||||
<ErrorMessage :message="$t('You do not have permission to view the billing page')" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@ -35,11 +35,11 @@ export default {
|
||||
return {
|
||||
currentTab: 0,
|
||||
tabs: [
|
||||
{ label: '概览', route: { name: 'BillingOverview' } },
|
||||
{ label: '订单记录', route: { name: 'BillingOrders' } },
|
||||
{ label: '余额明细', route: { name: 'BillingBalances' } },
|
||||
{ label: this.$t('Overview'), route: { name: 'BillingOverview' } },
|
||||
{ label: this.$t('Order Records'), route: { name: 'BillingOrders' } },
|
||||
{ label: this.$t('Balance Details'), route: { name: 'BillingBalances' } },
|
||||
{
|
||||
label: '开发者收益',
|
||||
label: this.$t('Developer Earnings'),
|
||||
route: { name: 'BillingMarketplacePayouts' },
|
||||
requireDeveloper: true,
|
||||
requirePro: true
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
@click="exportToCsv"
|
||||
:loading="exporting"
|
||||
>
|
||||
导出
|
||||
{{ $t('Export') }}
|
||||
</Button>
|
||||
</template>
|
||||
</ObjectList>
|
||||
@ -38,7 +38,7 @@ export default {
|
||||
fields: ['type', 'source', 'invoice', 'description'],
|
||||
columns: [
|
||||
{
|
||||
label: '时间',
|
||||
label: this.$t('Time'),
|
||||
fieldname: 'creation',
|
||||
format(value) {
|
||||
return new Date(value).toLocaleString('zh-CN', {
|
||||
@ -52,7 +52,7 @@ export default {
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '描述',
|
||||
label: this.$t('Description'),
|
||||
fieldname: 'description',
|
||||
format(value, row) {
|
||||
if (value !== null && value !== undefined) {
|
||||
@ -60,28 +60,28 @@ export default {
|
||||
}
|
||||
|
||||
if (row.type === 'Applied To Invoice' && row.invoice) {
|
||||
return `冲抵发票 ${row.invoice}`;
|
||||
return this.$t('Applied to Invoice {invoice}', { invoice: row.invoice });
|
||||
}
|
||||
|
||||
if (row.source === 'Prepaid Credits') {
|
||||
return '余额充值';
|
||||
return this.$t('Balance Recharge');
|
||||
}
|
||||
|
||||
if (row.source === 'Free Credits') {
|
||||
return '赠送余额';
|
||||
return this.$t('Free Credits');
|
||||
}
|
||||
|
||||
return row.amount < 0 ? row.type : row.source;
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '金额',
|
||||
label: this.$t('Amount'),
|
||||
fieldname: 'amount',
|
||||
align: 'right',
|
||||
format: this.formatCurrency
|
||||
},
|
||||
{
|
||||
label: '余额',
|
||||
label: this.$t('Balance'),
|
||||
fieldname: 'ending_balance',
|
||||
align: 'right',
|
||||
format: this.formatCurrency
|
||||
@ -132,10 +132,10 @@ export default {
|
||||
|
||||
// 定义CSV字段
|
||||
const fields = [
|
||||
'时间',
|
||||
'描述',
|
||||
'金额',
|
||||
'余额'
|
||||
this.$t('Time'),
|
||||
this.$t('Description'),
|
||||
this.$t('Amount'),
|
||||
this.$t('Balance')
|
||||
];
|
||||
|
||||
// 准备数据
|
||||
@ -146,11 +146,11 @@ export default {
|
||||
// 如果描述不存在,则使用备用逻辑
|
||||
if (!description) {
|
||||
if (row.type === 'Applied To Invoice' && row.invoice) {
|
||||
description = `冲抵发票 ${row.invoice}`;
|
||||
description = this.$t('Applied to Invoice {invoice}', { invoice: row.invoice });
|
||||
} else if (row.source === 'Prepaid Credits') {
|
||||
description = '余额充值';
|
||||
description = this.$t('Balance Recharge');
|
||||
} else if (row.source === 'Free Credits') {
|
||||
description = '赠送余额';
|
||||
description = this.$t('Free Credits');
|
||||
} else {
|
||||
description = row.amount < 0 ? row.type : row.source;
|
||||
}
|
||||
@ -176,7 +176,7 @@ export default {
|
||||
// 触发下载
|
||||
const blob = new Blob([csv], { type: 'text/csv;charset=utf-8' });
|
||||
const today = new Date().toISOString().split('T')[0];
|
||||
const filename = `余额记录-${today}.csv`;
|
||||
const filename = `${this.$t('Balance Records')}-${today}.csv`;
|
||||
const link = document.createElement('a');
|
||||
link.href = URL.createObjectURL(blob);
|
||||
link.download = filename;
|
||||
@ -186,7 +186,7 @@ export default {
|
||||
this.exporting = false;
|
||||
},
|
||||
handleExportError(error) {
|
||||
console.error('导出数据失败:', error);
|
||||
console.error(this.$t('Failed to export data'), error);
|
||||
this.exporting = false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
v-if="showPayout.status === 'Empty'"
|
||||
class="text-base text-gray-600"
|
||||
>
|
||||
无内容显示
|
||||
{{ $t('No content to display') }}
|
||||
</div>
|
||||
<PayoutTable v-else :payoutId="showPayout.name" />
|
||||
</template>
|
||||
@ -51,14 +51,14 @@ export default {
|
||||
return [
|
||||
{
|
||||
type: 'select',
|
||||
label: '状态',
|
||||
label: this.$t('Status'),
|
||||
class: !this.$isMobile ? 'w-36' : '',
|
||||
fieldname: 'status',
|
||||
options: [
|
||||
{ label: '', value: '' },
|
||||
{ label: '待结算', value: 'Draft' },
|
||||
{ label: '已付款', value: 'Paid' },
|
||||
{ label: '已结算', value: 'Commissioned' }
|
||||
{ label: this.$t('Pending Settlement'), value: 'Draft' },
|
||||
{ label: this.$t('Paid'), value: 'Paid' },
|
||||
{ label: this.$t('Settled'), value: 'Commissioned' }
|
||||
]
|
||||
}
|
||||
];
|
||||
@ -66,7 +66,7 @@ export default {
|
||||
orderBy: 'creation desc',
|
||||
columns: [
|
||||
{
|
||||
label: '日期',
|
||||
label: this.$t('Date'),
|
||||
fieldname: 'period_end',
|
||||
format(value) {
|
||||
return Intl.DateTimeFormat('en-US', {
|
||||
@ -76,10 +76,10 @@ export default {
|
||||
}).format(new Date(value));
|
||||
}
|
||||
},
|
||||
{ label: '支付方式', fieldname: 'mode_of_payment' },
|
||||
{ label: '状态', fieldname: 'status', type: 'Badge' },
|
||||
{ label: this.$t('Payment Method'), fieldname: 'mode_of_payment' },
|
||||
{ label: this.$t('Status'), fieldname: 'status', type: 'Badge' },
|
||||
{
|
||||
label: '总计',
|
||||
label: this.$t('Total'),
|
||||
fieldname: 'net_total_cny',
|
||||
align: 'right',
|
||||
format: (_, row) => {
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
<div>
|
||||
<FInput
|
||||
v-model="filters.search"
|
||||
placeholder="搜索订单..."
|
||||
:placeholder="$t('Search orders...')"
|
||||
type="text"
|
||||
class="w-60"
|
||||
@input="debouncedSearch"
|
||||
@ -20,7 +20,7 @@
|
||||
appearance="primary"
|
||||
@click="exportToCsv"
|
||||
>
|
||||
导出
|
||||
{{ $t('Export') }}
|
||||
</Button>
|
||||
<Button
|
||||
icon="refresh-cw"
|
||||
@ -34,8 +34,8 @@
|
||||
<template v-if="orders.length === 0">
|
||||
<div class="flex h-60 flex-col items-center justify-center space-y-2 p-4 text-center">
|
||||
<i-lucide-file-text class="h-8 w-8 text-gray-400" />
|
||||
<p class="text-base font-medium">无订单记录</p>
|
||||
<p class="text-sm text-gray-600">暂无订单记录可以显示</p>
|
||||
<p class="text-base font-medium">{{ $t('No Order Records') }}</p>
|
||||
<p class="text-sm text-gray-600">{{ $t('No order records to display') }}</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -78,7 +78,7 @@
|
||||
|
||||
<div class="flex items-center justify-between p-4">
|
||||
<div class="text-sm text-gray-600">
|
||||
显示 {{ orders.length }} 条订单,共 {{ totalCount }} 条
|
||||
{{ $t('Showing {count} orders, total {total}', { count: orders.length, total: totalCount }) }}
|
||||
</div>
|
||||
<Button
|
||||
v-if="hasMoreToLoad"
|
||||
@ -86,7 +86,7 @@
|
||||
:loading="loadingMore"
|
||||
appearance="primary"
|
||||
>
|
||||
加载更多
|
||||
{{ $t('Load More') }}
|
||||
</Button>
|
||||
</div>
|
||||
</template>
|
||||
@ -95,7 +95,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref, reactive, computed, onMounted } from 'vue';
|
||||
import { ref, reactive, computed, onMounted, getCurrentInstance } from 'vue';
|
||||
import { Button, Card, Input as FInput, createResource } from 'jingrow-ui';
|
||||
import StatusIndicator from '../components/StatusIndicator.vue';
|
||||
import { unparse } from 'papaparse';
|
||||
@ -109,6 +109,8 @@ export default {
|
||||
StatusIndicator,
|
||||
},
|
||||
setup() {
|
||||
const instance = getCurrentInstance();
|
||||
const $t = instance?.appContext.config.globalProperties.$t || ((key) => key);
|
||||
const pageSize = 20;
|
||||
const orders = ref([]);
|
||||
const totalCount = ref(0);
|
||||
@ -122,15 +124,15 @@ export default {
|
||||
|
||||
// 定义表格列
|
||||
const columns = [
|
||||
{ key: 'creation', label: '时间', class: '' },
|
||||
{ key: 'title', label: '标题', class: '' },
|
||||
{ key: 'order_id', label: '订单号', class: '' },
|
||||
{ key: 'trade_no', label: '交易号', class: '' },
|
||||
{ key: 'order_type', label: '订单类型', class: '' },
|
||||
{ key: 'payment_method', label: '支付方式', class: '' },
|
||||
{ key: 'description', label: '描述', class: '' },
|
||||
{ key: 'total', label: '金额', class: 'text-right' },
|
||||
{ key: 'status', label: '状态', class: '' }
|
||||
{ key: 'creation', label: $t('Time'), class: '' },
|
||||
{ key: 'title', label: $t('Title'), class: '' },
|
||||
{ key: 'order_id', label: $t('Order ID'), class: '' },
|
||||
{ key: 'trade_no', label: $t('Transaction ID'), class: '' },
|
||||
{ key: 'order_type', label: $t('Order Type'), class: '' },
|
||||
{ key: 'payment_method', label: $t('Payment Method'), class: '' },
|
||||
{ key: 'description', label: $t('Description'), class: '' },
|
||||
{ key: 'total', label: $t('Amount'), class: 'text-right' },
|
||||
{ key: 'status', label: $t('Status'), class: '' }
|
||||
];
|
||||
|
||||
// 计算是否还有更多数据可加载
|
||||
@ -177,15 +179,15 @@ export default {
|
||||
|
||||
// 定义CSV字段
|
||||
const fields = [
|
||||
'标题',
|
||||
'订单ID',
|
||||
'交易号',
|
||||
'订单类型',
|
||||
'支付方式',
|
||||
'描述',
|
||||
'金额',
|
||||
'状态',
|
||||
'创建时间'
|
||||
$t('Title'),
|
||||
$t('Order ID'),
|
||||
$t('Transaction ID'),
|
||||
$t('Order Type'),
|
||||
$t('Payment Method'),
|
||||
$t('Description'),
|
||||
$t('Amount'),
|
||||
$t('Status'),
|
||||
$t('Creation Time')
|
||||
];
|
||||
|
||||
// 准备数据
|
||||
@ -213,7 +215,7 @@ export default {
|
||||
// 触发下载
|
||||
const blob = new Blob([csv], { type: 'text/csv;charset=utf-8' });
|
||||
const today = new Date().toISOString().split('T')[0];
|
||||
const filename = `订单记录-${today}.csv`;
|
||||
const filename = `${$t('Order Records')}-${today}.csv`;
|
||||
const link = document.createElement('a');
|
||||
link.href = URL.createObjectURL(blob);
|
||||
link.download = filename;
|
||||
@ -302,14 +304,14 @@ export default {
|
||||
// 获取状态样式
|
||||
function getStatusProps(status) {
|
||||
const statusMap = {
|
||||
'待支付': { label: '待支付', color: 'orange' },
|
||||
'已支付': { label: '已支付', color: 'green' },
|
||||
'交易成功': { label: '交易成功', color: 'green' },
|
||||
'已取消': { label: '已取消', color: 'red' },
|
||||
'已退款': { label: '已退款', color: 'red' },
|
||||
'待支付': { label: $t('Pending Payment'), color: 'orange' },
|
||||
'已支付': { label: $t('Paid'), color: 'green' },
|
||||
'交易成功': { label: $t('Transaction Successful'), color: 'green' },
|
||||
'已取消': { label: $t('Cancelled'), color: 'red' },
|
||||
'已退款': { label: $t('Refunded'), color: 'red' },
|
||||
};
|
||||
|
||||
return statusMap[status] || { label: status, color: 'blue' };
|
||||
return statusMap[status] || { label: status || '', color: 'blue' };
|
||||
}
|
||||
|
||||
// 生命周期钩子
|
||||
|
||||
@ -28,14 +28,14 @@ export default {
|
||||
'brand',
|
||||
'stripe_mandate_id'
|
||||
],
|
||||
emptyStateMessage: '未添加任何卡片',
|
||||
emptyStateMessage: this.$t('No cards added'),
|
||||
columns: [
|
||||
{
|
||||
label: '卡片姓名',
|
||||
label: this.$t('Card Name'),
|
||||
fieldname: 'name_on_card'
|
||||
},
|
||||
{
|
||||
label: '卡片',
|
||||
label: this.$t('Card'),
|
||||
fieldname: 'last_4',
|
||||
width: 1.5,
|
||||
format(value) {
|
||||
@ -51,20 +51,20 @@ export default {
|
||||
{
|
||||
theme: 'green'
|
||||
},
|
||||
() => '默认'
|
||||
() => this.$t('Default')
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '有效期',
|
||||
label: this.$t('Expiry Date'),
|
||||
width: 0.5,
|
||||
format(value, row) {
|
||||
return `${row.expiry_month}/${row.expiry_year}`;
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '授权',
|
||||
label: this.$t('Authorization'),
|
||||
type: 'Component',
|
||||
width: 1,
|
||||
align: 'center',
|
||||
@ -86,7 +86,7 @@ export default {
|
||||
return h(
|
||||
Tooltip,
|
||||
{
|
||||
text: '此卡上次支付失败。请使用其他卡片。'
|
||||
text: this.$t('This card failed to pay last time. Please use another card.')
|
||||
},
|
||||
() =>
|
||||
h(FeatherIcon, {
|
||||
@ -107,7 +107,7 @@ export default {
|
||||
rowActions: ({ listResource, row }) => {
|
||||
return [
|
||||
{
|
||||
label: '设为默认',
|
||||
label: this.$t('Set as Default'),
|
||||
onClick: () => {
|
||||
toast.promise(
|
||||
listResource.runDocMethod.submit({
|
||||
@ -115,24 +115,24 @@ export default {
|
||||
name: row.name
|
||||
}),
|
||||
{
|
||||
loading: '正在设为默认...',
|
||||
success: '默认卡片已设置',
|
||||
error: '无法设置默认卡片'
|
||||
loading: this.$t('Setting as default...'),
|
||||
success: this.$t('Default card set'),
|
||||
error: this.$t('Failed to set default card')
|
||||
}
|
||||
);
|
||||
},
|
||||
condition: () => !row.is_default
|
||||
},
|
||||
{
|
||||
label: '移除',
|
||||
label: this.$t('Remove'),
|
||||
onClick: () => {
|
||||
if (row.is_default && this.$team.pg.payment_mode === 'Card') {
|
||||
toast.error('无法移除默认卡片');
|
||||
toast.error(this.$t('Cannot remove default card'));
|
||||
return;
|
||||
}
|
||||
confirmDialog({
|
||||
title: '移除卡片',
|
||||
message: '确定要移除此卡片吗?',
|
||||
title: this.$t('Remove Card'),
|
||||
message: this.$t('Are you sure you want to remove this card?'),
|
||||
onSuccess: ({ hide }) => {
|
||||
toast.promise(
|
||||
listResource.delete.submit(row.name, {
|
||||
@ -141,12 +141,12 @@ export default {
|
||||
}
|
||||
}),
|
||||
{
|
||||
loading: '正在移除卡片...',
|
||||
success: '卡片已移除',
|
||||
loading: this.$t('Removing card...'),
|
||||
success: this.$t('Card removed'),
|
||||
error: error =>
|
||||
error.messages?.length
|
||||
? error.messages.join('\n')
|
||||
: error.message || '无法移除卡片'
|
||||
: error.message || this.$t('Failed to remove card')
|
||||
}
|
||||
);
|
||||
}
|
||||
@ -158,7 +158,7 @@ export default {
|
||||
orderBy: 'creation desc',
|
||||
primaryAction() {
|
||||
return {
|
||||
label: '添加卡片',
|
||||
label: this.$t('Add Card'),
|
||||
slots: {
|
||||
prefix: icon('plus')
|
||||
},
|
||||
|
||||
@ -302,6 +302,10 @@ Start,开始,
|
||||
Start Date,开始日期,
|
||||
Start Time,开始时间,
|
||||
State,州,
|
||||
State/Province/Region,州/省/地区,
|
||||
City,城市,
|
||||
Address,地址,
|
||||
Postal Code,邮政编码,
|
||||
Status,状态,
|
||||
Step,步,
|
||||
Steps,脚步,
|
||||
@ -459,6 +463,7 @@ Site,站点,
|
||||
Duration,持续时间,
|
||||
Owner,创建者,
|
||||
Account Recharge,账户充值,
|
||||
Recharge,充值,
|
||||
Recharge your account balance to pay for your services.,为您的账户充值余额,用于支付您的服务费用。,
|
||||
Online Recharge,在线充值,
|
||||
Bank Transfer,对公汇款,
|
||||
@ -752,4 +757,69 @@ DNS Settings,DNS设置,
|
||||
Other Information,其他信息,
|
||||
Renew,续费,
|
||||
Rename,重命名,
|
||||
Order Records,订单记录,
|
||||
Balance Details,余额明细,
|
||||
Developer Earnings,开发者收益,
|
||||
You do not have permission to view the billing page,您无权查看账单页面,
|
||||
Search orders...,搜索订单...,
|
||||
No Order Records,无订单记录,
|
||||
No order records to display,暂无订单记录可以显示,
|
||||
Time,时间,
|
||||
Title,标题,
|
||||
Order ID,订单号,
|
||||
Transaction ID,交易号,
|
||||
Order Type,订单类型,
|
||||
Showing {count} orders, total {total},显示 {count} 条订单,共 {total} 条,
|
||||
Load More,加载更多,
|
||||
Creation Time,创建时间,
|
||||
Pending Payment,待支付,
|
||||
Transaction Successful,交易成功,
|
||||
Balance Recharge,余额充值,
|
||||
Free Credits,赠送余额,
|
||||
Applied to Invoice {invoice},冲抵发票 {invoice},
|
||||
Balance,余额,
|
||||
Balance Records,余额记录,
|
||||
Failed to export data,导出数据失败,
|
||||
No cards added,未添加任何卡片,
|
||||
Card Name,卡片姓名,
|
||||
Card,卡片,
|
||||
Default,默认,
|
||||
Expiry Date,有效期,
|
||||
Authorization,授权,
|
||||
This card failed to pay last time. Please use another card.,此卡上次支付失败。请使用其他卡片。,
|
||||
Set as Default,设为默认,
|
||||
Setting as default...,正在设为默认...,
|
||||
Default card set,默认卡片已设置,
|
||||
Failed to set default card,无法设置默认卡片,
|
||||
Cannot remove default card,无法移除默认卡片,
|
||||
Remove Card,移除卡片,
|
||||
Are you sure you want to remove this card?,确定要移除此卡片吗?,
|
||||
Removing card...,正在移除卡片...,
|
||||
Card removed,卡片已移除,
|
||||
Failed to remove card,无法移除卡片,
|
||||
Add Card,添加卡片,
|
||||
Pending Settlement,待结算,
|
||||
Settled,已结算,
|
||||
Account Balance,账户余额,
|
||||
Billing Address,账单地址,
|
||||
No address,无地址,
|
||||
Add Billing Address,添加账单地址,
|
||||
Edit,编辑,
|
||||
Billing Name,账单名称,
|
||||
Update Billing Information,更新账单信息,
|
||||
Billing name is required,账单名称为必填项,
|
||||
Billing name contains invalid characters,账单名称包含无效字符,
|
||||
Your monthly billing charges will be deducted from your account balance,您的每月账单费用将从账户余额中扣除,
|
||||
Your partner will pay your monthly subscription fees,您的合作伙伴将为您支付每月订阅费用,
|
||||
Confirm Payment Method,确认支付方式,
|
||||
By changing the payment method to <strong>Paid By Partner</strong>, the following details will be shared with your partner:<br><br><li>Site/Server Name</li> <li>Plan Name</li><li>Site/Server Active Days</li><br>Are you sure you want to continue?,通过将支付方式更改为<strong>由合作伙伴支付</strong>,以下详细信息将与您的合作伙伴共享:<br><br><li>站点/服务器名称</li> <li>计划名称</li><li>站点/服务器激活天数</li><br>您确定要继续吗?,
|
||||
Change Payment Method,更改支付方式,
|
||||
Please recharge your account balance before changing payment method.,在更改支付方式之前,请先为您的账户充值余额。,
|
||||
Pay with Alipay,使用支付宝支付,
|
||||
Billing Details,账单详情,
|
||||
Please add billing details to your account before continuing.,在继续之前,请为您的账户添加账单详情。,
|
||||
Country and City,国家和城市,
|
||||
State and Postal Code,州和邮政编码,
|
||||
{field} is required,{field} 是必填项,
|
||||
Billing information updated,账单信息已更新,
|
||||
|
||||
|
||||
|
Can't render this file because it has a wrong number of fields in line 390.
|
Loading…
x
Reference in New Issue
Block a user