【共创季稿事节】「毕业季 · 鸿蒙同行」我的鸿蒙课程设计复盘:校企合作项目中的收获与遗憾
文章目录
-
- 每日一句正能量
- 一、课程开始前:我以为“课程设计”就是把课堂知识拼成一个App
- 二、课程结构:为什么前半程学能力,后半程做工程
- 三、项目选题:从“校园超级App”收敛到设备巡检与报修
- 四、需求调研:我们原本以为用户最关心“页面好不好看”
- 五、项目架构:第一次主动把页面、业务和数据分开
- 六、团队分工:表格写得很清楚,执行时仍然失衡
- 七、状态机:我们第一次发现“已提交”不是一个简单布尔值
- 八、ArkUI 页面:从成功状态扩展到完整页面状态
- 九、离线队列:项目最有价值的技术点,也是返工最多的部分
- 十、项目时间线:第13周的联调危机
- 十一、项目界面与演示
- 十二、教师指导:给答案不如不断追问边界
- 十三、成绩评价:分数是结果,评价摘要更值得复盘
- 十四、最大的收获一:从“会接口”到“会设计状态”
- 十五、最大的收获二:学会把技术选择讲成“取舍”
- 十六、最大的收获三:团队协作必须有可见资产
- 十七、遗憾一:选题收敛得太晚
- 十八、遗憾二:测试成员介入太晚
- 十九、遗憾三:性能数据缺乏说服力
- 二十、遗憾四:项目缺少长期用户验证
- 二十一、收获与遗憾对照
- 二十二、如果重新做一次,我会怎样安排
- 二十三、课程成果如何沉淀成求职资产
- 二十四、课程设计对我的真正影响
- 二十五、总结

每日一句正能量
不被任何情绪而变得被动就是最好的状态。
情绪可以来,但不被它推着走。愤怒时不攻击,悲伤时不沉溺,焦虑时不乱做决定。

标记:参与方向三「毕业季 · 鸿蒙同行」文章投稿。
一、课程开始前:我以为“课程设计”就是把课堂知识拼成一个App
这门校企共建 HarmonyOS 课程持续 16 周。
前 7 周以 ArkTS、ArkUI、Stage Model、网络、数据和通知等基础能力为主;第 8 周开始进入团队课程设计;最后两周进行项目验收、视频演示和答辩。
我对课程设计最初的理解非常简单:
选一个功能多的题目,把课堂里学过的接口尽量用进去,最后做出几个好看的页面。
第一次选题评审就暴露了问题。我们提出的题目叫“校园超级服务平台”,计划包含:
- 校园地图;
- 课程表;
- 失物招领;
- 实验室预约;
- 校园资讯;
- 设备报修;
- AI问答;
- 手机和平板协同。
企业导师看完后问:
四个人、八周时间,你们最想解决的一个问题是什么?
我们答不上来。
这次评审让我意识到,课程设计不是功能数量比赛。它真正考察的是:
- 能不能识别真实问题;
- 能不能控制范围;
- 能不能完成核心闭环;
- 能不能解释技术选择;
- 能不能协作交付;
- 能不能诚实复盘不足。
二、课程结构:为什么前半程学能力,后半程做工程

课程大致分为五个阶段。
2.1 基础阶段:第1~4周
内容:
- ArkTS 基础;
- ArkUI 组件与布局;
- 状态管理;
- 页面路由;
- Stage Model;
- UIAbility 生命周期;
- Git 基本操作。
要求每名学生独立完成一个包含列表、表单、详情和错误状态的小应用。
2.2 平台能力阶段:第5~7周
内容:
- 网络请求;
- 本地数据;
- 通知;
- 权限;
- 资源适配;
- 多端布局;
- 调试与日志。
这个阶段最重要的改变,是老师不再只验收“能不能运行”,而是要求:
- 加载状态;
- 空数据;
- 错误提示;
- 重试;
- 缓存;
- 日志;
- 真机或模拟设备验证。
2.3 项目设计阶段:第8~10周
内容:
- 选题;
- 需求调研;
- 原型;
- 数据模型;
- 架构;
- 团队分工;
- 里程碑;
- 风险清单。
2.4 迭代开发阶段:第11~14周
每两周检查一次可运行版本,而不是只看PPT进度。
2.5 展示与复盘阶段:第15~16周
提交:
- 代码;
- README;
- 架构图;
- 测试记录;
- 演示视频;
- 答辩PPT;
- 个人贡献;
- 项目复盘。
华为开发者联盟提供的知识地图将官方指南、Codelabs、示例代码、API参考、FAQ和视频教程按开发任务旅程组织起来;开发者学堂也通过课程和 Codelabs 提供“学与练”的路径。课程设计阶段,我们不再只依赖课堂PPT,而是学会回到官方文档核对接口、约束和版本差异。
三、项目选题:从“校园超级App”收敛到设备巡检与报修

