
事情的起因其实很简单。去年有段时间我午休和晚上睡前习惯打开淘宝上的一个小程序——一个木鱼应用可以手动敲木鱼也有颂钵禅音听着笃、笃、笃的节奏慢慢就睡着了。效果出乎意料地好成了我每天助眠的必备工具。但它有两个致命问题第一不支持后台播放。 切到别的 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 之间切换需要专门维护播放状态机否则会出现正在播放却显示暂停切换音频后进度归零等各种诡异 BugApp 端Androiduniapp 的音频 API 封装了原生播放器但兼容性一般部分低端机型解码 .mp3 时会直接报错锁屏后系统省电策略杀进程 → 音频中断需要写原生前台服务保活音频资源最终做了双格式兼容MP3 OGG配合条件编译分别加载我最终的方案封装统一的 AudioManager 类内部根据平台自动选择音频 API小程序用 BackgroundAudioManager 保后台App 用原生前台服务播放状态用单向数据流管理所有状态变更通过事件总线通知 UI音频资源一律走 对象存储本地不打包任何音频文件教训 如果你的项目重度依赖音频第一天就去真机上测试后台播放 锁屏场景别等开发完了再踩坑。坑 2小程序包体积 —— 差点没上线成功uniapp 编译出来的初始包轻松破 2MB而微信小程序主包限制就是 2MB。这个问题不解决连审核都过不了。我做了什么所有音频图片资源走 对象存储 在线加载本地零音频图片文件部分 UI 改 CSS 绘制减少图片依赖uniapp 分包加载主包只放首页 核心框架非核心页面全部丢子包uniapp 自带的三方库能删的删能按需引入的绝不全量导入一顿操作之后主包压缩到了 1.8MB 以内刚好卡线过审。坑 3国际化i18n的隐形工作量一开始只想做中文版后来考虑海外用户加了英文切换。用了 vue-i18n本以为是把文案翻译一遍的事结果发现远不止如此。真正遇到的麻烦文案长度差异中文一行能说完的英文可能要两行。UI 布局大量硬编码了宽度切英文后按钮溢出、文字截断改了一轮 CSS动态内容翻译签到提示、课程分类标签、系统通知……这些不是静态文案是后端返回的需要前端做映射翻译tabbar的文案切换语言没有生效暂时还没解决。建议 i18n 最好从项目第一天就做至少架构上预留好。后期补的代价远大于一开始就规划。坑 4条件编译的代码腐化uniapp 的 #ifdef / #ifndef 很好用但当横跨小程序和 App 两端时代码很容易变成这样// #ifdef MP-WEIXIN// 微信登录、支付、分享逻辑……// #endif// #ifdef APP-PLUS// App 端登录、原生插件调用……// #endif业务逻辑里散落着大量条件编译块三个月后回头看自己都分不清哪个分支对应哪个平台。我的教训 后面重构时把所有平台差异抽到了 adapter 层业务代码只调 adapter 接口。不要让条件编译侵入业务逻辑。坑 5uniapp 内置组件的兼容性问题项目中用了不少 uniapp 内置组件scroll-view、swiper 等在小程序端表现良好但 App 端渲染效果经常不一致。比如 scroll-view 在 App 端的惯性滚动行为和小程序不一样swiper 的循环模式在部分安卓设备上有闪烁在IOS上显示有问题等各种兼容问题。解决方式 关键交互组件能使用三方成熟组件优先使用。四、后端架构一个人搞定的全栈设计这一节好好聊。前端是敲门砖后端才是真功夫。整体技术栈层 技术 说明运行时 .NET 10 ASP.NET Core Web API Kestrel 服务器高性能够用ORM SqlSugarCore 国产 ORMCodeFirst 自动建表数据库 PostgreSQL 16 / MySQL 8.0 双数据库兼容一行配置切换缓存 Redis 7 内存自动降级 StackExchange.Redis认证 JWT Token 黑名单 120 分钟有效期 7 天 RefreshToken日志 Serilog 三路输出控制台 文件 数据库存储 策略模式 本地 / 阿里云 OSS / 腾讯云 COS 无缝切换部署 Docker Compose 5 个服务一键编排五层 DDD 分层MuyuBackend/├── Api/ # 表现层Controllers 中间件 后台任务├── Application/ # 应用服务层31 个 Service DTOs├── Domain/ # 领域层29 个实体 枚举定义├── Infrastructure/ # 基础设施层DbContext 仓储 缓存 存储└── Common/ # 公共工具JSON 配置 扩展方法32 个 Controller17 个前台 15 个 Admin 后台31 个业务 Service28 张数据库表。说人话就是功能模块比你想象的要多得多——用户认证、功德系统、签到、任务、成就、反馈、微信客服、自动回复、资源管理、系统配置、日志审计……麻雀虽小五脏俱全。分层的好处是改一处不影响全局。比如后来从 PostgreSQL 切换到腾讯云 MySQL只改 Infrastructure 层的数据库配置业务代码一行不动。为什么选 SqlSugar 而不是 Entity Framework Core更轻量不需要 DbContext 那套复杂的变更追踪心里有数网上说SqlSugar性能更好:其实我也是第一次用哈哈Redis 缓存但不强依赖缓存架构有一个我特别满意的设计Redis 不可用时自动降级到 ConcurrentDictionary 内存缓存。请求 → 查 Redis → 命中返回→ 未命中查数据库 → 写 Redis → 返回→ 如果 Redis 挂了查数据库 → 写内存缓存 → 返回之后加了每分钟健康检查Redis 恢复后自动回切缓存过期时间加随机偏移避免缓存雪崩Castle DynamicProxy 实现 AOP 拦截Service 层加个 [Cache] 特性就完事不需要在业务代码里手写缓存逻辑这个自动降级方案强烈推荐给做独立产品的朋友。 用户量不大的时候自建 Docker Redis 的稳定性其实没有想象中高有个兜底方案会安心很多。审计日志吃过亏才知道重要上线初期为了赶进度用户操作没有记日志。有一次数据异常——用户反馈功德值对不上——我没有任何线索排查。后来补上了完整的日志体系AuditLogMiddleware记录所有 /api 请求包括请求体、响应状态、耗时ExceptionLogMiddleware全局异常捕获记录完整堆栈登录日志每次登录的时间、平台、IP、设备信息慢 SQL 日志SqlSugar AOP 自动捕获 1s 的查询异步写入 slow_sql_logs 表Serilog 三路输出开发环境看控制台生产环境落文件按日滚动保留 30 天关键数据入库方便管理后台直接查。给你一个忠告审计日志从第一天就做。 不是为了应付合规是为了出问题时你能快速定位。这是为自己写的代码。后台任务生产者-消费者解耦有些操作不需要等——比如用户敲完木鱼后同步功德值、清理过期 Token、发送通知邮件。这些耗时操作如果阻塞主线程用户体验会明显下降。实现了一个简单的 BackgroundTaskQueue QueuedHostedServiceController 把耗时任务丢进队列立刻返回后台线程依次消费队列不影响接口响应速度没有用消息队列RabbitMQ / Kafka因为用户量没到那个级别。一个内存队列 后台线程就搞定了。文件存储三种方案随时切音频文件和图片的存储搞了策略模式// 配置一行切换“Storage”: {“Provider”: “AliyunOss” // 或 “TencentCos” 或 “Local”}三种方案实现同一个 IFileStorage 接口业务代码完全不感知底层用的是哪个云。甚至能同时启用多个管理后台在页面上选。音频文件走 对象存储 加速设置了一年缓存时间因为音频资源很少变动。部署docker-compose 一把梭5 个服务用一个 docker-compose.yml 编排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~3 个工作日如果类目选错 → 驳回重来 → 再等 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 帮我做了这些事