普通视图

发现新文章,点击刷新页面。
昨天 — 2026年4月21日首页

独立开发复盘:我用 Uni-app + Strapi v5 肝了一个“会上瘾”的打卡小程序

作者 知航驿站
2026年4月21日 20:06

大家好,我是一名独立开发者。最近利用业余时间,我从零到一开发并上线了一款目标打卡/习惯养成类的小程序。

今天这篇文章,不仅是想向大家推荐一下我的心血之作,更想从创作灵感核心技术实现代码细节以及无数次踩坑的角度,和大家深度复盘一下整个项目的历程。如果你也想尝试用 Uni-app + Strapi 搞全栈独立开发,这篇“避坑指南 + 技术解析”绝对不容错过!


307c9942d27117ec00e7781976431a56.jpg

1fa52da0afde72c0faf8e72dc49c1c29.jpg

💡 创作灵感与产品心得:为什么还要做一个打卡应用?

市面上的打卡应用多如牛毛,为什么我还要自己造轮子? 其实原因很简单:我觉得现有的工具太“冷冰冰”了,缺乏足够的情绪反馈。

打卡/坚持习惯本身就是一件反人性的事情,如果工具只是一个无情的“待办列表”,那用户很容易就会放弃。因此,在产品设计之初,我定下了几个核心基调:

  1. 克制与聚焦:我限制了每天最多只能创建 12 个任务,到达 10 个时会温馨警告。目标泛滥等于没有目标。
  2. 正向反馈拉满:任务完成不能只是打个勾,必须要有“爽感”。我加入了物理震动、纸屑爆裂动画(撒花)、以及 3D 翻转的徽章解锁系统。
  3. 互助与抄作业:很多时候我们不知道该养成什么习惯,所以我做了一个“社区广场”(瀑布流布局),看到别人优秀的习惯,可以直接“一键 Copy”到自己的计划中。

🛠 技术选型:单兵作战的效率最优解

作为独立开发者,开发效率是第一生产力。我选择了这套组合拳:

  • 前端:Uni-app (Vue 3) + Tailwind CSS
    • Vue 3 的 Composition API 逻辑复用非常爽。
    • 结合原子化 CSS(如 Tailwind/UnoCSS),极大提升了切图速度,摆脱了起 class 名字的内耗。
  • 后端:Strapi v5 (Headless CMS)
    • 绝对的效率神器!不用手写繁琐的 CRUD 接口,建好模型直接生成 RESTful API。
    • 自带强大的 Admin 后台,数据管理极度舒适,让我能把 80% 的精力全放在前端交互和产品体验上。

💻 核心技术点与代码实现

1. 极致的微交互:让打卡“爽”起来

为了让用户点下“完成”的那一刻有真实的成就感,我结合了 CSS 动画和原生的触觉反馈:

// 核心打卡逻辑片段
const handleCheckIn = async (task) => {
  // 1. 触发 Haptic 震动反馈 (重震动带来物理按压感)
  uni.vibrateShort({ type: 'heavy' });
  
  // 2. 触发微动效:按钮自身的弹跳 + 全局撒花特效
  task.isBouncing = true; 
  uni.$emit('trigger-particle-confetti'); // 呼叫全局纸屑动画组件
  
  try {
    await api.completeTask(task.id);
    // 3. 检查是否触发徽章解锁
    checkBadgeUnlock(task);
  } catch (e) {
    // 错误处理...
  }
}

在徽章解锁时,我还写了一个 3D 翻牌效果(利用 CSS transform: rotateY 配合 animate-flip-y),让徽章展示更有仪式感。

2. Strapi 关系模型 Hack:如何优雅地记录“徽章解锁时间”?

在后端的开发中,我遇到了一个经典问题:多对多关联表的额外字段怎么存? User 和 Badge 是多对多关系,但在 Strapi 原生模型中,中间表无法轻易添加像 unlockedAt 这样的字段。

我的解法: 直接在 User Schema 中扩展一个轻量级的 JSON 字段 badge_unlock_records