我们重新提出了四个选题:
- 校园超级App;
- AI课堂全自动分析;
- 校园设备巡检与报修;
- 校园资讯聚合。
最终选择“校园设备巡检与报修”,原因是:
- 学校实验室、教室和公共区域存在设备巡检需求;
- 痛点明确;
- 流程完整;
- 数据可以模拟或小规模采集;
- 适合手机执行、平板查看;
- 可以实践网络、缓存、状态机、离线队列和通知;
- 八周内能完成核心版本。
3.1 核心用户
- 学生助管;
- 实验室管理员;
- 校园设备维护人员;
- 管理端教师。
3.2 核心闭环
接收巡检任务
→ 到达设备
→ 查看检查项
→ 填写巡检结果
→ 发现异常
→ 创建报修
→ 弱网时保存本地
→ 网络恢复后同步
→ 管理端查看处理状态
3.3 明确不做
- 全校资产管理;
- 自动识别所有设备故障;
- 复杂后台管理系统;
- 真实支付;
- 未经授权的校园统一身份认证;
- 大规模设备控制。
范围收敛后,我们第一次感觉项目真正有可能完成。
四、需求调研:我们原本以为用户最关心“页面好不好看”
我们访谈了两位实验室老师和几名学生助管。
最初准备的问题偏功能:
- 是否需要地图;
- 是否需要拍照;
- 是否需要统计图;
- 是否需要消息推送。
老师更关心的是:
- 任务有没有漏做;
- 异常有没有真正提交;
- 网络不好时记录会不会丢;
- 谁提交、什么时候提交;
- 重复报修怎么办;
- 设备状态不明确时怎样处理。
这次调研让我们把优先级改成:
- 数据不丢;
- 状态清楚;
- 流程可追踪;
- 异常可恢复;
- 页面再优化。
这也是课程设计带给我的第一个工程收获:真实用户常常不关心我们用了多少新接口,只关心事情能不能可靠完成。
五、项目架构:第一次主动把页面、业务和数据分开

工程分成五层。
5.1 交互层
- 任务列表;
- 设备详情;
- 巡检表单;
- 异常报修;
- 管理看板。
5.2 状态层
- 加载;
- 空数据;
- 错误;
- 表单;
- 同步;
- 筛选。
5.3 业务层
- 任务状态机;
- 表单校验;
- 报修规则;
- 权限判断;
- 重试与冲突策略。
5.4 数据层
- 网络接口;
- 本地缓存;
- 离线队列;
- 数据映射。
5.5 质量层
- 日志;
- 单元测试;
- UI测试;
- 性能记录;
- 演示数据。
5.6 工程目录
entry/src/main/ets/
├── pages/
│ ├── TaskListPage.ets
│ ├── TaskDetailPage.ets
│ ├── InspectionFormPage.ets
│ ├── RepairPage.ets
│ └── DashboardPage.ets
├── components/
├── model/
│ ├── InspectionTask.ets
│ ├── RepairOrder.ets
│ └── PageState.ets
├── service/
│ ├── InspectionService.ets
│ ├── RepairService.ets
│ └── TaskStateMachine.ets
├── repository/
│ ├── TaskRepository.ets
│ ├── CacheRepository.ets
│ └── OfflineQueue.ets
└── common/
├── Logger.ets
├── Result.ets
└── Constants.ets
六、团队分工:表格写得很清楚,执行时仍然失衡

