Files
oci-portal-dash/src/components/tenant/InvoicePayModal.vue
T

101 lines
3.2 KiB
Vue

<script setup lang="ts">
import { NInput } from 'naive-ui'
import { computed, ref, watch } from 'vue'
import { payInvoice } from '@/api/billing'
import FormModal from '@/components/FormModal.vue'
import { useToast } from '@/composables/useToast'
import { invoiceDate } from '@/components/tenant/invoiceStatus'
import { fmtMoney } from '@/composables/useFormat'
import type { Invoice, PaymentMethod } from '@/types/api'
/** 付款确认:经 OSP Gateway PayInvoice 按订阅默认付款方式即时扣款;
* email 是 API 必填项(接收付款回执),在此向用户收集。 */
const props = defineProps<{
show: boolean
cfgId: number
invoice: Invoice | null
methods: PaymentMethod[] | null
}>()
const emit = defineEmits<{ 'update:show': [boolean]; paid: [] }>()
const message = useToast()
const email = ref('')
const paying = ref(false)
const emailOk = computed(() => /.+@.+\..+/.test(email.value.trim()))
/** 扣款方式展示:优先第一张信用卡,其次任一登记方式 */
const payVia = computed(() => {
const ms = props.methods ?? []
const m = ms.find((x) => x.method === 'CREDIT_CARD') ?? ms[0]
if (!m) return '订阅默认付款方式'
if (m.method === 'CREDIT_CARD') return `${m.cardType || '银行卡'} •••• ${m.lastDigits}`
return `PayPal(${m.email})`
})
watch(
() => props.show,
(v) => {
if (v) paying.value = false
},
)
async function doPay() {
const inv = props.invoice
if (!inv || !emailOk.value) return
paying.value = true
try {
await payInvoice(props.cfgId, inv.internalId, email.value.trim())
message.success('付款已提交,发票状态稍后更新')
emit('update:show', false)
emit('paid')
} catch (e) {
message.error(e instanceof Error ? e.message : '付款失败')
} finally {
paying.value = false
}
}
</script>
<template>
<FormModal
:show="show"
title="支付发票"
:width="440"
submit-text="确认支付"
:submitting="paying"
:submit-disabled="!emailOk"
@update:show="emit('update:show', $event)"
@submit="doPay"
>
<template v-if="invoice">
<div class="rounded-md bg-wash px-4 py-3">
<div class="text-xs text-ink-3">应付金额</div>
<div class="mt-1 text-[24px] font-semibold tabular-nums">
{{ fmtMoney(invoice.amountDue || invoice.amount, invoice.currency) }}
</div>
<div class="mt-1 text-xs text-ink-3">
发票 {{ invoice.number }} · 到期 {{ invoiceDate(invoice.timeDue) }}
</div>
</div>
<div
class="mt-3 flex items-center justify-between rounded-md border border-line-soft px-4 py-2.5 text-[13px]"
>
<span class="text-ink-3">扣款方式</span>
<span class="font-medium">{{ payVia }}</span>
</div>
<div class="mt-3">
<div class="mb-1 text-xs text-ink-3">回执邮箱(必填)</div>
<NInput v-model:value="email" placeholder="billing@example.com" />
</div>
<div class="mt-3 text-xs leading-relaxed text-ink-3">
确认后经 OCI 支付网关按上述方式即时扣款,回执发送至邮箱;提交后发票转入处理中,
入账通常需要数分钟,期间请勿重复支付
</div>
</template>
</FormModal>
</template>