惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

F
Fortinet All Blogs
宝玉的分享
宝玉的分享
酷 壳 – CoolShell
酷 壳 – CoolShell
T
The Exploit Database - CXSecurity.com
Help Net Security
Help Net Security
腾讯CDC
Project Zero
Project Zero
C
CXSECURITY Database RSS Feed - CXSecurity.com
IT之家
IT之家
C
Cyber Attacks, Cyber Crime and Cyber Security
T
Tailwind CSS Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
D
Darknet – Hacking Tools, Hacker News & Cyber Security
L
LINUX DO - 最新话题
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
T
Threatpost
N
News | PayPal Newsroom
C
Cybersecurity and Infrastructure Security Agency CISA
Hacker News - Newest:
Hacker News - Newest: "LLM"
S
SegmentFault 最新的问题
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
P
Proofpoint News Feed
A
Arctic Wolf
B
Blog RSS Feed
Forbes - Security
Forbes - Security
P
Privacy & Cybersecurity Law Blog
Attack and Defense Labs
Attack and Defense Labs
V2EX - 技术
V2EX - 技术
P
Proofpoint News Feed
I
Intezer
Application and Cybersecurity Blog
Application and Cybersecurity Blog
阮一峰的网络日志
阮一峰的网络日志
aimingoo的专栏
aimingoo的专栏
T
Tenable Blog
MyScale Blog
MyScale Blog
U
Unit 42
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
WordPress大学
WordPress大学
W
WeLiveSecurity
D
DataBreaches.Net
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
G
GRAHAM CLULEY
有赞技术团队
有赞技术团队
Martin Fowler
Martin Fowler
罗磊的独立博客
The Last Watchdog
The Last Watchdog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
V
Vulnerabilities – Threatpost
美团技术团队
Microsoft Security Blog
Microsoft Security Blog

人人都是产品经理