// apps/api/src/extensions/users-permissions/strapi-server.ts
// 扩展 Strapi 默认的 User Schema
export default (plugin) => {
  plugin.contentTypes.user.attributes = {
    ...plugin.contentTypes.user.attributes,
    // 原生多对多关联
    badges: {
      type: 'relation',
      relation: 'manyToMany',
      target: 'api::badge.badge',
    },
    // 💡 Hack: 用 JSON 字段记录具体的解锁元数据
    badge_unlock_records: {
      type: 'json',
      // 数据结构示例: { "badge_id_1": "2023-10-01T12:00:00Z" }
    }
  };
  return plugin;
};

这样既保留了原生关系(方便在 Admin 面板查看),又解决了业务上的元数据存储需求。

3. 社区广场的“真”瀑布流与分页

社区页面的卡片高度是不固定的,传统的 Grid 布局会留下大片空白。我通过维护左右两列的数据数组,实现了原生的瀑布流效果:

// 瀑布流计算核心逻辑
const leftColumn = ref([]);
const rightColumn = ref([]);
let leftHeight = 0;
let rightHeight = 0;

const appendToMasonry = (items) => {
  items.forEach(item => {
    // 估算卡片高度 (基于内容长度)
    const estimatedHeight = calculateHeight(item);
    
    // 哪边矮往哪边塞
    if (leftHeight <= rightHeight) {
      leftColumn.value.push(item);
      leftHeight += estimatedHeight;
    } else {
      rightColumn.value.push(item);
      rightHeight += estimatedHeight;
    }
  });
};

配合 onReachBottom 触底事件,以及自己封装的 wd-loadmore 状态组件,整个信息流刷起来非常丝滑。


🚧 吐血踩坑录:那些让我熬夜的 Bug

全栈开发最怕的就是遇到莫名其妙的兼容性和环境问题。以下这几个坑,价值好几百根头发:

坑一:iOS 13 下 Swiper 圆角失效问题

症状:在旧版 iOS 中,给 <swiper> 设了 border-radiusoverflow: hidden,但里面的图片滑动时依然会无视圆角溢出。 解法:这是 transform 堆叠上下文导致的渲染 Bug。不仅要给 swiper 和 image 都加上圆角类名,还必须强制加上 transform: translateY(0);

<!-- 💡 注意 style 中的 transform 是精髓 -->
<swiper class="rounded-[5px]" style="transform: translateY(0);">
  <swiper-item>
    <image class="rounded-[5px]" src="..." />
  </swiper-item>
</swiper>

坑二:小程序下渐变文字(bg-clip-text)直接消失

症状:想用 Tailwind 的 bg-clip-text text-transparent 做炫酷的渐变文字,结果在微信小程序/iOS上文字直接隐身了。 解法:小程序对 <text> 标签的背景裁剪支持极差。如果要用,必须把 <text> 换成 <view> 标签来写文字,或者老老实实退回到纯色文本。

坑三:Strapi v5 生产环境部署大坑

  1. 插件报错:初始化 v5 时,报 Middleware plugin::email.rateLimit not found解法:手动执行 pnpm add @strapi/email 安装缺失依赖。
  2. RTK Query 压缩报错:打包上线后 Admin 面板报 Cannot read properties of undefined (reading 'merge')。原因是 Vite 压缩把 RTK Query 的方法名压没了。 解法:在 src/admin/vite.config.ts 中关闭 minify,并清理缓存!
// src/admin/vite.config.ts
export default {
  build: {
    minify: false, // 💡 必须设为 false
  },
};

(执行 npx rimraf .strapi build 清除缓存后再 build)


结语

从一行代码都没有,到完整的前后端链路打通;从构思微交互,到处理数据备份(云端同步 + 剪贴板文本导出);这个过程虽然辛苦,但当看到产品真正跑起来,有人开始用它记录生活时,一切都值了。

目前小程序已经上线,欢迎大家在微信搜索 简行一周 体验!

如果你对文章中的技术点感兴趣,或者在用 Uni-app / Strapi 的时候也遇到了头疼的问题,欢迎在评论区留言交流,我一定知无不言!

最后,如果你觉得这篇文章对你有启发,求个点赞 + 收藏,这对我这个独立开发者是莫大的鼓励!🚀

6e051cfd4b1574ab6dc9e48938b739d7.png

❌
❌