团队四人。
成员A:组长与业务层
负责:
- 需求;
- 状态机;
- 项目计划;
- 接口协调;
- 答辩。
成员B:ArkUI和多端适配
负责:
- 手机页面;
- 平板看板;
- 公共组件;
- 视觉统一。
成员C:数据层
负责:
- 网络;
- 缓存;
- 离线队列;
- 数据映射;
- 同步日志。
成员D:测试、文档与演示
负责:
- 测试用例;
- 缺陷跟踪;
- README;
- 演示视频;
- 材料整理。
这个分工的问题是:测试成员在前半程没有足够开发任务,直到后期才大量介入;组长和UI成员在联调阶段任务过重。
下一轮应该采用“模块主责+交叉评审”:
- 每个人有主责模块;
- 每个模块有第二评审人;
- 测试从需求阶段编写验收条件;
- 组长不承担所有协调和关键代码。
七、状态机:我们第一次发现“已提交”不是一个简单布尔值
最初任务只有:
completed: boolean
后来发现真实状态至少包含:
export type InspectionStatus =
'PENDING' |
'IN_PROGRESS' |
'WAITING_SYNC' |
'SUBMITTED' |
'REJECTED' |
'CLOSED'
状态流转:
export class TaskStateMachine {
private static allowed: Map<InspectionStatus, InspectionStatus[]> = new Map([
['PENDING', ['IN_PROGRESS']],
['IN_PROGRESS', ['WAITING_SYNC', 'SUBMITTED']],
['WAITING_SYNC', ['SUBMITTED', 'IN_PROGRESS']],
['SUBMITTED', ['REJECTED', 'CLOSED']],
['REJECTED', ['IN_PROGRESS']],
['CLOSED', []]
])
static canTransfer(
from: InspectionStatus,
to: InspectionStatus
): boolean {
return this.allowed.get(from)?.includes(to) ?? false
}
}
这个状态机解决了:
- 未开始不能直接关闭;
- 离线记录处于待同步;
- 驳回后可以重新处理;
- 已关闭任务不能继续修改。
它也成为答辩时最容易体现“项目不是页面拼接”的证据。
八、ArkUI 页面:从成功状态扩展到完整页面状态
export type PageState<T> =
| { status: 'loading' }
| { status: 'success', data: T }
| { status: 'empty' }
| { status: 'error', message: string }
@Entry
@Component
struct TaskListPage {
@State state: PageState<InspectionTask[]> = {
status: 'loading'
}
aboutToAppear(): void {
this.loadTasks()
}
build() {
Column() {
if (this.state.status === 'loading') {
LoadingProgress()
} else if (this.state.status === 'empty') {
Text('暂无巡检任务')
} else if (this.state.status === 'error') {
Column() {
Text(this.state.message)
Button('重试')
.onClick(() => this.loadTasks())
}
} else {
List({ space: 12 }) {
ForEach(
this.state.data,
(item: InspectionTask) => {
ListItem() {
TaskCard({ task: item })
}
},
(item: InspectionTask) => item.id
)
}
}
}
.width('100%')
.height('100%')
}
private async loadTasks(): Promise<void> {
this.state = { status: 'loading' }
try {
const tasks: InspectionTask[] =
await TaskRepository.getInstance().list()
this.state = tasks.length > 0
? { status: 'success', data: tasks }
: { status: 'empty' }
} catch (error) {
this.state = {
status: 'error',
message: '任务加载失败,请稍后重试'
}
}
}
}
课程前半程,我只会展示成功数据;课程结束时,我开始把错误和恢复当成页面的一部分。
九、离线队列:项目最有价值的技术点,也是返工最多的部分
设备间或地下实验室网络不稳定。我们设计本地离线队列:
export interface PendingOperation {
id: string
businessId: string
type: 'SUBMIT_INSPECTION' | 'CREATE_REPAIR'
payload: string
createdAt: number
expireAt: number
retryCount: number
}
export class OfflineQueue {
private items: PendingOperation[] = []
enqueue(item: PendingOperation): void {
const existed = this.items.some(
(current: PendingOperation) => current.id === item.id
)
if (!existed) {
this.items.push(item)
}
}
async flush(
sender: (item: PendingOperation) => Promise<boolean>
): Promise<void> {
const remained: PendingOperation[] = []
for (const item of this.items) {
if (item.expireAt < Date.now()) {
continue
}
const success: boolean = await sender(item)
if (!success) {
remained.push({
...item,
retryCount: item.retryCount + 1
})
}
}
this.items = remained
}
}
第一版遗漏了:
- 应用重启后的持久化;
- 服务端幂等;
- 记录过期提示;
- 已成功但客户端超时;
- 多次点击重复提交;
- 用户查看同步状态。
企业导师评审后,我们增加:
- 本地持久化;
- 请求ID;
- 队列去重;
- 最大重试;
- 同步状态;
- 手动重试;
- 冲突提示。
十、项目时间线:第13周的联调危机

