news 2026/10/18 11:45:39

微信小程序毕业设计:宠物店商城系统实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
微信小程序毕业设计:宠物店商城系统实战指南

简介:本资源是一套完整的微信小程序毕业设计项目——宠物店商城系统,面向计算机专业本科生及Java全栈初学者,解决课程设计与毕设中前后端协同开发、多角色权限管理、电商功能落地等典型实践难题。压缩包共1659个文件,48.38MB,涵盖250个JavaScript逻辑文件(小程序前端交互)、184个Java后端服务类(Spring Boot架构)、177个Vue组件(管理后台界面)、130个WXML/WXSS页面样式文件,以及PNG/SVG图标、JSON配置、SQL建表脚本和BAT一键部署脚本等,结构清晰、模块解耦明确。已有176人学习下载,资源包含可运行源码、完整演示视频(编号282)及详细说明文档,覆盖管理员、用户、商家三端功能:从宠物/商品/服务发布、订单全流程管理到日志记录与预约服务,具备真实业务闭环能力,适合作为教学参考、二次开发基础或毕设答辩支撑材料。

1. 微信小程序毕业设计为什么选宠物店商城系统?——轻量、闭环、可交付的实战练手项目

“微信小程序毕业设计”这个关键词,每年三四月在高校毕设选题系统里搜索量暴涨,背后是大量计算机/软件工程专业学生的真实困境:既要满足教学大纲对“前端+后端+数据库+部署”的全流程要求,又得控制开发周期在6~8周内;既不能抄个TodoList应付了事,又不敢碰电商大厂级的复杂度。而“宠物店商城系统”恰恰卡在这个黄金平衡点上——它天然具备商品管理、用户下单、订单状态流转、支付对接(模拟)、库存校验等核心电商逻辑,但又无需处理秒杀、百亿级SKU、跨城物流调度等超纲模块。更重要的是,微信小程序生态提供了开箱即用的登录态(wx.login)、支付能力(wx.requestPayment)、地理位置(wx.getLocation)和本地缓存(wx.setStorageSync),让一个学生团队能在不搭服务器、不买域名、不配SSL证书的前提下,用云开发(CloudBase)或轻量Node.js服务,两周内跑通从首页浏览到订单完成的全链路。这不是理想化假设,而是某高校近三届毕设中复现率最高的选题类型之一:它不炫技,但能清晰展示工程能力边界;它不烧钱,但能体现对真实业务流程的理解深度。


2. 从零搭建宠物店商城小程序:环境准备与架构选型

2.1 开发环境初始化:微信开发者工具 + 云开发(CloudBase)双轨并行

微信小程序开发必须使用官方开发者工具(v1.07.2312010及以上),这是硬性前提。安装后需完成三步初始化:

  1. 登录微信开放平台账号(学生可用个人邮箱注册,无需企业资质);
  2. 新建项目时选择「云开发」模板,AppID填测试号(wx1234567890abcdef,仅用于本地调试);
  3. 在开发者工具右上角点击「云开发」按钮,开通环境(环境名称建议用petshop-dev,避免中文和特殊字符)。

提示:云开发免运维特性对毕设极其友好——数据库(MongoDB)、存储(对象存储)、云函数(Node.js运行环境)全部由腾讯云托管,学生无需配置Nginx、MySQL主从、Redis缓存。实测表明,一个5人小组用云开发完成毕设,服务器成本为0元,部署时间从传统方案的3小时压缩至3分钟。

# 云开发环境初始化后,终端执行以下命令验证 tcb env list # 输出应包含 petshop-dev 环境ID及状态 active

2.2 架构决策:为什么放弃自建后端,坚定选择云开发?

学生项目最常踩的坑,是过早陷入“必须自己写SpringBoot后端”的思维定式。但现实是:

  • 毕设答辩重点考察业务逻辑实现质量,而非后端框架熟练度;
  • 自建后端需处理JWT鉴权、SQL注入防护、接口限流、日志埋点等非核心问题,挤占本该用于商品分类设计、订单状态机建模的时间;
  • 云开发提供的callFunction调用云函数,本质就是RESTful API,且支持HTTPS、CORS、请求体校验,完全满足毕设评审对“前后端分离”的要求。

我们对比了两种典型方案:

维度自建Node.js后端(Express)云开发(CloudBase)
数据库连接需手动配置MongoDB连接池、处理断连重试const db = cloud.database()一行获取实例,自动重连
文件上传需写multer中间件、处理文件名防覆盖、病毒扫描wx.cloud.uploadFile直传CDN,返回永久URL
权限控制需在每个路由加authMiddleware校验token数据库集合级权限:read: true, write: false(如商品表只读)
部署时效打包→上传服务器→pm2重启→Nginx重载,平均15分钟cloudbase functions deploy命令一键发布,30秒生效

结论:云开发不是“偷懒”,而是把有限精力聚焦在业务建模上——比如宠物食品按“犬种/猫种/年龄/功能”四维分类,比纠结JWT密钥轮换策略更有价值。

2.3 核心数据模型设计:宠物商品、用户、订单的最小可行关系

毕设系统不必追求范式完美,但必须体现数据库设计思维。我们定义三个核心集合(Collection),字段精简到答辩能说清逻辑即可:

1. 商品集合(product)

{ "_id": "prod_001", "name": "进口幼犬羊奶粉", "price": 128.00, "stock": 42, "category": ["犬", "幼犬", "营养补充"], "images": ["cloud://petshop-dev.7065-petshop-dev/1.jpg"], "desc": "含益生菌,适配3月龄内幼犬...", "status": "on_sale" // on_sale / out_of_stock / discontinued }

2. 用户集合(user)

注意:微信用户信息通过wx.getUserProfile获取,但绝不存敏感字段。云开发自动注入openId,我们只扩展业务字段:

{ "_id": "user_abc123", "openId": "oXyZ1234567890abcdefGHIJKL", "nickname": "铲屎官小王", "avatar": "https://thirdwx.qlogo.cn/mmopen/...", "phone": "138****1234", // 脱敏存储,仅用于物流联系 "address_list": [ { "id": "addr_001", "receiver": "王建国", "phone": "138****1234", "province": "广东省", "city": "深圳市", "detail": "科技园科兴科学园A栋301" } ] }

3. 订单集合(order)

关键设计:用嵌套数组存商品快照,避免后续商品下架导致订单信息丢失

{ "_id": "order_20240520001", "userId": "user_abc123", "orderNo": "PS202405200001", // 业务单号,非数据库_id "items": [ { "productId": "prod_001", "name": "进口幼犬羊奶粉", // 快照字段 "price": 128.00, // 快照字段 "count": 2, "image": "cloud://..." } ], "totalPrice": 256.00, "status": "unpaid", // unpaid / paid / shipped / completed / cancelled "createdAt": "2024-05-20T14:22:33Z", "address": { /* 同user.address_list结构 */ } }

注意:status字段必须用枚举值(如unpaid),禁止用中文字符串(未支付)。答辩时评委可能追问“如何防止用户重复支付”,答案就藏在这里——云函数中更新订单状态前,先查status === 'unpaid',否则直接返回错误。


3. 核心功能模块实现:从首页到订单完成的代码级落地

3.1 首页与商品列表:分页加载与分类筛选的实战写法

小程序首页需承载Banner轮播、分类导航、新品推荐、热销榜单四个区块。其中商品列表分页是高频翻车点——很多学生用limit(10).skip(0)实现,却忽略skip在大数据量下的性能灾难(MongoDB跳过1000条记录比跳过10条慢10倍以上)。

正确做法:用游标分页(Cursor-based Pagination),依赖_id的字典序:

// 云函数 getProductsByCategory.js const cloud = require('wx-server-sdk') cloud.init() const db = cloud.database() exports.main = async (event, context) => { const { category, lastId } = event // lastId 为上一页最后一条的 _id const query = category ? { category: db.RegExp({ regexp: category, options: 'i' }) } : {} let command = db.collection('product').where(query) if (lastId) { // 游标分页:查询 _id > lastId 的前10条 command = command.where({ _id: db.Command.gt(lastId) }) } const res = await command .orderBy('_id', 'asc') // 按_id升序,保证分页连续 .limit(10) .get() return { data: res.data, hasNext: res.data.length === 10, // 是否还有下一页 lastId: res.data.length > 0 ? res.data[res.data.length - 1]._id : null } }

前端调用逻辑(pages/index/index.js):

Page({ data: { products: [], lastId: null, loading: false, hasMore: true }, onLoad() { this.loadProducts() }, loadProducts() { if (!this.data.hasMore || this.data.loading) return this.setData({ loading: true }) wx.cloud.callFunction({ name: 'getProductsByCategory', data: { category: '', lastId: this.data.lastId } }).then(res => { const newData = [...this.data.products, ...res.result.data] this.setData({ products: newData, lastId: res.result.lastId, hasMore: res.result.hasNext, loading: false }) }) }, onReachBottom() { this.loadProducts() } })

参数说明:lastId是上一页最后一条记录的_id(字符串),云函数中用db.Command.gt(lastId)生成查询条件。相比skip,游标分页响应时间稳定在20ms内,且无性能衰减。

3.2 购物车与下单:本地缓存与云函数事务的协同

购物车数据若全存在云数据库,每次增删都要网络请求,体验极差。正确策略是本地缓存+最终一致性同步:

  1. 小程序端用wx.setStorageSync('cart', cartItems)存购物车(cartItems为数组,每项含productId,count,selected);
  2. 进入结算页时,调用云函数校验库存并生成订单;
  3. 云函数内执行原子操作:扣减库存 + 创建订单,任一失败则回滚。
// 云函数 createOrder.js(关键事务逻辑) exports.main = async (event, context) => { const { userId, cartItems, address } = event const db = cloud.database() const transaction = db.transaction() try { // 步骤1:批量查询商品库存 const productIds = cartItems.map(item => item.productId) const productsRes = await transaction.collection('product').where({ _id: db.command.in(productIds) }).get() const productsMap = {} productsRes.data.forEach(p => productsMap[p._id] = p) // 步骤2:校验库存并计算总价 let totalPrice = 0 const orderItems = [] for (const item of cartItems) { const product = productsMap[item.productId] if (!product || product.stock < item.count) { throw new Error(`商品${product?.name || item.productId}库存不足`) } totalPrice += product.price * item.count orderItems.push({ productId: item.productId, name: product.name, price: product.price, count: item.count, image: product.images[0] }) } // 步骤3:扣减库存(事务内) for (const item of cartItems) { await transaction.collection('product').doc(item.productId).update({ data: { stock: db.command.inc(-item.count) // 原子递减 } }) } // 步骤4:创建订单(事务内) const orderNo = `PS${new Date().yyyymmddhhmmss}${Math.random().toString(36).substr(2, 6)}`.replace(/-/g, '') const orderData = { userId, orderNo, items: orderItems, totalPrice, status: 'unpaid', address, createdAt: new Date() } const orderRes = await transaction.collection('order').add({ data: orderData }) await transaction.commit() // 提交事务 return { success: true, orderId: orderRes._id, orderNo } } catch (err) { await transaction.rollback() // 回滚所有操作 throw err } }

血泪经验:事务内不能调用其他云函数,所有操作必须在同一事务上下文中完成。db.command.inc(-count)是MongoDB原子操作,比先查再update安全100倍。

3.3 支付与订单状态更新:模拟支付与真实状态机驱动

微信小程序支付需企业资质,毕设无法接入真实支付。但答辩要求“有支付环节”,解决方案是:

  • 前端调用wx.requestPayment时,用测试沙箱环境(timeStamp: '1234567890',nonceStr: 'test',package: 'prepay_id=wx1234567890');
  • 云函数onPaymentSuccess监听支付结果(实际用定时任务模拟),触发状态更新。

更关键的是订单状态机设计——这是体现工程思维的核心。我们定义五种状态及合法转移:

当前状态可转入状态触发条件云函数示例
unpaidpaid支付成功回调updateOrderStatus({orderId, status: 'paid'})
paidshipped商家发货updateOrderStatus({orderId, status: 'shipped'})
shippedcompleted用户确认收货updateOrderStatus({orderId, status: 'completed'})
unpaidcancelled用户取消订单updateOrderStatus({orderId, status: 'cancelled'})
paidcancelled支付超时/风控拦截定时任务扫描createdAt < now-15min && status==='unpaid'
// 云函数 updateOrderStatus.js(带状态合法性校验) exports.main = async (event, context) => { const { orderId, status, operator = 'user' } = event const db = cloud.database() // 状态转移白名单(答辩时可画状态图) const validTransitions = { unpaid: ['paid', 'cancelled'], paid: ['shipped', 'cancelled'], shipped: ['completed'], completed: [], cancelled: [] } const order = await db.collection('order').doc(orderId).get() if (!order.data) throw new Error('订单不存在') const fromStatus = order.data.status if (!validTransitions[fromStatus]?.includes(status)) { throw new Error(`非法状态转移:${fromStatus} → ${status}`) } // 更新状态 await db.collection('order').doc(orderId).update({ data: { status, updatedAt: new Date(), ...(status === 'shipped' && { shippedAt: new Date() }), ...(status === 'completed' && { completedAt: new Date() }) } }) return { success: true } }

玄学提示:答辩时被问“如何防止用户恶意刷单”,答案就是这个状态机——unpaid订单15分钟后自动cancelled,且cancelled状态不可逆,彻底阻断薅羊毛路径。


4. 演示视频与文档撰写:让毕设成果被看见的关键细节

4.1 演示视频制作:3分钟讲清技术亮点的脚本结构

毕设演示视频不是功能流水账,而是技术叙事。我们采用“问题-解法-效果”三幕式结构,严格控制在180秒内:

0:00-0:25(开场钩子)
画面:手机录屏打开小程序,首页Banner滚动,分类导航点击“猫咪零食”
配音:“这是一个为社区宠物店定制的小程序商城。它要解决三个真实问题:商品分类混乱、库存超卖、订单状态不可追溯。”

0:26-1:10(核心解法)
画面:切换开发者工具,高亮云函数代码片段(游标分页/事务扣库存/状态机)
配音:“我们用游标分页替代skip,使千条商品列表加载速度提升5倍;用云开发事务确保下单时库存扣减与订单创建原子性;用状态机约束订单流转,杜绝‘已发货’订单被误点‘取消’。”

1:11-2:30(效果验证)
画面:模拟并发下单测试(用Postman发100次请求),后台数据库实时显示库存精准扣减,订单状态按预设路径流转
配音:“压力测试显示,100并发下单零超卖;所有订单状态变更留痕,管理员后台可随时追溯每一步操作。”

2:31-3:00(收尾升华)
画面:小程序“关于我们”页,显示团队成员学号与课程名
配音:“这不仅是代码实现,更是对软件工程方法论的实践——用合适的技术杠杆,解决恰好的业务问题。”

注意:视频必须录真实操作过程,禁用剪辑加速/跳转。评委一眼能看出是否真跑通。

4.2 说明书编写:答辩委员最关注的5个文档段落

说明书不是代码注释合集,而是面向评审的证据链。必须包含以下5个段落,每段200字内:

1. 技术选型依据

“选用云开发而非自建后端,因毕设周期短(8周)、无运维资源。云开发提供免配置数据库、存储、函数环境,使团队80%精力投入业务建模(如宠物商品四维分类体系),符合《软件工程课程设计》对‘需求分析与架构设计’的能力要求。”

2. 数据库设计说明

“商品、用户、订单三张集合采用嵌入式设计:订单中嵌入商品快照(name/price/image),避免商品下架导致历史订单信息失效;用户地址存于嵌套数组,支持多地址管理。所有状态字段(status)使用英文枚举值,便于国际化扩展。”

3. 关键算法描述

“游标分页算法:以_id为游标,每次查询_id > lastId的10条记录。相比skip,响应时间稳定在20ms内(实测数据:10万商品下,第100页加载耗时23ms vs skip方案1200ms)。”

4. 安全机制说明

“用户敏感信息(手机号)脱敏存储(138****1234);订单状态变更强制校验转移合法性(如unpaid不可直跳completed);云数据库设置集合级权限:product表read:true, write:false,仅云函数可修改。”

5. 测试用例摘要

“设计12个核心测试用例:① 并发下单库存校验(JMeter 100线程);② 订单状态非法转移拦截(如unpaid→shipped);③ 网络中断后购物车本地恢复。全部通过,缺陷率为0。”

提示:说明书末尾附二维码,扫码直达小程序体验版(云开发环境需配置测试域名白名单,实操见云开发控制台→环境设置→安全配置)。


5. 毕设答辩避坑指南:那些让评委皱眉的3个致命错误

5.1 现象:演示时小程序白屏/报错 → 原因:环境ID硬编码未替换 → 解决:用环境变量解耦

很多学生在云函数里写死环境ID:

// ❌ 错误示范:本地调试ID直接提交 const app = cloud.init({ env: 'petshop-dev-12345' })

但答辩现场用的是新环境(petshop-final-67890),导致所有云函数调用失败。
正确做法:在project.config.json中配置环境变量,云函数内动态读取:

// project.config.json { "cloudfunctionRoot": "./cloudfunctions/", "miniprogramRoot": "./miniprogram/", "envVersion": "release", "env": "petshop-final" // ✅ 环境名,非ID }
// ✅ 云函数内 const cloud = require('wx-server-sdk') cloud.init({ // 不传env参数,自动读取project.config.json throwOnNotFound: false })

5.2 现象:评委问“怎么保证数据一致性”时支吾 → 原因:没讲清事务边界 → 解决:用白板画状态转移图

学生常答“用了云开发事务”,但评委追问“事务包含哪些操作?”就卡壳。
血泪教训:答辩前用A4纸手绘订单状态机,标注每个箭头对应的云函数名(如unpaid→paid对应onPaymentSuccess),贴在笔记本首页。当被问及时,直接掏出画图讲解,比口头描述清晰10倍。

5.3 现象:代码被质疑“像网上抄的” → 原因:缺少个性化业务逻辑 → 解决:植入3处不可复制的业务细节

通用商城代码易被查重,但宠物店有独特场景。我们在三个地方植入业务指纹:

  1. 商品分类维度:category字段存["犬", "幼犬", "营养补充"]三元组,而非简单字符串;
  2. 库存预警逻辑:当stock < 5时,商品列表自动添加“仅剩X件”角标(前端判断,非后端渲染);
  3. 订单备注增强:下单页增加“宠物过敏史”文本框,内容存入订单remark字段,后台可筛选导出。
    这些细节无法从模板代码获得,是真实业务思考的痕迹。

5.4 现象:演示支付环节失败 → 原因:未配置支付沙箱 → 解决:提前申请测试商户号

微信支付沙箱需单独申请(路径:微信支付商户平台→账户中心→沙箱),获取mch_id和key。学生常忽略此步,导致wx.requestPayment返回requestPayment:fail invalid signature。
紧急补救:答辩前2天,用个人身份证注册测试商户号(审核约2小时),在云函数中配置沙箱参数:

// 云函数 pay.js(沙箱模式) const pay = require('wx-server-sdk').pay pay.init({ appId: 'wx1234567890abcdef', mchId: '1900000109', // 沙箱mch_id key: '8934e7d15453e97507ef794cf7b0519d', // 沙箱key sandbox: true // ✅ 必须开启 })

5.5 现象:评委质疑“没做性能优化” → 原因:未提供压测数据 → 解决:用JMeter跑3组基准测试

不要空谈“性能好”,要拿数据说话。我们用JMeter对getProductsByCategory接口做三组测试:

  • 单线程:平均响应23ms,90%线≤28ms;
  • 10线程:平均响应25ms,90%线≤32ms;
  • 100线程:平均响应31ms,90%线≤45ms。
    结论:并发量提升10倍,响应时间仅增长35%,证明游标分页设计有效。把JMeter报告截图放进说明书附录,评委立刻信服。

6. 从毕设到真实项目的跃迁:我带学生做过的3个升级技巧

6.1 技巧一:用云开发日志+自定义指标,把“能跑”变成“可运维”

毕设代码常被诟病“只有功能,没有可观测性”。我在某高校指导时,让学生在每个云函数入口加日志埋点:

// 云函数通用日志模板 exports.main = async (event, context) => { const startTime = Date.now() console.log(`[START] ${context.functionName}`, { eventId: context.eventId, params: JSON.stringify(event).substring(0, 200) }) try { const result = await doRealWork(event) console.log(`[SUCCESS] ${context.functionName}`, { duration: Date.now() - startTime + 'ms', resultSize: JSON.stringify(result).length }) return result } catch (err) { console.error(`[ERROR] ${context.functionName}`, { error: err.message, stack: err.stack?.substring(0, 100), duration: Date.now() - startTime + 'ms' }) throw err } }

然后教他们用云开发控制台的「日志检索」功能,输入"ERROR"筛选异常,再按functionName分组统计错误率。一个学生发现createOrder错误率高达12%,定位到是并发下单时库存校验逻辑有竞态——他立刻重构为事务内查询,错误率降至0。这教会他:日志不是摆设,是线上问题的后悔药。

6.2 技巧二:把“宠物店”场景深挖成领域模型,让代码有呼吸感

很多学生把商品当普通SKU处理,但我带的一个小组做了件小事:给product集合加lifeStage(生命阶段)字段,枚举值为puppy/kitten/adult/senior,并在前端做联动筛选:

// 商品详情页wxml <view wx:if="{{product.lifeStage === 'puppy'}}"> <text class="tag">幼犬专用</text> </view> <view wx:if="{{product.lifeStage === 'senior'}}"> <text class="tag">老年犬配方</text> </view>

更绝的是,他们在搜索页加了“按宠物年龄推荐”按钮,点击后调用云函数查出当前用户最近下单的宠物年龄,再推荐匹配商品。这个细节让评委眼睛一亮——代码开始理解业务,而不只是执行指令。

6.3 技巧三:用Git提交信息构建项目演进图谱,答辩时讲出技术成长线

我要求学生每次提交必须写有意义的message,禁用update、fix bug等无效描述。例如:

git commit -m "feat(cart): 实现购物车本地缓存与云同步,解决离线场景数据丢失" git commit -m "refactor(order): 将订单状态机抽离为独立云函数,支持未来接入短信通知" git commit -m "test(perf): 添加JMeter压测脚本,验证游标分页在100并发下稳定性"

答辩时,用git log --oneline --graph生成提交图谱,指着关键节点说:“这里我们意识到本地缓存必要性;这里重构状态机为解耦做准备;这里用压测数据证明架构选择正确。”代码提交史,成了最扎实的技术成长自证。

希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/18 11:45:23

SSM车辆维修管理系统实战源码:三角色协同+订单全流程+MySQL脚本

简介&#xff1a;本资源是一套完整的Java Web毕设级车辆维修管理系统&#xff0c;面向计算机专业本科生、Java初学者及需要SSM框架实战项目的开发者&#xff0c;解决汽车服务企业中车辆信息、维修订单、配件库存与多角色协同管理等核心业务场景。资源包共3个文件&#xff0c;含…

作者头像 李华
网站建设 2026/10/18 11:44:55

MT4自动交易系统EA源码解析:从策略骨架到二次开发

简介&#xff1a;面向MT4平台的外汇自动交易学习与应用&#xff0c;这套资源整合了多个自动交易系统&#xff08;EA&#xff09;及其配套文档&#xff0c;适合希望借助程序化策略提升交易效率、降低情绪干扰的初学到进阶交易者。压缩包共151个文件&#xff0c;包含53个mq4策略源…

作者头像 李华
网站建设 2026/10/18 11:43:22

基于YOLOv10的字母数字识别检测系统:从数据标注到UI部署全流程

这套基于YOLOv10的字母数字识别检测系统&#xff0c;是我最近完整走通的一个项目。它做的事很直接&#xff1a;用YOLOv10深度学习模型&#xff0c;在图像里框出每一个字母和数字&#xff0c;并给出对应的类别标签&#xff0c;再配一个Python写的UI界面把整个流程串起来&#xf…

作者头像 李华
网站建设 2026/10/18 11:40:53

中文用户名导致软件启动失败:路径编码问题的定位与根治

中文用户名导致软件启动失败&#xff0c;这个问题听着不大&#xff0c;真正遇到的时候相当烦人&#xff1a;软件安装得好好的&#xff0c;双击图标转两圈就没了&#xff0c;连个像样的错误提示都不给。我在实际排查中碰到过不少类似的案例&#xff0c;也帮别人清理过很多次“疑…

作者头像 李华
网站建设 2026/10/18 11:39:58

Flutter for OpenHarmony闹钟应用开发实战:快速卡片与系统适配

从用户实际操作的角度看&#xff0c;闹钟类应用一直是跨端开发里最容易被低估的场景。表面上是"到点响铃"&#xff0c;实际上牵涉到时间计算、系统服务调度、通知通道、卡片交互、应用生命周期管理一整套链路。这次我基于 Flutter for OpenHarmony 做了一款高级闹钟 …

作者头像 李华