淘宝的木鱼小程序下架后,我自己用 uniapp 写了一个

  1. 零 - 博客园老人回归
  2. 一 - 真实背景(淘宝木鱼下架)
  3. 二 - 技术选型与架构
  4. 三 - uniapp 五大踩坑
  5. 四 - 后端架构(基于真实代码)
  6. 五 - App 上架与备案
  7. 六 - AI 话题
  8. 七 - 真心话
  9. 八 - 体验入口 + 微信群

零、先跟大家打个招呼

image.png

打开博客园后台看了一眼,上次发文章已经是9年以前了,见上图,有几篇文章还是草稿状态。

这几年经历了不少事。换过城市,换过方向,唯一没变的是还在写代码。偶尔深夜翻翻园子里的文章,看到很多老朋友还在坚持分享,心里挺感慨的。

这些年没冒泡,不是因为离开了技术圈,恰恰相反——一直在闷头做事。写业务、做架构、带团队,也终于鼓起勇气,自己从零到一做出了一个完整的产品。

这次回来发文章,一是想跟大家分享这段经历,二是觉得 AI 时代对程序员来说,真的是一次难得的机会。一个人 + AI,能做到的事情比几年前多太多了。

园子里都是搞技术的,我就不整虚的了。下面是我做「睡眠木鱼」这个产品的完整复盘——技术选型、uniapp 踩坑、后端架构、上架备案、AI 提效、国际化……一条一条说清楚。


一、缘起:一个下架的小程序

事情的起因其实很简单。

去年有段时间,我午休和晚上睡前习惯打开淘宝上的一个小程序——一个木鱼应用,可以手动敲木鱼,也有颂钵禅音,听着"笃、笃、笃"的节奏慢慢就睡着了。效果出乎意料地好,成了我每天助眠的必备工具。

但它有两个致命问题:

第一,不支持后台播放。 切到别的 App 或者锁屏,声音就断了。这对一个助眠应用来说基本等于废了一半——你没法定时关闭后安心睡,也不能一边听一边刷别的。

第二,某一天我再打开,发现它下架了。 没有任何替代品可用。

那一刻的想法很简单也很程序员:既然没有,那我自己写一个好了。

就这样,「睡眠木鱼」这个项目开始了。


二、选型与架构

前端技术栈在flutter和uniapp之间选了 uni-app 3.0(基于 Vue 3):

  • 一套代码同时出微信小程序和 Android App,维护成本低
  • Vue 生态我熟,Composition API + TypeScript,上手快
  • 社区还算活跃,常见问题能找到参考
  • 理论上支持 10+ 平台(微信、支付宝、抖音、H5、鸿蒙等),未来扩展空间大

后端选型多说两句。很多人问我为什么用 .NET 而不是 Java / Go / Node,答案很简单:效率优先。

  • 写了很多年 C#,ASP.NET Core + Kestrel 是我最舒服的技术栈
  • 性能足够,到我这个用户量级绰绰有余
  • .NET 10 开发生态已经很成熟:依赖注入、中间件管道、健康检查都是开箱即用
  • 一个人维护,不存在团队协作的语言选型问题

选什么语言不重要,关键是你能用最熟的工具快速把东西做出来。

目前产品覆盖:

  • ✅ 微信小程序(直接搜索【睡眠木鱼】可用)
  • ✅ Android App(还未已上架,蓝凑云有下载链接)
  • 🚧 iOS / 鸿蒙(开发中)

三、uniapp 开发的真实踩坑记录

下面这些坑都是我在这个项目中实际遇到的,分享出来希望能帮到同样在用 uniapp 做产品的朋友。

坑 1:音频播放 —— 最大的技术挑战

这是整个项目最核心的功能,也是耗时最长、踩坑最多的模块。核心矛盾是:用户需要的"后台播放 + 定时关闭",在不同平台上的实现完全不一样。

