Stories

Detail Return Return

【分享+1】HarmonyOS官方模板優秀案例(第6期:商務辦公 · 筆記應用) - Stories Detail

💡 鴻蒙生態為開發者提供海量的HarmonyOS模板/組件,助力開發效率原地起飛 💡

★ 一鍵直達生態市場組件&模板市場 , 快速應用DevEco Studio插件市場集成組件&模板 ★

工作生活小幫手,筆記應用可以集中管理零散信息、提高信息獲取和協作效率。

本期案例介紹如何快速基於模板開發一款筆記應用

👉 覆蓋20+行業,點擊查看往期案例彙總貼,持續更新,點擊收藏!一鍵三連!常看常新!

【第6期】商務辦公 · 筆記應用

一、概述

1. 行業洞察

1)行業訴求:

  • 用户忠誠度低 :工具性產品功能相對單一,缺乏互動入口,用户黏性很低。
  • 同質化嚴重 :開源框架等技術的發展降低了開發門檻,許多工具應用在功能上高度重疊,尤其是SaaS工具市場,各種功能相似、定位重疊的產品層出不窮,導致用户選擇困難,開發者也難以脱穎而出。
  • 個性化需求滿足難度大 :隨着用户需求的不斷變化和多樣化,工具應用需要覆蓋的場景也越來越多,但很多工具提供的是通用功能,無法快速滿足客户的各種差異化需求,尤其是一些靜態分析工具等專業工具,用户難以開發自定義規則,對誤報和漏報的規則也無法快速修改。。

2)行業常用三方SDK

分類

三方庫名稱

功能

支持情況

SDK鏈接

媒體

阿里雲視頻播放器SDK

音視頻

已支持

極光安全認證SDK

騰訊優量匯SDK

美數AdMate SDK

穿山甲廣告SDK

騰訊圖靈盾風險識別SDK

支付寶SDK

Thinking SDK

七牛雲存儲SDK

友盟移動統計SDK

Utdid

騰訊微信SDK

騰訊QQ SDK

登錄認證

中國移動一鍵登錄SDK/易盾一鍵登錄SDK/創藍閃驗/極光安全認證/阿里雲號碼認證SDK/中國電信一鍵登錄SDK

登錄

已支持

分享

友盟/ShareSDK/微信分享/QQ分享/新浪微博SDK/MobTech ShareSDK

統計/推送/分享

已支持

支付

支付寶支付/微信支付/銀聯支付

支付

已支持

數據分析

友盟移動統計SD/神策數據SDK

數據收集、處理、分析、運用

已支持

性能監控

友盟應用性能監控SDK

異常上報和運營統計

已支持

推送

個推/華為推送/極光PUSH/阿里推送SDK

消息推送

已支持

存儲

七牛雲存儲-SDK/阿里雲OSS存儲SDK

存儲

以支持

説明:“以上三方庫及鏈接僅為示例,三方庫由三方開發者獨立提供,以其官方內容為準”

