Procházet zdrojové kódy

feat: 组件导航

simon před 8 měsíci
rodič
revize
48d6e5d303
27 změnil soubory, kde provedl 922 přidání a 43 odebrání
  1. 15 1
      build-profile.json5
  2. 1 1
      features/map/Index.ets
  3. 0 19
      features/map/src/main/ets/components/MainPage.ets
  4. 83 0
      features/map/src/main/ets/pages/KnowledgeMap.ets
  5. 132 0
      features/map/src/main/ets/view/KnowledgeMapContent.ets
  6. 52 0
      features/map/src/main/ets/view/NavBarItem.ets
  7. 13 0
      features/map/src/main/resources/base/media/ic_arrow.svg
  8. 7 0
      features/map/src/main/resources/base/media/ic_guide.svg
  9. 7 0
      features/map/src/main/resources/base/media/ic_medals.svg
  10. 7 0
      features/map/src/main/resources/base/media/ic_prepare.svg
  11. 7 0
      features/map/src/main/resources/base/media/ic_video.svg
  12. binární
      features/map/src/main/resources/base/media/knowledge_map_banner.png
  13. 321 0
      features/map/src/main/resources/rawfile/MapData.json
  14. 74 0
      features/quickstart/src/main/ets/pages/ArticleDetailPage.ets
  15. 31 0
      features/quickstart/src/main/ets/pages/BannerDetailPage.ets
  16. 36 17
      features/quickstart/src/main/ets/pages/QuickStartPage.ets
  17. 4 0
      features/quickstart/src/main/ets/view/Banner.ets
  18. 4 0
      features/quickstart/src/main/ets/view/EnablementView.ets
  19. 4 0
      features/quickstart/src/main/ets/view/TutorialView.ets
  20. 14 0
      features/quickstart/src/main/resources/base/media/ic_back.svg
  21. 53 5
      products/default/src/main/ets/pages/Index.ets
  22. 10 0
      products/default/src/main/resources/base/media/ic_01_off.svg
  23. 9 0
      products/default/src/main/resources/base/media/ic_01_on.svg
  24. 11 0
      products/default/src/main/resources/base/media/ic_02_off.svg
  25. 11 0
      products/default/src/main/resources/base/media/ic_02_on.svg
  26. 8 0
      products/default/src/main/resources/base/media/ic_03_off.svg
  27. 8 0
      products/default/src/main/resources/base/media/ic_03_on.svg

+ 15 - 1
build-profile.json5