微信小程序端:

  • InnerAudioContext 切后台就暂停,iOS 和 Android 表现还不一致
  • 要后台播放只能用 BackgroundAudioManager,但这个 API 同时只能管理一个音频实例,跟多音频切换的需求天然冲突
  • 两个 API 之间切换需要专门维护播放状态机,否则会出现"正在播放却显示暂停"“切换音频后进度归零"等各种诡异 Bug

App 端(Android):

  • uniapp 的音频 API 封装了原生播放器,但兼容性一般,部分低端机型解码 .mp3 时会直接报错
  • 锁屏后系统省电策略杀进程 → 音频中断,需要写原生前台服务保活
  • 音频资源最终做了双格式兼容(MP3 + OGG),配合条件编译分别加载

我最终的方案:

  1. 封装统一的 AudioManager 类,内部根据平台自动选择音频 API
  2. 小程序用 BackgroundAudioManager 保后台,App 用原生前台服务
  3. 播放状态用单向数据流管理,所有状态变更通过事件总线通知 UI
  4. 音频资源一律走 对象存储,本地不打包任何音频文件

教训: 如果你的项目重度依赖音频,第一天就去真机上测试后台播放 + 锁屏场景,别等开发完了再踩坑。

坑 2:小程序包体积 —— 差点没上线成功

uniapp 编译出来的初始包轻松破 2MB,而微信小程序主包限制就是 2MB。这个问题不解决,连审核都过不了。

我做了什么:

  • 所有音频,图片资源走 对象存储 在线加载,本地零音频图片文件
  • 部分 UI 改 CSS 绘制减少图片依赖
  • uniapp 分包加载:主包只放首页 + 核心框架,非核心页面全部丢子包
  • uniapp 自带的三方库能删的删,能按需引入的绝不全量导入

一顿操作之后,主包压缩到了 1.8MB 以内,刚好卡线过审。

坑 3:国际化(i18n)的隐形工作量

一开始只想做中文版,后来考虑海外用户,加了英文切换。用了 vue-i18n,本以为是"把文案翻译一遍"的事,结果发现远不止如此。

真正遇到的麻烦:

  • 文案长度差异:中文一行能说完的,英文可能要两行。UI 布局大量硬编码了宽度,切英文后按钮溢出、文字截断,改了一轮 CSS
  • 动态内容翻译:签到提示、课程分类标签、系统通知……这些不是静态文案,是后端返回的,需要前端做映射翻译
  • tabbar的文案切换语言没有生效:暂时还没解决。

建议: i18n 最好从项目第一天就做,至少架构上预留好。后期补的代价远大于一开始就规划。

坑 4:条件编译的代码腐化

uniapp 的 #ifdef / #ifndef 很好用,但当横跨小程序和 App 两端时,代码很容易变成这样:

1
2
3
4
5
6
7
// #ifdef MP-WEIXIN
// 微信登录、支付、分享逻辑……
// #endif

// #ifdef APP-PLUS  
// App 端登录、原生插件调用……
// #endif

业务逻辑里散落着大量条件编译块,三个月后回头看,自己都分不清哪个分支对应哪个平台。

我的教训: 后面重构时把所有平台差异抽到了 adapter 层,业务代码只调 adapter 接口。不要让条件编译侵入业务逻辑。

坑 5:uniapp 内置组件的兼容性问题

项目中用了不少 uniapp 内置组件(scroll-view、swiper 等),在小程序端表现良好,但 App 端渲染效果经常不一致。比如 scroll-view 在 App 端的惯性滚动行为和小程序不一样,swiper 的循环模式在部分安卓设备上有闪烁,在IOS上显示有问题等各种兼容问题。

解决方式: 关键交互组件能使用三方成熟组件优先使用。


四、后端架构:一个人搞定的全栈设计

这一节好好聊。前端是敲门砖,后端才是真功夫。

整体技术栈

