我用 HarmonyOS NEXT 做了一款排班倒班 App

我用 HarmonyOS NEXT 做了一款排班倒班 App,把 3D Soft UI 写进了日历

一款叫《班妥了》的鸿蒙原生 + 微信小程序双端排班应用,聊聊我为什么做、怎么做、踩了哪些坑。

0. 前言

我是一名 AI 平台工程师。去年开始给自己写一个排班工具,原因是市面上实在找不到一个「小而美、本地优先、能看清自己一年到底有多拼」的 App。于是从 0 开始用 HarmonyOS NEXT 撸了一版,又顺手做了个微信小程序版给同事用。

先放个成品图。左边手机端个人版月历,右边平板端团队排班:

1. 为什么做

排班这个场景其实很割裂:

  • Excel:自由但丑,且多端没法同步
  • 钉钉/企业微信排班:重 B 端,个人用起来被淹没在团队功能里
  • 国外 App(Shiftly、Shyft 等):云端 + 付费 + 国内访问偶尔抽风
  • 极简个人向:好看,但没有月历 / 没有统计 / 没有团队视图

我想做一个「会陪着我值夜班」的工具:

  • 打开就知道今天是什么班
  • 看一眼月历知道这个月节奏
  • 看一眼年度知道今年真的辛苦过
  • 团队里能让我快速看谁连班了、谁该轮休

2. 技术栈

端 技术
鸿蒙原生 ArkTS + HarmonyOS NEXT(Stage 模型)
微信小程序 原生 WXML/WXSS + 微信云开发
团队数据同步 HarmonyOS 端用分布式数据 + 云函数兜底

为什么不上 Flutter / RN? 鸿蒙 NEXT 已经不兼容 AOSP 套件,纯血鸿蒙的体验和性能 ArkTS 是唯一正解。微信小程序则是因为团队里有同事没装鸿蒙原生 App,得让 Ta 们扫个码就能用。

3. 关键模块拆解

3.1 数据模型

班次是循环 + 临时双轨:

typescript 复制代码
// 班次循环(持续到被打断)
interface ScheduleCycle {
  id: string;
  userId: string;
  startDate: string;        // 从哪天开始循环
  pattern: ShiftType[];     // [白班, 晚班, 夜班, 休] 这种顺序
  // ...
}

// 临时调整(覆盖某一天)
interface ScheduleOverride {
  date: string;             // 哪一天
  shift: ShiftType;         // 这一天的班次
  note?: string;
  cycleId: string;          // 属于哪个循环
}

月历渲染时先取循环再覆盖临时,这样既不破坏循环,又留了"今天和白班兄弟换一下"的口子。

3.2 月历的 3D 软 UI 怎么实现

这里我踩了第一个坑------毛玻璃在 ArkTS 里的写法跟 iOS 完全不同。

  • ❌ iOS 的 backdrop-filter: blur() 不能直接拿过来
  • ✅ HarmonyOS 的方案是用 Stack 叠两层 + 前景色用 Color.BlendMode.OVERLAY
  • ✅ 圆角和阴影用 borderRadius + shadow 复合,3D 感来自阴影的颜色(不是纯黑,而是品牌色的低饱和版)
typescript 复制代码
@Builder
function GlassCard() {
  Stack() {
    // 底层:背景模糊模拟
    Column().width('100%').height('100%')
      .backgroundColor('#F3E5F5')
      .blur(20)
    // 顶层:玻璃质感
    Column() {
      // 内容
    }
    .width('100%').height('100%')
    .backgroundColor('rgba(255,255,255,0.6)')
    .borderRadius(20)
    .shadow({ radius: 24, color: '#E8F5E9', offsetY: 8 })
  }
}

阴影颜色取自品牌色板(#E8F5E9 薄荷绿 / #F3E5F5 樱花粉 / #37474F 深石板),比纯黑阴影更柔和也更克制。

3.3 统计图表

没有用三方库,全部用 Canvas 自绘------鸿蒙的 Canvas 性能足够,个人版月统计这种轻量图表没必要引 ECharts。

typescript 复制代码
// 月度班次分布
@Builder
function ShiftDistribution(shifts: ShiftCount[]) {
  Canvas(this.context)
    .onReady(() => {
      // 画 5 条横条:早班 / 白班 / 晚班 / 夜班 / 休息
      shifts.forEach((s, i) => {
        const ratio = s.count / max;
        // 进度条用 渐变 + 圆头
      });
    })
}

4. 团队版的取舍

团队版没做云端账号体系,而是:

  • 主管在自己的鸿蒙 App 里排好班
  • 一键"发布"生成一个团队码
  • 成员扫这个码进入微信小程序,只读 + 申请调班
  • 主管再在 App 里批量调整并发布

这个设计绕开了企业级账号 / 权限 / 审计 的复杂度,对小团队(≤20 人)刚刚好。

5. 一些彩蛋

  • 今日片刻 :每天轮换一句鼓励 / 短句,从"不用预支整天的疲惫"到"公平比看起来平均更重要",不鸡汤、有点暖(设计师朋友说这是灵魂 😄)
  • 多主题:浅蓝 / 浅绿 / 樱花粉 / 深色模式
  • 年度回顾 :把这一年的工时、连班、夜班做成一张自己的日历热力图

6. 反思与不足

  • 团队版还没做权限分级------所有成员都能申请调班,没有"只能看自己"模式
  • iOS 暂未支持------纯血鸿蒙的优先级更高,鸿蒙版体验最完整
  • 没有云端账本 ------数据本地优先,换手机需要走备份恢复(这是设计选择,但确实劝退了一些人)

7. 体验一下

  • 鸿蒙原生版 :HarmonyOS 应用市场搜「班妥了」
  • 微信小程序版:扫下面这个码

如果你也是倒班人,欢迎反馈你最在意的功能;如果你是开发者,欢迎来喷我的代码 ☕️。

相关推荐
5008423 分钟前
React Native for OpenHarmony 实战:三方库 react-native-volume-control 的鸿蒙化适配指南
javascript·react native·react.js·electron·harmonyos
李游Leo14 小时前
HarmonyOS 7 DualCart 平行视界适配实录 04:EasyGo × 虚拟容器:商品比价双详情与分栏比例策略【鸿蒙心迹】
华为·harmonyos
李游Leo14 小时前
HarmonyOS 7 PixelBridge 原生库适配实录 06:Release 性能基线、资源释放、包体积与工程化验收【鸿蒙心迹】
华为·harmonyos
传奇开心果编程15 小时前
【ArkUI进阶练中学】第11课:安全与合规进阶
学习·ui·华为·harmonyos
熊猫钓鱼>_>16 小时前
Kotlin Multiplatform for OpenHarmony 实战:为 Reaktive 实现响应式原语适配(完整版 · 含摘要目录与技术图表)
华为·kotlin·大模型·ai编程·harmonyos·适配·reaktive
李游Leo19 小时前
HarmonyOS 7 + Spatial Recon Kit-C++:3DGS 高斯参数的非有限值隔离与可渲染性门禁【鸿蒙心迹】
开发语言·c++·3d·harmonyos
熊猫钓鱼>_>20 小时前
Kotlin Multiplatform for OpenHarmony 实战:为 MVIKotlin 实现单向数据流适配
华为·ai编程·鸿蒙·openharmony·适配·数据流·mvkotlin
传奇开心果编程20 小时前
【ArkUI进阶练中学】第12课:应用架构演进与遗留系统迁移
学习·ui·华为·harmonyos
传奇开心果编程1 天前
【ArkUI进阶练中学】第13课:元服务与卡片开发
学习·ui·华为·harmonyos