Files
EmailBill/Web/src/views/CalendarView.vue
孙诚 c763bc0fb7
All checks were successful
Docker Build & Deploy / Build Docker Image (push) Successful in 14s
Docker Build & Deploy / Deploy to Production (push) Successful in 6s
页面细节调整
2025-12-25 16:24:21 +08:00

217 lines
5.9 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.
<template>
<div class="calendar-container">
<van-calendar title="日历" :poppable="false" :show-confirm="false" :formatter="formatterCalendar" :min-date="minDate"
:max-date="maxDate" @month-show="onMonthShow" @select="onDateSelect" />
<!-- 日期交易列表弹出层 -->
<van-popup v-model:show="listVisible" position="bottom" :style="{ height: '85%' }" round closeable>
<div class="date-transactions">
<div class="popup-header">
<h3>{{ selectedDateText }}</h3>
<p v-if="dateTransactions.length"> {{ dateTransactions.length }} 笔交易</p>
</div>
<TransactionList :transactions="dateTransactions" :loading="listLoading" :finished="true" :show-delete="false"
@click="viewDetail" />
</div>
</van-popup>
<!-- 交易详情组件 -->
<TransactionDetail v-model:show="detailVisible" :transaction="currentTransaction" @save="onDetailSave" />
</div>
</template>
<script setup>
import { ref, onMounted, nextTick } from 'vue'
import { showToast } from 'vant'
import request from '@/api/request'
import { getTransactionDetail, getTransactionsByDate } from '@/api/transactionRecord'
import TransactionList from '@/components/TransactionList.vue'
import TransactionDetail from '@/components/TransactionDetail.vue'
const dailyStatistics = ref({})
const listVisible = ref(false)
const detailVisible = ref(false)
const dateTransactions = ref([])
const currentTransaction = ref(null)
const listLoading = ref(false)
const selectedDate = ref(null)
const selectedDateText = ref('')
// 设置日历可选范围例如过去2年到未来1年
const minDate = new Date(new Date().getFullYear() - 2, 0, 1) // 2年前的1月1日
const maxDate = new Date(new Date().getFullYear() + 1, 11, 31) // 明年12月31日
onMounted(async () => {
await nextTick()
setTimeout(() => {
// 计算页面高度滚动3/4高度以显示更多日期
const height = document.querySelector('.calendar-container').clientHeight * 0.45
document
.querySelector('.van-calendar__body')
.scrollBy({
top: -height,
behavior: 'smooth'
})
}, 300);
})
// 获取日历统计数据
const fetchDailyStatistics = async (year, month) => {
try {
const response = await request.get('/TransactionRecord/GetDailyStatistics', {
params: { year, month }
})
if (response.success && response.data) {
// 将数组转换为对象key为日期
const statsMap = {}
response.data.forEach(item => {
statsMap[item.date] = {
count: item.count,
amount: item.amount
}
})
dailyStatistics.value = {
...dailyStatistics.value,
...statsMap
}
}
} catch (error) {
console.error('获取日历统计数据失败:', error)
}
}
// 获取指定日期的交易列表
const fetchDateTransactions = async (date) => {
try {
listLoading.value = true
const dateStr = date.toLocaleString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit' }).replace(/\//g, '-')
const response = await getTransactionsByDate(dateStr)
if (response.success && response.data) {
dateTransactions.value = response.data
} else {
dateTransactions.value = []
showToast(response.message || '获取交易列表失败')
}
} catch (error) {
console.error('获取日期交易列表失败:', error)
dateTransactions.value = []
showToast('获取交易列表失败')
} finally {
listLoading.value = false
}
}
// 当月份显示时触发
const onMonthShow = ({ date }) => {
const year = date.getFullYear()
const month = date.getMonth() + 1
fetchDailyStatistics(year, month)
}
// 日期选择事件
const onDateSelect = (date) => {
selectedDate.value = date
selectedDateText.value = formatSelectedDate(date)
fetchDateTransactions(date)
listVisible.value = true
}
// 格式化选中的日期
const formatSelectedDate = (date) => {
return date.toLocaleDateString('zh-CN', {
year: 'numeric',
month: 'long',
day: 'numeric',
weekday: 'long'
})
}
// 查看详情
const viewDetail = async (transaction) => {
try {
const response = await getTransactionDetail(transaction.id)
if (response.success) {
currentTransaction.value = response.data
detailVisible.value = true
} else {
showToast(response.message || '获取详情失败')
}
} catch (error) {
console.error('获取详情出错:', error)
showToast('获取详情失败')
}
}
// 详情保存后的回调
const onDetailSave = () => {
// 重新加载当前日期的交易列表
if (selectedDate.value) {
fetchDateTransactions(selectedDate.value)
}
// 重新加载当前月份的统计数据
const now = selectedDate.value || new Date()
fetchDailyStatistics(now.getFullYear(), now.getMonth() + 1)
}
const formatterCalendar = (day) => {
const dayCopy = { ...day };
if (dayCopy.date.toDateString() === new Date().toDateString()) {
dayCopy.text = '今天';
}
// 格式化日期为 yyyy-MM-dd
const dateKey = dayCopy.date.toLocaleString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit' }).replace(/\//g, '-');
const stats = dailyStatistics.value[dateKey]
if (stats) {
dayCopy.topInfo = `${stats.count}` // 展示消费笔数
dayCopy.bottomInfo = `${stats.amount.toFixed(1)}` // 展示消费金额
}
return dayCopy;
};
// 初始加载当前月份数据
const now = new Date()
fetchDailyStatistics(now.getFullYear(), now.getMonth() + 1)
</script>
<style scoped>
.calendar-container {
height: 100vh;
display: flex;
flex-direction: column;
}
.calendar-container :deep(.van-calendar) {
height: 100%;
}
.date-transactions {
height: 100%;
display: flex;
flex-direction: column;
}
.popup-header {
padding: 16px;
border-bottom: 1px solid #ebedf0;
}
.popup-header h3 {
margin: 0 0 8px 0;
font-size: 18px;
font-weight: 600;
}
.popup-header p {
margin: 0;
font-size: 14px;
color: #969799;
}
</style>