【共创季稿事节】毕业季·一屏多态:HarmonyOS 6.1 全场景求职作战舱 Career Deck 实战
【共创季稿事节】毕业季·一屏多态:HarmonyOS 6.1 全场景求职作战舱 Career Deck 实战
方向三:毕业季 · 鸿蒙同行
毕业季里,手机上的一条面试提醒、平板上的一组投递进度、电脑上的一份简历和项目复盘,往往属于同一件事,却被迫散落在不同工具中。Career Deck 希望把这件事重新组织起来:同一份岗位、作品与面试准备状态,在手机端变成下一步行动,在平板端变成流程看板,在电脑端变成可持续处理的求职指挥台。
本文基于
career-deck的真实 ArkTS / ArkUI 工程,讲解一款 HarmonyOS 6.1 求职应用的产品建模、声明式状态、沉浸式窗口、固定导航安全区、手机/平板/PC 一多布局策略,以及 AI 面试教练的结构化服务端接入边界。重点不在“做三个不同页面”,而在“让一份毕业生求职任务在三种设备上自然延续”。

图 1:一屏多态不等于把同一张 UI 拉伸到不同尺寸,而是按设备角色重组同一份求职上下文。
一、从毕业设计到求职:真正的问题是什么
很多毕业生在项目完成后,会经历一种奇怪的断裂:毕业设计、创新赛作品和学习笔记都在,但它们没有自动变成求职过程中的“能力证据”。投递岗位时,要重新翻 Git 仓库、找截图、改项目介绍;收到面试通知时,临时回忆自己在 ArkTS、ArkUI、AI 服务接入中到底做过什么;面试结束后,复盘又散落在备忘录、日历和聊天记录里。

所以 Career Deck 不把自己定义为“求职待办”,而是一个面向鸿蒙毕业生的任务上下文容器。它试图把四类信息连接起来:

例如,一份“HarmonyOS AI 应用开发工程师”岗位不应该只触发“明天 14:00 面试”的提醒,还应该关联:
- ArkTS 状态管理:能否解释
@State的页面状态边界; - ArkUI:能否讲清页面如何根据状态刷新;
- AI 应用:能否说明模型返回异常 JSON 时如何容错;
- 工程实践:能否讲清密钥为什么不能放进客户端;
- 作品证据:AI 智能菜谱、技能成长地图、跨屏演讲台分别能证明什么。
这也是本文强调“毕业季”而非普通效率工具的原因。学生需要的不只是更多待办,而是从“我做过一些项目”走向“我能用项目证明我具备某项能力”。

二、全场景的第一原则:先定义设备角色
响应式布局经常被误解为“手机一列、平板两列、电脑三列”。这只是最后的视觉结果。真正应先回答的是:不同设备上,用户正在做的任务是不是同一种?
2.1 手机端:行动优先
手机是碎片化设备。用户在通勤、排队或面试前几分钟打开它,通常没有耐心浏览全部岗位。因此 Career Deck 的手机首页只回答一个问题:今天最应该完成什么?
首页依次呈现三层信息:
- 三项关键行动与在投岗位、面试数量、最佳匹配度;
- 下一场面试的时间、岗位和准备主题;
- 可点击完成的冲刺任务与作品证据入口。

