资讯动态

【中国方言题库|02】HarmonyOS ArkTS 方言详情实战:展示读音、释义、例句和文化背景

发布时间:2026/8/19 22:08:43 来源:尧图企业网站定制
摘要方言题库详情页既要帮助用户理解“这个题库学什么”也要把用户准确送入章节练习、随机练习或模拟考试。本文基于“中国方言题库”当前BankDetailPage.ets真实源码拆解路由参数、地区文化档案、本地学习进度、章节状态、宽屏双栏和底部安全区。需要特别说明当前组件已经展示题库简介、文化提示、重点与常见语境但没有独立渲染词条级读音、释义和例句这些内容只在题目模型及练习链路中出现不能被写成详情页现成功能。词条详情最小实现验收边界词条详情最小实现必须满足结构化字段来自本地内容层文本读音与真实音频分开没有音频资源时隐藏播放按钮例句和文化说明按字段条件渲染大字体与窄屏下内容不截断音频来源可追溯。完成这些检查后读音、释义、例句和文化背景才是可复核的页面能力。二十、把词条详情真正落到 ArkUI 的最小实现针对质量提醒中“词条级功能尚未实现”的缺口可以在不改变现有题库导航契约的前提下新增类型化词条模型。模型包含 id、bankId、expression、pronunciationText、meaning、example、cultureNote 和可选 audioResourceRepository 按 bankId 返回本地词条Service 负责去重、排序与缺失字段清洗页面不再从题干字符串猜测释义。export interface DialectEntry { id: string bankId: string expression: string pronunciationText?: string meaning: string example?: string cultureNote?: string audioResource?: Resource }ArkUI 词条卡片应始终展示表达与释义仅在 pronunciationText 存在时显示文本读音仅在 audioResource 存在时显示播放按钮。例句和文化说明均按可选字段条件渲染避免出现空白占位。播放按钮需要无障碍描述媒体资源在点击时创建并在页面离开时释放。if (entry.audioResource) { Button({ type: ButtonType.Circle }) { Image($r(app.media.ic_audio_play)).width(20).height(20) } .accessibilityText(播放${entry.expression}的方言读音) .onClick(() this.playLocalAudio(entry)) } Text(entry.meaning).fontColor(Colors.TEXT_SECONDARY) if (entry.example) { Text(例句${entry.example}).maxLines(3) }词条区可放在文化档案之后、章节列表之前。条目较多时使用 LazyForEach。没有真实录音时只展示文本读音不能把系统 TTS 标为真人方言音频。验收标准是字段来自结构化数据缺失字段不占空白大字体与窄屏下不截断音频来源可追溯。这样“读音、释义、例句和文化背景”才成为可测试的页面能力而不是产品目标描述。一、先校准标题中的能力边界技术写作最容易出现的问题是根据产品目标描述功能而没有回到组件实际渲染树。本文 brief 的目标是“展示读音、释义、例句和文化背景”但BankDetailPage.ets当前页面真正展示的是题库封面、名称、题量、已答和正确率。题库简介与地区文化提示。“你会练到”和“常见语境”标签。整体学习进度与章节进度。章节练习、随机练习和模拟考试入口。参数无效时的“未找到题库”空态。当前详情组件没有词条列表也没有读音字段、释义卡片和例句卡片。题目数据模型中确实存在stem、analysis、example、audioHint等内容但那不等于它们已经在题库详情页显示。因此本文的唯一标记是页面能力以当前 ArkUI 渲染树为准。下面一方面分析已实现的详情页结构另一方面给出如何在不伪造现状的前提下扩展词条读音、释义和例句。二、一个组件支持两种题库标识来源BankDetailContent提供fixedBankIdexport struct BankDetailContent { fixedBankId: string State bank: Bank | undefined undefined aboutToAppear(): void { if (this.fixedBankId.length 0) { this.bank getBankById(this.fixedBankId) return } const params router.getParams() as BankDetailParams | undefined if (params params.bankId) { this.bank getBankById(params.bankId) } } }这形成两种复用方式通用详情页通过 Router 接收bankId。四川话、粤语等固定页面可以嵌入同一内容组件并传入固定 ID。固定参数优先于路由参数可避免专属页面受到旧路由残留参数影响。组件只保存一个最终bank后续所有 UI 都围绕这个可选值构建。这里仍有一个工程边界router.getParams() as BankDetailParams只是类型断言不会在运行时验证。外部可能传入空字符串、数字或不存在的 ID。当前getBankById()返回undefined页面会进入空态这比强制非空断言更安全。若参数来自跨 Ability、通知或外部 Want应增加显式校验private resolveBankId(): string { const params router.getParams() as Recordstring, Object | undefined const value params ? params[bankId] : undefined return typeof value string ? value : }三、空态是详情页协议的一部分页面顶部始终显示TopBar。未找到题库时标题回退为“题库详情”主体显示空态图片和“未找到题库”if (this.bank undefined) { Column({ space: 12 }) { Image($r(app.media.img_empty_default)) Text(未找到题库) } }这避免了对this.bank!的访问发生在数据缺失分支。不过当前空态只有说明没有“返回题库列表”按钮。用户仍可依赖顶部返回但在深链恢复或页面栈异常时显式动作会更稳妥返回上一页。回到题库列表。若只是数据初始化未完成提供重试。要区分“加载中”和“未找到”。当前题库来自包内同步目录getBankById()是同步查询因此直接进入未找到空态合理如果以后改为异步数据库或网络源就应引入loading/error/empty/content四态不能在请求尚未完成时闪现“未找到”。四、地区档案将内容差异从 UI 树中抽离页面为六个题库配置BankDetailProfileinterface BankDetailProfile { subtitle: string intro: string cultureNote: string focusTags: string[] sceneTags: string[] }Map 按bankId存储地区内容。四川话侧重巴适表达、茶馆与川味生活粤语侧重茶餐厅、通勤与礼貌表达东北话强调语气和生活氛围上海话加入弄堂和海派语境闽南语结合俗语、戏曲与迁徙客家话围绕称谓、家风和土楼。private profile(): BankDetailProfile { const profile BANK_DETAIL_PROFILES.get(this.bankId()) return profile ? profile : DEFAULT_BANK_DETAIL_PROFILE }这种设计优于在每个Builder里写六组if。UI 结构保持一致内容差异集中在档案配置中新增题库时即使暂未补档案也会使用默认内容不至于白屏。但这些文化文本属于编辑内容不是实时数据。发布前要人工校对事实、措辞和地域尊重避免把方言刻板印象写成绝对结论。技术层可以保证字段完整却不能自动保证文化表述准确。五、Hero 将题库身份和真实学习反馈放在一起Hero 使用题库封面作为背景并叠加从透明到黑色的遮罩Image(this.bank!.cover) .width(100%) .height(this.useWideLayout() ? 260 : 210) .objectFit(ImageFit.Cover) Column() {} .linearGradient({ angle: 0, colors: [[#00000000, 0], [#B3000000, 1]] })底部文字包含题库名称、地区副标题和三项标签this.HeroTag(共 ${this.bank!.totalCount} 题) this.HeroTag(已答 ${this.bankFinished()} 题) this.HeroTag(正确率 ${Math.round(this.bankAccuracy() * 100)}%)题量来自当前题库目录已答与正确率来自UserDataManager查询本地进度不是静态示例。无学习记录时正确率回退到题库模型的accuracy而当前目录初始值为 0因此新用户会看到 0%不会凭空出现高正确率。Hero 的三个标签位于普通Row中。窄屏、大字体或总题量位数增加时存在横向拥挤风险。更稳妥的实现可以改为可换行Flex或者将题量保留在首行把学习状态放入下一行。六、学习进度需要统一的分母和上限页面通过以下方法计算整体进度private bankProgressRatio(): number { if (!this.bank || this.bank.totalCount 0) return 0 return Math.min(this.bankFinished() / this.bank.totalCount, 1) }BankSummaryCard同时展示已完成题数 / 总题数。章节数量。完成度百分比。正确率百分比。这个实现处理了总题数为 0 和旧进度超过新题量的情况。为了抵御损坏数据还可以将结果限制在[0, 1]return Math.max( 0, Math.min(this.bankFinished() / this.bank.totalCount, 1) )正确率也应保证finished 0、correct 0且correct finished。这些校验最好由UserDataManager或服务层统一完成避免首页、详情页和结果页各自修复出不同数字。七、简介与文化提示有不同阅读层级ProfileCard把内容分成题库简介和文化提示Text(this.profile().intro) .fontSize(Sizes.BODY_FONT) .lineHeight(22) Column({ space: 8 }) { Text(文化提示) Text(this.profile().cultureNote) } .backgroundColor(Colors.BACKGROUND_ALT)简介回答“学什么”文化提示回答“为什么这些表达有这样的语境”。文化提示使用次级背景和较小文字视觉上不与主要操作竞争。对长文本适配要关注不设置固定卡片高度让内容自然增长。使用合理行高避免密集段落。文化说明不是权威学术结论时避免绝对化词语。后续多语言版本应把文本移入资源或内容层不散落在页面常量中。目前档案文本与代码一起编译。若内容频繁更新可以迁移到结构化本地 JSON但仍应在构建期校验字段和bankId不能临时用无类型对象拼接。八、“本库重点”用标签提高扫描效率FocusCard展示两组标签focusTags高频口头词、听辨节奏、称谓表达等学习重点。sceneTags茶馆聊天、通勤借过、弄堂邻里等常见语境。TagBlock使用可换行 FlexFlex({ wrap: FlexWrap.Wrap }) { ForEach(tags, (tag: string) { Text(tag) .margin({ right: 8, bottom: 8 }) }, (tag: string) tag) }这比固定三列更适合中文长短不一的标签。ForEach 的 key 直接使用标签文本因此同一数组内不能出现重复标签否则组件复用可能异常。内容编辑阶段应做去重或用bankId index生成稳定 key。标签只是信息摘要不应伪装成可点击筛选器。当前没有.onClick()视觉也以浅色背景呈现符合只读标签语义。九、章节列表把进度与动作绑定到同一行章节条目包含序号、标题、已答/总题数、进度条和动作。进度通过题库 ID 与章节 ID 联合查询private chapterFinished(chapter: Chapter): number { const cp UserDataManager.getChapterProgress( this.chapterProgressList, this.bankId(), chapter.id ) return cp ? cp.finished : 0 }动作分为三态状态按钮文字行为未开始开始进入章节练习有进度未完成继续进入章节练习已完成完成只显示完成状态params: { bankId: this.bank.id, chapterId: chapter.id, mode: chapter }“完成”当前不再提供点击动作。若用户希望复习已完成章节这会形成操作阻断。更友好的做法是显示“复习”保留进入练习的能力同时用成功色或图标标识完成状态。章节完成的判断是finished total。如果练习允许重复答题finished的定义必须是“唯一题目已完成数”而不是“累计答题次数”否则重复练同一道题可能让章节提前完成。十、三种练习模式形成清晰路由契约详情页输出三类练习入口// 章节 { bankId, chapterId, mode: chapter } // 随机 { bankId, mode: random } // 模拟考试 { bankId, mode: exam }这比创建三个几乎相同的练习页面更容易维护。PracticePage应根据 mode 构建不同题集和交互规则chapter只选指定章节支持续学。random从题库中随机抽取数量与去重规则明确。exam固定题数或按真实可用题量出卷包含计时与交卷规则。路由参数仍需运行时校验。尤其是chapter模式必须有合法chapterIdrandom和exam不应误用旧的章节参数。目标页应在不合法时给出可解释错误或回退而不是空题集直接进入结果页。十一、底部双按钮必须避开系统导航区底部操作栏使用两个GreenButton并根据系统导航指示区计算底部 paddingprivate bottomSafePadding(): number { return Math.max( Sizes.BOTTOM_NAV_MIN_PADDING, this.getUIContext().px2vp(this.navigationIndicatorHeightPx) ) }.padding({ left: Sizes.PADDING_LARGE, right: Sizes.PADDING_LARGE, top: 10, bottom: this.bottomSafePadding() })这保证“随机练习”和“模拟考试”不会贴到手势区。仍要在以下环境实测三键导航与手势导航。横屏和分屏。平板底部任务栏。2in1 窗口缩放。系统字体放大后按钮文字是否完整。底部栏位于滚动内容外因此始终可操作代价是内容区必须保证最后一个章节能滚到操作栏上方不能被固定栏遮挡。十二、宽屏使用双栏但两栏滚动彼此独立当currentBp lg且页面宽度不小于 700vp详情页切为双栏Row({ space: 20 }) { Scroll() { this.HeroCard() this.BankSummaryCard() this.ProfileCard() } .width(38%) Scroll() { this.FocusCard() this.ChapterSection() } .layoutWeight(1) }左栏承担题库身份与介绍右栏承担学习重点和章节任务。这符合宽屏“概览 工作区”的阅读方式也避免把 Hero 拉伸到过宽。但两个独立 Scroll 会产生交互取舍指针位于哪一栏就只滚动那一栏键盘 PageDown 的焦点也需要验证。若章节很长、左栏很短右栏滚动是合理的若用户更习惯整体页面滚动可以考虑外层单 Scroll、内部 Row 的结构。选择哪一种应通过 2in1 鼠标与触控实测决定。十三、当前页面没有词条级读音、释义和例句这是本文最重要的真实性检查。BankDetailPage.ets的BankDetailProfile没有pronunciation、meaning或example字段渲染树也没有词条卡片。现有文化档案是题库级介绍不是具体词条解释。题目模型中存在可以承载相关内容的字段stem题干或待理解表达。analysis答案解释可作为释义依据。example部分题目的例句。audioHint部分历史听音题的提示文本。但是MockBanks当前将下线的audio题重新归类为vocab并没有证明详情页具备真实音频播放。因此不能把audioHint写成“支持标准读音播放”。若要真正实现标题目标应新增明确模型而不是从题干字符串猜interface DialectEntry { id: string bankId: string expression: string pronunciationText?: string audioResource?: Resource meaning: string example?: string cultureNote?: string sourceNote?: string }然后增加词条区分别处理文本读音、真实音频资源、释义、例句和来源说明。音频不存在时应隐藏播放按钮不能播放 TTS 后宣称是真人方言录音。十四、词条扩展应保持页面性能和可访问性若一次展示大量词条不应把所有音频对象和复杂卡片同时初始化。可以采用默认展示少量精选词条。使用 LazyForEach 或分页加载本地结构化数据。音频仅在点击时创建播放资源。离开页面时释放播放器和监听器。播放按钮提供“播放某词读音”的无障碍描述。文本读音和音频读音明确区分。词条卡片应允许长释义与两行以上例句自然增高避免固定高度截断。对于没有例句的条目整个区块不渲染不要显示“暂无”占据大量视觉空间。十五、文化内容要有来源意识页面的文化提示将语言放回茶馆、早茶、弄堂、歌仔戏、土楼等生活背景这比单纯背词更有记忆点。但方言文化容易涉及地域差异、代际差异和语境礼貌。工程上建议为内容补充interface CultureReference { title: string note: string regionScope: string reviewedAt: string sourceNote?: string }用户界面不一定展示完整引用格式但内容维护端应知道文本由谁审核、适用哪个地区、何时更新。某个表达在熟人玩笑中可用不代表适合正式场合释义页可增加语气和使用场景提示降低误用风险。十六、详情页的状态刷新要覆盖返回场景用户从详情页进入练习完成后返回progressList和chapterProgressList应刷新从而改变Hero 的已答与正确率。整体进度条。完成度和正确率摘要。对应章节的进度、按钮文字和完成状态。因为页面使用StorageLink前提是练习页完成写入后同步更新 AppStorage。如果只写 Preferences 而没有发布新状态返回详情页可能仍显示旧值。测试应覆盖“完成一题后返回”和“完成章节后返回”并验证无需重新启动应用即可更新。另外连续进入练习时要防止重复 push。按钮点击后可以短暂禁用或由统一导航服务处理幂等避免快速双击创建两层相同 PracticePage。十七、异常和边界测试清单参数与目录无bankId时显示空态。未知bankId不崩溃。固定 ID 优先于路由参数。题库没有章节时显示明确空态。题库总题数为 0 时进度为 0。学习状态新用户已答和正确率为 0。finished total时进度不超过 100%。损坏的负数进度被服务层修复。完成章节后按钮状态正确。已完成章节仍有合理复习路径。路由chapter 模式携带合法章节 ID。random 模式不依赖章节参数。exam 模式按真实题量组卷。快速双击不会重复入栈。返回后进度立即更新。多设备700vp 临界宽度切换稳定。双栏内容均可滚动且焦点可控。底部按钮不进入系统手势区。大字体下 Hero 标签和章节标题不重叠。横屏、平板和 2in1 上封面不失真。十八、从当前源码可以准确宣传什么可以准确描述六类地区方言题库拥有不同简介、文化提示和学习语境。页面展示题库总量、已答、正确率、章节数和完成度。章节支持开始或继续练习。支持随机练习与模拟考试入口。宽屏使用概览与章节双栏布局。底部操作根据系统导航区域留出安全距离。无效题库参数进入可解释空态。不能直接描述详情页已经展示每个方言词的读音、释义和例句。存在真人方言音频。文化内容经过某权威机构认证。正确率来自云端或全体用户。“热门”数字是实时使用人数。这些边界应同时约束技术文章、应用介绍、截图文案和审核备注。十九、总结当前BankDetailPage已经是一张完整的“题库理解与练习选择”页面通过bankId找到题库用地区档案补充简介与文化语境用本地状态计算整体与章节进度再把用户送入 chapter、random 或 exam 三种练习模式。宽屏双栏和底部安全区让同一套代码适配 phone、tablet 与 2in1。它尚不是词典式方言详情页。要实现词条级读音、释义、例句和文化背景需要新增结构化DialectEntry、真实音频来源、词条渲染和相应的加载与可访问性策略。把已实现和待实现能力明确分开正是高质量 HarmonyOS 工程文章最重要的可信度来源。---AI 辅助声明本文由 AI 辅助整理技术结论基于中国方言题库当前BankDetailPage.ets及其真实数据契约复核未在当前渲染树中实现的词条读音、释义、例句和音频能力均明确标为扩展方案没有写成已发布功能。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价