<template>
|
<div>
|
<!-- 顶部收支卡片 -->
|
<div class="finance-cards">
|
<!-- 月度收入 -->
|
<div class="finance-card income-card">
|
<div class="icon-box">
|
<img src="@/assets/BI/icon@2x.png" alt="图标" class="card-icon" />
|
</div>
|
<div class="card-body">
|
<div class="card-left">
|
<div class="card-title">月度收入</div>
|
<div class="card-amount">{{ income.amount }}</div>
|
</div>
|
<div class="card-right">
|
<div class="metric-row">
|
<span class="metric-label">回款率</span>
|
<span class="metric-value" :class="metricClass(income.repayRate)">
|
{{ formatPercent(income.repayRate.value) }}
|
<span class="arrow">{{ metricArrow(income.repayRate) }}</span>
|
</span>
|
</div>
|
<div class="metric-row">
|
<span class="metric-label">逾期数</span>
|
<span class="metric-value metric-up">{{ income.overdueCount }}</span>
|
</div>
|
<div class="metric-row">
|
<span class="metric-label">逾期率</span>
|
<span class="metric-value" :class="metricClass(income.overdueRate)">
|
{{ formatPercent(income.overdueRate.value) }}
|
<span class="arrow">{{ metricArrow(income.overdueRate) }}</span>
|
</span>
|
</div>
|
</div>
|
</div>
|
</div>
|
|
<!-- 月度支出 -->
|
<div class="finance-card expense-card">
|
<div class="icon-box">
|
<img src="@/assets/BI/icon@2x.png" alt="图标" class="card-icon" />
|
</div>
|
<div class="card-body">
|
<div class="card-left">
|
<div class="card-title">月度支出</div>
|
<div class="card-amount">{{ expense.amount }}</div>
|
</div>
|
<div class="card-right">
|
<div class="metric-row">
|
<span class="metric-label">付款率</span>
|
<span class="metric-value metric-down">{{ expense.netProfit }}</span>
|
</div>
|
<div class="metric-row">
|
<span class="metric-label">毛利润</span>
|
<span class="metric-value metric-down">{{ expense.grossProfit }}</span>
|
</div>
|
<div class="metric-row">
|
<span class="metric-label">利润率</span>
|
<span class="metric-value" :class="metricClass(expense.profitRate)">
|
{{ formatPercent(expense.profitRate.value) }}
|
<span class="arrow">{{ metricArrow(expense.profitRate) }}</span>
|
</span>
|
</div>
|
</div>
|
</div>
|
</div>
|
</div>
|
|
</div>
|
</template>
|
|
<script setup>
|
import { ref } from 'vue'
|
|
// 暂时使用本地示例数据,后续可接真实接口覆盖
|
const income = ref({
|
amount: 102,
|
repayRate: { value: 52, trend: 1 }, // 正向 ↑
|
overdueCount: 10092,
|
overdueRate: { value: 12, trend: 1 },
|
})
|
|
const expense = ref({
|
amount: 102,
|
netProfit: 291013,
|
grossProfit: 10092,
|
profitRate: { value: 12, trend: -1 }, // 负向 ↓
|
})
|
|
const formatPercent = (val) => {
|
const num = Number(val) || 0
|
return `${num.toFixed(2)}%`
|
}
|
|
const metricClass = (metric) =>
|
Number(metric.trend) >= 0 ? 'metric-up' : 'metric-down'
|
|
const metricArrow = (metric) =>
|
Number(metric.trend) >= 0 ? '↑' : '↓'
|
</script>
|
|
<style scoped>
|
.finance-cards {
|
display: flex;
|
justify-content: space-between;
|
gap: 16px;
|
}
|
|
.finance-card {
|
flex: 1;
|
display: flex;
|
align-items: center;
|
padding: 18px 24px;
|
background-image: url('@/assets/BI/border@2x.png');
|
background-size: 100% 100%;
|
background-position: center;
|
background-repeat: no-repeat;
|
min-height: 138px;
|
}
|
|
.icon-box {
|
width: 92px;
|
height: 92px;
|
/* border: 1px dashed rgba(208, 231, 255, 0.55); */
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
margin-right: 18px;
|
}
|
|
.card-icon {
|
width: 78px;
|
height: 78px;
|
}
|
|
.card-body {
|
flex: 1;
|
display: flex;
|
align-items: center;
|
justify-content: space-between;
|
gap: 18px;
|
}
|
|
.card-left {
|
min-width: 90px;
|
}
|
|
.card-title {
|
font-weight: 400;
|
font-size: 18px;
|
color: rgba(208, 231, 255, 0.7);
|
}
|
|
.card-amount {
|
font-weight: 500;
|
font-size: 36px;
|
line-height: 1.1;
|
margin-top: 8px;
|
background: linear-gradient(360deg, #008bfd 0%, #ffffff 100%);
|
-webkit-background-clip: text;
|
-webkit-text-fill-color: transparent;
|
background-clip: text;
|
}
|
|
.card-right {
|
flex: 1;
|
display: flex;
|
flex-direction: column;
|
gap: 10px;
|
padding-right: 6px;
|
}
|
|
.metric-row {
|
display: flex;
|
align-items: center;
|
justify-content: space-between;
|
font-size: 14px;
|
color: #d0e7ff;
|
white-space: nowrap;
|
}
|
|
.metric-label {
|
margin-right: 12px;
|
}
|
|
.metric-label {
|
opacity: 0.8;
|
}
|
|
.metric-value {
|
font-weight: 600;
|
display: inline-flex;
|
align-items: center;
|
}
|
|
.metric-value .arrow {
|
font-size: 13px;
|
margin-left: 4px;
|
}
|
|
.metric-up {
|
color: #00c853;
|
}
|
|
.metric-down {
|
color: #ff5252;
|
}
|
|
|
</style>
|