测试覆盖率
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
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
This commit is contained in:
181
.sisyphus/notepads/statistics-year-selection/learnings.md
Normal file
181
.sisyphus/notepads/statistics-year-selection/learnings.md
Normal file
@@ -0,0 +1,181 @@
|
||||
# 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 year
|
||||
- `currentMonth` - 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
|
||||
1. Add UI toggle to switch between year-month and year-only modes
|
||||
2. When year-only selected, set `currentMonth = 0` or null to indicate full year
|
||||
3. Backend API already supports year-only queries (when month=0 or null)
|
||||
4. 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
|
||||
|
||||
```csharp
|
||||
// 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.cs` lines 81-94
|
||||
- **Change**: Updated year/month filtering logic to support year-only queries
|
||||
|
||||
### Logic Changes
|
||||
```csharp
|
||||
// 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 > 0` check 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-tabs` component
|
||||
- Two modes: "按月" (month) and "按年" (year)
|
||||
- Tabs positioned above the date picker
|
||||
- Dynamic `columns-type` based on selection mode:
|
||||
- Year mode: `['year']`
|
||||
- Month mode: `['year', 'month']`
|
||||
|
||||
#### 3. State Management (Line 347)
|
||||
- Added `dateSelectionMode` ref: `'month'` | `'year'`
|
||||
- Default: `'month'` for backward compatibility
|
||||
- `currentMonth` set to `0` when 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 `0` for 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 update `selectedDate` array
|
||||
- When switching to year mode: `selectedDate = [year.toString()]`
|
||||
- When switching to month mode: `selectedDate = [year, month]`
|
||||
|
||||
#### 7. Styling (Lines 1690-1705)
|
||||
- Added `.date-picker-header` styles 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-type` prop
|
||||
- **van-popup**: Container for picker and tabs
|
||||
- Composition API with `watch` for reactive updates
|
||||
|
||||
### User Experience
|
||||
1. Click nav bar date → popup opens with "按月" default
|
||||
2. Switch to "按年" → picker shows only year column
|
||||
3. Select year and confirm → `currentMonth = 0`
|
||||
4. Nav bar shows "2025年" instead of "2025年1月"
|
||||
5. 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
|
||||
Reference in New Issue
Block a user