技术说明
运行时.NET 10 + ASP.NET Core Web APIKestrel 服务器,高性能够用
ORMSqlSugarCore国产 ORM,CodeFirst 自动建表
数据库PostgreSQL 16 / MySQL 8.0双数据库兼容,一行配置切换
缓存Redis 7 + 内存自动降级StackExchange.Redis
认证JWT + Token 黑名单120 分钟有效期 + 7 天 RefreshToken
日志Serilog三路输出:控制台 + 文件 + 数据库
存储策略模式本地 / 阿里云 OSS / 腾讯云 COS 无缝切换
部署Docker Compose5 个服务一键编排

五层 DDD 分层

1
2
3
4
5
6
MuyuBackend/
├── Api/              # 表现层:Controllers + 中间件 + 后台任务
├── Application/      # 应用服务层:31 个 Service + DTOs
├── Domain/           # 领域层:29 个实体 + 枚举定义
├── Infrastructure/   # 基础设施层:DbContext + 仓储 + 缓存 + 存储
└── Common/           # 公共工具:JSON 配置 + 扩展方法

32 个 Controller(17 个前台 + 15 个 Admin 后台),31 个业务 Service,28 张数据库表。

说人话就是:功能模块比你想象的要多得多——用户认证、功德系统、签到、任务、成就、反馈、微信客服、自动回复、资源管理、系统配置、日志审计……麻雀虽小,五脏俱全。

分层的好处是改一处不影响全局。比如后来从 PostgreSQL 切换到腾讯云 MySQL,只改 Infrastructure 层的数据库配置,业务代码一行不动。

为什么选 SqlSugar 而不是 Entity Framework Core

  • 更轻量:不需要 DbContext 那套复杂的变更追踪,心里有数
  • 网上说SqlSugar性能更好:其实我也是第一次用,哈哈

Redis 缓存,但不强依赖

缓存架构有一个我特别满意的设计:Redis 不可用时自动降级到 ConcurrentDictionary 内存缓存。

1
2
3
请求 → 查 Redis → 命中:返回
                 → 未命中:查数据库 → 写 Redis → 返回
                                    → 如果 Redis 挂了:查数据库 → 写内存缓存 → 返回

之后加了:

  1. 每分钟健康检查,Redis 恢复后自动回切
  2. 缓存过期时间加随机偏移,避免缓存雪崩
  3. Castle DynamicProxy 实现 AOP 拦截,Service 层加个 [Cache] 特性就完事,不需要在业务代码里手写缓存逻辑

这个自动降级方案强烈推荐给做独立产品的朋友。 用户量不大的时候,自建 Docker Redis 的稳定性其实没有想象中高,有个兜底方案会安心很多。

审计日志:吃过亏才知道重要

上线初期为了赶进度,用户操作没有记日志。有一次数据异常——用户反馈功德值对不上——我没有任何线索排查。

后来补上了完整的日志体系:

  • AuditLogMiddleware:记录所有 /api 请求,包括请求体、响应状态、耗时
  • ExceptionLogMiddleware:全局异常捕获,记录完整堆栈
  • 登录日志:每次登录的时间、平台、IP、设备信息
  • 慢 SQL 日志:SqlSugar AOP 自动捕获 >1s 的查询,异步写入 slow_sql_logs

Serilog 三路输出:开发环境看控制台,生产环境落文件(按日滚动保留 30 天),关键数据入库方便管理后台直接查。

给你一个忠告:审计日志从第一天就做。 不是为了应付合规,是为了出问题时你能快速定位。这是为自己写的代码。

后台任务:生产者-消费者解耦

有些操作不需要等——比如用户敲完木鱼后同步功德值、清理过期 Token、发送通知邮件。这些耗时操作如果阻塞主线程,用户体验会明显下降。

实现了一个简单的 BackgroundTaskQueue + QueuedHostedService

  • Controller 把耗时任务丢进队列,立刻返回
  • 后台线程依次消费队列,不影响接口响应速度

没有用消息队列(RabbitMQ / Kafka),因为用户量没到那个级别。一个内存队列 + 后台线程就搞定了。

文件存储:三种方案随时切

音频文件和图片的存储,搞了策略模式:

1
2
3
4
// 配置一行切换
"Storage": {
  "Provider": "AliyunOss"  // 或 "TencentCos" 或 "Local"
}

三种方案实现同一个 IFileStorage 接口,业务代码完全不感知底层用的是哪个云。甚至能同时启用多个,管理后台在页面上选。音频文件走 对象存储 加速,设置了一年缓存时间,因为音频资源很少变动。

部署:docker-compose 一把梭

5 个服务用一个 docker-compose.yml 编排:

1
2
3
4
5
6
services:
  postgres        # PostgreSQL 16 (带健康检查)
  redis           # Redis 7 (带健康检查)
  backend         # .NET 10 Web API (依赖 postgres + redis 健康)
  admin-frontend  # Vue 3 管理后台 (Nginx)
  miniapp-frontend # uni-app H5 (Nginx)

启动:docker-compose up -d,健康检查确保 backend 在 postgres 和 redis 都就绪后才启动,避免启动顺序导致的连接失败。

为什么没选微信云开发

一开始考虑过微信云开发(CloudBase),开箱即用,省掉运维。但最终没选:

原因:都是费用啊

最终选择了自建后端 + Docker 部署。虽然多了运维工作,但长期可控性更好。

监控与告警

没有上 Prometheus + Grafana 全家桶,用户量没到那个级别。但几个关键监控做了:

  • 健康检查端点/health 接口返回数据库和 Redis 连接状态
  • 慢 SQL 监控:自动记录 + 管理后台可视化查看
  • API 调用统计:管理后台有专门页面看接口调用趋势
  • 告警通知:系统异常通过管理后台 + 邮件通知

小而美,够用就行。


五、App 上架与备案 —— 比写代码更磨人的事

代码写完了不算完,真正的心累从「上架」开始。

微信小程序备案

小程序上线前必须完成备案,流程大概是:

  1. 提交主体信息(企业或个体户营业执照)
  2. 填写小程序基本信息 + 服务类目
  3. 提交审核,等待 1~3 个工作日
  4. 如果类目选错 → 驳回重来 → 再等 1~3 个工作日

Android App 上架

这更是一场修行。国内安卓应用市场大大小小十个左右,每个市场的审核标准、隐私政策要求、软著要求都不一样:

image.png

光是准备材料、填写各家表单、应对驳回就花了我好长时间。建议同步准备软著申请,这个周期最长(1~3 个月),一定要提前启动。

网站/小程序/APP ICP 备案

如果有配套官网,域名也需要 ICP 备案,又是一个独立流程。从提交到审核通过,顺利的话 1~2 周,不顺利反复驳回的话一个月起步。

一句话总结: 做独立产品,开发只占 40% 的时间,剩下的都是合规、上架、运营。心理预期要先建立好。


六、聊聊 AI:水平拉平了,但虎还是虎,高手+AI就是强强联合

这部分本来没有,但既然是跟园子里的老朋友们聊天,就多聊几句。

AI 真的拉平了程序员的水平差距

这是我的真实感受。

三年前,一个熟练后端和一个初级前端的差距是肉眼可见的——前者知道怎么调性能、怎么设计接口、怎么处理边界情况;后者可能连 Promise 链都绕不明白。

现在呢?AI 让初级程序员也能写出看起来"还行"的代码。复杂查询让 AI 写、页面布局让 AI 生成、甚至单元测试都能一键出。表面上,大家的产出差距在缩小。

这对行业来说是好事——门槛低了,更多人能参与到创造中来。但对每个个体来说,这也意味着:只靠"会写代码"已经不够了。

以前你比同事多会一个框架、多懂一个中间件,那就是实打实的竞争力。现在 AI 几秒钟就能给你讲清楚一个框架的用法。纯技能层面的领先优势,正在被快速抹平。

但前提:你得是虎

有一句话我特别认同——

AI 可以如虎添翼,但前提你得是虎。

什么意思?

AI 能把你的效率翻倍、甚至翻三倍。但如果你本来就是个空壳——不懂需求分析、没有架构思维、不会做技术判断——那 AI 只会帮你更快地产出一堆垃圾。