为什么你的产品找不到差异化?90%的失败都卡在第一步上(下) – 人人都是产品经理, 3年从30万到1300万用户、获2200万美元融资,这个AI教育产品用“抽卡”破解了获客难题 – 人人都是产品经理, 园区招商系统怎么做才能真正帮到去化?我加了这一个功能,推广链接转发400次阅读过万 – 人人都是产品经理, AI大事件:OpenAI发完网络安全模型又搞药物研发,小鹏汽车要抓”DeepSeek时刻” – 人人都是产品经理, 电商不是卖货,是一场更残酷的产品经理实战 – 人人都是产品经理, 没想到,活动营销又回来了! – 人人都是产品经理, 为何All-in海外KOC:一场关于AI时代窗口期的豪赌 – 人人都是产品经理, 重新理解企业的内部协作 – 人人都是产品经理, 苹果的 AI 战略到底是什么? – 人人都是产品经理, 医疗智能体·第2讲——合规护城河:等保、PIPL与HIPAA的架构实战 – 人人都是产品经理, 向量知识库五步法:从“答非所问”到“精准回复” – 人人都是产品经理, 鸿蒙PC三方库构建总指挥HPKBUILD(sha)库为例 – 人人都是产品经理, 何时该用LLM?AI产品经理的LLM设计指南 – 人人都是产品经理, 医疗信息领域的需求方、决策方、准入方以及关注点(二) – 人人都是产品经理, 即梦涨价:一场被误读的「傲慢」 – 人人都是产品经理, 面试AI PM必答题:Hermes和OpenClaw的区别,如何讲清楚业务价值 – 人人都是产品经理, AI的下一张船票:世界模型——AI产品经理必须理解的技术拐点 – 人人都是产品经理, 小红书做GEO,怎么让AI信你?记住这 3 个重要信息 – 人人都是产品经理, 5 家印度 AI 初创公司,看看印度 AI 再做什么 – 人人都是产品经理, AI项目跨团队协作:产品技术业务如何不打架 – 人人都是产品经理, Agentic Workflow(智能体工作流):让AI从”答案生成器”变成”数字员工” – 人人都是产品经理, lycium_plusplus 项目全景解读:OpenHarmony 三方库构建的“大管家” – 人人都是产品经理, 从爆单救火到前置履约:两套预采策略,把生鲜大促履约效率拉满 – 人人都是产品经理, 什么时候该补货?我用一轮数据做了一个决定 – 人人都是产品经理, 从“机械兜底”到“动态分流”:AI客服重复进线治理的4大底层逻辑 – 人人都是产品经理, 抖音拼效率,红书拼洞察 – 人人都是产品经理, 全民狂欢与退潮——为什么龙虾这波热潮冷却得如此之快? – 人人都是产品经理, Stripe押注!MPP重塑全球支付 – 人人都是产品经理, 小红书GEO:AI引用你的内容,不是因为你对,而是因为你看起来可信 – 人人都是产品经理, 前百度副总裁押注办公Agent,日韩付费爆发,Manus迎来强劲对手 – 人人都是产品经理, 企事业单位数字化的业务供需本质 – 人人都是产品经理, 医疗智能体·第1讲——医疗信息化重构:从“辅助软件”到“自主智能体”的范式转移 – 人人都是产品经理, 粉丝量就是空气!!! – 人人都是产品经理, 用户说“薯片碎了”,机器回“要买吗?”:意图识别的翻车与破局 – 人人都是产品经理, RAG召回准确率从75到90 我做对了这三件事 – 人人都是产品经理, AI大事件:Anthropic改收费、OpenAI发安全版、手术机器人纳入医保、阿里发布”秒悟” – 人人都是产品经理, Chrome 推出 Skills 新功能,Agent 重塑上网方式 – 人人都是产品经理, GitHub前创始人拿了a16z的1700万美元,做Agent时代的Git – 人人都是产品经理 拷贝或克隆其他 Flutter OH 项目到本地后无法运行 – 人人都是产品经理, 优惠券设计:优惠券创建 – 人人都是产品经理, 不用死磕文档!AI 助手 1 小时搞定飞书 CLI 安装 + 配置 + 知识库 – 人人都是产品经理, 用小龙虾做竞品分析报告:从2天到20分钟,我是怎么做到的 – 人人都是产品经理 用小龙虾做市场分析报告:搞懂这3个公式,市场规模不再靠猜 – 人人都是产品经理, 你早就在做 Harness 工程,只是不知道它叫这个名字 – 人人都是产品经理, Think Long就够?你可能想多了! – 人人都是产品经理, 货代SRM实战:供应商准入怎么做,才能让资源池不是通讯录而是可交付网络? – 人人都是产品经理, 如何做好用户调研?详解基本技巧 – 人人都是产品经理, 木鸟、途家、美团对打,平台春天行动开“卷” – 人人都是产品经理, 入职才发现公司不靠谱?小红书从业者求职避坑指南 – 人人都是产品经理, 美国 AI 三巨头联手封堵,中国 AI 突围之路在何方 – 人人都是产品经理, 小红书,放在需求对面的镜子 – 人人都是产品经理, AI 会带来大规模失业吗? – 人人都是产品经理, 从出单到补货前,我第一次犹豫:该不该放大? – 人人都是产品经理, Flutter 三方库鸿蒙化适配:5 种高效检查方式,快速判断是否需要适配 – 人人都是产品经理, 从做产品进阶拿结果:医美机构产品经理转岗科室运营经理 – 人人都是产品经理, 阿里HappyHorse,一场关于“Token经济”的阳谋 – 人人都是产品经理, To B AI:客户留存落地的观察与思考 – 人人都是产品经理, AI产品的“生命线”——数据采集、标注、清洗的产品化设计 – 人人都是产品经理, 谈谈AI Agent(二):当“孩子”能自己“体验世界”时,你该学什么? – 人人都是产品经理, UI/UX设计师的3层能力进阶,前两层让你活下来,第三层…才是真正的分水岭 – 人人都是产品经理, 2分钟 → 30秒,效率提升75%:B端产品经理如何用「规则枷锁」驯服AI幻觉? – 人人都是产品经理, 还没来得及学OpenClaw,来了个更猛的:Hermes Agent – 人人都是产品经理, AI日报:宇树机器人跑出10m/s刷新世界纪录 – 人人都是产品经理, 一文说透基金互金如何用情绪价值引导用户决策做转化 – 人人都是产品经理, 当浏览器开始替你”看”网页:AI 浏览器正在亲手拆掉它脚下的那张网 – 人人都是产品经理, 0代码,一天时间我Vibe Coding了个网站 – 人人都是产品经理, Hermes 和 OpenClaw 之争,Agent 的能力应该“装上去”还是“长出来”? – 人人都是产品经理 视频生成的“桌子”,字节Seedance 2掀完,阿里快乐马掀 – 人人都是产品经理, 从听不懂到完全信任:我的 Codex 深度产品体验 – 人人都是产品经理, 当虚拟偶像有了北京户口,与真人偶像还有什么区别? – 人人都是产品经理, 会说,远远比会做更重要 —— 对 SBTI 爆火现象的五层观察 – 人人都是产品经理, AI产品经理必看:当“搭环境”比“选模型”更重要,你的认知还在2024年吗? – 人人都是产品经理, 2026年AI产品商业化核心逻辑:从功能demo到规模化营收的3个必破卡点 – 人人都是产品经理, 京东围绕供应链,卷起裤腿下场的那些事儿 – 人人都是产品经理, SBTI一夜刷屏:它赢在了“太会说人话” – 人人都是产品经理, 折扣零售的真相:不是便宜,而是价值感! – 人人都是产品经理, 和甲方吵了一架,最后加钱做了——我学到的ToB产品经理生存法则 – 人人都是产品经理, 和几位小红书操盘手聊了8小时,干货全在这 – 人人都是产品经理, 智谱GLM-5.1登场,开源模型首超Opus4.6!!! – 人人都是产品经理 Anthropic收入凭什么反超OpenAI,终于有人把这事说清楚了 – 人人都是产品经理, 史上最有故事感的技术报告——Claude最强模型Mythos 7个极其精彩的细节 – 人人都是产品经理, 模型不是壁垒,Harness 也不是 – 人人都是产品经理, 抖音本地生活业务思考21 – 人人都是产品经理, Superpowers:145k Star的AI编码框架,到底是什么来头? Superpowers:145k Star的AI编码框架,到底是什么来头? – 人人都是产品经理, OpenAI 的路走错了,Anthropic Harness 解法启示:模型需要实践专科生 – 人人都是产品经理, 画原型图的前一步:设计站点地图 – 人人都是产品经理, 给 DeepSeek 的最后一封催更信 – 人人都是产品经理, 手把手教你用 Claude Code 搭建 AI 营销团队:5 个 Agent、12 项技能,独立完成研究、写作、设计全流程 – 人人都是产品经理, 你以为大模型在学语言?不,它在重新发明语言学 – 人人都是产品经理 所谓Skill,不过是AI时代的工业垃圾 – 人人都是产品经理, 聊一聊内容传播的几个方法 – 人人都是产品经理, 当平台开始吃掉生态:从 OpenClaw 被封杀,读懂 Anthropic 的这盘棋 – 人人都是产品经理, 你装了 10 个 AI 插件,Obsidian 还是一个文件夹 – 人人都是产品经理 关于AI智能体架构演进的系统性思考:从单体试水到多体协同的重构 – 人人都是产品经理, 当“人”变成Skill,我们又该何去何从? – 人人都是产品经理 Mythos 事件:前沿 AI 治理的意外实验 – 人人都是产品经理, 货代CRM:信用与风险管理怎么做,才能把坏账风险拦在放货之前? – 人人都是产品经理, 从HR收集自拍照到员工自助录入——我见证了园区人脸识别从”不可用”到”真好用”的全过程 – 人人都是产品经理 千问闯关AI混沌期:阿里画靶,吴嘉张弓,马云射箭? – 人人都是产品经理,
【小而美】HarmonyOS官方模板优秀案例(第5期:工具行业 · 日历应用)
华为开发者联盟 · 2025-08-28 · via 人人都是产品经理