图 2:移动端的核心不是展示完整看板,而是降低“我现在应该做什么”的决策成本。
2.2 平板端:流程优先
平板拥有更大的可阅读区域和更强的触控操作空间,适合把“今日行动”扩展为“本周流程”。左侧可以放岗位阶段与漏斗,中间放岗位列表和截止日期,右侧放当前岗位的准备建议。用户不需要在多个页面间来回跳转,就能理解投递、笔试、面试与 Offer 所在的阶段。
2.3 电脑/2in1:上下文优先
PC 的价值不在显示更多字,而在承接长时间任务:比对 JD、修改简历、整理项目截图、录制自我介绍、复盘面试。宽屏最适合三栏:
左:岗位列表、筛选、阶段统计
中:当前岗位详情、时间线、关联作品
右:AI 面试教练、项目追问、今晚行动
此时用户在“星河智能”的岗位上下文中,可以同时看到岗位状态、AI 智能菜谱这一关联项目和“结构化 JSON 容错”的追问。减少上下文切换,才是电脑端的生产力。
项目模块声明支持:
"deviceTypes": ["phone", "tablet", "2in1"]
这句配置只是入口;真正的一多适配来自后文的数据边界和布局策略。
三、数据先行:用岗位模型稳定三端体验
Career Deck 的核心领域对象是 JobApplication:
interface JobApplication {
company: string;
role: string;
stage: string;
deadline: string;
match: number;
color: string;
project: string;
}
它看起来很小,却足以驱动不同设备上的不同表达。手机端读取 deadline 和 stage,生成下一场面试卡;平板端把 stage 放进漏斗和列表;PC 端将 project 与 AI 准备内容放进右栏;match 则成为岗位准备覆盖度,而不是虚假的录取概率。
预置岗位数据:
const JOBS: JobApplication[] = [
{ company: '星河智能', role: 'HarmonyOS AI 应用开发',
stage: '一面准备', deadline: '明天 14:00', match: 86,
color: '#8A6CFF', project: 'AI 智能菜谱' },
{ company: '云栖科技', role: '鸿蒙应用开发实习生',
stage: '笔试中', deadline: '7 月 20 日', match: 74,
color: '#45D7C8', project: '技能成长地图' }
];
生产版本中,建议把 stage: string 收紧为联合类型:
type ApplicationStage = 'saved' | 'applied' | 'written' | 'interview' | 'offer' | 'rejected';
这样阶段统计、筛选、颜色映射不会因为“笔试中”“笔试”“在线笔试”等文案差异而失效。毕业生项目想体现工程意识,最值得展示的不是数据字段数量,而是类型能否限制无效状态。
四、ArkUI 声明式状态:不要让三个页面各自保存一份事实
页面维护以下状态:
@State currentTab: number = 0;
@State selectedJob: number = 0;
@State aiLoading: boolean = false;
@State aiVisible: boolean = false;
@State completedCount: number = 1;
它们分别表示当前任务域、当前关注岗位、AI 请求状态、AI 建议可见状态和今日完成数。ArkUI 的关键价值是:UI 不再主动“修改某个控件”,而是根据状态重新描述自己。
以任务完成为例:
.onClick(() => {
if (index >= this.completedCount) {
this.completedCount++;
promptAction.showToast({ message: '行动已记录,求职能量增加', duration: 1200 });
}
})
任务图标和颜色通过同一个条件推导:
Text(index < this.completedCount ? '✓' : (index + 1).toString())
.backgroundColor(index < this.completedCount ? '#91E7BB' : '#1D526D')
如果后续需要在平板、PC 同步完成数或让 AI 计划读取它,只需让它们订阅同一业务状态即可。反过来,如果每个页面都保存“自己的任务是否完成”,一多适配就会变成三份容易漂移的逻辑。
五、固定底栏与内容安全区:一个容易被忽略的适配细节
根页面采用 Stack,把内容与导航分层:
Stack({ alignContent: Alignment.Bottom }) {
if (this.currentTab === 0) {
this.ActionContent()
} else if (this.currentTab === 1) {
this.BoardContent()
} else {
this.CoachContent()
}
this.BottomBar()
}
每个内容区使用 Scroll,并设置:
.padding({ left: 18, right: 18, bottom: 105 })
这 105px 并非无意义留白。底栏高度是 78px,额外空间保证用户滚动到最后一项时不会被叠层导航遮住。手机端尤其容易暴露这个问题:布局看起来正常,但最后一条高频追问永远无法完整阅读。
平板和 PC 端可将 BottomBar 演进为左侧导航 rail,但 currentTab 和三块业务内容无需重写。这体现了适配的正确顺序:先稳定状态模型,再替换布局容器。
六、手机行动页:把求职焦虑改写成下一步行动
Hero 卡以“03 件关键行动等待完成”为中心,而不是显示复杂图表:
Text('03').fontSize(58).fontWeight(FontWeight.Bold)
Text('件关键行动等待完成')
下方的在投岗位、本周面试、最佳匹配度,只是为行动提供背景。紧接着的面试卡将时间和技术主题合并:
Text('星河智能 · HarmonyOS AI 应用开发')
Text('重点准备:ArkTS 状态管理、结构化输出、项目复盘')

手机端任务刻意覆盖三种毕业生最常忽略的能力:状态设计、AI 工程可靠性、项目表达。比如“整理 AI 智能菜谱异常兜底方案”不是背诵某个模型 API,而是准备如何解释:模型返回非 JSON、缺字段、超时时,端侧怎样提取、解析、默认值兜底和提示用户。
七、平板与 PC 进度地图:从卡片列表到岗位上下文
进度页通过五阶段漏斗建立流程感:待投递、已投递、笔试、面试、Offer。岗位卡展示公司、角色、当前阶段、截止时间、准备匹配度和关联作品。