2. 案例概覽(下載模板

基於以上行業分析,本期將介紹鴻蒙生態市場商務辦公類行業模板——筆記應用模板,為行業提供常用功能的開發案例,模板主要分首頁、我的兩大模塊。

  • Stage開發模型 + 聲明式UI開發範式。
  • 分層架構設計 + 組件化拆分,支持開發者在開發時既可以選擇完整使用模板,也可以根據需求單獨選用其中的業務組件。
  • 本模板已集成賬號服務,只需做少量配置和定製即可快速實現華為賬號一鍵登錄。

本模板主要頁面及核心功能如下所示:

​筆記模板
 |-- 首頁
 |    |-- 搜索
 |    |-- 筆記分類
 |    |    |-- 新建分類
 |    |    |-- 重命名 
 |    |    └-- 刪除分類
 |    |-- 排序
 |    |    |-- 按創建時間排序
 |    |    └-- 按修改時間排序     
 |    |-- 筆記列表
 |    |    |-- 複製內容
 |    |    |-- 移動到其他分類
 |    |    └-- 刪除
 |    |-- 創建筆記
 |    |    |-- 保存
 |    |    └-- 分享筆記
 |    └-- 編輯筆記
 |         |-- 保存
 |         └-- 分享筆記
 └-- 我的
      |-- 用户信息
      |    |-- 華為賬號一鍵登錄
      |    └-- 頭像暱稱修改
      └-- 回收站
      |    |-- 搜索筆記
      |    |-- 恢復筆記
      |    └-- 徹底刪除
      └-- 設置
           |-- 隱私協議
           |-- 保密設置
           |    |-- 手勢密碼
           |    └-- 指紋解鎖
           └-- 退出登錄

二、應用架構設計

1. 分層模塊化設計

  • 產品定製層:專注於滿足不同設備或使用場景的個性化需求,作為應用的入口,是用户直接互動的界面。
    • 本實踐暫時只支持直板機,為單HAP包形式,包含路由根節點、底部導航欄等。
  • 基礎特性層:用於存放相對獨立的功能UI和業務邏輯實現。
    • 本實踐的基礎特性層將應用底部導航欄的每個選項拆分成一個獨立的業務功能模塊。
    • 每個功能模塊都具備高內聚、低耦合、可定製的特點,支持產品的靈活部署。
  • 公共能力層:存放公共能力,包括公共UI組件、數據管理、外部交互和工具庫等共享功能。
    • 本實踐的公共能力層分為公共基礎能力和可分可合組件,均打包為HAR包被上層業務組件引用。
    • 公共基礎能力包含日誌、文件處理等工具類,公共類型定義,網絡庫,以及彈窗、加載等公共組件。
    • 可分可合組件將包含行業特點、可完全自閉環的能力抽出獨立的組件模塊,支持開發者在開發中單獨集成使用,詳見業務組件設計章節。

http://image.huawei.com/tiny-lts/v1/images/hi3ms/edf690f19332784457ac85f9514db6d1_1226x503.png

2. 業務組件設計

為支持開發者單獨獲取特定場景的頁面和功能,本模板將功能完全自閉環的部分能力抽離出獨立的行業組件模塊,不依賴公共基礎能力包,開發者可以單獨集成,開箱即用,降低使用難度。

三、行業場景技術方案

1. 富文本筆記編輯

1)場景説明

用户可創建和編輯富文本筆記,支持文本樣式修改、圖片插入、撤銷重做、內容複製等功能。

2)技術方案

  • 基於RichEditorController實現富文本編輯能力。
  • 使用StyledString管理帶樣式的文本內容。
  • 採用操作記錄棧(historyRecordArray)實現撤銷重做功能。
  • 集成系統剪貼板服務實現內容複製。

2. 筆記分類管理

1)場景説明

  • 用户可創建、重命名、刪除筆記分類,支持分類間筆記移動,右滑操作支持快速編輯和刪除。

2)技術方案

  • 採用SwipeAction實現右滑操作菜單。
  • 使用自定義彈窗組件進行分類管理。
  • 通過CategoryService統一管理分類數據。
  • 支持分類下筆記的批量遷移。

3. 搜索功能

1)場景説明

用户可在首頁通過搜索框輸入關鍵詞進行實時搜索,支持在正常筆記和回收站筆記中進行全文檢索,搜索結果實時展示。

2)技術方案

  • 用SearchController實現搜索框交互。
  • 支持實時搜索和提交搜索兩種模式。
  • 通過NoteService進行底層數據檢索。
  • 使用@Trace裝飾器實現狀態管理。
  • 支持分類內搜索和全局搜索。

四、模板代碼

