feat 搭建架构骨架
This commit is contained in:
226
src/views/finance/bill-detail.vue
Normal file
226
src/views/finance/bill-detail.vue
Normal file
@@ -0,0 +1,226 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, watch } from 'vue'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { AppButton, StatusTag } from '@/components'
|
||||
// 页面容器:数据只经 store,不直接 import api
|
||||
import { useFinanceStore } from '@/stores/modules/finance'
|
||||
import type { BillStatus } from '@/types/business/finance'
|
||||
import { formatMoney } from '@/utils/format'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const financeStore = useFinanceStore()
|
||||
const { currentBill } = storeToRefs(financeStore)
|
||||
|
||||
const billId = computed(() => String(route.params.id))
|
||||
|
||||
const STATUS_VARIANTS: Record<BillStatus, 'warning' | 'success' | 'info'> = {
|
||||
待支付: 'warning',
|
||||
已支付: 'success',
|
||||
未到期: 'info',
|
||||
}
|
||||
|
||||
async function load(): Promise<void> {
|
||||
await financeStore.fetchDetail(billId.value)
|
||||
if (currentBill.value?.status === '已支付') {
|
||||
await financeStore.fetchResult(billId.value)
|
||||
}
|
||||
}
|
||||
|
||||
function onPay(): void {
|
||||
void router.push(`/finance/bills/${billId.value}/pay`)
|
||||
}
|
||||
|
||||
watch(billId, () => {
|
||||
void load()
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
void load()
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="bill-detail">
|
||||
<nav class="bill-detail__breadcrumb text-secondary">
|
||||
<RouterLink to="/finance" class="link">
|
||||
财务中心
|
||||
</RouterLink>
|
||||
<span> > </span>
|
||||
<RouterLink to="/finance/bills" class="link">
|
||||
账单明细
|
||||
</RouterLink>
|
||||
<span> > </span>
|
||||
<span>账单详情</span>
|
||||
</nav>
|
||||
|
||||
<template v-if="currentBill">
|
||||
<section class="bill-detail__card card">
|
||||
<div class="bill-detail__card-head">
|
||||
<h3 class="bill-detail__card-title">
|
||||
订单信息
|
||||
</h3>
|
||||
<StatusTag :label="currentBill.status" :variant="STATUS_VARIANTS[currentBill.status]" />
|
||||
</div>
|
||||
<div class="bill-detail__fields">
|
||||
<div class="bill-detail__field">
|
||||
<span class="bill-detail__label text-secondary">账单名称</span>
|
||||
<span class="bill-detail__value">{{ currentBill.planName }}</span>
|
||||
</div>
|
||||
<div class="bill-detail__field">
|
||||
<span class="bill-detail__label text-secondary">账单号</span>
|
||||
<span class="bill-detail__value">{{ currentBill.billNo }}</span>
|
||||
</div>
|
||||
<div class="bill-detail__field">
|
||||
<span class="bill-detail__label text-secondary">项目名称</span>
|
||||
<span class="bill-detail__value">{{ currentBill.projectName }}</span>
|
||||
</div>
|
||||
<div class="bill-detail__field">
|
||||
<span class="bill-detail__label text-secondary">订单金额</span>
|
||||
<span class="bill-detail__value bill-detail__value--amount">¥{{ formatMoney(currentBill.amount) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 待支付:立即支付 -->
|
||||
<div v-if="currentBill.status === '待支付'" class="bill-detail__pay">
|
||||
<AppButton type="primary" @click="onPay">
|
||||
立即支付
|
||||
</AppButton>
|
||||
</div>
|
||||
|
||||
<!-- 已支付:支付信息 -->
|
||||
<template v-else-if="currentBill.status === '已支付'">
|
||||
<div class="bill-detail__pay-info">
|
||||
<h4 class="bill-detail__sub-title">
|
||||
支付信息
|
||||
</h4>
|
||||
<div class="bill-detail__fields">
|
||||
<div class="bill-detail__field">
|
||||
<span class="bill-detail__label text-secondary">付款金额</span>
|
||||
<span class="bill-detail__value bill-detail__value--amount">¥{{ formatMoney(financeStore.result?.amount ?? currentBill.amount) }}</span>
|
||||
</div>
|
||||
<div class="bill-detail__field">
|
||||
<span class="bill-detail__label text-secondary">支付方式</span>
|
||||
<span class="bill-detail__value">微信支付</span>
|
||||
</div>
|
||||
<div class="bill-detail__field">
|
||||
<span class="bill-detail__label text-secondary">支付时间</span>
|
||||
<span class="bill-detail__value">{{ financeStore.result?.payTime ?? '—' }}</span>
|
||||
</div>
|
||||
<div class="bill-detail__field">
|
||||
<span class="bill-detail__label text-secondary">交易流水号</span>
|
||||
<span class="bill-detail__value">{{ financeStore.result?.tradeNo ?? currentBill.tradeNo ?? '—' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 未到期:提示 -->
|
||||
<div v-else class="bill-detail__tip text-secondary">
|
||||
账单尚未到期,到期后可前往账单明细完成支付。
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<p v-else class="bill-detail__empty text-secondary">
|
||||
账单不存在或已下线
|
||||
</p>
|
||||
|
||||
<div class="bill-detail__back">
|
||||
<AppButton @click="router.push('/finance/bills')">
|
||||
返回
|
||||
</AppButton>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.bill-detail {
|
||||
padding-top: @spacing-lg;
|
||||
padding-bottom: @spacing-xxl;
|
||||
|
||||
&__breadcrumb {
|
||||
margin-bottom: @spacing-base;
|
||||
font-size: @font-size-base;
|
||||
}
|
||||
|
||||
&__card {
|
||||
padding: @spacing-lg;
|
||||
border-radius: @radius-lg;
|
||||
background: @white;
|
||||
box-shadow: @shadow-base;
|
||||
}
|
||||
|
||||
&__card-head {
|
||||
.flex(row, space-between, center);
|
||||
margin-bottom: @spacing-base;
|
||||
}
|
||||
|
||||
&__card-title {
|
||||
font-size: @font-size-lg;
|
||||
font-weight: 600;
|
||||
color: @heading-color;
|
||||
}
|
||||
|
||||
&__fields {
|
||||
.flex(column, flex-start);
|
||||
gap: @spacing-sm;
|
||||
}
|
||||
|
||||
&__field {
|
||||
.flex(row, flex-start, center);
|
||||
gap: @spacing-base;
|
||||
font-size: @font-size-base;
|
||||
}
|
||||
|
||||
&__label {
|
||||
width: 80px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
&__value {
|
||||
color: @heading-color;
|
||||
|
||||
&--amount {
|
||||
font-weight: 600;
|
||||
color: @danger-color;
|
||||
}
|
||||
}
|
||||
|
||||
&__pay {
|
||||
margin-top: @spacing-lg;
|
||||
}
|
||||
|
||||
&__pay-info {
|
||||
margin-top: @spacing-lg;
|
||||
padding-top: @spacing-base;
|
||||
border-top: 1px solid @border-color;
|
||||
}
|
||||
|
||||
&__sub-title {
|
||||
margin-bottom: @spacing-sm;
|
||||
font-size: @font-size-base;
|
||||
font-weight: 600;
|
||||
color: @heading-color;
|
||||
}
|
||||
|
||||
&__tip {
|
||||
margin-top: @spacing-lg;
|
||||
padding: @spacing-base;
|
||||
border-radius: @radius-base;
|
||||
background: @bg-color;
|
||||
font-size: @font-size-base;
|
||||
}
|
||||
|
||||
&__empty {
|
||||
padding: @spacing-xl 0;
|
||||
text-align: center;
|
||||
font-size: @font-size-base;
|
||||
}
|
||||
|
||||
&__back {
|
||||
margin-top: @spacing-lg;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user