第18次课程详情页面课程详情页面是用户学习的核心界面需要清晰地展示课程内容、代码示例和关键要点。本次课程将学习如何渲染不同类型的内容段落。学习目标掌握课程内容渲染方法学会实现 ContentSection 段落组件设计提示与警告样式实现完成按钮交互完成课程详情页面开发18.1 课程内容结构LessonContent 数据结构interfaceLessonContent{sections:ContentSection[];// 内容段落codeExamples:CodeExample[];// 代码示例keyTakeaways:string[];// 关键要点}interfaceContentSection{type:text|tip|warning|heading;title?:string;content:string;}interfaceCodeExample{title:string;code:string;language:string;explanation?:string;isEditable:boolean;}内容类型说明类型说明样式text普通文本默认样式heading标题加粗大字tip提示信息蓝色背景warning警告信息红色背景18.2 页面头部设计导航栏Row(){// 返回按钮Text(←).fontSize(24).fontColor(this.isDarkMode?#ffffff:#1a1a2e).onClick(()router.back())// 标题Text(this.lesson?.title??).fontSize(18).fontWeight(FontWeight.Medium).fontColor(this.isDarkMode?#ffffff:#1a1a2e).margin({left:16}).layoutWeight(1).maxLines(1).textOverflow({overflow:TextOverflow.Ellipsis})// 收藏按钮Text(this.isBookmarked?★:☆).fontSize(24).fontColor(this.isBookmarked?#fcc419:(this.isDarkMode?#9ca3af:#6c757d)).onClick(()this.toggleBookmark())}.width(100%).padding(16).backgroundColor(this.isDarkMode?#282c34:#ffffff)18.3 ContentSection 段落渲染段落组件实现BuilderSectionContent(section:ContentSection){Column(){// 标题如果有if(section.title){Text(section.title).fontSize(16).fontWeight(FontWeight.Bold).fontColor(this.isDarkMode?#ffffff:#1a1a2e).margin({bottom:8})}// 根据类型渲染不同样式if(section.typetip){this.TipContent(section.content)}elseif(section.typewarning){this.WarningContent(section.content)}else{this.TextContent(section.content)}}.width(100%).padding({left:16,right:16,top:16}).alignItems(HorizontalAlign.Start)}普通文本BuilderTextContent(content:string){Text(content).fontSize(14).fontColor(this.isDarkMode?#e6e6e6:#333333).lineHeight(22)}18.4 提示与警告样式提示样式TipBuilderTipContent(content:string){Row(){Text().fontSize(16)Text(content).fontSize(14).fontColor(this.isDarkMode?#ffffff:#1a1a2e).margin({left:8}).layoutWeight(1)}.width(100%).padding(12).backgroundColor(this.isDarkMode?rgba(97,218,251,0.15):rgba(97,218,251,0.1)).borderRadius(8)}警告样式WarningBuilderWarningContent(content:string){Row(){Text(⚠️).fontSize(16)Text(content).fontSize(14).fontColor(this.isDarkMode?#ffffff:#1a1a2e).margin({left:8}).layoutWeight(1)}.width(100%).padding(12).backgroundColor(this.isDarkMode?rgba(255,107,107,0.15):rgba(255,107,107,0.1)).borderRadius(8)}18.5 代码示例展示代码示例区域if(this.lesson.content.codeExamples.length0){Text(代码示例).fontSize(18).fontWeight(FontWeight.Bold).fontColor(this.isDarkMode?#ffffff:#1a1a2e).padding({left:16,right:16,top:24}).width(100%)ForEach(this.lesson.content.codeExamples,(example:CodeExample){Column(){// 代码块组件CodeBlock({code:example.code,language:example.language,title:example.title,explanation:example.explanation})// 在调试器中打开按钮if(example.isEditable){Button( 在调试器中打开).fontSize(13).fontColor(#61DAFB).backgroundColor(this.isDarkMode?#1e2127:#f0f9ff).borderRadius(16).margin({top:8}).onClick((){router.pushUrl({url:pages/CodePlayground,params:{title:example.title,code:example.code,language:example.language,explanation:example.explanation}});})}}.margin({left:16,right:16,top:12}).alignItems(HorizontalAlign.End)})}18.6 关键要点展示要点列表BuilderKeyTakeawaysSection(){Column(){Text( 关键要点).fontSize(16).fontWeight(FontWeight.Bold).fontColor(this.isDarkMode?#ffffff:#1a1a2e).margin({bottom:12})ForEach(this.lesson?.content.keyTakeaways??[],(takeaway:string,index:number){Row(){// 序号圆圈Text(${index1}).fontSize(12).fontColor(#ffffff).backgroundColor(#61DAFB).width(20).height(20).textAlign(TextAlign.Center).borderRadius(10)// 要点内容Text(takeaway).fontSize(14).fontColor(this.isDarkMode?#e6e6e6:#333333).margin({left:12}).layoutWeight(1)}.width(100%).margin({bottom:8})})}.width(100%).padding(16).margin({left:16,right:16,top:24}).backgroundColor(this.isDarkMode?#282c34:#ffffff).borderRadius(12).alignItems(HorizontalAlign.Start)}18.7 完成按钮交互按钮设计BuilderCompleteButton(){Button(this.isCompleted?✓ 已完成:标记为完成).width(90%).height(48).fontSize(16).fontWeight(FontWeight.Medium).backgroundColor(this.isCompleted?#51cf66:#61DAFB).fontColor(this.isCompleted?#ffffff:#1a1a2e).borderRadius(24).margin({top:24}).onClick(()this.markComplete())}完成逻辑privateasyncmarkComplete():Promisevoid{if(this.lesson!this.isCompleted){// 标记课程完成awaitProgressService.markLessonComplete(this.lesson.id,this.moduleId);this.isCompletedtrue;// 检查并颁发徽章constprogressawaitProgressService.loadProgress();awaitBadgeService.checkAndAwardBadges(progress);}}18.8 完整页面代码/** * 课程详情页 */import{router}fromkit.ArkUI;import{TutorialService}from../services/TutorialService;import{ProgressService}from../services/ProgressService;import{BookmarkService}from../services/BookmarkService;import{BadgeService}from../services/BadgeService;import{Lesson,ContentSection,CodeExample}from../models/Models;import{CodeBlock}from../components/CodeBlock;interfaceRouterParams{moduleId:string;lessonId:string;}EntryComponentstruct LessonDetail{Statelesson:Lesson|undefinedundefined;StatemoduleId:string;StateisBookmarked:booleanfalse;StateisCompleted:booleanfalse;StorageLink(isDarkMode)isDarkMode:booleanfalse;aboutToAppear():void{constparamsrouter.getParams()asRouterParams;if(params?.moduleIdparams?.lessonId){this.moduleIdparams.moduleId;this.lessonTutorialService.getLessonById(params.moduleId,params.lessonId);this.isBookmarkedBookmarkService.isBookmarked(params.lessonId);this.checkCompletion();}}privateasynccheckCompletion():Promisevoid{constprogressawaitProgressService.loadProgress();this.isCompletedprogress.completedLessons.includes(this.lesson?.id??);}build(){Column(){// 头部导航this.HeaderSection()// 内容区域if(this.lesson){Scroll(){Column(){// 课程描述Text(this.lesson.description).fontSize(14).fontColor(this.isDarkMode?#d1d5db:#495057).padding({left:16,right:16,top:16}).width(100%)// 内容段落ForEach(this.lesson.content.sections,(section:ContentSection){this.SectionContent(section)})// 代码示例this.CodeExamplesSection()// 关键要点if(this.lesson.content.keyTakeaways.length0){this.KeyTakeawaysSection()}// 完成按钮this.CompleteButton()}.padding({bottom:40})}.layoutWeight(1).scrollBar(BarState.Off)}}.width(100%).height(100%).backgroundColor(this.isDarkMode?#1a1a2e:#f8f9fa)}// ... Builder 方法实现}本次课程小结通过本次课程你已经✅ 掌握了课程内容渲染方法✅ 学会了实现 ContentSection 段落组件✅ 设计了提示与警告样式✅ 实现了完成按钮交互✅ 完成了课程详情页面开发课后练习添加目录导航实现课程内容目录快速跳转添加阅读进度显示当前阅读位置百分比添加字体设置支持调整字体大小下次预告第19次CodeBlock 代码块组件我们将开发代码展示组件代码展示设计语法高亮基础代码复制功能Toast 提示反馈实现专业的代码展示效果
HarmonyOS APP<玩转React>开源教程十八:课程详情页面
第18次课程详情页面课程详情页面是用户学习的核心界面需要清晰地展示课程内容、代码示例和关键要点。本次课程将学习如何渲染不同类型的内容段落。学习目标掌握课程内容渲染方法学会实现 ContentSection 段落组件设计提示与警告样式实现完成按钮交互完成课程详情页面开发18.1 课程内容结构LessonContent 数据结构interfaceLessonContent{sections:ContentSection[];// 内容段落codeExamples:CodeExample[];// 代码示例keyTakeaways:string[];// 关键要点}interfaceContentSection{type:text|tip|warning|heading;title?:string;content:string;}interfaceCodeExample{title:string;code:string;language:string;explanation?:string;isEditable:boolean;}内容类型说明类型说明样式text普通文本默认样式heading标题加粗大字tip提示信息蓝色背景warning警告信息红色背景18.2 页面头部设计导航栏Row(){// 返回按钮Text(←).fontSize(24).fontColor(this.isDarkMode?#ffffff:#1a1a2e).onClick(()router.back())// 标题Text(this.lesson?.title??).fontSize(18).fontWeight(FontWeight.Medium).fontColor(this.isDarkMode?#ffffff:#1a1a2e).margin({left:16}).layoutWeight(1).maxLines(1).textOverflow({overflow:TextOverflow.Ellipsis})// 收藏按钮Text(this.isBookmarked?★:☆).fontSize(24).fontColor(this.isBookmarked?#fcc419:(this.isDarkMode?#9ca3af:#6c757d)).onClick(()this.toggleBookmark())}.width(100%).padding(16).backgroundColor(this.isDarkMode?#282c34:#ffffff)18.3 ContentSection 段落渲染段落组件实现BuilderSectionContent(section:ContentSection){Column(){// 标题如果有if(section.title){Text(section.title).fontSize(16).fontWeight(FontWeight.Bold).fontColor(this.isDarkMode?#ffffff:#1a1a2e).margin({bottom:8})}// 根据类型渲染不同样式if(section.typetip){this.TipContent(section.content)}elseif(section.typewarning){this.WarningContent(section.content)}else{this.TextContent(section.content)}}.width(100%).padding({left:16,right:16,top:16}).alignItems(HorizontalAlign.Start)}普通文本BuilderTextContent(content:string){Text(content).fontSize(14).fontColor(this.isDarkMode?#e6e6e6:#333333).lineHeight(22)}18.4 提示与警告样式提示样式TipBuilderTipContent(content:string){Row(){Text().fontSize(16)Text(content).fontSize(14).fontColor(this.isDarkMode?#ffffff:#1a1a2e).margin({left:8}).layoutWeight(1)}.width(100%).padding(12).backgroundColor(this.isDarkMode?rgba(97,218,251,0.15):rgba(97,218,251,0.1)).borderRadius(8)}警告样式WarningBuilderWarningContent(content:string){Row(){Text(⚠️).fontSize(16)Text(content).fontSize(14).fontColor(this.isDarkMode?#ffffff:#1a1a2e).margin({left:8}).layoutWeight(1)}.width(100%).padding(12).backgroundColor(this.isDarkMode?rgba(255,107,107,0.15):rgba(255,107,107,0.1)).borderRadius(8)}18.5 代码示例展示代码示例区域if(this.lesson.content.codeExamples.length0){Text(代码示例).fontSize(18).fontWeight(FontWeight.Bold).fontColor(this.isDarkMode?#ffffff:#1a1a2e).padding({left:16,right:16,top:24}).width(100%)ForEach(this.lesson.content.codeExamples,(example:CodeExample){Column(){// 代码块组件CodeBlock({code:example.code,language:example.language,title:example.title,explanation:example.explanation})// 在调试器中打开按钮if(example.isEditable){Button( 在调试器中打开).fontSize(13).fontColor(#61DAFB).backgroundColor(this.isDarkMode?#1e2127:#f0f9ff).borderRadius(16).margin({top:8}).onClick((){router.pushUrl({url:pages/CodePlayground,params:{title:example.title,code:example.code,language:example.language,explanation:example.explanation}});})}}.margin({left:16,right:16,top:12}).alignItems(HorizontalAlign.End)})}18.6 关键要点展示要点列表BuilderKeyTakeawaysSection(){Column(){Text( 关键要点).fontSize(16).fontWeight(FontWeight.Bold).fontColor(this.isDarkMode?#ffffff:#1a1a2e).margin({bottom:12})ForEach(this.lesson?.content.keyTakeaways??[],(takeaway:string,index:number){Row(){// 序号圆圈Text(${index1}).fontSize(12).fontColor(#ffffff).backgroundColor(#61DAFB).width(20).height(20).textAlign(TextAlign.Center).borderRadius(10)// 要点内容Text(takeaway).fontSize(14).fontColor(this.isDarkMode?#e6e6e6:#333333).margin({left:12}).layoutWeight(1)}.width(100%).margin({bottom:8})})}.width(100%).padding(16).margin({left:16,right:16,top:24}).backgroundColor(this.isDarkMode?#282c34:#ffffff).borderRadius(12).alignItems(HorizontalAlign.Start)}18.7 完成按钮交互按钮设计BuilderCompleteButton(){Button(this.isCompleted?✓ 已完成:标记为完成).width(90%).height(48).fontSize(16).fontWeight(FontWeight.Medium).backgroundColor(this.isCompleted?#51cf66:#61DAFB).fontColor(this.isCompleted?#ffffff:#1a1a2e).borderRadius(24).margin({top:24}).onClick(()this.markComplete())}完成逻辑privateasyncmarkComplete():Promisevoid{if(this.lesson!this.isCompleted){// 标记课程完成awaitProgressService.markLessonComplete(this.lesson.id,this.moduleId);this.isCompletedtrue;// 检查并颁发徽章constprogressawaitProgressService.loadProgress();awaitBadgeService.checkAndAwardBadges(progress);}}18.8 完整页面代码/** * 课程详情页 */import{router}fromkit.ArkUI;import{TutorialService}from../services/TutorialService;import{ProgressService}from../services/ProgressService;import{BookmarkService}from../services/BookmarkService;import{BadgeService}from../services/BadgeService;import{Lesson,ContentSection,CodeExample}from../models/Models;import{CodeBlock}from../components/CodeBlock;interfaceRouterParams{moduleId:string;lessonId:string;}EntryComponentstruct LessonDetail{Statelesson:Lesson|undefinedundefined;StatemoduleId:string;StateisBookmarked:booleanfalse;StateisCompleted:booleanfalse;StorageLink(isDarkMode)isDarkMode:booleanfalse;aboutToAppear():void{constparamsrouter.getParams()asRouterParams;if(params?.moduleIdparams?.lessonId){this.moduleIdparams.moduleId;this.lessonTutorialService.getLessonById(params.moduleId,params.lessonId);this.isBookmarkedBookmarkService.isBookmarked(params.lessonId);this.checkCompletion();}}privateasynccheckCompletion():Promisevoid{constprogressawaitProgressService.loadProgress();this.isCompletedprogress.completedLessons.includes(this.lesson?.id??);}build(){Column(){// 头部导航this.HeaderSection()// 内容区域if(this.lesson){Scroll(){Column(){// 课程描述Text(this.lesson.description).fontSize(14).fontColor(this.isDarkMode?#d1d5db:#495057).padding({left:16,right:16,top:16}).width(100%)// 内容段落ForEach(this.lesson.content.sections,(section:ContentSection){this.SectionContent(section)})// 代码示例this.CodeExamplesSection()// 关键要点if(this.lesson.content.keyTakeaways.length0){this.KeyTakeawaysSection()}// 完成按钮this.CompleteButton()}.padding({bottom:40})}.layoutWeight(1).scrollBar(BarState.Off)}}.width(100%).height(100%).backgroundColor(this.isDarkMode?#1a1a2e:#f8f9fa)}// ... Builder 方法实现}本次课程小结通过本次课程你已经✅ 掌握了课程内容渲染方法✅ 学会了实现 ContentSection 段落组件✅ 设计了提示与警告样式✅ 实现了完成按钮交互✅ 完成了课程详情页面开发课后练习添加目录导航实现课程内容目录快速跳转添加阅读进度显示当前阅读位置百分比添加字体设置支持调整字体大小下次预告第19次CodeBlock 代码块组件我们将开发代码展示组件代码展示设计语法高亮基础代码复制功能Toast 提示反馈实现专业的代码展示效果