第8周:选题评审
从超级App收敛到巡检与报修。
第9周:用户访谈
确认数据可靠性高于页面丰富度。
第10周:架构评审
确定状态机和离线同步。
第11周:V0.3
完成任务列表和详情。
第12周:V0.6
完成报修、本地缓存和手机端核心流程。
第13周:联调危机
数据接口字段发生变化:
旧字段:status = 0 / 1 / 2
新字段:healthStatus = NORMAL / WARNING / OFFLINE
问题包括:
- UI使用旧字段;
- 本地缓存使用旧模型;
- 测试数据没有更新;
- 统计页面映射失败;
- 没有接口版本记录。
团队花了两天统一模型和数据映射。
第14周:V1.0
补充:
- 弱网;
- 测试;
- 平板看板;
- 空状态;
- 同步状态。
第16周:答辩
项目完成核心闭环,但仍有明显不足。
十一、项目界面与演示

演示流程:
- 手机端打开当天巡检任务;
- 进入门禁设备详情;
- 发现设备离线;
- 填写报修;
- 关闭网络;
- 提交后显示“待同步”;
- 恢复网络;
- 离线队列自动补传;
- 平板看板刷新异常数量;
- 管理端状态变为“已提交”。
配套演示视频脚本已单独输出。由于没有真实课程工程和设备,本次不伪造可播放视频文件。
十二、教师指导:给答案不如不断追问边界
校内教师主要指导:
- 课程目标;
- 需求范围;
- 文档规范;
- 团队过程;
- 答辩表达;
- 学术和材料真实性。
企业导师主要指导:
- 工程分层;
- 接口边界;
- 异常处理;
- 测试;
- 日志;
- 用户体验;
- 真实上线差距。
几个印象最深的问题:
如果网络成功但客户端超时,重试会不会创建两条报修?
为什么状态判断写在页面里,而不是业务层?
平板看板是简单放大手机页面,还是承担不同任务?
你们的性能数据如何测量?
哪些代码是每个人真正完成的?
这些问题迫使我们从“项目展示”走向“工程解释”。
十三、成绩评价:分数是结果,评价摘要更值得复盘

文中的成绩单是示意材料,不能作为正式成绩证明。
匿名化样例评分:
| 评价项 | 权重 | 得分 |
|---|---|---|
| 需求与选题 | 20 | 17 |
| 技术实现 | 30 | 26 |
| 团队协作 | 20 | 15 |
| 测试与文档 | 15 | 11 |
| 展示与答辩 | 15 | 13 |
| 总评 | 100 | 82 |
比总分更重要的是评价:
- 痛点真实;
- 核心闭环完整;
- 弱网处理有思考;
- 团队分工后期失衡;
- 测试介入太晚;
- 性能证据不足;
- 复盘比较诚实。
十四、最大的收获一:从“会接口”到“会设计状态”
课程开始时,我衡量能力的方式是:
- 会多少组件;
- 会多少Kit;
- 能写多少页面。
课程结束后,我更关心:
- 状态有哪些;
- 状态如何流转;
- 异常如何恢复;
- 数据来自哪里;
- 页面何时更新;
- 请求会不会重复;
- 缓存是否过期;
- 用户是否知道同步结果。
这比记住更多接口更接近工程能力。
十五、最大的收获二:学会把技术选择讲成“取舍”
例如,为什么做离线队列?
不是因为它“技术含量高”,而是因为现场网络不稳定,巡检记录不能丢。
为什么不做实时设备控制?
因为课程项目没有真实设备授权和安全条件,范围会失控。
为什么平板只做管理看板?
因为平板更适合集中查看,不适合在设备现场填写所有细节。
为什么保留UNKNOWN状态?
因为服务端旧数据、版本变化和异常输入都可能出现,不能把未知强行当正常。
答辩真正有效的表达不是“用了什么”,而是“为什么这样做、放弃了什么”。
十六、最大的收获三:团队协作必须有可见资产
我们后期建立了四张表:
- 任务看板;
- 接口字段表;
- 风险清单;
- 缺陷与测试表。
接口字段表:
字段
类型
是否为空
枚举
默认值
负责人
变更日期
影响模块
风险清单:
风险
概率
影响
负责人
处理方案
截止时间
状态
这些工具看似不如写代码有成就感,却直接减少了返工。
十七、遗憾一:选题收敛得太晚
前两周仍然舍不得删除:
- 地图;
- AI问答;
- 校园资讯;
- 服务卡片;
- 跨设备接续。
最终很多功能没有完成,前期讨论也浪费时间。
下一次应该在选题阶段坚持:
一个核心用户
一个核心问题
一个完整闭环
一个鸿蒙特色能力
一组可验证数据
十八、遗憾二:测试成员介入太晚
测试成员前期主要写文档,第13周才集中写用例,结果发现:
- 状态非法流转;
- 表单重复提交;
- 缓存模型兼容;
- 页面空状态;
- 快速切换请求覆盖。
如果测试从需求阶段介入,可以提前把验收条件写成用例。
下一轮应该采用:
需求完成 = 代码 + 测试 + 日志 + 文档
十九、遗憾三:性能数据缺乏说服力
我们只记录了少量手工数据:
- 首屏加载;
- 列表刷新;
- 离线补传。
但没有统一:
- 测试设备;
- 网络条件;
- 样本数量;
- 平均值;
- 最大值;
- 优化前后版本。
答辩中虽然给出了数据,却难以证明可重复。
下一轮应建立测试基线:
设备:
系统版本:
应用版本:
网络:
数据量:
执行次数:
平均值:
P95:
内存:
结果:
二十、遗憾四:项目缺少长期用户验证
我们只邀请少量同学和教师试用,没有真实运行一个学期,也没有接入真实设备和学校系统。
因此,不能夸大为:
- 已经提升校园巡检效率;
- 已经减少设备故障;
- 已经在学校正式部署。
准确的结论应该是:
教学原型完成了核心流程验证,小规模试用能够发现交互和状态问题,但尚未经过真实长期部署验证。
二十一、收获与遗憾对照

