Skip to content

Commit 5b35a9e

Browse files
committed
feat(website): 年度报告页面集成车票明细数据
1 parent 55f792b commit 5b35a9e

File tree

3 files changed

+71
-2
lines changed

3 files changed

+71
-2
lines changed

package/website/src/api/annualReport.ts

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,51 @@ import type {
66
LocationMetrics,
77
SeasonMetrics,
88
EmotionMetrics,
9-
EasterEgg
9+
EasterEgg,
10+
ExpenseMetrics,
11+
TicketDetail
1012
} from '@/types/annualReport';
1113
import type { Photo } from '@/types/album';
1214
import axios from 'axios'
1315

1416
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || ''
1517
const api = axios.create({ baseURL: API_BASE_URL })
1618

19+
export async function getReportExpenses(startTime: string, endTime: string): Promise<ExpenseMetrics> {
20+
const { data } = await api.get<ExpenseMetrics>('/api/annual-report/expenses', {
21+
params: {
22+
start_time: startTime,
23+
end_time: endTime
24+
}
25+
});
26+
return data
27+
}
28+
29+
export async function getReportExpenseDetails(startTime: string, endTime: string): Promise<TicketDetail[]> {
30+
const retries = 2;
31+
let lastError;
32+
33+
for (let i = 0; i <= retries; i++) {
34+
try {
35+
const { data } = await api.get<TicketDetail[]>('/api/annual-report/expenses/details', {
36+
params: {
37+
start_time: startTime,
38+
end_time: endTime
39+
}
40+
});
41+
return data;
42+
} catch (error) {
43+
lastError = error;
44+
if (i < retries) {
45+
// Exponential backoff or constant delay could be used here
46+
await new Promise(resolve => setTimeout(resolve, 500));
47+
continue;
48+
}
49+
}
50+
}
51+
throw lastError;
52+
}
53+
1754
export async function getReportSummary(startTime: string, endTime: string): Promise<{user: UserInfo, time: TimeMetrics}> {
1855
const { data } = await api.get<{user: UserInfo, time: TimeMetrics}>('/api/annual-report/summary', {
1956
params: {

package/website/src/types/annualReport.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,31 @@ export interface EasterEgg {
8282
};
8383
}
8484

85+
export interface MonthlyExpense {
86+
month: string;
87+
amount: number;
88+
}
89+
90+
export interface ExpenseMetrics {
91+
totalAmount: number;
92+
totalCount: number;
93+
averagePrice: number;
94+
monthlyTrend: MonthlyExpense[];
95+
maxExpenseTicket?: string;
96+
maxExpenseAmount?: number;
97+
}
98+
99+
export interface TicketDetail {
100+
id: string;
101+
train_code: string;
102+
departure_station: string;
103+
arrival_station: string;
104+
date_time: string;
105+
price: number;
106+
seat_type: string;
107+
name: string;
108+
}
109+
85110
export interface AnnualReportData {
86111
year: number;
87112
user: UserInfo;
@@ -91,4 +116,5 @@ export interface AnnualReportData {
91116
location: LocationMetrics;
92117
season: SeasonMetrics;
93118
easterEgg: EasterEgg;
119+
expense: ExpenseMetrics;
94120
}

package/website/src/views/annual-report/index.vue

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
<script setup lang="ts">
22
import { ref, onMounted } from 'vue';
3-
import { getReportEasterEgg, getReportSummary ,getReportMemory, getReportLocation, getReportSeason, getReportEmotion} from '@/api/annualReport';
3+
import { getReportEasterEgg, getReportSummary ,getReportMemory, getReportLocation, getReportSeason, getReportEmotion, getReportExpenses} from '@/api/annualReport';
44
import type { AnnualReportData } from '@/types/annualReport';
55
import AnnualContainer from '@/components/annual-report/AnnualContainer.vue';
66
import SectionCover from '@/components/annual-report/SectionCover.vue';
77
import SectionPhotoWall from '@/components/annual-report/SectionPhotoWall.vue';
88
import SectionTime from '@/components/annual-report/SectionTime.vue';
99
import SectionAccount from '@/components/annual-report/SectionAccount.vue';
10+
import SectionExpense from '@/components/annual-report/SectionExpense.vue';
1011
import SectionCategory from '@/components/annual-report/SectionCategory.vue';
1112
import SectionHighlight from '@/components/annual-report/SectionHighlight.vue';
1213
import SectionEmotion from '@/components/annual-report/SectionEmotion.vue';
@@ -40,6 +41,8 @@ onMounted(async () => {
4041
reportData.value.emotion = emotionData;
4142
const easterEggData = await getReportEasterEgg(startTime, endTime);
4243
reportData.value.easterEgg = easterEggData;
44+
const expenseData = await getReportExpenses(startTime, endTime);
45+
reportData.value.expense = expenseData;
4346
} catch (error) {
4447
console.error('Failed to load report data', error);
4548
} finally {
@@ -79,6 +82,9 @@ const handleReplay = () => {
7982
<!-- 3. Account -->
8083
<SectionAccount :time="reportData.time" :emotion="reportData.emotion" />
8184

85+
<!-- 3.5 Expense -->
86+
<SectionExpense v-if="reportData.expense" :data="reportData.expense" :startTime="startTime" :endTime="endTime" />
87+
8288
<!-- 4. Category -->
8389
<SectionCategory :data="reportData.memory" />
8490

0 commit comments

Comments
 (0)