1. 工程結構(下載模板

詳細代碼結構如下所示:

Notes
  |- common                                        // 公共層
  |   |- datasource/src/main/ets/                  // 公共資源
  |   |    |- CategoryService.ets                  // 分類服務
  |   |    |- Data.ets                             // mock數據
  |   |    |- Model.ets                            // 建立模型
  |   |    └- NoteService.ets                      // 筆記服務
  |   └- utils/src/main/ets                        // 公共組件模塊(hsp)
  |        |- constants 
  |        |     CommonConstants.ets               // 公共常量        
  |        |     DateConstants.ets                 // 日期格式化常量                   
  |        └- utils                                // 工具類
  |              AccountUtil.ets                   // 賬號
  |              AppUtil.ets                       // 應用  
  |              DateUtil.ets                      // 日期處理
  |              LogUtil.ets                       // 日誌工具   
  |              ObjectUtil.ets                    // 對象工具   
  |              ShowToast.ets                     // 吐司   
  |              StringUtil.ets                    // 字符串工具
  |
  |- components                                    // 公共組件
  |   |- richeditor/src/main/ets/                  // 富文本組件
  |   |    |- common 
  |   |    |     Constants.ets                     // 公共常量         
  |   |    |- components                           
  |   |    |     RichEditorArea.ets                // 富文本編輯
  |   |    |     SnapshotPreview.ets               // 截圖預覽
  |   |    |- model 
  |   |    |     AlignmentInfo.ets                 // 編輯富文本框段落選項       
  |   |    └- util
  |   |          CommonUtils.ets                   // 常用(沉睡/截圖)     
  |   |          ControllerUtil.ets                // 本項目使用      
  |   |          ImageUtils.ets                    // 圖片處理
  |   |          PickerUtil.ets                    // 選擇、保存圖片    
  |   |          PopupUtils.ets                    // 截圖計算
  |   |          RichEditorUtil.ets                // 富文本編輯器工具類
  |   |    
  |   └- secretlock/src/main/ets/                  // 應用密碼設置組件
  |        |- components                           
  |        |     SecretLockSwitch.ets              // 密碼設置開關
  |        |- model 
  |        |     AuthOptions.ets                   // 認證參數類
  |        |     SecretLock.ets                    // 密碼鎖-保密設置(持久化)
  |        |- pages                           
  |        |     DrawLock.ets                      // 密碼設置繪製頁面
  |        └- util                           
  |              AuthUtil.ets                      // 生物識別認證工具類    
  |
  └- product/phone                               
      └---src/main/ets 
           |- common
           |   LoginConstants.ets                  // 登錄常量
           |- components
           |   RightArrow.ets                      // 右箭頭                  
           |- entryability
           |   EntryAbility.ets                    // 主頁面                                                                                                                       
           └- pages
               mine                                // 我的-相關頁面
                |- MineView.ets                    // 我的頁面入口
                |- PrivacyAgreement.ets            // 隱私協議(隱私政策)
                |- QuickLoginPage.ets              // 一鍵登錄
                |- SecretSetting.ets               // 保密設置
                |- Setting.ets                     // 設置
                |- Trash.ets                       // 回收站
                └- UserInfoPage.ets                // 用户信息
               EditorCategory.ets                  // 編輯分類
               EditNotes.ets                       // 編輯筆記
               Index.ets                           // 入口頁面

2. 關鍵代碼解讀

本篇代碼非應用的全量代碼,只包括應用的部分能力的關鍵代碼。

1)筆記多選管理

​// 筆記卡片長按事件處理
handleLangPress(item: Note) {
  // 非多選狀態下生效
  if (!this.selectedController.isCtrl) {
    this.selectedController.isCtrl = true;
    item.isSelected = true;
    this.selectedController.selectedCount = 1;
  }
}

// 全選功能實現
handleSelectAll() {
  if (this.selectedController.selectedCount === this.noteList.length) {
    this.noteList.forEach(item => item.isSelected = false);
    this.selectedController.selectedCount = 0;
  } else {
    this.noteList.forEach(item => item.isSelected = true);
    this.selectedController.selectedCount = this.noteList.length;
  }
}

