chore(hmos): 导入生产环境鸿蒙工程

- 以 D:\SmartSenior 生产工程为源,纳入 AppScope、entry、cjagent、hvigor 及根配置
- 移除 build-profile.json5 的 signingConfigs(p12/p7b/cer 路径与加密口令)及 products.signingConfig 引用
- 不纳入本地与开发产物:local.properties、.idea、.hvigor、.codegenie、demo、backup_a2a_native、SESSION_LOG.md、build_err.txt、build/、oh_modules
- .gitignore 追加 .codegenie 与密钥文件通配(*.p12/*.p7b/*.cer/*.jks/*.keystore/*.pem)
This commit is contained in:
CAPTAIN1275
2026-09-29 18:44:37 +08:00
parent d7f0e2f8a8
commit baf307e9d5
184 changed files with 31334 additions and 0 deletions
@@ -0,0 +1,211 @@
// 老人端 · 膳食推荐(ArkTS 严格类型,无 any)
// 接口:GET /elderly-portal/recommendations/
import { router } from '@kit.ArkUI';
import { promptAction } from '@kit.ArkUI';
import { HdsNavigation, HdsNavigationTitleMode, ScrollEffectType } from '@kit.UIDesignKit';
import { hdsMaterial } from '@hms.hds.hdsMaterial';
import { BusinessError } from '@kit.BasicServicesKit';
import { normalizeError } from '../../common/ApiConstants';
import { api, RequestError } from '../../utils/Request';
import { FontScaleLevel, FONT_SCALE_MAP } from '../../utils/FontScale';
interface Recommendation {
id: number;
service_date: string;
meal_period: string;
dish_name: string;
price: string;
reason: string;
}
interface RecommendationsResponse {
elderly_id: number | null;
recommendations: Array<Recommendation>;
}
function periodIcon(period: string): string {
if (period === '早餐') {
return '🌅';
}
if (period === '午餐') {
return '🍚';
}
return '🌙';
}
function periodColor(period: string): string {
if (period === '早餐') {
return '#FF9500';
}
if (period === '午餐') {
return '#007AFF';
}
return '#34C759';
}
function formatDateLabel(dateStr: string): string {
if (!dateStr || dateStr.length === 0) {
return '';
}
const parts: Array<string> = dateStr.split('-');
if (parts.length !== 3) {
return dateStr;
}
const month = parseInt(parts[1], 10);
const day = parseInt(parts[2], 10);
return `${month}月${day}日`;
}
function isToday(dateStr: string): boolean {
if (!dateStr || dateStr.length === 0) {
return false;
}
const now = new Date();
const mm = String(now.getMonth() + 1).padStart(2, '0');
const dd = String(now.getDate()).padStart(2, '0');
return dateStr === `${now.getFullYear()}-${mm}-${dd}`;
}
@Entry
@Component
struct ElderlyRecommendations {
@StorageProp('fontScale') fontScaleLevel: FontScaleLevel = 'system';
@State recommendations: Array<Recommendation> = [];
@State loading: boolean = true;
private scroller: Scroller = new Scroller();
private scaleFor(): number {
return FONT_SCALE_MAP[this.fontScaleLevel] ?? 1.0;
}
aboutToAppear(): void {
this.load();
}
private async load(): Promise<void> {
this.loading = true;
try {
const res = await api.get<RecommendationsResponse>('/elderly-portal/recommendations/');
this.recommendations = res.recommendations;
} catch (err) {
const message = err instanceof RequestError ? err.message : normalizeError(err as BusinessError | Error);
promptAction.showToast({ message: message });
} finally {
this.loading = false;
}
}
@Builder
RecommendCard(item: Recommendation) {
Column({ space: 8 }) {
Row({ space: 10 }) {
Text(periodIcon(item.meal_period))
.fontSize(Math.round(24 * this.scaleFor()))
Text(`${item.meal_period} · ${isToday(item.service_date) ? '今日' : formatDateLabel(item.service_date)}`)
.fontSize(Math.round(17 * this.scaleFor()))
.fontWeight(FontWeight.Bold)
.fontColor($r('app.color.text_primary'))
Blank()
Text(`¥${item.price}`)
.fontSize(Math.round(16 * this.scaleFor()))
.fontWeight(FontWeight.Bold)
.fontColor('#FF9500')
}
.width('100%')
Text(item.dish_name)
.fontSize(Math.round(20 * this.scaleFor()))
.fontWeight(FontWeight.Medium)
.fontColor(periodColor(item.meal_period))
.width('100%')
if (item.reason && item.reason.length > 0) {
Text(item.reason)
.fontSize(Math.round(15 * this.scaleFor()))
.fontColor($r('app.color.text_secondary'))
.lineHeight(22)
.width('100%')
}
}
.width('100%')
.padding(16)
.backgroundColor($r('app.color.background_card'))
.borderRadius(18)
.alignItems(HorizontalAlign.Start)
}
build() {
HdsNavigation() {
Column() {
Scroll(this.scroller) {
Column({ space: 12 }) {
if (this.loading) {
Text('加载中...')
.fontSize(Math.round(16 * this.scaleFor()))
.fontColor($r('app.color.inactive_tab'))
.margin({ top: 40 })
} else if (this.recommendations.length === 0) {
Column({ space: 8 }) {
Text('暂无膳食推荐')
.fontSize(Math.round(20 * this.scaleFor()))
.fontWeight(FontWeight.Bold)
.fontColor($r('app.color.text_primary'))
Text('护理团队会根据您的健康状况推送个性化餐食建议')
.fontSize(Math.round(15 * this.scaleFor()))
.fontColor($r('app.color.text_secondary'))
.textAlign(TextAlign.Center)
}
.width('100%')
.padding(24)
.backgroundColor($r('app.color.background_card'))
.borderRadius(16)
.alignItems(HorizontalAlign.Center)
} else {
ForEach(this.recommendations, (item: Recommendation) => {
Column() {
this.RecommendCard(item)
}
.width('100%')
}, (item: Recommendation) => String(item.id))
}
}
.width('100%')
.padding({ left: 16, right: 16, top: 92, bottom: 30 })
}
.width('100%')
.layoutWeight(1)
.scrollBar(BarState.Auto)
.edgeEffect(EdgeEffect.Spring)
}
.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'))
}
}