// 老人端 · 我的面板(ArkTS 严格类型,无 any) // 对齐小程序 ElderlyProfilePanel:账号卡 + 菜单 + 退出登录 import { router } from '@kit.ArkUI'; import { promptAction } from '@kit.ArkUI'; import { common } from '@kit.AbilityKit'; import { BusinessError } from '@kit.BasicServicesKit'; import { AuthStore } from '../../utils/AuthStore'; import { normalizeError } from '../../common/ApiConstants'; import { api, RequestError } from '../../utils/Request'; import { FontScaleLevel, FontScaleOption, FONT_SCALE_LABELS, FONT_SCALE_MAP, loadFontScale, setFontScale } from '../../utils/FontScale'; interface ProfileDashboard { elderly_id: number | null; elderly_name: string; service_date: string; } interface ProfileMenu { key: string; title: string; desc: string; route: string; // 空字符串表示未实现 } @Component export struct ElderlyProfilePanel { @State userName: string = ''; @State userId: number = 0; @State elderlyName: string = ''; @State fontScale: FontScaleLevel = 'normal'; @StorageProp('fontScale') fontScaleLevel: FontScaleLevel = 'system'; private scaleFor(): number { return FONT_SCALE_MAP[this.fontScaleLevel] ?? 1.0; } menus: Array = [ { key: 'meal', title: '餐饮服务', desc: '查看并选择定制餐', route: 'pages/elderly/ElderlyMealOrder' }, { key: 'activities', title: '活动安排', desc: '查看今天和本周的社工活动', route: 'pages/elderly/Activities' }, { key: 'notifications', title: '消息通知', desc: '查看护理记录和订餐状态消息', route: 'pages/notifications/Notifications' }, { key: 'history', title: '历史订餐', desc: '查看过往和近期的订餐记录', route: 'pages/elderly/ElderlyHistory' }, ]; aboutToAppear(): void { this.loadAuth(); this.loadDashboard(); loadFontScale(getContext(this) as common.UIAbilityContext).then((level: FontScaleLevel) => { this.fontScale = level; }); } private async loadDashboard(): Promise { try { const res = await api.get('/elderly-portal/dashboard/'); this.elderlyName = res.elderly_name || ''; } catch (err) { console.warn('[ElderlyProfile] load dashboard failed:', normalizeError(err as BusinessError | Error)); } } private changeFontScale(level: FontScaleLevel): void { this.fontScale = level; setFontScale(getContext(this) as common.UIAbilityContext, level); promptAction.showToast({ message: `字体已调整为${FONT_SCALE_LABELS.find((item) => item.level === level)?.label ?? ''}` }); } private async loadAuth(): Promise { const state = await AuthStore.getState(); this.userName = state.userName; this.userId = state.userId; } private onMenuClick(menu: ProfileMenu): void { if (menu.route.length === 0) { promptAction.showToast({ message: '功能开发中' }); return; } router.pushUrl({ url: menu.route }).catch(() => {}); } private async logout(): Promise { await AuthStore.logout(); promptAction.showToast({ message: '已退出登录' }); router.replaceUrl({ url: 'pages/Login' }).catch(() => {}); } @Builder MenuRow(menu: ProfileMenu) { Row({ space: 12 }) { Column({ space: 6 }) { Text(menu.title) .fontSize(Math.round(17 * this.scaleFor())) .fontWeight(FontWeight.Medium) .fontColor($r('app.color.text_primary')) Text(menu.desc) .fontSize(Math.round(15 * this.scaleFor())) .fontColor($r('app.color.text_secondary')) } .layoutWeight(1) .alignItems(HorizontalAlign.Start) Text('›') .fontSize(Math.round(22 * this.scaleFor())) .fontColor($r('app.color.inactive_tab')) } .width('100%') .padding(14) .backgroundColor($r('app.color.background_card')) .borderRadius(14) .onClick(() => { this.onMenuClick(menu); }) } build() { Scroll() { Column({ space: 12 }) { // 用户信息卡 Column({ space: 8 }) { Stack() { Circle() .width(64) .height(64) .fill($r('app.color.accent_blue')) Text((this.elderlyName || this.userName || '客').substring(0, 1)) .fontSize(Math.round(26 * this.scaleFor())) .fontWeight(FontWeight.Bold) .fontColor('#FFFFFF') } .width(64) .height(64) Text(this.elderlyName || this.userName || '用户') .fontSize(Math.round(22 * this.scaleFor())) .fontWeight(FontWeight.Bold) .fontColor($r('app.color.text_primary')) Text(this.elderlyName.length > 0 ? '长者账号' : '账号') .fontSize(Math.round(13 * this.scaleFor())) .fontColor($r('app.color.text_secondary')) } .width('92%') .padding({ top: 16, bottom: 14 }) .backgroundColor($r('app.color.background_card')) .borderRadius(16) .margin({ top: 16 }) // 账号编号 Row() { Text('账号编号') .fontSize(Math.round(15 * this.scaleFor())) .fontColor($r('app.color.text_secondary')) Blank() Text(this.userId > 0 ? String(this.userId) : '--') .fontSize(Math.round(15 * this.scaleFor())) .fontColor($r('app.color.text_primary')) } .width('92%') .padding(14) .backgroundColor($r('app.color.background_card')) .borderRadius(14) // 字体大小 Column({ space: 8 }) { Text('字体大小') .fontSize(Math.round(15 * this.scaleFor())) .fontColor($r('app.color.text_primary')) .width('100%') Flex({ wrap: FlexWrap.Wrap, alignItems: ItemAlign.Center }) { ForEach(FONT_SCALE_LABELS, (item: FontScaleOption) => { Text(item.label) .fontSize(Math.round(15 * this.scaleFor())) .fontColor(this.fontScale === item.level ? '#FFFFFF' : $r('app.color.text_primary')) .padding({ left: 18, right: 18, top: 10, bottom: 10 }) .backgroundColor(this.fontScale === item.level ? $r('app.color.accent_blue') : $r('app.color.background_card')) .borderRadius(10) .margin({ right: 10, bottom: 10 }) .onClick(() => { this.changeFontScale(item.level); }) }, (item: FontScaleOption) => item.level) } .width('100%') } .width('92%') .padding(14) .backgroundColor($r('app.color.background_card')) .borderRadius(14) .alignItems(HorizontalAlign.Start) // 菜单 Column({ space: 8 }) { ForEach(this.menus, (menu: ProfileMenu) => { this.MenuRow(menu) }, (menu: ProfileMenu) => menu.key) } .width('92%') // 退出登录 Text('退出登录') .fontSize(Math.round(17 * this.scaleFor())) .fontWeight(FontWeight.Medium) .fontColor($r('app.color.accent_red')) .textAlign(TextAlign.Center) .width('92%') .padding(14) .backgroundColor($r('app.color.background_card')) .borderRadius(14) // 避让底部悬浮 Tab .margin({ bottom: 130 }) .onClick(() => { this.logout(); }) } .width('100%') .alignItems(HorizontalAlign.Center) } .scrollBar(BarState.Auto) .edgeEffect(EdgeEffect.Spring) .width('100%') .height('100%') } }