@@ -1,6 +1,20 @@
 {
   "app": {
-    "signingConfigs": [],
+    "signingConfigs": [
+      {
+        "name": "default",
+        "type": "HarmonyOS",
+        "material": {
+          "certpath": "C:\\Users\\Administrator\\.ohos\\config\\default_QuickStart_LJXtieXHEAEw6XdSIp7eNmaJemggqghwREmZyiLnAKY=.cer",
+          "keyAlias": "debugKey",
+          "keyPassword": "0000001BB6F620D88CDB83C6CED96B878A3DD522723BC60F3D862FCBAEB444A3C63CE28E149EA504844304",
+          "profile": "C:\\Users\\Administrator\\.ohos\\config\\default_QuickStart_LJXtieXHEAEw6XdSIp7eNmaJemggqghwREmZyiLnAKY=.p7b",
+          "signAlg": "SHA256withECDSA",
+          "storeFile": "C:\\Users\\Administrator\\.ohos\\config\\default_QuickStart_LJXtieXHEAEw6XdSIp7eNmaJemggqghwREmZyiLnAKY=.p12",
+          "storePassword": "0000001BC284FE9DA3F622D0718464B5165A139704D070FE958C059C15A9A9CC33FAF01120914C510369FE"
+        }
+      }
+    ],
     "products": [
       {
         "name": "default",

+ 1 - 1
features/map/Index.ets

@@ -1 +1 @@
-export { MainPage } from './src/main/ets/components/MainPage';
+export { KnowledgeMap } from './src/main/ets/pages/KnowledgeMap';

+ 0 - 19
features/map/src/main/ets/components/MainPage.ets

@@ -1,19 +0,0 @@
-@Component
-export struct MainPage {
-  @State message: string = 'Hello World';
-
-  build() {
-    Row() {
-      Column() {
-        Text(this.message)
-          .fontSize($r('app.float.page_text_font_size'))
-          .fontWeight(FontWeight.Bold)
-          .onClick(() => {
-            this.message = 'Welcome';
-          })
-      }
-      .width('100%')
-    }
-    .height('100%')
-  }
-}

+ 83 - 0
features/map/src/main/ets/pages/KnowledgeMap.ets

@@ -0,0 +1,83 @@
+import { KnowledgeMapContent, Section } from '../view/KnowledgeMapContent';
+import { NavBarItem, NavBarItemType } from '../view/NavBarItem';
+import { BusinessError } from '@kit.BasicServicesKit';
+import { util } from '@kit.ArkTS';
+
+@Preview
+@Component
+export struct KnowledgeMap {
+  @Provide('knowledgeMapPageStack') knowledgeMapPageStack: NavPathStack = new NavPathStack();
+  @State navBarList: NavBarItemType[] =
+    [{ order: '01', title: '准备学习' }, { order: '02', title: '构建应用' }, { order: '03', title: '应用测试' },
+      { order: '04', title: '上架' }, { order: '05', title: '运营增长' }, { order: '06', title: '商业变现' },
+      { order: '07', title: '跟多' }];
+  @State sections: Section[] = [];
+  @State currentNavBarIndex: number = -1;
+
+  @Builder
+  PageMap(name: string) {
+    if (name === 'KnowledgeMapContent') {
+      KnowledgeMapContent({ section: this.sections[this.currentNavBarIndex] });
+    }
+  }
+
+  aboutToAppear(): void {
+    this.getSections();
+  }
+
+  build() {
+    Navigation(this.knowledgeMapPageStack) {
+      Scroll() {
+        Column() {
+          Text('知识图谱')
+            .fontFamily("HarmonyHeiTi-Bold")
+            .fontSize(24)
+            .fontColor(Color.Black)
+            .textAlign(TextAlign.Start)
+            .lineHeight(33)
+            .fontWeight(700)
+            .width('100%')
+
+          Image($r('app.media.knowledge_map_banner')).width('100%').borderRadius(16).margin({ top: 19, bottom: 8 })
+
+          Text('通过循序渐进的学习路径,无经验和有经验的开发者都可以轻松掌握ArkTS语言声明式开发范式,体验更简洁、更友好的HarmonyOS应用开发旅程。')
+            .fontFamily('HarmonyHeiTi')
+            .fontSize(14)
+            .fontColor('rgba(0,0,0,0.60)')
+            .fontWeight(600)
+            .textAlign(TextAlign.Start)
+
+          List({ space: 12 }) {
+            ForEach(this.navBarList, (item: NavBarItemType) => {
+              ListItem() {
+                NavBarItem({ navBarItem: item, currentNavBarIndex: this.currentNavBarIndex })
+              }.width('100%')
+            }, (item: NavBarItemType) => item.title)
+          }.width('100%').margin({ top: 24 })
+        }.padding({
+          top: 12,
+          right: 16,
+          bottom: 12,
+          left: 16
+        })
+      }
+      .backgroundColor("#F1F3F5")
+      .align(Alignment.TopStart)
+      .constraintSize({ minHeight: '100%' })
+      .edgeEffect(EdgeEffect.Spring)
+    }.hideTitleBar(true).navDestination(this.PageMap).mode(NavigationMode.Stack)
+  }
+
+  private getSections() {
+    try {
+      this.getUIContext().getHostContext()?.resourceManager.getRawFileContent("MapData.json",
+        (_err: BusinessError, value: Uint8Array) => {
+          const textDecoder = util.TextDecoder.create('utf-8', { ignoreBOM: true });
+          const res = textDecoder.decodeToString(value)
+          this.sections = JSON.parse(res) as Section[]
+        });
+    } catch (err) {
+      console.error(`callback getRawFileContent failed, err is  ${JSON.stringify(err)}`);
+    }
+  }
+}

+ 132 - 0
features/map/src/main/ets/view/KnowledgeMapContent.ets

@@ -0,0 +1,132 @@
+interface KnowledgeBaseItem {
+  type: string,
+  title: string
+}
+
+interface Material {
+  subtitle: string,
+  knowledgeBase: KnowledgeBaseItem[]
+}
+
+export interface Section {
+  title: string,
+  brief: string,
+  materials: Material[]
+}
+
+const TypeMapIcon: Record<string, string> = {
+  '指南': 'app.media.ic_guide',
+  '准备': 'app.media.ic_prepare',
+  '学习与获取证书': 'app.media.ic_medals',
+  '视频教程': 'app.media.ic_video'
+}
+
+@Component
+export struct KnowledgeMapContent {
+  scroller: Scroller = new Scroller();
+  @Prop section: Section;
+
+  @Builder
+  KnowledgeBlockLine(knowledgeBaseItem: KnowledgeBaseItem) {
+    Row() {
+      Image($r(TypeMapIcon[knowledgeBaseItem.type]))
+        .width(20)
+        .height(20)
+
+      Column() {
+        Text(knowledgeBaseItem.title)
+          .fontFamily('HarmonyHeiTi-Medium')
+          .fontSize(16)
+          .fontWeight(500)
+
+        Text(knowledgeBaseItem.type)
+          .fontFamily('HarmonyHeiTi')
+          .fontSize(14)
+          .fontWeight(400)
+      }
+      .alignItems(HorizontalAlign.Start)
+      .margin({ left: 18 })
+
+      Blank()
+      Image($r('app.media.ic_arrow'))
+        .width(12)
+        .height(24)
+    }
+    .width('100%')
+    .height(64)
+    .alignItems(VerticalAlign.Center)
+  }
+
+  @Builder
+  KnowledgeBlock(material: Material) {
+    Column() {
+      Text(material.subtitle)
+        .fontFamily('HarmonyHeiTi-Medium')
+        .fontSize(14)
+        .fontWeight(500)
+        .margin({ bottom: 8 })
+
+      List({ space: 12 }) {
+        ForEach(material.knowledgeBase, (item: KnowledgeBaseItem) => {
+          ListItem() {
+            this.KnowledgeBlockLine(item)
+          }
+        },
+          (item: KnowledgeBaseItem) => item.title)
+      }
+      .backgroundColor(Color.White)
+      .borderRadius(16)
+      .padding({ left: 12, right: 12 })
+      .divider({
+        strokeWidth: 0.5,
+        startMargin: 38,
+        endMargin: 0,
+        color: '#F2F2F2'
+      })
+    }
+    .width('100%')
+    .margin({ top: 20 })
+    .alignItems(HorizontalAlign.Start)
+  }
+
+  build() {
+    NavDestination() {
+      Scroll(this.scroller) {
+        Column() {
+          Text(this.section?.title)
+            .fontFamily('HarmonyHeiTi-Bold')
+            .fontSize(20)
+            .fontWeight(700)
+            .fontColor(Color.Black)
+
+          Text(this.section?.brief)
+            .fontFamily('HarmonyHeiTi')
+            .fontSize(12)
+            .fontWeight(400)
+            .fontColor('rgba(0,0,0,0.60)')
+            .textAlign(TextAlign.JUSTIFY)
+            .margin({ top: 12 })
+
+          ForEach(this.section?.materials, (material: Material) => {
+            this.KnowledgeBlock(material)
+          },
+            (material: Material) => material.subtitle)
+        }
+        .alignItems(HorizontalAlign.Start)
+        .padding({
+          top: 12,
+          left: 16,
+          bottom: 12,
+          right: 16
+        })
+      }
+      .align(Alignment.TopStart)
+      .constraintSize({ minHeight: '100%' })
+      .edgeEffect(EdgeEffect.Spring)
+      .scrollable(ScrollDirection.Vertical)
+      .scrollBar(BarState.Auto)
+      .backgroundColor('#F1F3F5')
+    }
+    .hideTitleBar(true)
+  }
+}

+ 52 - 0
features/map/src/main/ets/view/NavBarItem.ets

@@ -0,0 +1,52 @@
+export interface NavBarItemType {
+  order: string,
+  title: string
+}
+
+@Component
+export struct NavBarItem {
+  @Prop navBarItem: NavBarItemType;
+  @Consume('knowledgeMapPageStack') knowledgeMapPageStack: NavPathStack;
+  @Link currentNavBarIndex: number;
+
+  build() {
+    Row() {
+      Text(this.navBarItem.order)
+        .margin({ right: 6 })
+        .fontFamily('HarmonyHeiTi-Bold')
+        .fontSize(21)
+        .fontColor('#182431')
+        .textAlign(TextAlign.Start)
+        .lineHeight(22)
+        .fontWeight(700)
+
+      Text(this.navBarItem.title)
+        .fontFamily('HarmonyHeiTi-Medium')
+        .fontSize(16)
+        .fontColor('#182431')
+        .textAlign(TextAlign.Start)
+        .lineHeight(22)
+        .fontWeight(500)
+
+      Blank()
+
+      Image($r('app.media.ic_arrow'))
+        .width(12)
+        .height(24)
+    }
+    .width('100%')
+    .height(48)
+    .borderRadius(16)
+    .alignItems(VerticalAlign.Center)
+    .padding({ left: 12, right: 12 })
+    .backgroundColor(
+      this.currentNavBarIndex === Number(this.navBarItem.order) - 1 ?
+        '#1a0a59f7' : Color.Transparent
+    )
+    .onClick(() => {
+      const index = Number(this.navBarItem.order) - 1;
+      this.currentNavBarIndex = index;
+      this.knowledgeMapPageStack.replacePath({ name: 'KnowledgeMapContent' })
+    })
+  }
+}

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 13 - 0
features/map/src/main/resources/base/media/ic_arrow.svg


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 7 - 0
features/map/src/main/resources/base/media/ic_guide.svg


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 7 - 0
features/map/src/main/resources/base/media/ic_medals.svg


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 7 - 0
features/map/src/main/resources/base/media/ic_prepare.svg


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 7 - 0
features/map/src/main/resources/base/media/ic_video.svg


binární
features/map/src/main/resources/base/media/knowledge_map_banner.png


+ 321 - 0
features/map/src/main/resources/rawfile/MapData.json

@@ -0,0 +1,321 @@
+[
+  {
+    "title": "准备与学习",
+    "brief": "加入HarmonyOS生态,注册成为开发者,通过HarmonyOS课程了解基本概念和基础知识,轻松开启HarmonyOS的开发旅程。",
+    "materials": [
+      {
+        "subtitle": "HarmonyOS简介",
+        "knowledgeBase": [
+          {
+            "type": "准备",
+            "title": "注册账号"
+          },
+          {
+            "type": "准备",
+            "title": "实名认证"
+          },
+          {
+            "type": "学习与获取证书",
+            "title": "HarmonyOS第一课"
+          },
+          {
+            "type": "学习与获取证书",
+            "title": "HarmonyOS应用开发者基础认证"
+          }
+        ]
+      },
+      {
+        "subtitle": "赋能套件介绍",
+        "knowledgeBase": [
+          {
+            "type": "指南",
+            "title": "开发"
+          },
+          {
+            "type": "指南",
+            "title": "最佳实践"
+          },
+          {
+            "type": "指南",
+            "title": "API参考"
+          },
+          {
+            "type": "指南",
+            "title": "视频教程"
+          },
+          {
+            "type": "指南",
+            "title": "Codelabs"
+          },
+          {
+            "type": "指南",
+            "title": "FAQ"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "title": "构建应用",
+    "brief": "为了帮助开发者更好的理解HarmonyOS提供的能力,我们对重点功能提供了开发指导,辅助开发者完成应用的开发。",
+    "materials": [
+      {
+        "subtitle": "开发工具",
+        "knowledgeBase": [
+          {
+            "type": "指南",
+            "title": "DevEco Studio"
+          },
+          {
+            "type": "指南",
+            "title": "低代码开发"
+          },
+          {
+            "type": "视频教程",
+            "title": "使用DevEco Studio高效开发"
+          }
+        ]
+      },
+      {
+        "subtitle": "开发语言",
+        "knowledgeBase": [
+          {
+            "type": "指南",
+            "title": "ArkTS"
+          },
+          {
+            "type": "视频教程",
+            "title": "ArkTS基础知识"
+          },
+          {
+            "type": "视频教程",
+            "title": "ArkTS开发实践"
+          }
+        ]
+      },
+      {
+        "subtitle": "开发框架",
+        "knowledgeBase": [
+          {
+            "type": "指南",
+            "title": "ArkTS"
+          },
+          {
+            "type": "视频教程",
+            "title": "ArkUI之属性动画"
+          }
+        ]
+      },
+      {
+        "subtitle": "HarmonyOS云开发",
+        "knowledgeBase": [
+          {
+            "type": "指南",
+            "title": "体验HarmonyOS云开发"
+          },
+          {
+            "type": "指南",
+            "title": "云开发"
+          },
+          {
+            "type": "视频教程",
+            "title": "HarmonyOS云开发"
+          }
+        ]
+      },
+      {
+        "subtitle": "集成开放能力",
+        "knowledgeBase": [
+          {
+            "type": "指南",
+            "title": "推送服务"
+          },
+          {
+            "type": "指南",
+            "title": "广告服务"
+          },
+          {
+            "type": "指南",
+            "title": "帐号服务"
+          },
+          {
+            "type": "指南",
+            "title": "分析服务"
+          },
+          {
+            "type": "指南",
+            "title": "应用内支付服务"
+          },
+          {
+            "type": "指南",
+            "title": "云函数"
+          },
+          {
+            "type": "指南",
+            "title": "云存储"
+          },
+          {
+            "type": "指南",
+            "title": "云数据库"
+          }
+        ]
+      },
+      {
+        "subtitle": "编译调试",
+        "knowledgeBase": [
+          {
+            "type": "指南",
+            "title": "编译构建"
+          },
+          {
+            "type": "指南",
+            "title": "应用签名"
+          },
+          {
+            "type": "指南",
+            "title": "云调试"
+          },
+          {
+            "type": "视频教程",
+            "title": "HarmonyOS应用调试前准备"
+          },
+          {
+            "type": "视频教程",
+            "title": "HarmonyOS应用调试"
+          },
+          {
+            "type": "视频教程",
+            "title": "HarmonyOS调试工具介绍"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "title": "应用测试",
+    "brief": "HarmonyOS应用/服务开发完成后,在发布到应用/服务市场前,还需要对应用进行:漏洞、隐私、兼容性、稳定性、性能等测试,确保HarmonyOS应用/服务纯净、安全,给用户带来更好的使用体验。",
+    "materials": [
+      {
+        "subtitle": "",
+        "knowledgeBase": [
+          {
+            "type": "指南",
+            "title": "云测试"
+          },
+          {
+            "type": "指南",
+            "title": "开放式测试"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "title": "上架",
+    "brief": "HarmonyOS应用/服务开发、测试完成后,将应用/服务发布至应用市场,用户可以通过应用市场、负一屏等渠道获取到对应的HarmonyOS应用/服务。",
+    "materials": [
+      {
+        "subtitle": "应用发布",
+        "knowledgeBase": [
+          {
+            "type": "指南",
+            "title": "发布HarmonyOS应用"
+          },
+          {
+            "type": "指南",
+            "title": "发布元服务"
+          },
+          {
+            "type": "指南",
+            "title": "分阶段发布"
+          },
+          {
+            "type": "视频教程",
+            "title": "发布HarmonyOS应用"
+          },
+          {
+            "type": "视频教程",
+            "title": "发布元服务"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "title": "运营增长",
+    "brief": "HarmonyOS应用/服务发布以后,通过数据及时了解运营情况、质量表现,制定增长策略,借助App Linking、崩溃服务等能力,实现应用及服务的用户增长以及质量提升。",
+    "materials": [
+      {
+        "subtitle": "应用发布",
+        "knowledgeBase": [
+          {
+            "type": "指南",
+            "title": "应用分析"
+          },
+          {
+            "type": "指南",
+            "title": "App Linking"
+          },
+          {
+            "type": "指南",
+            "title": "崩溃服务"
+          },
+          {
+            "type": "视频教程",
+            "title": "远程配置"
+          },
+          {
+            "type": "视频教程",
+            "title": "发布元服务"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "title": "商业变现",
+    "brief": "HarmonyOS应用/服务发布以后,通过数据及时了解运营情况、质量表现,制定增长策略,借助App Linking、崩溃服务等能力,实现应用及服务的用户增长以及质量提升。",
+    "materials": [
+      {
+        "subtitle": "",
+        "knowledgeBase": [
+          {
+            "type": "指南",
+            "title": "流量变现 "
+          },
+          {
+            "type": "指南",
+            "title": "联运服务"
+          },
+          {
+            "type": "指南",
+            "title": "付费服务"
+          },
+          {
+            "type": "指南",
+            "title": "结算指南"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "title": "更多",
+    "brief": "",
+    "materials": [
+      {
+        "subtitle": "",
+        "knowledgeBase": [
+          {
+            "type": "指南",
+            "title": "常见问题"
+          },
+          {
+            "type": "指南",
+            "title": "版本说明"
+          }
+        ]
+      }
+    ]
+  }
+]

+ 74 - 0
features/quickstart/src/main/ets/pages/ArticleDetailPage.ets

@@ -0,0 +1,74 @@
+import { ArticleClass } from '../model/ArticleClass';
+import { webview } from '@kit.ArkWeb';
+
+@Preview
+@Component
+export struct ArticleDetailPage {
+  @State articleDetail: ArticleClass | null = null;
+  @Consume('articlePathStack') articlePathStack: NavPathStack;
+
+  aboutToAppear(): void {
+    this.articleDetail = this.articlePathStack.getParamByName('articleDetail')[0] as ArticleClass;
+  }
+
+  build() {
+    NavDestination() {
+      Column() {
+        Row() {
+          Row() {
+            Image($r('app.media.ic_back'))
+              .width(40)
+              .height(40)
+              .onClick(() => {
+                this.articlePathStack.pop()
+              })
+
+            Row() {
+              Text(this.articleDetail?.title)
+                .fontFamily('HarmonyHeiTi-Bold')
+                .fontSize(20)
+                .textAlign(TextAlign.Start)
+                .textOverflow({ overflow: TextOverflow.Ellipsis })
+                .maxLines(1)
+                .fontWeight(700)
+                .margin({ left: 8 })
+            }
+          }
+          .width('80%')
+        }
+        .justifyContent(FlexAlign.SpaceBetween)
+        .width('100%')
+        .height(56)
+
+        // web
+        WebComponent({ articleDetail: this.articleDetail })
+      }
+      .padding({ left: 16, right: 16 })
+      .width('100%')
+      .height('100%')
+      .justifyContent(FlexAlign.SpaceBetween)
+    }
+    .hideTitleBar(true)
+  }
+}
+
+@Component
+struct WebComponent {
+  @Prop articleDetail: ArticleClass | null;
+  private webviewController: webview.WebviewController = new webview.WebviewController();
+
+  build() {
+    Column() {
+      Web({ src: this.articleDetail?.webUrl, controller: this.webviewController })
+        .darkMode(WebDarkMode.Auto)
+        .domStorageAccess(true)
+        .zoomAccess(true)
+        .fileAccess(true)
+        .mixedMode(MixedMode.All)
+        .cacheMode(CacheMode.None)
+        .javaScriptAccess(true)
+        .width('100%')
+        .layoutWeight(1)
+    }
+  }
+}

+ 31 - 0
features/quickstart/src/main/ets/pages/BannerDetailPage.ets

@@ -0,0 +1,31 @@
+import { BannerClass } from '../model/BannerClass';
+import { webview } from '@kit.ArkWeb';
+
+@Component
+export struct BannerDetailPage {
+  @State bannerClass: BannerClass | null = null;
+  controller: webview.WebviewController = new webview.WebviewController();
+  @Consume('articlePathStack') articlePathStack: NavPathStack;
+
+  aboutToAppear(): void {
+    this.bannerClass = this.articlePathStack.getParamByName('bannerDetail')[0] as BannerClass;
+  }
+
+  build() {
+    NavDestination() {
+      Column() {
+        Web({ src: this.bannerClass?.url, controller: this.controller })
+          .darkMode(WebDarkMode.Auto)
+          .domStorageAccess(true)
+          .zoomAccess(true)
+          .fileAccess(true)
+          .mixedMode(MixedMode.All)
+          .javaScriptAccess(true)
+          .width('100%')
+          .layoutWeight(1)
+      }
+    }
+    .width('100%')
+    .height('100%')
+  }
+}

+ 36 - 17
features/quickstart/src/main/ets/pages/QuickStartPage.ets

@@ -1,30 +1,49 @@
+import { ArticleClass } from '../model/ArticleClass';
+import { BannerClass } from '../model/BannerClass';
 import { Banner } from '../view/Banner';
 import { EnablementView } from '../view/EnablementView';
 import { TutorialView } from '../view/TutorialView';
+import { ArticleDetailPage } from './ArticleDetailPage';
+import { BannerDetailPage } from './BannerDetailPage';
 
 @Component
 export struct QuickStartPage {
   @State message: string = '快速入门';
+  @Provide('articlePathStack') articlePathStack: NavPathStack = new NavPathStack();
+
+  @Builder
+  quickStartRouter(name: string, param?: ArticleClass | BannerClass) {
+    if (name === 'articleDetail') {
+      ArticleDetailPage()
+    } else if (name === 'bannerDetail') {
+      BannerDetailPage()
+    }
+  }
 
   build() {
-    Column() {
-      Text(this.message)
-        .fontSize(24)
-        .fontWeight(700)
-        .width('100%')
-        .textAlign(TextAlign.Start)
-        .padding({ left: 16 })
-        .fontFamily('HarmonyHeiTi-Bold')
-        .lineHeight(33)
+    Navigation(this.articlePathStack) {
+      Column() {
+        Text(this.message)
+          .fontSize(24)
+          .fontWeight(700)
+          .width('100%')
+          .textAlign(TextAlign.Start)
+          .padding({ left: 16 })
+          .fontFamily('HarmonyHeiTi-Bold')
+          .lineHeight(33)
 
-      Scroll() {
-        Column() {
-          Banner()
-          EnablementView()
-          TutorialView()
-        }
-      }.layoutWeight(1).scrollBar(BarState.Off).align(Alignment.TopStart)
+        Scroll() {
+          Column() {
+            Banner()
+            EnablementView()
+            TutorialView()
+          }
+        }.layoutWeight(1).scrollBar(BarState.Off).align(Alignment.TopStart)
 
-    }.height('100%').width('100%').backgroundColor('#F1F3F5')
+      }.height('100%').width('100%').backgroundColor('#F1F3F5')
+    }
+    .navDestination(this.quickStartRouter)
+    .hideTitleBar(true)
+    .mode(NavigationMode.Stack)
   }
 }

+ 4 - 0
features/quickstart/src/main/ets/view/Banner.ets

@@ -5,6 +5,7 @@ import { bufferToString } from '../util/BufferUtil';
 @Component
 export struct Banner {
   @State bannerList: BannerClass[] = [];
+  @Consume('articlePathStack') articlePathStack: NavPathStack;
 
   getBannerDataFromJSON() {
     this.getUIContext().getHostContext()?.resourceManager.getRawFileContent('BannerData.json')
@@ -28,6 +29,9 @@ export struct Banner {
           .width('100%')
           .padding({ top: 11, left: 16, right: 16 })
           .borderRadius(16)
+          .onClick(() => {
+            this.articlePathStack.pushPathByName('bannerDetail', item)
+          })
       }, (item: BannerClass) => item.id)
     }.autoPlay(true).interval(5000).loop(true).indicator(new DotIndicator().color('#1A0000').selectedColor('#0A59F7'))
   }

+ 4 - 0
features/quickstart/src/main/ets/view/EnablementView.ets

@@ -5,6 +5,7 @@ import { bufferToString } from '../util/BufferUtil';
 @Component
 export struct EnablementView {
   @State enablementList: ArticleClass[] = [];
+  @Consume('articlePathStack') articlePathStack: NavPathStack;
 
   getEnablementDataFromJSON() {
     this.getUIContext().getHostContext()?.resourceManager.getRawFileContent("EnablementData.json").then(value => {
@@ -33,6 +34,9 @@ export struct EnablementView {
         ForEach(this.enablementList, (item: ArticleClass) => {
           GridItem() {
             EnablementItem({ enablementItem: item })
+              .onClick(() => {
+                this.articlePathStack.pushPathByName('articleDetail', item)
+              })
           }
         }, (item: ArticleClass) => item.id)
       }

+ 4 - 0
features/quickstart/src/main/ets/view/TutorialView.ets

@@ -5,6 +5,7 @@ import { bufferToString } from '../util/BufferUtil';
 @Component
 export struct TutorialView {
   @State tutorialList: ArticleClass[] = [];
+  @Consume('articlePathStack') articlePathStack: NavPathStack;
 
   getTutorialDataFromJSON() {
     this.getUIContext().getHostContext()?.resourceManager.getRawFileContent("TutorialData.json").then(value => {
@@ -33,6 +34,9 @@ export struct TutorialView {
         ForEach(this.tutorialList, (item: ArticleClass) => {
           ListItem() {
             TutorialItem({ tutorialItem: item })
+              .onClick(() => {
+                this.articlePathStack.pushPathByName('articleDetail', item)
+              })
           }
         },
           (item: ArticleClass) => item.id)

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 14 - 0
features/quickstart/src/main/resources/base/media/ic_back.svg


+ 53 - 5
products/default/src/main/ets/pages/Index.ets

@@ -1,14 +1,62 @@
-import { CourseLearning } from 'learning'
-import { QuickStartPage } from 'quickstart'
+import { CourseLearning } from 'learning';
+import { KnowledgeMap } from 'map';
+import { QuickStartPage } from 'quickstart';
 
+@Preview
 @Entry
 @Component
 struct Index {
-  build() {
+  @State currentIndex: number = 0;
+  private tabsController: TabsController = new TabsController();
+
+  @Builder
+  tabBarBuilder(title: string, targetIndex: number, selectedIcon: Resource, unselectIcon: Resource) {
     Column() {
-      QuickStartPage()
-      // CourseLearning()
+      Image(this.currentIndex === targetIndex ? selectedIcon : unselectIcon)
+        .width(24)
+        .height(24)
+
+      Text(title)
+        .fontFamily("HarmonyHeiTi-Medium")
+        .fontSize(10)
+        .fontColor(this.currentIndex === targetIndex ? '#0A59F7' : 'rgba(0,0,0,0.60)')
+        .textAlign(TextAlign.Center)
+        .lineHeight(14)
+        .fontWeight(500)
+    }
+    .width('100%')
+    .height('100%')
+    .justifyContent(FlexAlign.Center)
+    .alignItems(HorizontalAlign.Center)
+    .onClick(() => {
+      this.currentIndex = targetIndex;
+      this.tabsController.changeIndex(targetIndex);
+    })
+  }
+
+  build() {
+    Tabs({ barPosition: BarPosition.End, controller: this.tabsController }) {
+      TabContent() {
+        QuickStartPage()
+      }
+      .tabBar(this.tabBarBuilder('快速入门', 0, $r('app.media.ic_01_on'), $r('app.media.ic_01_off')))
+
+      TabContent() {
+        CourseLearning()
+      }
+      .tabBar(this.tabBarBuilder('课程学习', 1, $r('app.media.ic_02_on'), $r('app.media.ic_02_off')))
+
+      TabContent() {
+        KnowledgeMap()
+      }
+      .tabBar(this.tabBarBuilder('知识地图', 2, $r('app.media.ic_03_on'), $r('app.media.ic_03_off')))
     }
+    .scrollable(false)
+    .vertical(false)
+    .divider({
+      strokeWidth: 0.5,
+      color: '#0D182431'
+    })
     .backgroundColor('#F1F3F5')
     .padding({ top: 36, bottom: 28 })
   }

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 10 - 0
products/default/src/main/resources/base/media/ic_01_off.svg


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 9 - 0
products/default/src/main/resources/base/media/ic_01_on.svg


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 11 - 0
products/default/src/main/resources/base/media/ic_02_off.svg


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 11 - 0
products/default/src/main/resources/base/media/ic_02_on.svg


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 8 - 0
products/default/src/main/resources/base/media/ic_03_off.svg


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 8 - 0
products/default/src/main/resources/base/media/ic_03_on.svg