All checks were successful
Docker Build & Deploy / Build Docker Image (push) Successful in 27s
Docker Build & Deploy / Deploy to Production (push) Successful in 9s
Docker Build & Deploy / Cleanup Dangling Images (push) Successful in 2s
Docker Build & Deploy / WeChat Notification (push) Successful in 2s
6.7 KiB
6.7 KiB
Learnings - Statistics Year Selection Enhancement
[2026-01-28] Initial Analysis
Current Implementation
- File:
Web/src/views/StatisticsView.vue - Current picker:
columns-type="['year', 'month'](year-month only) - State variables:
currentYear- integer yearcurrentMonth- integer month (1-12)selectedDate- array['YYYY', 'MM']for picker
- API calls: All endpoints use
{ year, month }parameters
Vant UI Year-Only Pattern
- Key prop:
columns-type="['year']" - Picker value: Single-element array
['YYYY'] - Confirmation:
selectedValues[0]contains year string
Implementation Strategy
- Add UI toggle to switch between year-month and year-only modes
- When year-only selected, set
currentMonth = 0or null to indicate full year - Backend API already supports year-only queries (when month=0 or null)
- Update display logic to show "YYYY年" vs "YYYY年MM月"
API Compatibility - CRITICAL FINDING
- Backend limitation:
TransactionRecordRepository.BuildQuery()(lines 81-86) requires BOTH year AND month - Current logic:
if (year.HasValue && month.HasValue)- year-only queries are NOT supported - Must modify repository to support year-only queries:
- When year provided but month is null/0: query entire year (Jan 1 to Dec 31)
- When both year and month provided: query specific month (current behavior)
- All statistics endpoints use
QueryAsync(year, month, ...)pattern
Required Backend Changes
File: Repository/TransactionRecordRepository.cs
Method: BuildQuery() lines 81-86
Change: Modify year/month filtering logic to support year-only queries
// Current (line 81-86):
if (year.HasValue && month.HasValue)
{
var dateStart = new DateTime(year.Value, month.Value, 1);
var dateEnd = dateStart.AddMonths(1);
query = query.Where(t => t.OccurredAt >= dateStart && t.OccurredAt < dateEnd);
}
// Needed:
if (year.HasValue)
{
if (month.HasValue && month.Value > 0)
{
// Specific month
var dateStart = new DateTime(year.Value, month.Value, 1);
var dateEnd = dateStart.AddMonths(1);
query = query.Where(t => t.OccurredAt >= dateStart && t.OccurredAt < dateEnd);
}
else
{
// Entire year
var dateStart = new DateTime(year.Value, 1, 1);
var dateEnd = new DateTime(year.Value + 1, 1, 1);
query = query.Where(t => t.OccurredAt >= dateStart && t.OccurredAt < dateEnd);
}
}
Existing Patterns
- BudgetView.vue uses same year-month picker pattern
- Dayjs used for all date formatting:
dayjs().format('YYYY-MM-DD') - Date picker values always arrays for Vant UI
[2026-01-28] Repository BuildQuery() Enhancement
Implementation Completed
- File Modified:
Repository/TransactionRecordRepository.cslines 81-94 - Change: Updated year/month filtering logic to support year-only queries
Logic Changes
// Old: Required both year AND month
if (year.HasValue && month.HasValue) { ... }
// New: Support year-only queries
if (year.HasValue)
{
if (month.HasValue && month.Value > 0)
{
// 查询指定年月
var dateStart = new DateTime(year.Value, month.Value, 1);
var dateEnd = dateStart.AddMonths(1);
query = query.Where(t => t.OccurredAt >= dateStart && t.OccurredAt < dateEnd);
}
else
{
// 查询整年数据(1月1日到下年1月1日)
var dateStart = new DateTime(year.Value, 1, 1);
var dateEnd = new DateTime(year.Value + 1, 1, 1);
query = query.Where(t => t.OccurredAt >= dateStart && t.OccurredAt < dateEnd);
}
}
Behavior
- Month-specific (month.HasValue && month.Value > 0): Query from 1st of month to 1st of next month
- Year-only (month is null or 0): Query from Jan 1 to Jan 1 of next year
- No year provided: No date filtering applied
Verification
- All 14 tests pass:
dotnet test WebApi.Test/WebApi.Test.csproj - No breaking changes to existing functionality
- Chinese comments added for business logic clarity
Key Pattern
- Use
month.Value > 0check to distinguish year-only (0/null) from month-specific (1-12) - Date range is exclusive on upper bound (
< dateEnd) to avoid including boundary dates
[2026-01-28] Frontend Year-Only Selection Implementation
Changes Made
File: Web/src/views/StatisticsView.vue
1. Nav Bar Title Display (Line 12)
- Updated to show "YYYY年" when
currentMonth === 0 - Shows "YYYY年MM月" when month is selected
- Template:
{{ currentMonth === 0 ? \${currentYear}年` : `${currentYear}年${currentMonth}月` }}`
2. Date Picker Popup (Lines 268-289)
- Added toggle switch using
van-tabscomponent - Two modes: "按月" (month) and "按年" (year)
- Tabs positioned above the date picker
- Dynamic
columns-typebased on selection mode:- Year mode:
['year'] - Month mode:
['year', 'month']
- Year mode:
3. State Management (Line 347)
- Added
dateSelectionModeref:'month'|'year' - Default:
'month'for backward compatibility currentMonthset to0when year-only selected
4. Confirmation Handler (Lines 532-544)
- Updated to handle both year-only and year-month modes
- When year mode:
newMonth = 0 - When month mode:
newMonth = parseInt(selectedValues[1])
5. API Calls (All Statistics Endpoints)
- Updated all API calls to use
month: currentMonth.value || 0 - Ensures backend receives
0for year-only queries - Modified functions:
fetchMonthlyData()(line 574)fetchCategoryData()(lines 592, 610, 626)fetchDailyData()(line 649)fetchBalanceData()(line 672)loadCategoryBills()(line 1146)
6. Mode Switching Watcher (Lines 1355-1366)
- Added
watch(dateSelectionMode)to updateselectedDatearray - When switching to year mode:
selectedDate = [year.toString()] - When switching to month mode:
selectedDate = [year, month]
7. Styling (Lines 1690-1705)
- Added
.date-picker-headerstyles for tabs - Clean, minimal design matching Vant UI conventions
- Proper spacing and background colors
Vant UI Patterns Used
- van-tabs: For mode switching toggle
- van-date-picker: Dynamic
columns-typeprop - van-popup: Container for picker and tabs
- Composition API with
watchfor reactive updates
User Experience
- Click nav bar date → popup opens with "按月" default
- Switch to "按年" → picker shows only year column
- Select year and confirm →
currentMonth = 0 - Nav bar shows "2025年" instead of "2025年1月"
- All statistics refresh with year-only data
Verification
- Build succeeds:
cd Web && pnpm build - No TypeScript errors
- No breaking changes to existing functionality
- Backward compatible with month-only selection