// 多選工具欄構建
@Builder
toolBarBuilder(){
  if (this.selectedController.isCtrl){
    Row(){
      ForEach(toolBarList, (item: ToolBar) => {
        Column({ space: 5 }){
          Image(item.icon)
            .width(24)
            .height(24)
          Text(item.name)
            .fontSize(10)
            .fontColor($r('sys.color.font_secondary'))
        }
        .onClick(() => {
           this.handleToolBarClick(item.name)
        })
      }, (item: ToolBar) => JSON.stringify(item))
    }
    .margin({ top: 10 })
    .padding({ bottom: 10 })
    .justifyContent(FlexAlign.SpaceAround)
    .width('100%')
    .height(70)
    .backgroundColor($r('sys.color.comp_background_list_card'))
  }
}

2)富文本編輯器控制

​// 富文本編輯器控制器
richEditorController: RichEditorController = RichEditorController.instance;

// 撤銷重做功能實現
@Builder
toolBar() {
  Row({ space: 12 }) {
    Image(this.richEditorController.currentIndex < 1 ? 
          $r('app.media.undo_expire') : $r('app.media.undo_effect'))
      .width(40)
      .height(40)
      .onClick(() => {
        this.richEditorController.onDo(); // 撤銷
      });

    Image(this.richEditorController.currentIndex >= this.richEditorController.historyRecordArray.length - 1 ?
          $r('app.media.redo_expire') : $r('app.media.redo_effect'))
      .width(40)
      .height(40)
      .onClick(() => {
        this.richEditorController.reDo(); // 重做
      });
  }
}

// 內容複製功能
copyNoteText() {
  let copyText = this.currentNote?.description || '';
  let plainTextData = new unifiedDataChannel.UnifiedData();
  let plainText = new unifiedDataChannel.PlainText();
  plainText.details = {
    key: 'delayPlaintext',
    value: copyText,
  };
  plainText.textContent = copyText;
  plainText.abstract = 'delayTextContent';
  plainTextData.addRecord(plainText);
  let systemPasteboard: pasteboard.SystemPasteboard = pasteboard.getSystemPasteboard();
  systemPasteboard.setUnifiedData(plainTextData);
}

3)分類管理實現

​// 分類右滑操作菜單
@Builder
categoryEnd(item: Category){
  Row() {
    Image($r('app.media.edit_category'))
      .width(40)
      .height(40)
      .margin({ left: 16, right: 16})
      .onClick(() => {
        this.isEditCategoryName = true;
        this.categoryId = item.id;
        // 打開編輯分類彈窗
      })

    Image($r('app.media.delete_category'))
      .width(40)
      .height(40)
      .onClick(() => {
        this.categoryId = item.id;
        // 打開刪除分類彈窗
      })
  }
  .width(112)
  .height(48)
}

// 分類刪除對話框
@ComponentV2
struct DeleteCategoryDialog {
  @Param @Require params: DeleteCategoryParam;
  noteService: NoteService = NoteService.instance;
  categoryService: CategoryService = CategoryService.instance;

  build() {
    Column({ space: 30 }) {
      // 僅刪除分類選項
      Row() {
        Text('僅刪除分類')
          .fontSize(16)
          .onClick(() => {
            this.noteService.moveNotesCategory(this.params.categoryId);
            this.categoryService.deleteCategoryById(this.params.categoryId);
          });
      }
      
      // 刪除分類和筆記選項
      Row() {
        Text('刪除分類和筆記')
          .fontSize(16)
          .fontColor(Color.Red)
          .onClick(() => {
            let notes = this.noteService.getNoteList(this.params.categoryId);
            notes.forEach((item) => {
              this.noteService.deleteNote(item.id);
            });
            this.categoryService.deleteCategoryById(this.params.categoryId);
          });
      }
    }
  }
}

4)響應式佈局適配

​// 斷點響應式樣式定義
@Styles
topAreaStyle() {
  .width('100%')
  .padding(new BreakpointType<Padding>({
    sm: {
      top: 12,
      bottom: 20,
      left: $r('sys.float.padding_level8'),
      right: $r('sys.float.padding_level8'),
    },
    md: {
      top: 12,
      bottom: 20,
      left: $r('sys.float.padding_level12'),
      right: $r('sys.float.padding_level12'),
    },
    lg: {
      top: 12,
      bottom: 20,
      left: $r('sys.float.padding_level16'),
      right: $r('sys.float.padding_level16'),
    },
  }).getValue(this.globalInfo.currentBreakpoint));
}