收获
- 建立工程分层;
- 学会异常设计;
- 学会Code Review;
- 学会接口协作;
- 学会测试和日志;
- 学会答辩表达;
- 学会诚实描述项目边界。
遗憾
- 范围收敛晚;
- 测试介入晚;
- 性能数据不足;
- 缺少长期验证;
- 团队负载不均;
- 官方文档核对不够及时;
- 演示素材准备集中在最后一周。
二十二、如果重新做一次,我会怎样安排
第8周
- 访谈;
- 选题;
- 范围;
- 成功指标。
第9周
- 原型;
- 状态机;
- 数据模型;
- 测试验收条件。
第10周
- 架构;
- 接口契约;
- 分工;
- 环境和自动化。
第11~12周
- 核心闭环;
- 每周可运行版本;
- 测试同步编写。
第13周
- 弱网;
- 异常;
- 性能基线。
第14周
- 多端适配;
- 用户试用;
- 缺陷修复。
第15周
- 冻结功能;
- 测试;
- 视频;
- 文档。
第16周
- 答辩;
- 复盘;
- 资产归档。
二十三、课程成果如何沉淀成求职资产
课程结束后,我们整理:
- README;
- 项目介绍;
- 架构图;
- 代码片段;
- 测试报告;
- 视频;
- 个人贡献;
- 失败复盘;
- V2.0计划。
简历项目描述不再写:
使用ArkTS和ArkUI完成校园巡检系统。
而写成:
面向校园实验室弱网巡检场景,负责任务状态机与离线同步模块;通过本地队列、请求幂等标识和同步状态提示保障记录可恢复,并将手机执行端与平板管理看板分工设计;课程样例完成20轮弱网流程测试,核心记录无丢失。
数据必须来自真实测试,不能为了简历好看编造。
二十四、课程设计对我的真正影响
这门课程没有让我在16周内成为高级HarmonyOS工程师。
它让我完成了一个更重要的转变:
- 从个人作业到团队项目;
- 从成功路径到异常路径;
- 从接口调用到架构边界;
- 从功能截图到测试证据;
- 从临时演示到资产沉淀;
- 从追求高分到诚实复盘。
这些能力不只适用于HarmonyOS,也适用于后续实习、毕业设计和任何软件工程项目。
二十五、总结
回看这次校企合作鸿蒙课程设计,最值得保留的不是最终82分,也不是答辩那天顺利跑通的演示,而是我们第一次经历了一个接近真实工程的小型周期:
- 选题被否定;
- 范围被收缩;
- 接口发生变化;
- 代码被评审;
- 弱网暴露问题;
- 团队任务失衡;
- 测试发现缺陷;
- 答辩被追问;
- 项目留下遗憾。
课程设计的价值不在于证明我们已经可以独立上线商业应用,而在于让我们提前看到学校作业和企业工程之间的距离,并学会用更可靠的方法缩短这段距离。
“毕业季 · 鸿蒙同行”对我来说,是一次从课堂知识到工程实践的过渡。收获让我更有信心,遗憾则提醒我:下一次面对真实项目时,应该更早控制范围、更早测试、更早沟通,并用真正可复现的证据评价成果。
转载自:https://blog.csdn.net/u014727709/article/details/163017075
欢迎 👍点赞✍评论⭐收藏,欢迎指正
更多推荐



所有评论(0)