import { AppColor, AppSpacing, AppFontSize, AppRadius, LoadingView, ErrorState, Avatar, LabeledRow } from 'uikit'; import { SessionManager, SessionStore } from 'common'; import { ProfileViewModel } from '../viewmodel/ProfileViewModel'; import { ClassGroup } from '../model/ProfileModels'; /** * 我的页:资料展示 + 模拟登录 / 退出登录。 */ @ComponentV2 export struct ProfilePage { @Local viewModel: ProfileViewModel = ProfileViewModel.create(); @Local session: SessionStore = SessionManager.get(); aboutToAppear(): void { this.viewModel.load(); } @Monitor('session.token') onSessionChange(): void { this.viewModel.load(); } build() { Column() { if (!this.viewModel.loggedIn) { this.loginCard() } else if (this.viewModel.loading) { Column() { LoadingView({ text: '加载中...' }) } .width('100%') .height('100%') .justifyContent(FlexAlign.Center) } else if (this.viewModel.error.length > 0) { ErrorState({ message: this.viewModel.error, onRetry: () => { this.viewModel.load(); } }) } else { Scroll() { Column({ space: AppSpacing.md }) { this.profileHeader() this.infoCard() if (this.viewModel.profile.classGroups.length > 0) { this.classGroupCard() } this.logoutButton() } .width('100%') .padding(AppSpacing.lg) } .width('100%') .height('100%') .scrollBar(BarState.Off) } } .width('100%') .height('100%') .backgroundColor(AppColor.background) } @Builder loginCard() { Column({ space: AppSpacing.md }) { Text('👤') .fontSize(40) Text('未登录') .fontSize(AppFontSize.title) .fontWeight(FontWeight.Bold) .fontColor(AppColor.textPrimary) Text('登录后即可查看个人信息') .fontSize(AppFontSize.body) .fontColor(AppColor.textMuted) Text('模拟登录') .fontSize(AppFontSize.body) .fontColor(AppColor.white) .padding({ left: 32, right: 32, top: 10, bottom: 10 }) .backgroundColor(AppColor.gold) .borderRadius(AppRadius.pill) .onClick(() => { this.viewModel.login(); }) } .width('100%') .height('100%') .justifyContent(FlexAlign.Center) } @Builder profileHeader() { Row({ space: AppSpacing.md }) { Avatar({ name: this.viewModel.profile.displayName, diameter: 56 }) Column({ space: 4 }) { Row({ space: 8 }) { Text(this.viewModel.profile.displayName) .fontSize(AppFontSize.headline) .fontWeight(FontWeight.Bold) .fontColor(AppColor.textPrimary) Text(this.viewModel.profile.role) .fontSize(AppFontSize.caption) .fontColor(AppColor.gold) .padding({ left: 10, right: 10, top: 4, bottom: 4 }) .backgroundColor(AppColor.neutralChip) .borderRadius(AppRadius.pill) } Text(this.viewModel.profile.studentId) .fontSize(AppFontSize.caption) .fontColor(AppColor.textMuted) } .layoutWeight(1) .alignItems(HorizontalAlign.Start) } .width('100%') .padding(AppSpacing.md) .backgroundColor(AppColor.white) .borderRadius(AppRadius.lg) } @Builder infoCard() { Column({ space: 0 }) { Text('个人信息') .fontSize(AppFontSize.title) .fontWeight(FontWeight.Bold) .fontColor(AppColor.textPrimary) .width('100%') .margin({ bottom: 4 }) LabeledRow({ label: '姓名', value: this.viewModel.profile.name }) LabeledRow({ label: '学号', value: this.viewModel.profile.studentId }) LabeledRow({ label: '手机号', value: this.viewModel.profile.phone }) LabeledRow({ label: '角色', value: this.viewModel.profile.role }) LabeledRow({ label: '小组', value: this.viewModel.profile.group }) LabeledRow({ label: '登录方式', value: this.viewModel.profile.loginType }) } .width('100%') .padding(AppSpacing.md) .backgroundColor(AppColor.white) .borderRadius(AppRadius.lg) } @Builder classGroupCard() { Column({ space: 0 }) { Text('小组分组') .fontSize(AppFontSize.title) .fontWeight(FontWeight.Bold) .fontColor(AppColor.textPrimary) .width('100%') .margin({ bottom: 4 }) ForEach(this.viewModel.profile.classGroups, (cg: ClassGroup) => { Row() { Text(cg.period) .fontSize(AppFontSize.body) .fontColor(AppColor.textMuted) Blank() Text(cg.group + ' · ' + cg.role) .fontSize(AppFontSize.body) .fontColor(AppColor.textPrimary) } .width('100%') .padding({ top: 12, bottom: 12 }) }, (cg: ClassGroup) => cg.period + cg.group) } .width('100%') .padding(AppSpacing.md) .backgroundColor(AppColor.white) .borderRadius(AppRadius.lg) } @Builder logoutButton() { Text('退出登录') .fontSize(AppFontSize.body) .fontColor(AppColor.danger) .width('100%') .height(48) .textAlign(TextAlign.Center) .backgroundColor(AppColor.white) .borderRadius(AppRadius.md) .border({ width: 1, color: AppColor.danger }) .onClick(() => { this.viewModel.logout(); }) } }