|
|
@@ -12,6 +12,18 @@ import { buildAccountMembership, summarizeCompanionLearning } from './account-me
|
|
|
|
|
|
type SourceItem = Record<string, unknown>;
|
|
|
|
|
|
+interface CoachPanelSummary {
|
|
|
+ todaySchedules: number;
|
|
|
+ completedLessons: number;
|
|
|
+ reviewIncome: number;
|
|
|
+ reviewRecords: number;
|
|
|
+ totalLessons: number;
|
|
|
+ totalHours: number;
|
|
|
+ course30: number;
|
|
|
+ course60: number;
|
|
|
+ trialLessons: number;
|
|
|
+}
|
|
|
+
|
|
|
@Component({
|
|
|
selector: 'app-account-page',
|
|
|
standalone: true,
|
|
|
@@ -23,7 +35,8 @@ type SourceItem = Record<string, unknown>;
|
|
|
export class AccountPageComponent implements OnInit {
|
|
|
readonly session = inject(SessionService);
|
|
|
readonly version = APP_VERSION;
|
|
|
- readonly orderCounts = signal<Record<string, number>>({ all: 0, unpaid: 0, paid: 0, issued: 0, signed: 0 });
|
|
|
+ readonly coachPanel = signal<CoachPanelSummary>({ todaySchedules: 0, completedLessons: 0, reviewIncome: 0, reviewRecords: 0, totalLessons: 0, totalHours: 0, course30: 0, course60: 0, trialLessons: 0 });
|
|
|
+ readonly coachPanelLoading = signal(false);
|
|
|
readonly antiForgetItems = signal<SourceItem[]>([]);
|
|
|
readonly antiForgetLoading = signal(false);
|
|
|
readonly antiForgetError = signal('');
|
|
|
@@ -53,12 +66,7 @@ export class AccountPageComponent implements OnInit {
|
|
|
this.loadAntiForget();
|
|
|
return;
|
|
|
}
|
|
|
- for (const fast of ['all', 'unpaid', 'paid', 'issued', 'signed']) {
|
|
|
- this.api.get<unknown>('order_list', { uid, fast, psize: 1, norc: 1 }).subscribe({
|
|
|
- next: ({ page }) => this.orderCounts.update((counts) => ({ ...counts, [fast]: Number(page?.itemCount ?? 0) })),
|
|
|
- error: () => undefined,
|
|
|
- });
|
|
|
- }
|
|
|
+ this.loadCoachPanel(uid);
|
|
|
}
|
|
|
|
|
|
private loadCompanionSummary(uid: number): void {
|
|
|
@@ -107,7 +115,76 @@ export class AccountPageComponent implements OnInit {
|
|
|
});
|
|
|
}
|
|
|
|
|
|
+ private loadCoachPanel(uid: number): void {
|
|
|
+ this.coachPanelLoading.set(true);
|
|
|
+ forkJoin({
|
|
|
+ stats: this.api.post<Record<string, number>>('e_order_tongji', { uid }).pipe(catchError(() => of(null))),
|
|
|
+ today: this.api.get<unknown>('content_list', {
|
|
|
+ uid,
|
|
|
+ nid: 29,
|
|
|
+ myfield2: `pl=${uid}`,
|
|
|
+ dateFilter: this.today(),
|
|
|
+ psize: 200,
|
|
|
+ }).pipe(catchError(() => of(null))),
|
|
|
+ completed: this.api.get<unknown>('content_list', {
|
|
|
+ uid,
|
|
|
+ nid: 29,
|
|
|
+ myfield2: `pl=${uid}`,
|
|
|
+ orders: 'B.yysj=DESC',
|
|
|
+ dszt: 30,
|
|
|
+ xiaokejilu: 1,
|
|
|
+ cpage: 1,
|
|
|
+ psize: 1,
|
|
|
+ }).pipe(catchError(() => of(null))),
|
|
|
+ incomeList: this.api.post<unknown>('e_get_21list', {
|
|
|
+ status: 1,
|
|
|
+ shouru: 1,
|
|
|
+ uid,
|
|
|
+ cpage: 1,
|
|
|
+ psize: 1,
|
|
|
+ }).pipe(catchError(() => of(null))),
|
|
|
+ incomeTotal: this.api.post<unknown>('e_get_21list_tj', { uid }).pipe(catchError(() => of(null))),
|
|
|
+ }).pipe(finalize(() => this.coachPanelLoading.set(false))).subscribe(({ stats, today, completed, incomeList, incomeTotal }) => {
|
|
|
+ const statValues = stats?.result ?? {};
|
|
|
+ this.coachPanel.set({
|
|
|
+ todaySchedules: this.itemCount(today),
|
|
|
+ completedLessons: this.itemCount(completed),
|
|
|
+ reviewIncome: this.incomeAmount(incomeTotal),
|
|
|
+ reviewRecords: this.itemCount(incomeList),
|
|
|
+ totalLessons: Number(statValues['t_total'] ?? 0),
|
|
|
+ totalHours: Number(statValues['t_shichang'] ?? 0),
|
|
|
+ course30: Number(statValues['t30'] ?? 0),
|
|
|
+ course60: Number(statValues['t60'] ?? 0),
|
|
|
+ trialLessons: Number(statValues['t_tiyan'] ?? 0),
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
logout(): void { this.session.logout(); void this.router.navigateByUrl('/pages/member/wxauth'); }
|
|
|
avatarUrl(): string { return this.api.assetUrl(this.session.user()?.userFace); }
|
|
|
|
|
|
+ private itemCount(envelope: unknown): number {
|
|
|
+ const value = envelope as { page?: { itemCount?: unknown }; result?: unknown } | null;
|
|
|
+ const pageTotal = Number(value?.page?.itemCount);
|
|
|
+ if (Number.isFinite(pageTotal)) return pageTotal;
|
|
|
+ return this.toList(value?.result).length;
|
|
|
+ }
|
|
|
+
|
|
|
+ private incomeAmount(envelope: unknown): number {
|
|
|
+ const value = envelope as { result?: unknown } | null;
|
|
|
+ return Number(this.toList(value?.result)[0]?.['num'] ?? 0);
|
|
|
+ }
|
|
|
+
|
|
|
+ private toList(value: unknown): SourceItem[] {
|
|
|
+ if (Array.isArray(value)) return value.filter((item): item is SourceItem => Boolean(item) && typeof item === 'object');
|
|
|
+ if (value && typeof value === 'object') {
|
|
|
+ for (const nested of Object.values(value)) if (Array.isArray(nested)) return nested as SourceItem[];
|
|
|
+ }
|
|
|
+ return [];
|
|
|
+ }
|
|
|
+
|
|
|
+ private today(): string {
|
|
|
+ const now = new Date();
|
|
|
+ return `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}`;
|
|
|
+ }
|
|
|
}
|