ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

【中国方言题库|01】HarmonyOS ArkTS 方言题库首页实战:组织地区入口、推荐内容和学习进度

【中国方言题库|01】HarmonyOS ArkTS 方言题库首页实战:组织地区入口、推荐内容和学习进度 摘要题库应用的首页不是把所有功能堆在一屏而是要回答三个问题用户上次学到哪里、现在最值得做什么、怎样用最短路径进入目标题库。本文基于“中国方言题库”真实 ArkTS 源码拆解HomePage、Index、MockBanks与BankCard的协作方式展示如何用 ArkUI 组织六个地区题库、七类题型、本地学习统计、快速入口以及 phone、tablet、2in1 的断点布局。所有题量和学习进度都来自当前题库与本地记录不虚构在线热度、排行榜或云端推荐。一、首页的目标不是“内容多”而是降低下一步决策成本中国方言题库当前包名为com.example.one11版本配置为1.0.2模块声明支持phone、tablet和2in1。应用首页面对的不是普通资讯浏览而是反复学习场景新用户需要快速理解题库覆盖范围老用户需要马上看到自己的进度明确下一次点击。源码中的首页按以下顺序组织品牌与搜索 - 今日练习概览 - 继续练习与快速操作 - 题型分类 - 推荐题库这个顺序有明确的信息优先级。标题负责建立产品身份Hero 区给出题量和用户状态快速操作把“继续学习”放到最短路径分类适合按题型探索推荐题库则按地区提供完整入口。用户不必先理解应用所有页面就能开始一次答题。本文的唯一标记是首页统计必须由本地学习记录实时推导。题量、已答、正确率、考试次数和收藏数都应能回到实际数据源不能用装饰性数字填满界面。二、主导航先解决跨设备结构Index.ets定义五个主入口private tabs: TabItem[] [ { title: 首页, iconNormal: $r(app.media.ic_tab_home), iconSelected: $r(app.media.ic_tab_home_selected) }, { title: 题库, iconNormal: $r(app.media.ic_tab_bank), iconSelected: $r(app.media.ic_tab_bank_selected) }, { title: 报考, iconNormal: $r(app.media.ic_tab_exam), iconSelected: $r(app.media.ic_tab_exam_selected) }, { title: 收藏, iconNormal: $r(app.media.ic_tab_favorite), iconSelected: $r(app.media.ic_tab_favorite_selected) }, { title: 我的, iconNormal: $r(app.media.ic_tab_mine), iconSelected: $r(app.media.ic_tab_mine_selected) } ]当前选中项通过StorageLink(currentTabIndex)共享。首页中的“更多”“继续练习”“错题复习”等入口可以直接切换主 Tab而搜索、分类等二级功能使用router.pushUrl()进入独立页面。这形成两个清晰层级主功能切换修改currentTabIndex不增加页面栈。二级任务使用 Router 跳转支持系统返回。在窄窗口中Index使用底部导航在更宽断点中改为左侧导航栏。底部导航高度并非写死在系统手势区上方而是读取navigationIndicatorHeightPx经过px2vp()转换后与最小安全距离取最大值private bottomSafePadding(): number { return Math.max( Sizes.BOTTOM_NAV_MIN_PADDING, this.getUIContext().px2vp(this.navigationIndicatorHeightPx) ) }这种做法比固定增加一段 padding 更可靠因为不同设备、导航模式和窗口状态的避让高度可能不同。三、首页状态只连接“需要显示的数据”HomePage通过StorageLink订阅四类学习记录StorageLink(bankProgress) progressList: BankProgress[] [] StorageLink(examHistory) examHistory: ExamHistory[] [] StorageLink(favoriteRecords) favRecords: FavoriteRecord[] [] StorageLink(wrongRecords) wrongRecords: WrongRecord[] []首页没有直接操作 Preferences也没有自己解析数据库文件而是把已有状态交给StatService.summarize()private myStats() { return StatService.summarize( this.progressList, this.examHistory, this.favRecords, this.wrongRecords ) }这条边界很重要。页面负责展示统计规则应在服务层持久化读取应在数据管理层。否则每个页面都各自计算正确率很容易出现首页、题库详情和“我的”页面数字不一致。对于 ArkUI 状态还要注意数组更新方式。如果服务只是修改原数组中对象的字段却没有触发可观察状态更新页面可能不会刷新。稳妥做法是在数据服务完成写入后以明确的新数组或统一状态发布方式更新 AppStorage让 Hero、题库卡片和徽标一起变化。四、题库目录来自真实题目集合MockBanks.ets中定义六个地区export const REGIONS: Region[] [ { id: sichuan, name: 四川话, shortName: 川, cover: $r(app.media.img_bank_cover_sichuan) }, { id: yue, name: 粤语, shortName: 粤, cover: $r(app.media.img_bank_cover_yue) }, { id: northeast, name: 东北话, shortName: 东, cover: $r(app.media.img_bank_cover_northeast) }, { id: shanghai, name: 上海话, shortName: 沪, cover: $r(app.media.img_bank_cover_shanghai) }, { id: minnan, name: 闽南语, shortName: 闽, cover: $r(app.media.img_bank_cover_minnan) }, { id: hakka, name: 客家话, shortName: 客, cover: $r(app.media.img_bank_cover_hakka) } ]题型包含词汇、看义猜词、方言差异、情景对话、方言文化、俗语歇后语和地区特色。源码不是把目录卡片上的题量永久写成一个常数而是在syncCatalogCounts()中从题目集合回填每个题库、章节和分类的数量。function syncCatalogCounts(): void { const categoryCounts: Mapstring, number new Mapstring, number() for (const bank of BANKS) { const questions getQuestions(bank.id) bank.totalCount questions.length for (const chapter of bank.chapters) { chapter.total questions.filter( (question: Question) question.chapterId chapter.id ).length } for (const question of questions) { categoryCounts.set( question.type, (categoryCounts.get(question.type) || 0) 1 ) } } }由此导出的TOTAL_QUESTIONS和TOTAL_REGIONS才能用于首页 Hero。题库内容调整后首页总量会跟随变化避免“介绍写 1500 题实际包内只有另一数量”的审核风险。源码还对题干去重并把已经下线的听音题重新归类为词汇题而不是直接丢弃。这说明首页分类数字必须在转换与去重之后计算不能拿原始素材条数当作用户真正能答的题量。五、Hero 区展示目录规模与个人状态首页 Hero 由两类信息组成目录事实总题量与覆盖地区数。用户事实已答题数、正确率、考试次数和收藏数。Text(${TOTAL_QUESTIONS.toLocaleString()} 题) Text(覆盖 ${TOTAL_REGIONS} 个地区方言) this.HeroStat(${this.myStats().totalAnswered}, 已答) this.HeroStat(${this.myStats().accuracyPercent}%, 正确率) this.HeroStat(${this.myStats().examCount}, 考试) this.HeroStat(${this.myStats().favoriteCount}, 收藏)这里没有把“热门度”当成学习成果也没有写一个静态正确率。新用户没有记录时应自然显示 0而不是用样例数据制造“应用很活跃”的错觉。若正确率分母为 0统计服务应返回 0不能出现NaN%。Hero 的地图图片使用固定视觉尺寸并配合objectFit(ImageFit.Cover)文字区域则由Blank()分隔。适配时要特别测试系统字体放大因为 32vp 的题量和右侧 108vp 图片在窄屏上可能竞争空间。若长数字或本地化文案导致拥挤可以让图片缩小、限制文字行数或在极窄宽度切换为上下结构。六、快速操作要对应真实可达路径首页的主行动“继续练习”通过切换到题库 Tab 实现.onClick(() { this.currentTabIndex 1 })第二行提供“真实题量计时测试”和“错题复习”。错题复习会同时设置收藏页内部 Tabthis.favoriteTabIndex 2 this.currentTabIndex 3这种联动很适合主导航内的跨模块入口但必须保证目标页面也使用同一个StorageLink(favoriteTabIndex)否则首页写入了状态收藏页却仍停留在默认分栏。回归测试至少覆盖无错题时点击“错题复习”出现明确空态。有错题时进入收藏页的错题分栏。从错题页返回首页后主导航状态正确。连续快速点击不会叠加路由或丢失选中状态。“继续练习”当前只是进入题库列表并没有读取最近一次题库直接恢复章节因此文案使用“从热门题库开始”是合理的。如果未来要真正实现续学应保存最近题库和章节 ID并在目标不存在时降级到题库列表不能只把按钮改名为“继续上次”。七、分类入口使用可复核的参数契约首页显示七个题型和一个“查看全部”每个分类通过 Router 传递类型与名称router.pushUrl({ url: pages/SearchPage, params: { categoryType: cat.type, categoryName: cat.name } })这里的契约是categoryType用于筛选categoryName用于展示。目标页应对参数缺失、未知类型和旧版本书签做兜底。如果直接断言参数一定存在外部恢复页面或路由重建时可能白屏。分类项宽度为23%四列换行并设置单行省略。它能在常见手机宽度上形成规整网格但“俗语歇后语”这类长名称可能被省略。省略虽然避免布局破坏却可能降低可辨认性。可选改进包括允许两行并给容器稳定高度。使用更短但准确的显示名。在平板宽度下增加列数或提升项目宽度。为图标提供明确的无障碍描述。不要通过把字体缩到不可读来维持四列。AppGallery 的正文和关键文字对比、字号与可触达性比“每行必须四个”更重要。八、推荐题库不是网络推荐算法首页“推荐题库”实际遍历本地BANKSForEach(BANKS, (bank: Bank) { BankCard({ bank: bank }) }, (bank: Bank) bank.id)因此这里的“推荐”含义是产品预设的地区入口而不是基于账号画像、云端行为或全网热度的个性化推荐。商店介绍和隐私政策不应把它描述成 AI 推荐。题库模型中有hot字段卡片将数值叠加到封面左下角。但当前源码没有证明它来自在线访问统计。更稳妥的产品处理有两种把字段明确解释为编辑排序权重不向用户展示成真实热度。若要展示“热度”说明它是本地预设推荐指数而非实时用户数。最不应做的是把 98、95 等静态值写成“98 万人在学”。任何用户量、下载量、排名或趋势都需要真实平台数据。九、BankCard 将题库事实和用户进度合并BankCard同时显示题库封面、题量、正确率、已答数量和进度条。它不是直接采用题库模型里的默认准确率而是优先读取用户真实进度private realAccuracy(): number { const p UserDataManager.getProgress(this.progressList, this.bank.id) if (p p.finished 0) return p.correct / p.finished return this.bank.accuracy } private progressRatio(): number { if (this.bank.totalCount 0) return 0 return Math.min(this.realFinished() / this.bank.totalCount, 1) }这里有两个细节值得保留分母为 0 时返回 0避免异常值。使用Math.min(..., 1)避免题库调整后旧进度超过新题量导致进度条溢出。还可以进一步处理下限若损坏数据出现负数建议把比例限制在[0, 1]。正确率也应验证correct finished数据修复应在服务层完成而不是让每张卡片各自猜测。十、卡片按自身宽度切换而不是只看设备名题库卡片通过onAreaChange记录实际宽度State cardWidth: number 360 private useCompactLayout(): boolean { return this.cardWidth 0 this.cardWidth 280 }宽度小于 280vp 时使用纵向紧凑卡片否则使用横向卡片。这个策略比“平板永远横向、手机永远纵向”更适合多窗口同一台 2in1 设备在窄窗口和宽窗口中可以采用不同卡片。首页的推荐区也根据断点和页面实际宽度决定布局private useGridLayout(): boolean { return this.currentBp lg this.pageWidth 700 }宽布局中每张卡片占32%形成三列其他情况使用单列。这是“页面决定列数、卡片决定内部形态”的两级自适应页面容器决定一行放几张。卡片根据自己得到的宽度决定横向或紧凑布局。这种职责分配可复用性更高。BankCard 不必知道自己位于首页、搜索结果还是收藏页只需要响应可用空间。十一、为何首页末尾仍保留 92vp 空白HomePage的内容末尾有Blank().height(92)这是为了让最后一张题库卡片在底部导航上方仍能滚动到可见位置。但固定 92vp 与Index中动态计算的导航安全高度存在潜在重复如果手势区更高空白可能仍不足如果侧边导航模式没有底部栏空白又显得过多。更一致的方案是把底部内容 inset 作为共享状态或布局参数传给页面Scroll() { // content } .contentEndOffset(this.bottomContentInset)具体 API 需按项目 SDK 可用性选取也可以让 Index 的内容容器统一留出空间。关键是底部导航与页面末尾不要分别维护两个互不相干的常数。十二、搜索入口要保持功能边界清楚Header 右侧搜索按钮进入pages/SearchPage。搜索属于二级任务因此使用路由而不是主 Tab。按钮当前用Stack包裹图片并提供 46vp 的触控区域满足常用触控尺寸。发布前还应验证搜索图标在浅色和深色背景下有足够对比。无输入时有推荐或历史而不是空白页。不存在匹配项时显示明确空态。输入法弹出后搜索结果和返回按钮仍可触达。从分类入口进入时标题和筛选条件正确。如果搜索仅针对本地题库就不应因为模块声明了INTERNET而偷偷改成在线联想网络权限的实际用途必须单独从源码核实并在隐私材料中准确说明。十三、性能重点不是“少写组件”而是控制重复计算首页每次重建都会调用myStats()多次推荐卡片也会查找对应进度。当前数据规模不大但随着题库和历史增长重复遍历可能影响滑动和状态更新。可以从三个方向优化在服务层把进度数组转换为按bankId索引的 Map。在学习记录变化时计算一次首页统计快照。题库目录计数只在题库初始化或内容变更时同步不在每个卡片构建周期重复扫描。优化前要用真实测量判断瓶颈。不要为了六个题库引入复杂缓存框架也不要把所有状态塞进全局单例。首页真正需要的是稳定的统计快照与低成本查找。十四、状态、空态和异常态都要能解释首页正常态很完整但工程交付还应显式覆盖状态页面表现首次启动统计全部为 0推荐题库仍可进入无收藏/错题对应计数为 0点击后显示空态题库为空总题量为 0练习入口禁用或说明原因本地数据损坏使用安全默认值并记录诊断信息路由参数错误回退到题库列表不白屏图片资源失败保持卡片尺寸显示替代背景当前目录内容来自包内数据不需要把题库加载包装成虚假的网络 Loading。若初始化确实有异步 Preferences 恢复可以在首屏使用稳定骨架或延迟展示个人统计但地区入口不必等待用户数据后才能出现。十五、无障碍和国际化不能最后补方言学习应用包含大量具有文化语境的文本。首页至少要为搜索图标、题库封面和可点击卡片提供可理解的无障碍信息。只显示“川”“粤”等短字时读屏描述应是“四川话题库”“粤语题库”而不是单个字符。虽然当前产品以中文为主也应避免通过字符串拼接破坏后续本地化。例如Text(${TOTAL_QUESTIONS.toLocaleString()} 题)在单一中文版本中可用但更完整的工程可以使用字符串资源和占位符。应用名、模块说明、隐私文案与 AppGallery 素材也应统一引用当前品牌“中国方言题库”。十六、首页测试应围绕数据变化和窗口变化建议把首页回归拆成以下用例数据用例新用户统计为 0。完成一道题后已答和正确率变化。收藏一道题后收藏计数变化。产生错题后主导航徽标与错题入口同步。删除历史后考试次数更新。题库总量变更后总题量和卡片题量一致。交互用例搜索按钮进入搜索页并可返回。每个分类传递正确categoryType。“更多”切换到题库 Tab。“计时测试”切换到报考 Tab。“错题复习”打开收藏页错题分栏。六张题库卡片进入各自详情页。适配用例手机底部导航不进入手势区。平板/2in1 使用侧边导航。700vp 附近窗口缩放时推荐区切换稳定。卡片宽度跨过 280vp 时内部布局不闪烁。系统字体放大后标题、统计和长题型名仍可读。十七、从首页源码能得出的边界结论基于当前真实实现可以准确描述首页覆盖六个地区方言题库。首页提供七类题型入口和全部分类入口。总题量来自去重、归类后的本地题目集合。已答、正确率、考试和收藏来自本地用户记录汇总。推荐题库是本地产品排序不是云端个性化推荐。支持 phone、tablet、2in1并在不同宽度使用底部或侧边导航。题库卡片按实际宽度切换横向与紧凑结构。不能从首页源码直接声称有多少真实在线用户。题库热度是实时平台统计。支持云同步、账号漫游或 AI 推荐。所有声明设备都已经完成真机测试。当前工作区版本已经在 AppGallery 公开。技术文章和上架文案都应守住这条事实边界。十八、总结中国方言题库首页的核心设计不是视觉装饰而是把目录事实、学习状态和下一步行动压缩到一屏Index负责多设备主导航HomePage负责信息顺序MockBanks负责真实目录与题量StatService负责学习汇总BankCard负责题库事实与用户进度的响应式呈现。对于 HarmonyOS 5.0 以上的多设备应用这套结构有三个可复用经验主 Tab 与二级路由分层避免页面栈混乱。页面列数与卡片内部布局分别响应可用空间。所有统计都从真实本地记录推导不用静态数字伪造活跃度。首页不是数据仓库也不是业务规则中心。它应当是一张可靠的学习仪表盘用户看到的每个数字都能解释每个入口都能到达每种窗口都能继续完成核心任务。---AI 辅助声明本文由 AI 辅助整理所有技术结论基于中国方言题库当前可读取的 ArkTS、模块配置、题库目录和组件源码复核未运行的真机测试、平台数据和公开发布状态均未写成已通过。
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表