💡 鸿蒙生态为开发者提供海量的HarmonyOS模板/组件,助力开发效率原地起飞 💡

★ 一键直达生态市场组件&模板市场 , 快速应用DevEco Studio插件市场集成组件&模板 ★

工具行业群英荟萃,是小而美应用的主要聚集赛道

本期介绍的案例是其中一类:日常刚需的日历应用

👉 覆盖20+行业,本帖以汇总形式持续更新中,点击收藏!一键三连!常看常新!

【第5期】工具行业 · 日历应用

一、概述

1、行业洞察

行业诉求:

日历类应用,未来竞争将聚焦于 AI 驱动的个性化体验、场景化生态构建及文化适配能力正从单一工具进化为连接工作、生活、社交的 “时间操作系统”。

商业模式是日历类应用的重要场景诉求,目前免费增值为主,差异化变现破局,如何结合小艺做个性化推荐是差异化的根本。

满足用户的进阶需求:社交协作,隐私保护。

行业常用三方SDK

SDK链接:岳鹰全景监控SDk支付宝支付 SDK穿山甲广告SDK快手联盟广告SDK友盟SDK腾讯微信SDK腾讯优量汇极光 SDK高德地图百度地图腾讯地图定位高德地图定位

说明:“以上三方库及链接仅为示例,三方库由三方开发者独立提供,以其官方内容为准”

