一、开发环境准备
工具安装:
- 下载安装DevEco Studio 4.0+(支持HarmonyOS 5)
- 配置HarmonyOS SDK 5.0+
- 确保Node.js版本≥14
项目初始化:
ohpm init @harmony/hospital-report-app
二、核心功能模块实现
1. 报告列表展示
// ReportList.ets
@Component
struct ReportList {
@State reports: Array<ReportItem> = []
@State isLoading: boolean = true
aboutToAppear() {
this.fetchReports()
}
async fetchReports() {
try {
const result = await ReportService.getReportList()
this.reports = result.data
} catch (error) {
logger.error('获取报告列表失败', error)
} finally {
this.isLoading = false
}
}
build() {
Column() {
if (this.isLoading) {
LoadingProgress()
} else {
List({ space: 12 }) {
ForEach(this.reports, (item) => {
ListItem() {
ReportCard({ report: item })
.onClick(() => {
router.pushUrl({
url: 'pages/ReportDetail',
params: { reportId: item.id }
})
})
}
})
}
}
}
}
}
2. 报告详情查看
// ReportDetail.ets
@Component
struct ReportDetail {
@State report: MedicalReport = null
@State isImageLoading: boolean = false
aboutToAppear() {
const params = router.getParams()
this.loadReportDetail(params['reportId'])
}
async loadReportDetail(reportId: string) {
this.isImageLoading = true
try {
this.report = await ReportService.getReportDetail(reportId)
} finally {
this.isImageLoading = false
}
}
build() {
Column() {
// 报告基本信息
ReportHeader({ report: this.report })
// PDF报告查看
if (this.report?.fileType === 'pdf') {
PDFViewer({
src: this.report.fileUrl,
controller: this.pdfController
})
}
// 图片报告查看
else if (this.report?.fileType === 'image') {
Stack() {
Image(this.report.fileUrl)
.width('100%')
.objectFit(ImageFit.Contain)
if (this.isImageLoading) {
LoadingProgress()
}
}
}
// 分享按钮
Button('分享报告', { type: ButtonType.Capsule })
.onClick(() => this.shareReport())
}
}
}
三、HarmonyOS 5特色功能集成
1. 分布式报告共享
// 跨设备分享报告
async function shareToOtherDevice(report: MedicalReport) {
try {
const devices = deviceManager.getAvailableDeviceListSync([DeviceType.SMART_PHONE])
const result = await featureAbility.startAbilityForResult({
deviceId: devices[0].deviceId,
bundleName: 'com.example.medical',
abilityName: 'ReportReceiverAbility',
parameters: {
reportData: JSON.stringify(report),
action: 'shareReport'
}
})
logger.info('分享结果:', result)
} catch (error) {
logger.error('跨设备分享失败', error)
}
}
2. 原子化服务入口
// module.json5配置
{
"abilities": [
{
"name": "QuickViewAbility",
"srcEntry": "./ets/quickview/QuickView.ets",
"label": "快速查看",
"icon": "$media:icon",
"startWindowIcon": "$media:icon",
"exported": true,
"skills": [
{
"actions": [
"action.system.view",
"action.medical.report.view"
],
"uris": [
{
"scheme": "medicalreport",
"host": "quickview"
}
]
}
]
}
]
}
3. 卡片服务实现
// ReportCard.ets
@Component
export struct ReportCard {
@Prop report: ReportItem
@State isFavorite: boolean = false
build() {
Column() {
Row() {
Image(this.report.typeIcon)
.width(24)
.height(24)
Text(this.report.name)
.fontSize(16)
.fontWeight(FontWeight.Medium)
Blank()
Image($r('app.media.favorite'))
.visibility(this.isFavorite ? Visibility.Visible : Visibility.None)
}
Divider()
Row() {
Text('检查日期:')
.fontColor('#666')
Text(this.report.date)
.margin({ left: 8 })
}
// 更多报告信息...
}
.onClick(() => {
postCardAction(this, {
action: 'router',
abilityName: 'ReportDetailAbility',
params: { reportId: this.report.id }
})
})
}
}
四、数据安全与管理
1. 加密存储敏感数据
// 使用HarmonyOS加密API
import cryptoFramework from '@ohos.security.cryptoFramework';
async function encryptReportData(data: string): Promise<string> {
try {
const cipher = cryptoFramework.createCipher('RSA1024|PKCS1');
await cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, publicKey);
const input: cryptoFramework.DataBlob = { data: stringToUint8Array(data) };
const output = await cipher.doFinal(input);
return uint8ArrayToString(output.data);
} catch (error) {
logger.error('加密失败:', error);
throw error;
}
}
2. 数据库操作
// 使用关系型数据库存储报告缓存
const STORE_CONFIG = {
name: 'medical_reports.db',
securityLevel: relationalStore.SecurityLevel.S4, // 最高安全级别
encryptKey: new Uint8Array(32) // 32字节加密密钥
};
relationalStore.getRdbStore(context, STORE_CONFIG, (err, store) => {
if (err) {
logger.error('数据库初始化失败:', err);
return;
}
// 创建报告表
store.executeSql(`
CREATE TABLE IF NOT EXISTS reports (
id TEXT PRIMARY KEY,
patient_id TEXT,
report_data TEXT,
created_time INTEGER
)`
);
});
五、UI/UX设计实现
1. 医疗风格主题
// resources/base/theme/medical_theme.json
{
"color": {
"medical_primary": "#1a73e8",
"medical_secondary": "#34a853",
"medical_warning": "#fbbc05",
"medical_danger": "#ea4335"
},
"font": {
"medical_title": {
"size": 20,
"weight": 500
},
"medical_body": {
"size": 14,
"weight": 400
}
}
}
2. 报告分类导航
// ReportCategory.ets
@Component
struct ReportCategory {
@State categories: Array<Category> = [
{ id: 'lab', name: '检验报告', icon: 'lab' },
{ id: 'image', name: '影像报告', icon: 'radiology' },
{ id: 'pathology', name: '病理报告', icon: 'microscope' }
]
build() {
GridRow({ columns: 4, gutter: 8 }) {
ForEach(this.categories, (category) => {
GridCol({ span: 1 }) {
Column() {
Image($r(`app.media.${category.icon}`))
.width(48)
.height(48)
Text(category.name)
.margin({ top: 8 })
}
.onClick(() => this.filterByCategory(category.id))
}
})
}
}
}
六、测试与发布
1. 单元测试示例
// ReportService.test.ets
describe('ReportService Test', () => {
beforeAll(() => {
// 初始化测试环境
});
it('should fetch report list successfully', async () => {
const mockData = [{ id: '1', name: '血常规' }];
jest.spyOn(http, 'request').mockResolvedValue({ data: mockData });
const result = await ReportService.getReportList();
expect(result).toEqual(mockData);
});
it('should handle network error', async () => {
jest.spyOn(http, 'request').mockRejectedValue(new Error('Network Error'));
await expect(ReportService.getReportList())
.rejects
.toThrow('获取报告列表失败');
});
});
2. 应用发布准备
签名配置:
hdc appmode install --signature [签名文件] --bundle-name [包名]
上架华为应用市场:
- 准备医疗类应用特殊资质文件
- 确保符合《移动医疗应用数据安全规范》
- 提交隐私合规审查
七、性能优化建议
报告图片懒加载:
// LazyImage.ets @Component struct LazyImage { @Prop src: string @State isLoaded: boolean = false build() { Stack() { if (this.isLoaded) { Image(this.src) .onComplete(() => this.isLoaded = true) } else { Placeholder() } } } }
数据预加载:
// 在用户登录后预加载常用报告 UserService.onLogin(() => { ReportService.prefetchReports(); });
缓存策略:
// 使用两级缓存 const CACHE_STRATEGY = { memoryCache: new Map<string, any>(), diskCache: new PreferencesCache(), async get(key: string) { if (this.memoryCache.has(key)) { return this.memoryCache.get(key); } const diskData = await this.diskCache.get(key); if (diskData) this.memoryCache.set(key, diskData); return diskData; } };
通过以上实现,您可以构建一个符合HarmonyOS 5设计规范、功能完善的医院报告查看小程序,充分利用鸿蒙的分布式能力和安全特性,为患者提供安全便捷的报告查询体验。