// 不同視圖模式適配
@Builder
showNoteList() {
  if (this.noteSearchController.isSearching && this.noteList.length === 0) {
    SearchNoResult()
  }
  if (!this.noteSearchController.isSearching && this.noteList.length === 0){
    EmptyNotes()
  } else if (this.showListType === SHOW_METHOD_ENUM.normalList) {
    this.cardList() // 列表視圖
  } else {
    this.waterCardList() // 瀑布流視圖
  }
}

// 瀑布流佈局實現
@Builder
waterCardList() {
  Column() {
    WaterFlow() {
      LazyForEach(this.dataList, (item: Note) => {
        FlowItem() {
          this.cardItem(item, 9) // 9行文本顯示
        }
        .width('100%')
        .gesture(
          LongPressGesture({ repeat: false, fingers: 1, duration: 500 })
            .onAction((event: GestureEvent|undefined) => {
              if(event){
                this.handleLangPress(item)
              }
            })
        )
      }, (item:Note) => item.id)
    }
    .columnsTemplate('1fr 1fr') // 兩列布局
    .columnsGap(obtainGutter(this.globalInfo.currentBreakpoint, 'WaterFlow'))
    .rowsGap(16)
  }
}

以上代碼展示了商務筆記應用的核心功能實現,包括多選管理、富文本編輯、分類管理和響應式佈局等關鍵技術方案。

3. 模板集成

本模板提供了兩種代碼集成方式,供開發者自由選用。

1)整體集成(下載模板

開發者可以選擇直接基於模板工程開發自己的應用工程。

  • 模板代碼獲取:
    • 通過IDE插件創建模板工程,開發指導。
    • 通過生態市場下載源碼, 下載模板。
    • 通過開源倉訪問源碼,倉庫地址。
  • 打開模板工程,根據README説明中的快速入門章節,將自己的應用信息配置在模板工程內,即可運行並查看模板效果。

  • 對接開發者自己的服務器接口,轉換數據結構,展示真實的雲側數據。

commons/lib_common/src/main/ets/httprequest/HttpRequestApi.ets文件中的mock接口替換為真實的服務器接口。

commons/lib_common/src/main/ets/httprequest/HttpRequest.ets文件中將雲側開發者自定義的數據結構轉換為端側數據結構。

根據自己的業務內容修改模板,進行定製化開發。

2)按需集成

若開發者已搭建好自己的應用工程,但暫未實現其中的部分場景能力,可以選擇取用其中的業務組件,集成在自己的工程中。

  • 組件代碼獲取:
    • 通過IDE插件下載組件源碼。開發指導
    • 通過生態市場下載組件源碼。 下載地址
  • 下載組件源碼,根據README中的説明,將組件包配置在自己的工程中。

  • 根據API參考和示例代碼,將組件集成在自己的對應場景中。

以上是第6期“商務辦公-筆記應用”行業案例的內容,更多行業敬請期待~

歡迎下載使用行業模板“點擊下載”,若您有體驗和開發問題,或者迫不及待想了解XX行業的優秀案例,歡迎在評論區留言,小編會快馬加鞭為您解答~

同時誠邀您添加下方二維碼加入“組件模板開發者社羣”,精彩上新&活動不錯過!

👉 HarmonyOS官方模板優秀案例系列持續更新, 點擊查看往期案例彙總貼, 點擊收藏 “方便查找!

👉【互動有禮】邀請你成為HarmonyOS官方模板產品經理,優化方案由你制定!點擊參加

👉 HarmonyOS組件模板相關推薦鴻蒙應用開發者激勵計劃2025,點擊查看

Add a new Comments

Some HTML is okay.