jcloud/dashboard/src2/components/billing/PaymentDetails.vue
2025-04-12 17:39:38 +08:00

227 lines
6.4 KiB
Vue
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.

<template>
<div class="flex flex-col gap-4 py-10">
<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-2xl font-bold text-blue-600 py-6">
{{ availableCredits || currency + ' 0.00' }}
</div>
</div>
<div class="shrink-0">
<Button
:label="'充值'"
@click="
() => {
showMessage = false;
showAddPrepaidCreditsDialog = true;
}
"
>
<template #prefix>
<FeatherIcon class="h-4" name="plus" />
</template>
</Button>
</div>
</div>
<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 v-if="billingDetailsSummary" class="leading-5 text-gray-700">
{{ billingDetailsSummary }}
</div>
<div v-else class="text-gray-700">无地址</div>
</div>
<div class="shrink-0">
<Button
:label="billingDetailsSummary ? '编辑' : '添加账单地址'"
@click="
() => {
showMessage = false;
showBillingDetailsDialog = true;
}
"
>
<template v-if="!billingDetailsSummary" #prefix>
<FeatherIcon class="h-4" name="plus" />
</template>
</Button>
</div>
</div>
</div>
</div>
<BillingDetailsDialog
v-if="showBillingDetailsDialog"
v-model="showBillingDetailsDialog"
:showMessage="showMessage"
@success="billingDetails.reload()"
/>
<AddPrepaidCreditsDialog
v-if="showAddPrepaidCreditsDialog"
v-model="showAddPrepaidCreditsDialog"
:showMessage="showMessage"
@success="upcomingInvoice.reload()"
/>
</template>
<script setup>
import DropdownItem from './DropdownItem.vue';
import BillingDetailsDialog from './BillingDetailsDialog.vue';
import AddPrepaidCreditsDialog from './AddPrepaidCreditsDialog.vue';
import { Dropdown, Button, FeatherIcon, createResource } from 'jingrow-ui';
import {
confirmDialog,
renderDialog,
} from '../../utils/components';
import { computed, ref, inject, h, defineAsyncComponent, onMounted, nextTick } from 'vue';
import router from '../../router';
// 英文国家名到中文的映射
const countryToZh = {
'China': '中国',
'United States': '美国',
// 可以根据需要添加更多国家
};
const team = inject('team');
const {
availableCredits,
upcomingInvoice,
currentBillingAmount,
unpaidInvoices,
} = inject('billing');
const showBillingDetailsDialog = ref(false);
const showAddPrepaidCreditsDialog = ref(false);
const currency = computed(() => (team.pg.currency == 'CNY' ? '¥' : '$'));
const billingDetails = createResource({
url: 'jcloud.api.account.get_billing_information',
cache: 'billingDetails',
auto: true,
});
const changePaymentMode = createResource({
url: 'jcloud.api.billing.change_payment_mode',
onSuccess: () => setTimeout(() => team.reload(), 1000),
});
const billingDetailsSummary = computed(() => {
let _billingDetails = billingDetails.data;
if (!_billingDetails) return '';
const { address_line1, city, state, country, pincode } =
_billingDetails || {};
// 转换国家名称为中文
const displayCountry = countryToZh[country] || country;
// 调整为中国用户习惯的地址格式
// 中国地址格式:[国家] [省/自治区/直辖市] [市] [区/详细地址] [邮编]
if (country === 'China') {
// 中国地址使用中文格式
return [
displayCountry,
state, // 省/自治区/直辖市
city, // 市
address_line1, // 详细地址
pincode ? `邮编: ${pincode}` : '' // 邮编
]
.filter(Boolean)
.join(' ');
} else {
// 国外地址保持原来的格式
return [
address_line1,
city,
state,
displayCountry,
pincode
]
.filter(Boolean)
.join(', ');
}
});
const paymentModeOptions = [
{
label: '余额支付',
value: 'Prepaid Credits',
description: '您的每月账单费用将从账户余额中扣除',
component: () =>
h(DropdownItem, {
label: '余额支付',
active: team.pg.payment_mode === 'Prepaid Credits',
onClick: () => updatePaymentMode('Prepaid Credits'),
}),
},
{
label: '由合作伙伴支付',
value: 'Paid By Partner',
condition: () => team.pg.partner_email,
description: '您的合作伙伴将为您支付每月订阅费用',
component: () =>
h(DropdownItem, {
label: '由合作伙伴支付',
active: team.pg.payment_mode === 'Paid by Partner',
onClick: () =>
confirmDialog({
title: '确认支付方式',
message: `通过将支付方式更改为<strong>由合作伙伴支付</strong>,以下详细信息将与您的合作伙伴共享:<br><br><li>站点/服务器名称</li> <li>计划名称</li><li>站点/服务器激活天数</li><br>您确定要继续吗?`,
primaryAction: {
label: '更改支付方式',
variant: 'solid',
onClick: ({ hide }) => {
updatePaymentMode('Paid By Partner');
hide();
},
},
}),
}),
},
];
const paymentMode = computed(() => {
return paymentModeOptions.find((o) => o.value === team.pg.payment_mode);
});
// 修改onMounted钩子添加自动设置支付方式为余额支付的逻辑
onMounted(() => {
// 如果当前没有设置支付方式,自动设置为余额支付
nextTick(() => {
if (!team.pg.payment_mode) {
updatePaymentMode('Prepaid Credits');
}
});
});
function payUnpaidInvoices() {
let _unpaidInvoices = unpaidInvoices.data;
if (_unpaidInvoices.length > 1) {
showAddPrepaidCreditsDialog.value = true;
} else {
let invoice = _unpaidInvoices[0];
showAddPrepaidCreditsDialog.value = true;
}
}
const showMessage = ref(false);
function updatePaymentMode(mode) {
showMessage.value = false;
if (mode === 'Paid By Partner' && Boolean(unpaidInvoices.data.length > 0)) {
if (unpaidInvoices.data) {
payUnpaidInvoices();
return;
}
if (currentBillingAmount.value) {
const finalizeInvoicesDialog = defineAsyncComponent(
() => import('./FinalizeInvoicesDialog.vue'),
);
renderDialog(h(finalizeInvoicesDialog));
return;
}
}
if (!changePaymentMode.loading) changePaymentMode.submit({ mode });
}
</script>