| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111 |
- import { CommonModule } from '@angular/common';
- import { ChangeDetectionStrategy, Component, computed, inject, OnInit, signal } from '@angular/core';
- import { Router, RouterLink } from '@angular/router';
- import { Award, BookMarked, ChevronRight, CircleHelp, History, LogOut, LucideAngularModule, MessageSquare, Settings, ShieldCheck, UserRound } from 'lucide-angular';
- import { finalize } from 'rxjs';
- import { APP_VERSION } from '../../core/app.constants';
- import { ApiService } from '../../core/api.service';
- import { AntiForgetHistorySummary } from '../../core/anti-forget';
- import { AppUser } from '../../core/models';
- import { SessionService } from '../../core/session.service';
- import { buildAccountMembership, CompanionLearningSummary } from './account-membership';
- interface CoachPanelSummary {
- todaySchedules: number;
- completedLessons: number;
- reviewIncome: number;
- reviewRecords: number;
- totalLessons: number;
- totalHours: number;
- course30: number;
- course60: number;
- trialLessons: number;
- }
- interface AccountOverview {
- profile: Partial<AppUser>;
- coachPanel?: CoachPanelSummary;
- companionSummary?: Pick<CompanionLearningSummary, 'completedSessions' | 'completedMinutes'>;
- antiForgetSummary?: AntiForgetHistorySummary;
- refreshedAt: string;
- }
- @Component({
- selector: 'app-account-page',
- standalone: true,
- imports: [CommonModule, RouterLink, LucideAngularModule],
- templateUrl: './account-page.component.html',
- styleUrl: './account-page.component.scss',
- changeDetection: ChangeDetectionStrategy.OnPush,
- })
- export class AccountPageComponent implements OnInit {
- readonly session = inject(SessionService);
- readonly version = APP_VERSION;
- 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 antiForgetLoading = signal(false);
- readonly antiForgetError = signal('');
- readonly avatarFailed = signal(false);
- readonly companionLoading = signal(false);
- readonly antiForgetSummary = signal<AntiForgetHistorySummary>({ total: 0, completed: 0, progress: 0, todayTotal: 0, todayCompleted: 0, duePending: 0, scheduled: 0, scheduledDays: 0 });
- readonly membership = computed(() => buildAccountMembership(this.session.user()));
- readonly companionSummary = signal<CompanionLearningSummary>({ completedSessions: 0, completedMinutes: 0, durationLabel: '0 小时' });
- readonly icons = { Award, BookMarked, ChevronRight, CircleHelp, History, LogOut, MessageSquare, Settings, ShieldCheck, UserRound };
- readonly services = [
- { path: '/pages/his/well', label: '专项训练', icon: Award },
- { path: '/pages/member/starshop', label: '生词本', icon: BookMarked },
- { path: '/pages/his/his', label: '学习记录', icon: History },
- { path: '/pages/member/feedback', label: '意见反馈', icon: MessageSquare },
- ];
- private readonly api = inject(ApiService);
- private readonly router = inject(Router);
- ngOnInit(): void {
- const uid = this.session.user()?.userId;
- if (!uid) return;
- this.loadAccountOverview(false);
- }
- loadAntiForget(): void { this.loadAccountOverview(true); }
- private loadAccountOverview(refresh: boolean): void {
- const uid = this.session.user()?.userId;
- if (!uid) return;
- const coach = Number(this.session.groupId()) === 3;
- this.coachPanelLoading.set(coach);
- this.companionLoading.set(!coach);
- this.antiForgetLoading.set(!coach);
- this.antiForgetError.set('');
- this.api.post<AccountOverview>('app_account_overview', { uid, refresh }).pipe(
- finalize(() => {
- this.coachPanelLoading.set(false);
- this.companionLoading.set(false);
- this.antiForgetLoading.set(false);
- }),
- ).subscribe({
- next: ({ result }) => {
- if (!result) return;
- this.session.patchUser(result.profile ?? {});
- if (result.coachPanel) this.coachPanel.set(result.coachPanel);
- if (result.companionSummary) {
- const minutes = Number(result.companionSummary.completedMinutes ?? 0);
- this.companionSummary.set({ ...result.companionSummary, durationLabel: this.formatMinutes(minutes) });
- }
- if (result.antiForgetSummary) this.antiForgetSummary.set(result.antiForgetSummary);
- },
- error: () => this.antiForgetError.set('抗遗忘数据暂时无法加载'),
- });
- }
- logout(): void { this.session.logout(); void this.router.navigateByUrl('/pages/member/wxauth'); }
- avatarUrl(): string { return this.api.assetUrl(this.session.user()?.userFace); }
- private formatMinutes(minutes: number): string {
- if (!minutes) return '0 小时';
- const hours = Math.floor(minutes / 60);
- const remainder = minutes % 60;
- if (!hours) return `${remainder} 分钟`;
- return remainder ? `${hours} 小时 ${remainder} 分钟` : `${hours} 小时`;
- }
- }
|