当前卡片选中状态由 selectedJob 驱动:
.backgroundColor(this.selectedJob === index ? '#16374B' : '#102432')
.border({ width: 1, color: this.selectedJob === index ? job.color : '#25495F' })
.onClick(() => { this.selectedJob = index })
这正是平板双列和 PC 三栏的基础。手机端点击仅负责高亮;平板端可在右列读取 JOBS[selectedJob] 显示详情;PC 端则可以让详情栏和 AI 教练栏同时订阅它。
匹配度 match 必须被解释为“准备覆盖度”,不是录用率。真实实现应拆分为技能覆盖、项目关联、表达准备、待补能力,并明确显示缺口。数字只有帮助用户做下一步选择时才有价值。
八、沉浸式窗口:HarmonyOS 6.1 下的全屏不等于隐藏系统栏
深色界面若被白色系统栏打断,视觉确实不完整。但粗暴隐藏状态栏和导航栏在模拟器或不同手势环境中可能产生异常。Career Deck 的策略是:让内容全屏延展,同时保留系统栏,并统一背景色。
mainWindow.setWindowLayoutFullScreen(true);
mainWindow.setWindowSystemBarEnable(['status', 'navigation']);
mainWindow.setWindowSystemBarProperties({
statusBarColor: '#07131F',
navigationBarColor: '#07131F',
statusBarContentColor: '#FFFFFF',
navigationBarContentColor: '#FFFFFF'
});
这段代码值得在 6.0→6.1 升级复盘中强调:系统栏、窗口内容与固定导航属于三个不同层级。窗口沉浸不自动解决内容安全区;保留系统栏也不意味着出现白边。需要在手机、平板、2in1 的不同窗口下分别验证图标对比度、底部手势区和滚动末尾可达性。
九、AI 面试教练:先完成交互闭环,再接入模型
教练页将目标岗位、技术标签、建议和追问放进一个上下文:

当前版本用本地状态模拟生成过程:
private GenerateCoach(): void {
if (this.aiLoading) return;
this.aiLoading = true;
setTimeout(() => {
this.aiLoading = false;
this.aiVisible = true;
promptAction.showToast({ message: '面试冲刺建议已生成', duration: 1400 });
}, 900);
}
这是有意为之。先验证“生成中是否禁止重复点击、建议文本应该多长、用户是否能根据建议行动”,再引入模型服务。否则很容易得到“模型能回答、产品却没有合适承接方式”的 Demo。
真实接入时,客户端请求业务服务端,服务端持有密钥、注入提示词、校验 JSON:
{
"priority": "high",
"actions": [
{"minutes": 20, "task": "复盘 @State 状态边界", "output": "两分钟讲解"},
{"minutes": 25, "task": "整理 JSON 容错", "output": "异常流程图"}
],
"questions": [
{"question": "为什么不把所有状态放进 AppStorage?", "intent": "状态边界"}
]
}
模型输出必须是结构化契约,而不是一篇长文。端侧才能稳定渲染行动、问题与优先级;服务端才能统一处理限流、鉴权、日志和敏感信息;用户也能清楚地修改或拒绝建议。
十、高频追问:将项目事实转化为面试表达

