feat(entry): 复刻四大主页面与底部导航

This commit is contained in:
AndyChen1024
2026-09-11 20:48:15 +08:00
parent d9f1893f67
commit 58a91134a1
6 changed files with 812 additions and 49 deletions

View File

@@ -0,0 +1,184 @@
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();
})
}
}