Files
EmailBill/Web/src/views/calendarV2/modules/TransactionList.vue

177 lines
3.9 KiB
Vue
Raw Normal View History

<!--
CalendarV2 专用的交易列表组件
特殊功能
- 自定义 headerItems 数量Smart 按钮
- 与日历视图紧密集成
- 使用统一的 BillListComponent 展示账单列表
迁移说明已迁移至使用 BillListComponent保留自定义 header Smart 按钮
-->
2026-02-03 17:56:32 +08:00
<template>
<!-- 交易列表 -->
<div class="transactions">
<!-- 自定义 header (保留) -->
2026-02-03 17:56:32 +08:00
<div class="txn-header">
<h2 class="txn-title">
交易记录
</h2>
<div class="txn-actions">
<div class="txn-badge badge-success">
{{ transactionCount }} Items
</div>
<button
class="smart-btn"
@click="onSmartClick"
>
<van-icon name="fire" />
<span>Smart</span>
</button>
</div>
</div>
<!-- 统一的账单列表组件 -->
<BillListComponent
data-source="custom"
:transactions="transactions"
:loading="transactionsLoading"
:finished="true"
:show-delete="false"
:enable-filter="false"
@click="onTransactionClick"
/>
2026-02-03 17:56:32 +08:00
</div>
</template>
<script setup>
import { computed, watch, ref } from 'vue'
import { getTransactionsByDate } from '@/api/transactionRecord'
import BillListComponent from '@/components/Bill/BillListComponent.vue'
2026-02-03 17:56:32 +08:00
const props = defineProps({
selectedDate: Date
})
const emit = defineEmits(['transactionClick', 'smartClick'])
// 组件内部数据
const transactions = ref([])
const transactionsLoading = ref(false)
// 格式化日期为 key (yyyy-MM-dd)
const formatDateKey = (date) => {
const year = date.getFullYear()
const month = String(date.getMonth() + 1).padStart(2, '0')
const day = String(date.getDate()).padStart(2, '0')
return `${year}-${month}-${day}`
}
// 获取选中日期的交易列表
const fetchDayTransactions = async (date) => {
try {
transactionsLoading.value = true
const dateKey = formatDateKey(date)
const response = await getTransactionsByDate(dateKey)
if (response.success && response.data) {
// 直接使用原始数据,交给 BillListComponent 处理格式化
transactions.value = response.data
2026-02-03 17:56:32 +08:00
}
} catch (error) {
console.error('获取交易记录失败:', error)
} finally {
transactionsLoading.value = false
}
}
// 监听 selectedDate 变化,重新加载数据
watch(
() => props.selectedDate,
async (newDate) => {
if (newDate) {
await fetchDayTransactions(newDate)
}
},
{ immediate: true }
)
2026-02-03 17:56:32 +08:00
// 交易数量
const transactionCount = computed(() => transactions.value.length)
// 点击交易卡片
const onTransactionClick = (txn) => {
emit('transactionClick', txn)
}
// 点击 Smart 按钮
const onSmartClick = () => {
emit('smartClick')
}
</script>
<style scoped>
@import '@/assets/theme.css';
/* ========== 交易列表容器 ========== */
2026-02-03 17:56:32 +08:00
.transactions {
display: flex;
flex-direction: column;
gap: var(--spacing-lg);
padding: var(--spacing-3xl);
padding-top: 0;
}
/* ========== 自定义 Header (保留) ========== */
2026-02-03 17:56:32 +08:00
.txn-header {
display: flex;
align-items: center;
justify-content: space-between;
}
.txn-title {
font-family: var(--font-display);
font-size: var(--font-xl);
font-weight: var(--font-bold);
color: var(--text-primary);
margin: 0;
}
.txn-actions {
display: flex;
align-items: center;
gap: var(--spacing-md);
}
.txn-badge {
padding: 6px 12px;
font-size: var(--font-base);
font-weight: var(--font-semibold);
border-radius: var(--radius-sm);
}
.badge-success {
background-color: var(--accent-success-bg);
color: var(--accent-success);
}
.smart-btn {
display: flex;
align-items: center;
margin-left: 6px;
gap: 6px;
padding: 6px 12px;
background-color: var(--accent-info-bg);
color: var(--accent-info);
border: none;
border-radius: var(--radius-sm);
font-size: var(--font-base);
font-weight: var(--font-semibold);
cursor: pointer;
transition: opacity 0.2s;
}
.smart-btn:active {
opacity: 0.7;
}
</style>