Career Deck 提供的追问不是标准答案库,而是提醒毕业生从自己的项目出发回答:
- 为什么局部 UI 状态使用
@State,而不是把所有数据丢入AppStorage? - 大模型返回 Markdown 包裹、缺字段或半截 JSON 时,页面如何不白屏?
- 手机、平板、PC 为什么不能只把字体和卡片放大?
三题分别对应状态边界、AI 可靠性和全场景产品设计。能解释这三类选择,说明开发者不仅会搭界面,还知道业务数据、工程约束与用户体验如何互相影响。
十一、从 6.0 到 6.1:适配不只是改版本号
升级时建议按四个维度检查:
- 窗口:状态栏颜色、导航手势区、横竖屏、窗口缩放;
- 组件:当前 SDK 是否支持链式属性,避免凭经验使用过期 API;
- 布局:固定元素是否遮挡滚动内容,宽屏是否真正重新组织信息;
- 服务:模型密钥是否隔离、异常是否有降级、输出是否有 Schema。
每次构建失败先看第一条错误,定位对应代码后做最小修复。不要为了“编过”而使用 any、关闭类型规则或删除业务字段。毕业生项目最能说明工程能力的,往往正是这种从错误到修复再到验证的过程。
十二、构建与验证
cd career-deck-demo
unset NODE_OPTIONS
export DEVECO_SDK_HOME="/Applications/DevEco-Studio.app/Contents/sdk"
export JAVA_HOME="/Applications/DevEco-Studio.app/Contents/jbr/Contents/Home"
/Applications/DevEco-Studio.app/Contents/tools/node/bin/node \
/Applications/DevEco-Studio.app/Contents/tools/hvigor/bin/hvigorw.js \
--mode module -p module=entry@default -p product=default \
-p requiredDeviceType=phone assembleHap
产物:
career-deck-demo/entry/build/default/outputs/default/entry-default-unsigned.hap
验证清单应包括:三个 Tab 切换、任务完成状态、岗位高亮、AI 防重复点击、滚动底部可达性、系统栏视觉连续性,以及在更宽窗口下是否能自然扩展为双列和三栏。若安装提示 install sign info inconsistent,通常是模拟器存在同包名不同签名的旧包,属于部署环境问题,应卸载旧包或统一签名,不是业务代码错误。
结语:让同一份努力在不同设备上继续
Career Deck 的核心不是“做一个求职 App”,而是验证一个全场景原则:共享的应该是业务状态,不应该是固定 UI。手机帮用户完成下一步,平板帮助用户看清流程,PC 帮用户处理复杂上下文;ArkTS 让岗位、任务和项目有稳定类型,ArkUI 让状态变化自然反映在界面上,HarmonyOS 的一多能力让这条求职任务不必在设备切换时中断。
对毕业生来说,这个项目也可以成为一段完整的成长叙事:从自身求职痛点出发,定义岗位模型,设计不同设备角色,处理窗口和安全区,完成 AI 输出边界,并通过构建和设备验证交付可运行作品。
从毕业设计到鸿蒙开发者,关键不是做出更多页面,而是学会把真实问题拆成稳定的数据、清晰的状态、适合场景的界面和可验证的工程结果。
项目亮点
- HarmonyOS 6.1 + ArkTS + ArkUI;
- 手机行动流、平板流程看板、PC 三栏指挥台的一多设计;
- 岗位—能力—作品—行动的毕业生求职闭环;
- 状态驱动任务完成、岗位选择和 AI 生成交互;
- 沉浸式窗口与固定导航内容安全区适配;
- AI 面试教练的结构化输出、服务端密钥隔离与异常降级方案;
- 6 张运行截图已上传华为云 OBS 并直接嵌入本文。
十三、把一多布局落到代码:从“同一列卡片”到“同一状态的不同容器”
本文前面反复强调手机、平板、PC 不应复制同一个界面。这个结论必须落到代码设计,否则所谓“一屏多态”仍会停留在概念图。
在 Career Deck 中,第一步不是写三个页面,而是保证所有设备都能围绕同一个选择状态工作:
@State selectedJob: number = 0;
private currentJob(): JobApplication {
return JOBS[this.selectedJob];
}
手机端可以把 currentJob() 只用于“下一场面试”卡;平板端可以在岗位列表右侧展示详情;PC 端可把它同时提供给详情栏、作品栏和 AI 问答栏。数据选择只发生一次,呈现容器根据宽度变化。
一个推荐的布局分级策略是:
phone < 600vp:单列,优先行动
medium 600vp~840vp:双列,列表与详情并存
large ≥ 840vp:三栏,列表/详情/教练同时存在
具体的阈值应根据实际窗口和内容密度调整,不应该被当成绝对标准。关键在于每个区间有不同的信息优先级:
| 宽度 | 主任务 | 核心容器 | 应避免的问题 |
|---|---|---|---|
| 窄屏 | 完成下一步 | 单列 Scroll | 卡片横向挤压、文字缩小到不可读 |
| 中屏 | 对比多个岗位 | Grid 双列 | 右侧详情仍依赖页面跳转 |
| 宽屏 | 深度准备某个岗位 | Row 三栏 | 单列无限拉宽、空白过多 |
假设将进度页拆成 JobListPane、JobDetailPane、CoachPane 三个组件,宽屏可以使用:
Row() {
JobListPane({ selectedJob: $selectedJob })
.layoutWeight(3)
JobDetailPane({ job: this.currentJob() })
.layoutWeight(4)
CoachPane({ job: this.currentJob() })
.layoutWeight(3)
}
.width('100%')
.height('100%')
中屏可保留前两栏,教练内容以抽屉或详情底部卡片呈现;窄屏则让用户通过底部 Tab 在行动、进度和教练之间切换。注意:这里被复用的是 selectedJob 和领域模型,而不是某个固定宽度的 UI。这种结构才允许应用随着设备扩展而不造成业务逻辑复制。
13.1 为什么不能靠缩小字体解决窄屏
初学者处理小屏时,常见做法是把字号、间距、卡片宽度统统缩小。但求职场景中,岗位名称、截止时间、面试准备主题都属于高价值信息,缩小到难以扫读会直接降低效率。
更好的顺序是:
- 先减少同时出现的信息;
- 再改变内容排列方式;
- 最后才调整字号和间距。
例如 PC 端同时显示“关联作品”“高频追问”“准备计划”是合理的;手机端只显示一条“重点准备:ArkTS 状态管理、结构化输出、项目复盘”更符合使用情境。信息被折叠,不代表信息被删除,它只是被放在更合适的入口里。
13.2 为什么不能靠拉宽卡片解决宽屏
反过来,宽屏常见问题是单列卡片被拉到整屏,文字每行过长,视线需要横跨很大距离。PC 端应该增加并行任务区,而不是增加每张卡的长度。Career Deck 的三栏结构能让用户把注意力稳定在当前岗位上下文中:左边选岗位,中间读详情,右边准备问题。它比“页面更宽”更接近工作台体验。
十四、作品证据库:毕业生最需要的不是更多项目,而是更可解释的项目
在求职中,“我做过项目”几乎没有信息量。面试官真正想知道的是:项目解决了什么问题?你负责什么?技术选择是什么?遇到异常如何处理?最后如何验证?
因此 Career Deck 中的 project 字段不是一个展示名称,而是岗位与能力证据之间的连接点。下一步可以把它扩展为:
interface ProjectProof {
id: string;
name: string;
scenario: string;
skills: string[];
highlights: string[];
screenshots: string[];
articleUrl?: string;
repositoryUrl?: string;
interviewStories: InterviewStory[];
}
interface InterviewStory {
question: string;
situation: string;
decision: string;
result: string;
}
以“AI 智能菜谱”为例,作品证据不该只写“接入大模型生成菜谱”,而应拆为:
场景:用户输入冰箱食材,生成可执行菜谱。
问题:模型自由文本不能稳定渲染为原生卡片。
决策:定义 recipes JSON 契约,在端侧完成提取、解析、默认值与异常提示。
结果:页面可展示用料、步骤、采购清单;异常输出不会导致白屏。
以“技能成长地图”为例:
场景:毕业生不知道当前短板和每日行动。
问题:任务、能力进度、AI 计划需要同步刷新。
决策:使用 @State 作为当前页面状态源,按 Builder 拆分成长卡、任务、星图与计划。
结果:任务完成后,视觉状态和统计数据一致更新;后续可抽离为持久化 Store。
以“跨屏演讲台”为例:
场景:演讲者需要手机提词和大屏展示。
问题:不同设备不应展示相同界面,而要围绕同一演讲状态协同。
决策:抽象当前页、计时状态和讲稿内容;手机承担控制,大屏承担展示。
结果:设备角色清晰,跨端协同有明确的状态边界。
当 Career Deck 在电脑端打开一个岗位时,可以根据岗位技能标签自动推荐上述故事。这样“作品库”不再只是收藏夹,而变成面试前的证据检索系统。
十五、AI 规划的提示词、Schema 与降级:为什么必须把模型当成不可信输入
大模型适合将职位描述、项目摘要和能力缺口归纳成准备建议,但它不保证每次都严格遵守格式。可能返回 Markdown 代码块、在 JSON 前后附带解释、漏掉字段,或者在网络异常时根本没有内容。
因此,真实接入应有四层防线:
提示词约束
↓
服务端 Schema 校验
↓
端侧类型映射与默认值
↓
可理解的失败反馈与本地降级
15.1 提示词只负责减少不确定性
服务端可要求模型只返回 JSON,并给出字段样例:
你是一名 HarmonyOS 面试教练。
根据岗位、项目和可用时间生成准备计划。
必须只返回 JSON,不输出 Markdown。
每项 action 必须包含 minutes、task、output。
question 必须关联已提供的项目事实,不能编造经历。
提示词不是安全机制,也不是解析机制。它只能让模型更可能遵守契约。
15.2 服务端负责强校验
服务端在转发给客户端前,应验证:
priority是否在允许枚举内;actions是否为数组,数量是否合理;- 每项
minutes是否为正整数且不超过用户可用时间; task和question是否为空;- 返回内容是否包含敏感或不当建议。
验证失败时,服务端可以重试一次、使用规则模板生成基础建议,或返回明确错误码。不要把无法解析的模型原文直接塞给 App。
15.3 端侧继续做最后一道防护
即使服务端已校验,端侧仍需要处理网络超时、空响应和版本不兼容。推荐定义:
interface CoachAction {
minutes: number;
task: string;
output: string;
}
interface CoachPlan {
priority: 'low' | 'medium' | 'high';
summary: string;
actions: CoachAction[];
questions: string[];
}
解析后再映射到 UI。summary 缺失时显示默认说明;actions 为空时显示本地任务模板;请求失败时保留上一份计划,而不是清空整个页面。
15.4 本地规则是合理降级,不是“假 AI”
Career Deck 当前的本地模拟建议,本质上是产品原型阶段的降级策略。规则可以根据 stage、deadline、match 与项目标签先给出稳定建议:
如果 stage=interview 且 deadline<24h:
优先展示项目追问、两分钟自我介绍和技术复盘。
如果 match<70:
优先展示待补能力和关联练习。
如果 stage=written:
展示笔试时间、算法/基础复习任务。
即使模型服务暂时不可用,用户仍能得到基本行动方案。可靠的 AI 应用不是“必须联网才有功能”,而是“联网时更个性化,离线时仍然可用”。
十六、毕业生如何用这个项目讲述自己的 HarmonyOS 成长
一篇技术文章和一个应用最终都要回到“我从中学到了什么”。Career Deck 适合从四个层次讲述:
16.1 从真实问题开始
不是为了练习 TabBar 而做三栏页面,而是发现求职信息分散、项目难以复用、不同设备上的任务不同,于是设计一套求职作战舱。
16.2 用数据模型控制复杂度
用 JobApplication 将岗位、阶段、匹配度、截止时间、关联项目收敛为稳定对象,让多页面和多设备能够围绕同一事实工作。
16.3 用声明式状态完成可验证交互
@State 管理任务完成、岗位选择、AI 生成状态,避免直接操作视图;任务点击、岗位高亮、生成按钮防抖都有可运行结果。
16.4 用一多思路而不是“多写几套 UI”做适配
手机突出行动,平板突出流程,PC 突出上下文;共享状态而非复制页面。即使当前主要在手机模拟器验证,工程设计已经为平板与 2in1 的布局演进保留了边界。
这些内容比“我用了某某组件”更接近面试中的工程表达。毕业生可以用 STAR 或问题—方案—结果结构,清晰说明自己的贡献。
十七、测试策略:不同设备不是只换一张截图
要证明一多体验可用,至少应定义一组跨形态测试场景:
| 场景 | 手机 | 平板 | PC/2in1 |
|---|---|---|---|
| 打开应用 | 关键行动是否一屏可读 | 看板和详情是否有合理层级 | 三栏是否有稳定初始选中项 |
| 选择岗位 | 高亮、行动建议是否联动 | 右侧详情是否同步 | 中/右栏是否同时更新 |
| 完成任务 | 对勾、XP、Toast 是否刷新 | 统计卡是否联动 | AI 建议是否可读取新进度 |
| AI 生成 | 是否防重复点击 | 结果是否不挤压列表 | 是否可同时查看项目追问 |
| 滚动尾部 | 是否被底栏遮挡 | 双列高度是否一致 | 独立栏是否可滚动 |
| 系统窗口 | 系统栏是否连续 | 分屏后文字是否溢出 | 改变窗口宽度是否切换布局 |
模拟器能够完成基础布局与交互验证,但对真实多端协同、输入方式、设备性能仍需要云调试或真机补充。文章中应该诚实区分“已在模拟器验证”和“已为多端设计预留架构”,不要把尚未验证的能力说成已完成事实。
十八、总结:一屏多态的真正含义
Career Deck 的“一屏多态”不是视觉特效,而是一套设计顺序:
先明确同一个任务的业务状态
↓
再定义不同设备承担的角色
↓
最后让布局随设备能力改变
对求职场景而言,手机是行动入口,平板是流程看板,电脑是指挥台;对工程而言,ArkTS 类型是数据边界,ArkUI 状态是更新边界,服务端 Schema 是 AI 边界,窗口和安全区是体验边界。
毕业季会结束,但这种能力会继续使用:把真实问题转化成清晰模型,把模型转化成可运行界面,把界面放到正确设备和正确场景中,再用构建、诊断和测试证明它能工作。这正是从学生走向 HarmonyOS 开发者时最值得积累的能力。
十九、补充:从原型代码到可维护工程的拆分路线
当前 career-deck-demo 为了快速验证交互和视觉,将主页面集中在 IndexPage.ets 中。这种做法适合第一阶段:可以迅速确认任务流、卡片层级、底栏切换与 AI 建议是否合理。但当需求增长到持久化、真实网络、多端分栏和作品库时,应及时按职责拆分。
推荐的演进目录如下:
entry/src/main/ets/
├── common/
│ ├── Theme.ets 色彩、间距、断点与设计令牌
│ └── WindowClass.ets 窗口等级判断
├── model/
│ ├── JobApplication.ets 岗位、阶段、匹配度模型
│ ├── ProjectProof.ets 项目证据模型
│ └── CoachPlan.ets AI 计划模型
├── store/
│ └── CareerStore.ets 岗位、任务、选中态与持久化
├── service/
│ ├── CareerApi.ets 服务端请求
│ └── CoachService.ets AI 计划请求与解析
├── components/
│ ├── JobCard.ets
│ ├── InterviewCard.ets
│ ├── ActionTask.ets
│ └── CoachQuestion.ets
└── pages/
├── PhoneHome.ets
├── TabletBoard.ets
└── DesktopDeck.ets
拆分的目的不是让文件变多,而是明确谁负责什么:
model不依赖 UI,只描述业务事实;store负责状态更新、持久化和跨视图共享;service负责不可信网络与 AI 响应;components只接收明确输入、发出明确事件;pages根据设备形态组合组件。
这种结构会让“手机、平板、PC 三端不同布局”变成页面组合层的变化,而不会侵入网络解析和业务规则。对于毕业生项目,这也是从“一个能跑的作业”升级为“一个可以继续开发的工程”的关键一步。
二十、性能与体验:求职工具不需要炫技,但需要稳定
Career Deck 的视觉采用深色渐变、彩色状态卡和固定导航。它不是动画密集型应用,但仍然要注意性能和体验的基本原则。
20.1 列表项不要在 build 中做重计算
岗位匹配度、状态颜色、推荐项目等应在数据层或计算属性中提前处理。若每次状态刷新都在 ForEach 内执行复杂字符串处理、网络请求或深层数组过滤,岗位列表增多后会出现滚动卡顿。
20.2 长列表要考虑虚拟化与分页
Demo 只有三条岗位,ForEach 完全足够。真实求职记录可能有几十甚至上百条,应根据 ArkUI 当前版本能力选择合适的列表组件、分页或按阶段加载,避免一次渲染全部历史记录。
20.3 颜色不应成为唯一状态表达
当前卡片通过颜色突出岗位阶段和选中状态,但不能只依赖颜色。文本“笔试中”“一面准备”、图标、进度和布局同样需要表达状态。这对色觉差异用户、强光环境和电脑端远距离浏览都更友好。
20.4 空状态、失败状态和权限状态同样属于设计
真实服务接入后,至少需要补齐:
- 暂无岗位:引导用户新增第一条投递;
- 网络失败:保留缓存内容并提示刷新;
- AI 服务不可用:显示规则推荐任务;
- 通知权限未授予:解释开启面试提醒的价值;
- 到期岗位:提示归档、复盘或更新状态。
这些状态通常不会出现在精美截图里,却决定应用是否真的能长期使用。
二十一、构建报错与升级踩坑:把“修错”也变成项目成果
HarmonyOS 开发中,经常会遇到看起来和业务无关的构建问题:SDK 环境变量不正确、JDK 路径缺失、NODE_OPTIONS 污染构建、组件属性与当前 API 不匹配、已安装应用签名不一致等。
这些问题不应被视为“无关紧要的环境麻烦”。对于毕业生而言,能够定位并解释它们,也是工程能力的一部分。
21.1 SDK 与 JDK 环境
命令行构建必须确保 SDK、JDK 和 Hvigor 来自匹配的 DevEco Studio 环境。若 DEVECO_SDK_HOME 指向不完整 SDK,常会出现“SDK component missing”一类配置错误;若 Java 不可用,Hvigor 脚本也无法正常运行。
21.2 严格 ArkTS 约束
ArkTS 的价值在于将很多潜在运行时问题提前暴露。面对对象字面量、未知网络响应和动态字段时,不要用 any 一把梭;应补齐 interface,明确可空字段,逐层做转换。这样 AI 教练服务返回异常时,端侧不会因为一段未检查的数据而白屏。
21.3 HAP 签名不一致
若模拟器已有相同包名、不同签名的旧应用,安装会报:
install sign info inconsistent
解决方式通常是卸载模拟器中旧包,再安装当前构建产物,或保持签名配置一致。它不是页面代码错误,也不应通过修改包名来“掩盖”问题。理解安装、签名与部署链路,是将项目真正交付到设备上的必要能力。
21.4 旧 API 与新环境
在升级或复制工程时,应注意某些路由、窗口或组件 API 可能出现弃用提示。正确做法不是忽略所有警告,也不是立即大规模替换,而是确认当前 SDK 文档、定位实际使用场景、完成最小可验证迁移。每次升级都应该留下变更记录:改了什么、为什么改、如何验证。
二十二、发布前的最终清单
如果将 Career Deck 作为毕业设计、创新赛或作品集项目提交,建议在发布前逐项检查。
业务与数据
- 岗位阶段有统一枚举,不使用散落文本;
- 截止日期统一为时间戳或标准日期格式;
- 匹配度可解释,有能力缺口说明;
- 作品证据包含问题、方案、结果与链接;
- 任务完成状态可持久化、可恢复。
UI 与多端
- 手机端十秒内能找到下一步行动;
- 平板端能同时看岗位列表和详情;
- PC 端能并行处理岗位、项目和追问;
- 固定导航不遮挡滚动内容;
- 系统栏颜色与页面主题一致;
- 文字、颜色、触控区域满足基本可读性。
AI 与安全
- API Key 不在客户端;
- AI 输出有 Schema 和服务端校验;
- 端侧处理超时、空响应、畸形 JSON;
- AI 不对用户就业结果做确定性承诺;
- 用户简历、项目与投递信息最小化收集。
工程与交付
- ArkTS 诊断无新增错误;
- Hvigor 构建成功;
- HAP 安装到模拟器或设备;
- 关键交互完成回归验证;
- README 说明构建方式、运行环境与已知限制;
- 截图、文章和代码中的项目名称、包名一致。
这份清单本身也是毕业生项目可以展示的“工程化证据”。它说明开发者知道一个 App 的完成,不是停在页面展示,而是包括数据边界、体验边界、安全边界和交付边界。