真正的「虎」是什么?

  • 能独立判断一个需求值不值得做。 AI 不会告诉你"这个功能用户根本不需要”,但你会。
  • 能看出 AI 生成的代码哪里有问题。 AI 写出来的代码看起来没 Bug,但性能瓶颈、安全漏洞、扩展性问题,它不会主动提醒你。
  • 知道"为什么这么做"而不只是"怎么做"。 AI 能给你方案,但选哪个方案、为什么选这个,是你的判断。
  • 有产品思维。 技术是为产品服务的,AI 能在技术上帮你,但它不知道你的用户是谁、痛点在哪。

所以我的建议很简单:把 AI 当最强的副驾驶,但方向盘永远握在自己手里。 用它来放大你的优势,别指望它替你补齐短板。

我是怎么用 AI 的(说点实际的)

在这个项目中,AI 帮我做了这些事:

音频处理脚本 —— 上百个音频文件批量转码、压缩、统一采样率。描述需求 → AI 出 Python + ffmpeg 脚本 → 微调 → 跑通。这种体力活太适合 AI 了。

界面实现 —— 渐变、动画、暗色模式适配、6 套主题皮肤的 CSS。以前反复调样式半小时,现在描述效果让 AI 出代码,几分钟一版,不行就 refine。

文案与英文本地化 —— 英文版的产品描述、功能说明、隐私政策,AI 翻译 + 人工校对。前提是,我得有能力判断翻译质量。

后端增删改查 —— 接口模板、数据校验逻辑、SQL 语句,这类重复性工作丢给 AI 写初版,我 review 和调优。比自己从零写快太多了。

刻意没让 AI 做的事: 整体架构设计(五层 DDD 怎么分层)、数据库表设计(28 张表之间的关系)、技术选型决策(为什么用 SqlSugar 而不是 EF Core)、用户体验打磨(什么样的敲击反馈最舒服)。这些需要判断力的核心环节,目前 AI 还不够格。

总结一句话

AI 正在把程序员的「技能红利」变成「判断力红利」。未来拉开差距的,不再是你会几个框架,而是——你能看到什么需求、做出什么判断、创造什么价值。

如虎添翼的前提:你得先是虎。是狼是羊都得先练成虎。


七、几点真心话

1. 解决问题比技术炫技重要

睡眠木鱼的技术栈并不复杂,uniapp + .NET + SqlSugar + PostgreSQL,没有任何黑科技。但它解决的「助眠」需求是真实存在的,用户是真的在用。

别陷入「我要用最新技术」的陷阱。用什么技术不重要,解决什么问题才重要。

2. 敢上线比完美更重要

第一个版本只有一个功能:敲木鱼。没有排行榜,没有音频库,没有个人中心,连英文版都没有。

他们的反馈才让我知道接下来该做什么。如果等我把它做"完美"再上线,可能现在还没发布。

3. 独立开发是一场持久战

开发占 40%,上架合规占 30%,运营推广占 30%。不要指望一夜爆火,做好长期投入的准备。


八、欢迎体验 & 一起交流

体验入口:

👉 微信小程序搜索 「睡眠木鱼」

image.png

技术交流群:

我自己在做 uniapp 开发、.NET 后端、小程序上架、独立产品运营的过程中,踩了太多坑。建了一个群,欢迎同样在做独立开发的朋友加入,聊技术、聊产品、聊踩坑,互相取经。

获取路径:睡眠木鱼小程序->我的->微信客服->按照关键词回复即可。


代码是冷的,产品是有温度的。做点别人真正用得上的东西,是一个程序员最大的浪漫。


Licensed under CC BY-NC-SA 4.0
页面浏览量Loading
如果觉得我的博客能帮助到你,欢迎点击右侧的赞助进行投喂。如有技术咨询,也可以加本人好友。
总访客数:Loading 总访问量:Loading 实时统计

使用 Hugo 构建
主题 StackJimmy 设计