Files
EmailBill/Web/src/views/calendarV2/modules/TransactionList.vue
SunCheng 1ba446f05a feat(calendar-v2): add delete functionality to transaction list
添加左滑删除功能:
- 启用 show-delete prop
- 实现 onTransactionDelete 事件处理器
- 删除后更新本地列表数据
2026-02-19 22:03:24 +08:00

196 lines
4.5 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.
<!--
CalendarV2 专用的交易列表组件
特殊功能
- 自定义 headerItems 数量Smart 按钮
- 与日历视图紧密集成
- 使用统一的 BillListComponent 展示账单列表
迁移说明已迁移至使用 BillListComponent保留自定义 header Smart 按钮
-->
<template>
<!-- 交易列表 -->
<div class="transactions">
<!-- 自定义 header (保留) -->
<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="true"
:enable-filter="false"
@click="onTransactionClick"
@delete="onTransactionDelete"
/>
</div>
</template>
<script setup>
import { computed, watch, ref } from 'vue'
import { getTransactionsByDate } from '@/api/transactionRecord'
import BillListComponent from '@/components/Bill/BillListComponent.vue'
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
}
} catch (error) {
console.error('获取交易记录失败:', error)
} finally {
transactionsLoading.value = false
}
}
// 监听 selectedDate 变化,重新加载数据
watch(
() => props.selectedDate,
async (newDate) => {
if (newDate) {
await fetchDayTransactions(newDate)
}
},
{ immediate: true }
)
// 交易数量
const transactionCount = computed(() => transactions.value.length)
// 点击交易卡片
const onTransactionClick = (txn) => {
emit('transactionClick', txn)
}
// 删除交易后的处理
const onTransactionDelete = (deletedId) => {
// BillListComponent 已经完成删除 API 调用
// 这里只需要从本地列表中移除该项
transactions.value = transactions.value.filter((t) => t.id !== deletedId)
}
// 点击 Smart 按钮
const onSmartClick = () => {
emit('smartClick')
}
</script>
<style scoped>
@import '@/assets/theme.css';
/* ========== 交易列表容器 ========== */
.transactions {
display: flex;
flex-direction: column;
gap: var(--spacing-lg);
padding: var(--spacing-xl, 16px);
padding-top: 0;
}
/* 移除 BillListComponent 内部的左右 padding/margin */
:deep(.van-cell-group) {
margin-left: 0 !important;
margin-right: 0 !important;
}
:deep(.van-list) {
padding-left: 0 !important;
padding-right: 0 !important;
}
/* ========== 自定义 Header (保留) ========== */
.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>