二十三、最终复盘:为什么是 Career Deck
我选择求职作战舱作为 HarmonyOS 6.1 一多适配案例,是因为它天然包含三个设备都合理存在的场景:
- 手机:随时提醒、轻量完成、面试路上复习;
- 平板:流程整理、双列浏览、触控查看项目;
- PC:简历编辑、岗位对比、项目复盘、AI 问答准备。
它也天然包含毕业生最需要建立的四种能力:
- 把个人问题抽象为产品需求;
- 把需求沉淀为类型模型和状态流;
- 把同一任务针对不同设备设计不同体验;
- 把 AI 放进受控、可解释、可降级的工程体系。
因此,Career Deck 不是一个简单的“求职工具”,而是一份关于鸿蒙全场景开发的实践记录。它提醒我:设备越多,越不能先想“页面怎么铺”;AI 越强,越不能先想“让它生成什么”。真正应先确定的,是用户在此刻要完成什么任务、数据由谁负责、失败时如何退化、换到另一台设备后如何继续。
如果这份项目最终能够帮助一名毕业生在面试前更从容地讲清自己的作品,那么它的价值就不只是一套漂亮界面;如果它也能帮助开发者理解“一次开发、多端部署”应如何从状态和任务开始设计,那么这次 HarmonyOS 6.1 实战就完成了最初的目标。
更多推荐

所有评论(0)