// 护理记录历史列表(ArkTS 严格类型,无 any) // 数据来源:/tasks/nursing-records/ import { router, promptAction } from '@kit.ArkUI'; import { HdsNavigation, HdsNavigationTitleMode, ScrollEffectType } from '@kit.UIDesignKit'; import { hdsMaterial } from '@hms.hds.hdsMaterial'; import { BusinessError } from '@kit.BasicServicesKit'; import { Page, normalizeError } from '../../common/ApiConstants'; import { api } from '../../utils/Request'; import { ProtectedImage } from '../../components/ProtectedImage'; interface ApiRecord { id: number; elderly_name: string; nurse_name: string | null; raw_text: string; images: Array | null; created_at: string; } // 记录详情页路由参数 interface RecordDetailParams { id: string; } function formatTime(iso: string): string { const d = new Date(iso); if (Number.isNaN(d.getTime())) { return '--'; } const mm = String(d.getMonth() + 1).padStart(2, '0'); const dd = String(d.getDate()).padStart(2, '0'); const hh = String(d.getHours()).padStart(2, '0'); const mi = String(d.getMinutes()).padStart(2, '0'); return `${mm}/${dd} ${hh}:${mi}`; } @Entry @Component struct History { @State records: ApiRecord[] = []; @State loading: boolean = true; @State total: number = 0; @State page: number = 1; @State hasMore: boolean = true; private scroller: Scroller = new Scroller(); async aboutToAppear(): Promise { await this.loadPage(1); } async onPageShow(): Promise { await this.loadPage(1); } private async loadPage(p: number): Promise { if (p === 1) { this.loading = true; } try { const res = await api.get>('/tasks/nursing-records/', { page: p, page_size: 20, ordering: '-created_at', }); this.total = res.count; this.page = p; this.hasMore = this.records.length + res.results.length < res.count; if (p === 1) { this.records = res.results; } else { this.records = this.records.concat(res.results); } } catch (err) { promptAction.showToast({ message: normalizeError(err as BusinessError | Error) }); } finally { this.loading = false; } } private loadMore(): void { if (!this.loading && this.hasMore) { this.loadPage(this.page + 1); } } private openDetail(item: ApiRecord): void { const params: RecordDetailParams = { id: String(item.id) }; router.pushUrl({ url: 'pages/nurse/RecordDetail', params: params, }).catch((err: BusinessError) => { promptAction.showToast({ message: `页面打开失败:${normalizeError(err)}` }); }); } @Builder RecordItem(item: ApiRecord) { Column({ space: 8 }) { Row() { Text(item.elderly_name) .fontSize(16) .fontWeight(FontWeight.Medium) .fontColor($r('app.color.text_primary')) Blank() Text(formatTime(item.created_at)) .fontSize(12) .fontColor($r('app.color.inactive_tab')) } .width('100%') Text(item.raw_text && item.raw_text.length > 0 ? item.raw_text : '(无文字内容)') .fontSize(13) .fontColor($r('app.color.text_secondary')) .maxLines(2) .textOverflow({ overflow: TextOverflow.Ellipsis }) .width('100%') if (item.images && item.images.length > 0) { Row({ space: 8 }) { ForEach(item.images.slice(0, 3), (img: string) => { Stack() { ProtectedImage({ mediaPath: img }) } .width(64) .height(64) .borderRadius(8) .clip(true) }, (img: string) => img) if (item.images.length > 3) { Text(`+${item.images.length - 3}`) .fontSize(12) .fontColor($r('app.color.text_secondary')) } } .width('100%') } } .width('100%') .padding(16) .backgroundColor($r('app.color.background_card')) .borderRadius(14) .alignItems(HorizontalAlign.Start) } build() { HdsNavigation() { Column() { Scroll(this.scroller) { Column({ space: 10 }) { ForEach(this.records, (item: ApiRecord) => { Column() { this.RecordItem(item) } .width('100%') .onClick(() => { this.openDetail(item); }) }, (item: ApiRecord) => String(item.id)) if (this.loading) { Text('加载中...') .fontSize(13) .fontColor($r('app.color.inactive_tab')) .padding(12) } } .width('100%') .padding({ left: 16, right: 16, top: 92, bottom: 24 }) } .width('100%') .layoutWeight(1) .scrollBar(BarState.Auto) .edgeEffect(EdgeEffect.Spring) .onReachEnd(() => { this.loadMore(); }) } .width('100%') .height('100%') } .mode(NavigationMode.Stack) .titleBar({ content: { title: { mainTitle: '历史记录', }, }, style: { scrollEffectOpts: { enableScrollEffect: false, scrollEffectType: ScrollEffectType.GRADIENT_BLUR, }, systemMaterialEffect: { materialType: hdsMaterial.MaterialType.ADAPTIVE, materialLevel: hdsMaterial.MaterialLevel.EXQUISITE, }, }, avoidLayoutSafeArea: false, enableComponentSafeArea: false, }) .bindToScrollable([this.scroller]) .hideBackButton(false) .titleMode(HdsNavigationTitleMode.MINI) .ignoreLayoutSafeArea([LayoutSafeAreaType.SYSTEM], [LayoutSafeAreaEdge.TOP, LayoutSafeAreaEdge.BOTTOM]) .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM]) .backgroundColor($r('app.color.background')) } }