统计样式微调
This commit is contained in:
@@ -13,8 +13,20 @@ public interface ITransactionRecordRepository : IBaseRepository<TransactionRecor
|
|||||||
/// <param name="lastId">上一页最后一条记录的ID</param>
|
/// <param name="lastId">上一页最后一条记录的ID</param>
|
||||||
/// <param name="pageSize">每页数量</param>
|
/// <param name="pageSize">每页数量</param>
|
||||||
/// <param name="searchKeyword">搜索关键词(搜索交易摘要和分类)</param>
|
/// <param name="searchKeyword">搜索关键词(搜索交易摘要和分类)</param>
|
||||||
|
/// <param name="classify">筛选分类</param>
|
||||||
|
/// <param name="type">筛选交易类型</param>
|
||||||
|
/// <param name="year">筛选年份</param>
|
||||||
|
/// <param name="month">筛选月份</param>
|
||||||
/// <returns>交易记录列表、最后发生时间和最后ID</returns>
|
/// <returns>交易记录列表、最后发生时间和最后ID</returns>
|
||||||
Task<(List<TransactionRecord> list, DateTime? lastOccurredAt, long lastId)> GetPagedListAsync(DateTime? lastOccurredAt, long? lastId, int pageSize = 20, string? searchKeyword = null);
|
Task<(List<TransactionRecord> list, DateTime? lastOccurredAt, long lastId)> GetPagedListAsync(
|
||||||
|
DateTime? lastOccurredAt,
|
||||||
|
long? lastId,
|
||||||
|
int pageSize = 20,
|
||||||
|
string? searchKeyword = null,
|
||||||
|
string? classify = null,
|
||||||
|
TransactionType? type = null,
|
||||||
|
int? year = null,
|
||||||
|
int? month = null);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取总数
|
/// 获取总数
|
||||||
@@ -150,7 +162,15 @@ public class TransactionRecordRepository(IFreeSql freeSql) : BaseRepository<Tran
|
|||||||
.FirstAsync();
|
.FirstAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<(List<TransactionRecord> list, DateTime? lastOccurredAt, long lastId)> GetPagedListAsync(DateTime? lastOccurredAt, long? lastId, int pageSize = 20, string? searchKeyword = null)
|
public async Task<(List<TransactionRecord> list, DateTime? lastOccurredAt, long lastId)> GetPagedListAsync(
|
||||||
|
DateTime? lastOccurredAt,
|
||||||
|
long? lastId,
|
||||||
|
int pageSize = 20,
|
||||||
|
string? searchKeyword = null,
|
||||||
|
string? classify = null,
|
||||||
|
TransactionType? type = null,
|
||||||
|
int? year = null,
|
||||||
|
int? month = null)
|
||||||
{
|
{
|
||||||
var query = FreeSql.Select<TransactionRecord>();
|
var query = FreeSql.Select<TransactionRecord>();
|
||||||
|
|
||||||
@@ -163,6 +183,26 @@ public class TransactionRecordRepository(IFreeSql freeSql) : BaseRepository<Tran
|
|||||||
t.ImportFrom.Contains(searchKeyword));
|
t.ImportFrom.Contains(searchKeyword));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 按分类筛选
|
||||||
|
if (!string.IsNullOrWhiteSpace(classify))
|
||||||
|
{
|
||||||
|
query = query.Where(t => t.Classify == classify);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 按交易类型筛选
|
||||||
|
if (type.HasValue)
|
||||||
|
{
|
||||||
|
query = query.Where(t => t.Type == type.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 按年月筛选
|
||||||
|
if (year.HasValue && month.HasValue)
|
||||||
|
{
|
||||||
|
var startDate = new DateTime(year.Value, month.Value, 1);
|
||||||
|
var endDate = startDate.AddMonths(1);
|
||||||
|
query = query.Where(t => t.OccurredAt >= startDate && t.OccurredAt < endDate);
|
||||||
|
}
|
||||||
|
|
||||||
// 如果提供了游标,则获取小于游标位置的记录
|
// 如果提供了游标,则获取小于游标位置的记录
|
||||||
if (lastOccurredAt.HasValue && lastId.HasValue)
|
if (lastOccurredAt.HasValue && lastId.HasValue)
|
||||||
{
|
{
|
||||||
@@ -200,7 +240,6 @@ public class TransactionRecordRepository(IFreeSql freeSql) : BaseRepository<Tran
|
|||||||
|
|
||||||
var records = await FreeSql.Select<TransactionRecord>()
|
var records = await FreeSql.Select<TransactionRecord>()
|
||||||
.Where(t => t.OccurredAt >= startDate && t.OccurredAt < endDate)
|
.Where(t => t.OccurredAt >= startDate && t.OccurredAt < endDate)
|
||||||
.Where(t => t.Type == TransactionType.Expense || t.Type == TransactionType.Income) // 统计消费和收入
|
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
var statistics = records
|
var statistics = records
|
||||||
|
|||||||
@@ -98,16 +98,21 @@
|
|||||||
<div
|
<div
|
||||||
v-for="(category) in expenseCategories"
|
v-for="(category) in expenseCategories"
|
||||||
:key="category.classify"
|
:key="category.classify"
|
||||||
class="category-item"
|
class="category-item clickable"
|
||||||
|
@click="goToCategoryBills(category.classify, 0)"
|
||||||
>
|
>
|
||||||
<div class="category-info">
|
<div class="category-info">
|
||||||
<div class="category-color" :style="{ backgroundColor: category.color }"></div>
|
<div class="category-color" :style="{ backgroundColor: category.color }"></div>
|
||||||
<span class="category-name">{{ category.classify || '未分类' }}</span>
|
<div class="category-name-with-count">
|
||||||
|
<span class="category-name">{{ category.classify || '未分类' }}</span>
|
||||||
|
<span class="category-count">{{ category.count }}笔</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="category-stats">
|
<div class="category-stats">
|
||||||
<div class="category-amount">¥{{ formatMoney(category.amount) }}</div>
|
<div class="category-amount">¥{{ formatMoney(category.amount) }}</div>
|
||||||
<div class="category-percent">{{ category.percent }}%</div>
|
<div class="category-percent">{{ category.percent }}%</div>
|
||||||
</div>
|
</div>
|
||||||
|
<van-icon name="arrow" class="category-arrow" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -129,16 +134,21 @@
|
|||||||
<div
|
<div
|
||||||
v-for="category in incomeCategories"
|
v-for="category in incomeCategories"
|
||||||
:key="category.classify"
|
:key="category.classify"
|
||||||
class="category-item"
|
class="category-item clickable"
|
||||||
|
@click="goToCategoryBills(category.classify, 1)"
|
||||||
>
|
>
|
||||||
<div class="category-info">
|
<div class="category-info">
|
||||||
<div class="category-color income-color"></div>
|
<div class="category-color income-color"></div>
|
||||||
<span class="category-name">{{ category.classify || '未分类' }}</span>
|
<div class="category-name-with-count">
|
||||||
|
<span class="category-name">{{ category.classify || '未分类' }}</span>
|
||||||
|
<span class="category-count">{{ category.count }}笔</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="category-stats">
|
<div class="category-stats">
|
||||||
<div class="category-amount income-text">¥{{ formatMoney(category.amount) }}</div>
|
<div class="category-amount income-text">¥{{ formatMoney(category.amount) }}</div>
|
||||||
<div class="category-percent">{{ category.percent }}%</div>
|
<div class="category-percent">{{ category.percent }}%</div>
|
||||||
</div>
|
</div>
|
||||||
|
<van-icon name="arrow" class="category-arrow" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -234,14 +244,51 @@
|
|||||||
@cancel="showMonthPicker = false"
|
@cancel="showMonthPicker = false"
|
||||||
/>
|
/>
|
||||||
</van-popup>
|
</van-popup>
|
||||||
|
|
||||||
|
<!-- 分类账单列表弹出层 -->
|
||||||
|
<van-popup
|
||||||
|
v-model:show="billListVisible"
|
||||||
|
position="bottom"
|
||||||
|
:style="{ height: '85%' }"
|
||||||
|
round
|
||||||
|
closeable
|
||||||
|
>
|
||||||
|
<div class="category-bills">
|
||||||
|
<div class="popup-header">
|
||||||
|
<h3>{{ selectedCategoryTitle }}</h3>
|
||||||
|
<p v-if="categoryBills.length">共 {{ categoryBills.length }} 笔交易</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="bills-scroll-container">
|
||||||
|
<TransactionList
|
||||||
|
:transactions="categoryBills"
|
||||||
|
:loading="billListLoading"
|
||||||
|
:finished="billListFinished"
|
||||||
|
:show-delete="false"
|
||||||
|
@load="loadCategoryBills"
|
||||||
|
@click="viewBillDetail"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</van-popup>
|
||||||
|
|
||||||
|
<!-- 交易详情编辑组件 -->
|
||||||
|
<TransactionDetail
|
||||||
|
v-model:show="detailVisible"
|
||||||
|
:transaction="currentTransaction"
|
||||||
|
@save="onBillSave"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed, onMounted } from 'vue'
|
import { ref, computed, onMounted, onActivated } from 'vue'
|
||||||
import { showToast } from 'vant'
|
import { showToast } from 'vant'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { getMonthlyStatistics, getCategoryStatistics, getTrendStatistics } from '@/api/statistics'
|
import { getMonthlyStatistics, getCategoryStatistics, getTrendStatistics } from '@/api/statistics'
|
||||||
|
import { getTransactionList, getTransactionDetail } from '@/api/transactionRecord'
|
||||||
|
import TransactionList from '@/components/TransactionList.vue'
|
||||||
|
import TransactionDetail from '@/components/TransactionDetail.vue'
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
@@ -253,6 +300,21 @@ const currentYear = ref(new Date().getFullYear())
|
|||||||
const currentMonth = ref(new Date().getMonth() + 1)
|
const currentMonth = ref(new Date().getMonth() + 1)
|
||||||
const selectedDate = ref([new Date().getFullYear().toString(), (new Date().getMonth() + 1).toString().padStart(2, '0')])
|
const selectedDate = ref([new Date().getFullYear().toString(), (new Date().getMonth() + 1).toString().padStart(2, '0')])
|
||||||
|
|
||||||
|
// 账单列表相关
|
||||||
|
const billListVisible = ref(false)
|
||||||
|
const billListLoading = ref(false)
|
||||||
|
const billListFinished = ref(false)
|
||||||
|
const categoryBills = ref([])
|
||||||
|
const selectedCategoryTitle = ref('')
|
||||||
|
const selectedClassify = ref('')
|
||||||
|
const selectedType = ref(null)
|
||||||
|
const lastBillId = ref(null)
|
||||||
|
const lastBillTime = ref(null)
|
||||||
|
|
||||||
|
// 详情编辑相关
|
||||||
|
const detailVisible = ref(false)
|
||||||
|
const currentTransaction = ref(null)
|
||||||
|
|
||||||
// 月度数据
|
// 月度数据
|
||||||
const monthlyData = ref({
|
const monthlyData = ref({
|
||||||
totalExpense: 0,
|
totalExpense: 0,
|
||||||
@@ -433,6 +495,7 @@ const fetchCategoryData = async () => {
|
|||||||
expenseCategories.value = expenseResponse.data.map((item, index) => ({
|
expenseCategories.value = expenseResponse.data.map((item, index) => ({
|
||||||
classify: item.classify,
|
classify: item.classify,
|
||||||
amount: item.amount,
|
amount: item.amount,
|
||||||
|
count: item.count,
|
||||||
percent: item.percent,
|
percent: item.percent,
|
||||||
color: colors[index % colors.length]
|
color: colors[index % colors.length]
|
||||||
}))
|
}))
|
||||||
@@ -449,6 +512,7 @@ const fetchCategoryData = async () => {
|
|||||||
incomeCategories.value = incomeResponse.data.map(item => ({
|
incomeCategories.value = incomeResponse.data.map(item => ({
|
||||||
classify: item.classify,
|
classify: item.classify,
|
||||||
amount: item.amount,
|
amount: item.amount,
|
||||||
|
count: item.count,
|
||||||
percent: item.percent
|
percent: item.percent
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
@@ -496,10 +560,107 @@ const goToAnalysis = () => {
|
|||||||
router.push('/bill-analysis')
|
router.push('/bill-analysis')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 打开分类账单列表
|
||||||
|
const goToCategoryBills = (classify, type) => {
|
||||||
|
selectedClassify.value = classify || ''
|
||||||
|
selectedType.value = type
|
||||||
|
selectedCategoryTitle.value = `${classify || '未分类'} - ${type === 0 ? '支出' : '收入'}`
|
||||||
|
|
||||||
|
// 重置分页状态
|
||||||
|
categoryBills.value = []
|
||||||
|
lastBillId.value = null
|
||||||
|
lastBillTime.value = null
|
||||||
|
billListFinished.value = false
|
||||||
|
|
||||||
|
billListVisible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载分类账单数据
|
||||||
|
const loadCategoryBills = async () => {
|
||||||
|
if (billListLoading.value || billListFinished.value) return
|
||||||
|
|
||||||
|
billListLoading.value = true
|
||||||
|
try {
|
||||||
|
const params = {
|
||||||
|
classify: selectedClassify.value,
|
||||||
|
type: selectedType.value,
|
||||||
|
year: currentYear.value,
|
||||||
|
month: currentMonth.value
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastBillTime.value && lastBillId.value) {
|
||||||
|
params.lastOccurredAt = lastBillTime.value
|
||||||
|
params.lastId = lastBillId.value
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await getTransactionList(params)
|
||||||
|
|
||||||
|
if (response.success) {
|
||||||
|
const newList = response.data || []
|
||||||
|
categoryBills.value = [...categoryBills.value, ...newList]
|
||||||
|
|
||||||
|
if (newList.length > 0) {
|
||||||
|
const lastRecord = newList[newList.length - 1]
|
||||||
|
lastBillId.value = response.lastId || lastRecord.id
|
||||||
|
lastBillTime.value = response.lastTime || lastRecord.occurredAt
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newList.length === 0 || newList.length < 20) {
|
||||||
|
billListFinished.value = true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
showToast(response.message || '加载账单失败')
|
||||||
|
billListFinished.value = true
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载分类账单失败:', error)
|
||||||
|
showToast('加载账单失败')
|
||||||
|
billListFinished.value = true
|
||||||
|
} finally {
|
||||||
|
billListLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查看账单详情
|
||||||
|
const viewBillDetail = 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 onBillSave = async () => {
|
||||||
|
// 刷新统计数据
|
||||||
|
await fetchStatistics()
|
||||||
|
|
||||||
|
// 刷新账单列表
|
||||||
|
categoryBills.value = []
|
||||||
|
lastBillId.value = null
|
||||||
|
lastBillTime.value = null
|
||||||
|
billListFinished.value = false
|
||||||
|
await loadCategoryBills()
|
||||||
|
|
||||||
|
showToast('保存成功')
|
||||||
|
}
|
||||||
|
|
||||||
// 初始化
|
// 初始化
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
fetchStatistics()
|
fetchStatistics()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 页面激活时刷新数据(从其他页面返回时)
|
||||||
|
onActivated(() => {
|
||||||
|
fetchStatistics()
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
@@ -641,10 +802,11 @@ onMounted(() => {
|
|||||||
|
|
||||||
.category-item {
|
.category-item {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 12px 0;
|
padding: 12px 0;
|
||||||
border-bottom: 1px solid #ebedf0;
|
border-bottom: 1px solid #ebedf0;
|
||||||
|
transition: background-color 0.2s;
|
||||||
|
gap: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark) {
|
@media (prefers-color-scheme: dark) {
|
||||||
@@ -657,10 +819,32 @@ onMounted(() => {
|
|||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.category-item.clickable {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.category-item.clickable:active {
|
||||||
|
background-color: #f7f8fa;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
.category-item.clickable:active {
|
||||||
|
background-color: #141414;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.category-info {
|
.category-info {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.category-name-with-count {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.category-color {
|
.category-color {
|
||||||
@@ -674,11 +858,23 @@ onMounted(() => {
|
|||||||
color: var(--van-text-color);
|
color: var(--van-text-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.category-count {
|
||||||
|
font-size: 12px;
|
||||||
|
color: var(--van-text-color-3);
|
||||||
|
}
|
||||||
|
|
||||||
.category-stats {
|
.category-stats {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
align-items: center;
|
||||||
align-items: flex-end;
|
gap: 8px;
|
||||||
gap: 4px;
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.category-arrow {
|
||||||
|
margin-left: 8px;
|
||||||
|
color: var(--van-text-color-3);
|
||||||
|
font-size: 16px;
|
||||||
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.category-amount {
|
.category-amount {
|
||||||
@@ -838,4 +1034,73 @@ onMounted(() => {
|
|||||||
color: var(--van-text-color);
|
color: var(--van-text-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 分类账单列表弹出层 */
|
||||||
|
.category-bills {
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
background: #f7f8fa;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
.category-bills {
|
||||||
|
background: #141414;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.category-bills .popup-header {
|
||||||
|
padding: 20px 16px;
|
||||||
|
background: #fff;
|
||||||
|
border-bottom: 1px solid #ebedf0;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
.category-bills .popup-header {
|
||||||
|
background: #1f1f1f;
|
||||||
|
border-bottom: 1px solid #2c2c2c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.category-bills .popup-header h3 {
|
||||||
|
margin: 0 0 8px 0;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--van-text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.category-bills .popup-header p {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 14px;
|
||||||
|
color: var(--van-text-color-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 账单列表滚动容器 */
|
||||||
|
.bills-scroll-container {
|
||||||
|
flex: 1;
|
||||||
|
overflow-y: auto;
|
||||||
|
overflow-x: hidden;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 修复深色模式下van组件的背景色 */
|
||||||
|
.category-bills :deep(.van-list) {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.category-bills :deep(.van-cell-group) {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
.category-bills :deep(.van-cell) {
|
||||||
|
background-color: #1f1f1f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.category-bills :deep(.van-swipe-cell) {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
@@ -18,12 +18,25 @@ public class TransactionRecordController(
|
|||||||
public async Task<PagedResponse<Entity.TransactionRecord>> GetListAsync(
|
public async Task<PagedResponse<Entity.TransactionRecord>> GetListAsync(
|
||||||
[FromQuery] DateTime? lastOccurredAt = null,
|
[FromQuery] DateTime? lastOccurredAt = null,
|
||||||
[FromQuery] long? lastId = null,
|
[FromQuery] long? lastId = null,
|
||||||
[FromQuery] string? searchKeyword = null
|
[FromQuery] string? searchKeyword = null,
|
||||||
|
[FromQuery] string? classify = null,
|
||||||
|
[FromQuery] int? type = null,
|
||||||
|
[FromQuery] int? year = null,
|
||||||
|
[FromQuery] int? month = null
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var (list, lastTime, lastIdResult) = await transactionRepository.GetPagedListAsync(lastOccurredAt, lastId, 20, searchKeyword);
|
TransactionType? transactionType = type.HasValue ? (TransactionType)type.Value : null;
|
||||||
|
var (list, lastTime, lastIdResult) = await transactionRepository.GetPagedListAsync(
|
||||||
|
lastOccurredAt,
|
||||||
|
lastId,
|
||||||
|
20,
|
||||||
|
searchKeyword,
|
||||||
|
classify,
|
||||||
|
transactionType,
|
||||||
|
year,
|
||||||
|
month);
|
||||||
var total = await transactionRepository.GetTotalCountAsync();
|
var total = await transactionRepository.GetTotalCountAsync();
|
||||||
|
|
||||||
return new PagedResponse<Entity.TransactionRecord>
|
return new PagedResponse<Entity.TransactionRecord>
|
||||||
|
|||||||
Reference in New Issue
Block a user