2、案例概览(下载模板

基于以上行业分析,本期将介绍鸿蒙生态市场生活服务类行业模板——日历应用模板,为行业提供常用功能的开发案例,模板主要分为万年历、黄历、和我的三大模块。

  • Stage开发模型 + 声明式UI开发范式。
  • 分层架构设计 + 组件化拆分,支持开发者在开发时既可以选择完整使用模板,也可以根据需求单独选用其中的业务组件。
  • 本模板已集成华为账号等服务,只需做少量配置和定制即可快速实现华为账号的登录。

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

日历模板

 |-- 万年历

 |    |-- 日历选择

 |    |-- 吉日查询

 |    |-- 日期计算

 |    |-- 节日节气

 |    └-- 宜忌展示

 |-- 黄历

 |    |-- 日期切换

 |    |-- 宜忌展示

 |    |-- 五行、冲煞

 |    |-- 彭祖百忌

 └-- 我的

 |     |-- 个人信息

 |     └-- 设置

 |       └-- 主题切换

 |       └-- 隐私协议

 |       └-- 用户协议

二、应用架构设计

1、分层模块化设计

产品定制层:专注于满足不同设备或使用场景的个性化需求,作为应用的入口,是用户直接互动的界面。

本实践暂时只支持直板机,为单HAP包形式,包含路由根节点、底部导航栏等。

基础特性层:用于存放相对独立的功能UI和业务逻辑实现。

本实践的基础特性层将应用底部导航栏的每个选项拆分成一个独立的业务功能模块。

每个功能模块都具备高内聚、低耦合、可定制的特点,支持产品的灵活部署。

公共能力层:存放公共能力,包括公共UI组件、数据管理、外部交互和工具库等共享功能。

本实践的公共能力层分为公共基础能力和可分可合组件,均打包为HAR包被上层业务组件引用。

公共基础能力包含日志、文件处理等工具类,公共类型定义,网络库,以及弹窗、加载等公共组件。

可分可合组件将包含行业特点、可完全自闭环的能力抽出独立的组件模块,支持开发者在开发中单独集成使用,详见业务组件设计章节。

2、业务组件设计

为支持开发者单独获取特定场景的页面和功能,本模板将功能完全自闭环的部分能力抽离出独立的行业组件模块,不依赖公共基础能力包,开发者可以单独集成,开箱即用,降低使用难度。

三、行业场景技术方案

1、个人信息

场景说明

支持华为账号一键登录及其他方式(账号密码登录)。

用户登录后展示昵称和头像,点击用户信息栏可进入用户主页,查看并编辑个人信息和历史动态。

支持添加重要提醒(日程、生日、纪念日、代办),更新提醒,删除提醒。

技术方案

华为账号一键登录

通过Account Kit实现华为账号一键登录,并获取用户手机号,关联应用已有用户。

头像修改

通过Scenario Fusion Kit提供的选择头像Button快速拉起头像选择页面,供用户完成华为账号头像或其他头像的选择与展示。

重要提醒

通过@kit.CalendarKit提供的提供日历与日程管理能力将应用中的工作、生活中与时间相关的日程服务与系统日历进行集成,从而实现日程管理、事件创建、查询等功能。

主题切换

通过全局主题对象,控制全局的主题颜色切换,并使用持久化存储当前主题选择。

代码参考

部分核心代码参见华为账号一键登录实现章节。

2、黄历

场景说明

    • 支持根据日期查看当日黄历信息。
    • 切换日期查询其他日期黄历。
    • 根据选择日期查看今日宜今日忌。
    • 支持根据选择的黄历查看白话文。

技术方案

根据万年历选择日期进行对应日期黄历的展示。

通过日历选择组件暴露的句柄,感知当前选择的日期,并通过句柄同步修改万年历对应的日期。

代码参考

部分核心代码参见黄历实现章节。

3、万年历

  • 场景说明

支持日历查看,日期切换,设置周首日。

支持查看今日宜,今日忌。

支持实用工具查询(吉日查询,日期计算,节日节气)。

支持查看城市限行。

支持查看历史上的今天。

技术方案

日历查看

通过使用Swiper组件结合计算每月的日期实现日期轮播查看。

头像修改

通过Scenario Fusion Kit提供的选择头像Button快速拉起头像选择页面,供用户完成华为账号头像或其他头像的选择与展示。

实用工具

使用工具结合DatePicker日期选择器,实现日期选择并根据条件计算。

城市限行

通过申请位置权限,或者当前城市的限行车牌尾号,并进行展示。

代码参考

部分核心代码参见万年历实现章节。

四、模板代码

1、工程结构下载模板

详细代码结构如下所示:

Application

├──├──commons

│   ├──common                                // 公共能力层

│     ├──src/main/ets                        // 基础能力

│     │  └──components                       // 公共组件

│     │  └──dividerTmp                       // 下划线公共组件

│     │  └──https                            // 网络请求库

│     │  └──models                           // 公共接口常量

│     │  └──quickLogin                       // 华为账号一键登录

│     │  └──style                            // 公共样式

│     │  └──utils                            // 工具类

│     │  └──viewmodels                       // 接口层

│     └──Index.ets                           // 对外接口类

│  ├──router_module                          // 全局路由组件

├──├──components                             // 公共组件

│   ├──base_apis                             // 通用组件(模态框,弹窗,选择器等)

│   ├──base_calendar                         // 日历组件

│   ├──calendar_almanac                      // 黄历组件

│   ├──calendar_events                       // 重要提醒组件

│   ├──date_calculation                      // 日期计算组件

│   ├──festival_solar                        // 节日节气组件

│   ├──login_info                            // 登录组件组件

│   ├──vip_center                            // 开通会员组件

│   ├──traffic_restriction                   // 城市限行组件

│   ├──yiji_query                            // 宜忌查询组件

├──features                                  // 基础特性层

│  ├──almanac/src/main/ets                   // 黄历

│  │  ├──pages                               // 首页入口

│     │  ├──AlmanacView                      // 黄历入口

│  ├──almanac/src/main/resources             // 资源文件目录

│  ├──almanac/Index.ets                      // 对外接口类

│  ├──perpetual/src/main/ets                 // 万年历

│  │  ├──components                          // 万年历组件

│  │  ├──pages                               

│     │  ├──PerpetualCalendar                // 万年历组件入口

│  ├──perpetual/src/main/resources           // 资源文件目录

│  ├──perpetual/Index.ets                    // 对外接口类

│  ├──mine/src/main/ets                      // 我的(包含一键登录)

│  │  └──pages                               // 我的入口页

│     │  ├──MinePage                         // 登录

│  │  └──components                          // 我的页面入口

│  └──mine/src/main/resources                // 资源文件目录

└─product/entry/src/main   

   ├─ets

   │  ├─widget

   │  │  ├──pages            

   │  │      ├──WidgetCard.ets       // 服务卡片    

   │  ├─entryability

   │  │      ├──EntryAbility.ets             // 应用程序入口

   │  ├─page

   │  │  ├──Index.ets                        // 入口

   │  │  ├──PrivacyPage.ets                  // 隐私协议   

   │  │  ├──SafePage.ets                     // 隐私协议弹窗  

   │  │  ├──SplashPage.ets                   // 闪屏页        

   │  │  ├──TabContainer.ets                 // tab页入口

   └─resources

2、关键代码解读

本篇代码非应用的全量代码,只包括应用的部分能力的关键代码。

若需获取全量代码,请查看模板集成章节。

个人信息

华为账号一键登录

​typescript

    getQuickLoginAnonymousPhone() {

    // 创建授权请求,并设置参数

    const authRequest = new authentication.HuaweiIDProvider().createAuthorizationWithHuaweiIDRequest();

    // 获取手机号需要传如下scope,传参数之前需要先申请对应scope权限,才能返回对应数据

    authRequest.scopes = ['quickLoginAnonymousPhone'];

    authRequest.permissions = ['serviceauthcode'];

    // 用户是否需要登录授权,该值为true且用户未登录或未授权时,会拉起用户登录或授权页面

    authRequest.forceAuthorization = false;

    // 用于防跨站点请求伪造

    authRequest.state = util.generateRandomUUID();

    try {

      const controller = new authentication.AuthenticationController(getContext(this));

      controller.executeRequest(authRequest).then((response) => {

        const authorizationWithHuaweiIDResponse = response as authentication.AuthorizationWithHuaweiIDResponse;

        const state = authorizationWithHuaweiIDResponse.state;

        if (state !== undefined && authRequest.state !== state) {

          hilog.error(0x0000, 'testTag', `Failed to authorize. The state is different, response state: ${state}`);

          return;

        }

        hilog.info(0x0000, 'testTag', 'Succeeded in authentication.');

        const authorizationWithHuaweiIDCredential = authorizationWithHuaweiIDResponse.data!;

        const code = authorizationWithHuaweiIDCredential.authorizationCode;

        const unionID = authorizationWithHuaweiIDCredential.unionID;

        const openID = authorizationWithHuaweiIDCredential.openID;

        const anonymousPhone = authorizationWithHuaweiIDCredential?.extraInfo?.quickLoginAnonymousPhone as string;

        if (anonymousPhone) {

          hilog.info(0x0000, 'testTag', 'Succeeded in authentication.');

          this.quickLoginAnonymousPhone = anonymousPhone;

          return;

        } else {

          this.quickLoginAnonymousPhone = '123xxxxxx456'

        }

        // 开发者处理code、unionID、openID

        this.authorizationCode = code

      }).catch((err: BusinessError) => {

        this.dealAllPhoneError(err);

      });

    } catch (error) {

      this.dealAllPhoneError(error);

    }

  }

重要提醒

typescript

class CalendarManage {

  context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;

  private static _instance: CalendarManage

 

  static get instance() {

    if (!CalendarManage._instance) {

      CalendarManage._instance = new CalendarManage()

    }

    return CalendarManage._instance

  }

 

  public getCalendarPermission(): Promise<string> {

    const permissions: Permissions[] = ['ohos.permission.READ_CALENDAR', 'ohos.permission.WRITE_CALENDAR'];

    let atManager = abilityAccessCtrl.createAtManager();

    return new Promise((resolve, reject) => {

      atManager.requestPermissionsFromUser(this.context, permissions).then((result: PermissionRequestResult) => {

        resolve('success')

      }).catch((error: BusinessError) => {

        reject('failed')

        console.error(`get Permission error, error. Code: ${error.code}, message: ${error.message}`);

      })

    })

  }

 

  /*

    * 添加提醒到日历

    * */

  private async calendarEvent(calendar: calendarManager.Calendar,

    calendarInfo: UserEventItem): Promise<CalendarInfo> {

    const event: calendarManager.Event = {

      title: calendarInfo.content,

      type: calendarManager.EventType.NORMAL,

      id: calendarInfo.eventId,

      isLunar:calendarInfo.date[0].isLunar,

      startTime: new Date(dayjs(calendarInfo.date[0].date).format('YYYY-MM-DD') + ' ' +

      calendarInfo.date[0].time).getTime(),

      endTime: new Date(dayjs(calendarInfo.date[1].date).format('YYYY-MM-DD') + ' ' +

      calendarInfo.date[1].time).getTime(),

      reminderTime: CalendarManage.getReminderTime(calendarInfo.remindList),

      recurrenceRule: {

        recurrenceFrequency: repeatMap[calendarInfo.repeatType],

      },

    };

    return new Promise(async (resolve, reject) => {

      if (calendarInfo.eventId) {

        calendar.updateEvent(event).then(() => {

          resolve({

            status: 'success',

          })

        }).catch((err: BusinessError) => {

          console.error(`Failed to update event. Code: ${err.code}, message: ${err.message}`);

        });

      } else {

        calendar.addEvent(event).then((data: number) => {

          console.info(`Succeeded in adding event, id -> ${data}`);

          resolve({

            status: 'success',

            data: data,

          })

        }).catch((err: BusinessError) => {

          resolve({

            status: 'failed',

          })

        });

      }

    })

  }

  /*

    * 根据提醒参数创建日历参数

    * */

  public async calendarEventCreate(calendarInfo: UserEventItem, operationType?: string): Promise<CalendarInfo> {

    if (calendarInfo.remindList[0] === '不提醒') {

      return {

        status: 'not need calendar',

      }

    }

    let permission = await this.getCalendarPermission()

    if (permission !== 'success') {

      return {

        status: 'permission failed',

      }

    }

    let calendar: calendarManager.Calendar | undefined = undefined;

    // 指定日历账户信息

    const calendarAccount: calendarManager.CalendarAccount = {

      name: '日历模板',

      type: calendarManager.CalendarType.LOCAL,

      // 日历账户显示名称,该字段如果不填,创建的日历账户在界面显示为空字符串。

      displayName: '日历模板',

    };

    let calendarMgr: calendarManager.CalendarManager | null = calendarManager.getCalendarManager(this.context);

    // 创建日历账户

    try {

      calendar = await calendarMgr?.createCalendar(calendarAccount)

      let res: CalendarInfo

      if (operationType === 'delete') {

        res = await this.calendarEventDelete(calendar, calendarInfo)

      } else {

        res = await this.calendarEvent(calendar, calendarInfo)

      }

      return res

    } catch (e) {

      return {

        status: 'calendar operation failed',

      }

    }

  }

  /*

    * 删除已经添加到日历的提醒

    * */

  private async calendarEventDelete(calendar: calendarManager.Calendar,

    calendarInfo: UserEventItem): Promise<CalendarInfo> {

    try {

      await calendar.deleteEvent(calendarInfo.eventId)

      return {

        status: 'success',

      }

    } catch (e) {

      return {

        status: 'failed',

      }

    }

  }

}

黄历

重要提醒

typescript

/**

 * 抛出句柄

 */

export class CalendarController {

     public static vm: CalendarVM = CalendarVM.instance;

   

     public setSelectDate(date: Date) {

       CalendarController.vm.changeDate(date)

     }

   

     public getTodayYiJi() {

       CalendarController.vm.getTodayYiJi()

     }

}

切换日期

​typescript

/**

 * 切换日期

 */  

public changeDate(date: Date) {

    let gap = (date.getFullYear() - this.curDate.year()) * 12 + date.getMonth() - this.curDate.month()

    this.dateListSource.clearData()

    let i = -2

    while (i <= 2) {

      let month = this.getDateList(i + gap)

      this.dateListSource.pushData(month)

      i++

    }

    this.curIndex = 2

    this.selectDate = dayjs(date)

 }

获取今日宜和忌

​typescript

/**

 * 获取今日宜和忌

 */  

public getTodayYiJi() {

    const todayLunar = Lunar.fromDate(new Date(this.selectDate.format('YYYY-MM-DD')));

    const yi = todayLunar.getDayYi();

    const ji = todayLunar.getDayJi();

    this.todayYiJi = {

      yi,

      ji,

    }

  }

万年历

展示日历

typescript

/**

 * 展示日历

 */  

Swiper(this.swiperController) {

        LazyForEach(this.vm.dateListSource, (item: DateModelList) => {

          Grid() {

            ForEach(item, (item: DateModel) => {

              GridItem() {

              }

            },(item: DateModel) => JSON.stringify(item));

          }

          .columnsTemplate('1fr 1fr 1fr 1fr 1fr 1fr 1fr')

          .maxCount(7)

          .columnsGap(0)

          .rowsGap(0)

          .padding({ bottom: 20 })

        },(item: DateModelList) => JSON.stringify(item));

}

获取位置权限

typescript

/**

 * 获取位置权限

 */  

getCurrentLocation() {

    this.permissionRequestUtils.locationPermissionRequest().then(async (res) => {

      if (res === 'success') {

        this.locationPermission = res

        this.permissionRequestUtils.getCurrentLocation().then((res: string) => {

          this.location = res

        }).catch((err:BusinessError) => {

          this.location = '北京'

        })

      } else {

        this.dealError()

      }

    }).catch(() => {

      this.dealError()

    })

}

3、模板集成

本模板提供了两种代码集成方式,供开发者自由选用。

整体集成下载模板

开发者可以选择直接基于模板工程开发自己的应用工程。

模板代码获取:

通过IDE插件创建模板工程,开发指导

通过生态市场下载源码,下载模板

通过开源仓访问源码,仓库地址

打开模板工程,根据README说明中的快速入门章节,将自己的应用信息配置在模板工程内,即可运行并查看模板效果。

对接开发者自己的服务器接口,转换数据结构,展示真实的云侧数据。

将commons/lib_common/src/main/ets/httprequest/HttpRequestApi.ets文件中的mock接口替换为真实的服务器接口。

在commons/lib_common/src/main/ets/httprequest/HttpRequest.ets文件中将云侧开发者自定义的数据结构转换为端侧数据结构。

根据自己的业务内容修改模板,进行定制化开发。

按需集成

若开发者已搭建好自己的应用工程,但暂未实现其中的部分场景能力,可以选择取用其中的业务组件,集成在自己的工程中。

组件代码获取:

通过IDE插件下载组件源码。开发指导

通过生态市场下载组件源码。下载地址

下载组件源码,根据README中的说明,将组件包配置在自己的工程中。

根据API参考和示例代码,将组件集成在自己的对应场景中。

以上是第五期“工具行业-日历应用”行业优秀案例的内容,更多行业敬请期待~

欢迎下载使用行业模板“点击下载”,若您有体验和开发问题,或者迫不及待想了解XX行业的优秀案例,欢迎在评论区留言,小编会快马加鞭为您解答~

同时诚邀您添加下方二维码加入“组件模板活动社群”,精彩上新&活动不错过!

👉 系列持续更新,欢迎收藏本帖!

HarmonyOS官方模板优秀案例 | 便捷生活行业 · 购物中心-点击查看

HarmonyOS官方模板优秀案例 | 新闻行业 · 综合新闻-点击查看

HarmonyOS官方模板优秀案例 | 教育行业 · 教育备考-点击查看

HarmonyOS官方模板优秀案例 | 餐饮行业 · 美食菜谱-点击查看

HarmonyOS官方模板优秀案例 | 工具行业 · 日历应用-点击查看

👉 HarmonyOS组件模板相关推荐

  • 【活动ing】HarmonyOS组件/模板集成创新活动,报名时间截止2025年8月30日,点击查看
  • 鸿蒙应用开发者激励计划2025,点击查看