Skip to content

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

订阅到期提醒管理器 (Subscription Renewal Tracker)

微信小程序,帮用户记录各类订阅/会员服务,在到期前自动推送提醒,避免忘记续费或错过取消免费试用。

技术栈:微信小程序原生框架(WXML/WXSS/JS)+ 微信云开发(云函数 + 云数据库 + 定时触发器),无需自建服务器、无需域名备案。

小程序只能在微信内打开,为了方便没有微信环境的招聘方/访客直接在浏览器里预览界面,配了一个只读静态演示页,见下方「网页演示版」一节。

目录结构

├── app.js / app.json / app.wxss     # 小程序入口配置
├── pages/
│   ├── index/                       # 订阅列表页(首页)
│   ├── edit/                        # 添加/编辑订阅页
│   └── household/                   # 共享组管理页(创建/加入/邀请)
├── cloudfunctions/
│   ├── addSubscription/             # 新增一条订阅
│   ├── getSubscriptions/            # 获取当前用户的订阅列表(含我参与的共享组订阅)
│   ├── updateSubscription/          # 编辑一条订阅
│   ├── deleteSubscription/          # 软删除一条订阅
│   ├── scanExpiring/                # 每日定时扫描,命中到期规则就推送提醒(共享订阅通知全部成员)
│   ├── createHousehold/             # 创建一个共享组,生成邀请码
│   ├── joinHousehold/               # 凭邀请码加入一个共享组
│   └── getHouseholds/               # 获取当前用户所在的共享组列表
└── web-demo/
    └── index.html                   # 只读静态网页演示版,写死示例数据,不连真实数据库

首次运行前需要做的事(按顺序)

  1. 用微信开发者工具打开本项目文件夹:菜单选"导入项目",目录选这个文件夹,AppID 填你在 mp.weixin.qq.com 后台"开发管理 -> 开发设置"里看到的那个。

  2. 开通云开发环境:工具栏点"云开发",首次会引导你创建一个环境(有免费额度)。记下环境ID,填到 app.js 里 wx.cloud.init 的 env 字段。

  3. 建数据库集合:云开发控制台 -> 数据库 -> 新建集合,需要建两个:subscriptions 和 households(代码里写死了这两个名字)。权限都选"仅创建者可读写"(共享组的可见性完全由云函数里的权限校验控制,不依赖数据库的默认读写规则)。

  4. 上传并部署云函数:在开发者工具左侧 cloudfunctions 目录下,右键每一个函数文件夹(addSubscription / getSubscriptions / updateSubscription / deleteSubscription / scanExpiring / createHousehold / joinHousehold / getHouseholds),选择"上传并部署:云端安装依赖"。八个都要传一遍。

  5. 申请订阅消息模板:mp.weixin.qq.com -> 基础功能 -> 订阅消息 -> 公共模板库,搜"到期提醒"或"续费提醒"相关的模板,选用后拿到模板ID,分别填到:

    • pages/edit/edit.js 里的 TEMPLATE_ID
    • cloudfunctions/scanExpiring/index.js 里的 TEMPLATE_ID (两处要填同一个ID)
  6. 确认定时触发器生效:cloudfunctions/scanExpiring/config.json 里配置了每天 9:00 自动跑一次(cron: 0 0 9 * * * *)。部署完云函数后,去云开发控制台 -> 云函数 -> scanExpiring -> 触发管理,确认触发器已启用;开发调试阶段也可以在控制台手动点"测试"直接触发一次。

数据库字段说明(subscriptions 集合)

字段 类型 说明
_openid String 云开发自动注入,天然按用户隔离数据;共享订阅的创建者也存在这个字段里,只有创建者能编辑/删除
name String 订阅名称
amount Number 金额(共享订阅是总金额,不是人均金额)
currency String 币种,默认 CNY
cycleType String monthly / yearly / custom
cycleDays Number 自定义周期天数
nextBillingDate String 'YYYY-MM-DD'
remindDaysBefore Number 提前几天提醒,默认 3
isActive Boolean 软删除标记
lastRemindedAt String 最近一次提醒日期,防止同一天重复推送
groupId String | null 共享给哪个 households 集合的组,不共享则为 null
isShared Boolean 是否共享订阅,等价于 groupId 是否非空,冗余存一份方便前端查询判断

数据库字段说明(households 集合,共享组)

字段 类型 说明
name String 组名,如"家庭账单"
ownerOpenid String 创建者
members Array<String> 成员 _openid 列表,创建者也在里面
inviteCode String 6 位邀请码,用于加入这个组
createdAt Date 创建时间

设计取舍:共享关系没有直接把 members 数组塞进每一条 subscriptions 文档,而是单独建了 households 集合,用 groupId 关联。原因是一个共享组通常对应多条订阅(比如一家人共享 Netflix + Disney+ + 一份云存储),组成员变动时只需要改 households 一条记录,不用批量改所有关联的订阅;邀请码、组名这些也是"组"的属性而不是"某一条订阅"的属性,放在订阅文档上不合适。代价是查询订阅列表、扫描到期提醒时都要多一次 households 查询做人数/成员名单的关联,但这个项目量级下(个人/家庭用户,几条到几十条订阅)这点开销可以忽略,换来的是数据一致性更好维护。

共享账单闭环怎么跑通

  1. 打开"我的订阅"首页 -> 右上角"管理共享组" -> 创建一个组(比如"家庭账单"),拿到 6 位邀请码。
  2. 把邀请码告诉家人,或者点"分享邀请"通过微信直接转发小程序卡片(卡片链接里带了邀请码,对方点开后邀请码会自动填好)。
  3. 对方在"管理共享组"页输入邀请码 -> 加入,双方现在都在同一个 households.members 里。
  4. 添加/编辑一条订阅时,"共享给"选择器里选这个组,保存后这条订阅的 groupId 就指向这个组。
  5. 组内所有成员打开首页都能看到这条订阅,金额按当前组人数自动平均分摊,摊到自己头上的部分单独在首页统计卡片和列表条目里显示。
  6. 到期提醒触发时(scanExpiring),会给组内每一个成员分别发送订阅消息,不再只发给创建者。

网页演示版(H5 Demo Preview)

微信小程序只能在微信客户端内打开,招聘方/访客大概率没有微信环境去实际体验。为了解决这个问题,web-demo/index.html 是一个只读的静态演示页,用浏览器直接打开这一个文件就能看,不需要装任何依赖、不需要起服务、不连接真实云数据库:

  • 页面顶部有明显的"演示模式 / Demo Preview"标注,避免被误认为生产环境。
  • 界面完整复刻小程序首页:统计卡片(订阅数 / 我自己的订阅 / 共享分摊)、按到期时间排序的订阅列表、共享订阅的分摊标签、skeleton loading 骨架屏 -> 数据这个真实加载过程、按紧急程度分级的左侧颜色条(红/橙/绿)。
  • 数据是几条写死在 <script> 里的示例订阅(RAW_DATA),到期日期用相对"今天"的偏移天数生成,所以不管什么时候打开都会显示"最近到期",不会像固定日期一样过一阵子就变得不合理。
  • 点击订阅条目/"管理共享组"/右下角"+"这些交互,会弹出提示说明这是演示模式、完整功能需要在小程序内体验,而不是静默失败。
  • 目前只做了静态版本,没有接入云开发的 HTTP 触发云函数做真实只读数据源(那样需要额外设计一层免鉴权只读接口和跨域配置),优先保证这一版能直接打开就用,是后续如果需要"看真实数据"时可以再加的方向。

打开方式:直接双击 web-demo/index.html 用浏览器打开,或者 cd web-demo && python3 -m http.server 8080 起个本地静态服务器后访问 http://localhost:8080。

已知简化点(后续可以继续做的方向)

  • pages/edit/edit.js 的 loadExisting 目前是从上一页缓存的列表里找数据回显,正式做法应该是单独写一个 getSubscriptionDetail 云函数按 _id 查询。
  • 订阅消息是"一次性"授权机制,scanExpiring 在用户没有最近重新授权的情况下会发送失败,这是微信平台限制导致的预期行为,不是 bug(详见项目开发计划书第 7 节)。
  • 月度支出统计(index.js 里的 own/shared 两个 total)目前对 custom 周期类型做了简化处理,没有按 cycleDays 精确折算成月度等价支出。
  • 共享订阅目前只有创建者能编辑/删除,其他成员只能查看和被通知,避免多人同时编辑冲突;退出共享组、把成员踢出组这些管理功能还没做,目前只能通过邀请码加入,没有对应的退出/移除入口。
  • 邀请码没有做唯一性校验(6 位随机码理论上有极低概率重复),个人项目量级下影响可以忽略,真要严谨的话应该在生成时查重。

未来规划

  • 微信支付账单自动识别:设想是通过微信支付的账单/交易流水查询接口,自动识别用户新产生的订阅类扣费,免去手动添加这一步,甚至能在续费金额变化时自动提醒。目前没有实现、也没有写任何对接代码——这类接口面向的是已接入微信支付、有真实收单场景的商户/服务商,需要商户号资质,个人主体 + "工具"类目的小程序申请不到,是平台资质门槛问题,不是技术难度问题。评估后主动排除,只作为路线图记录。

相关文档

配套的完整开发计划书(需求范围、系统架构、8周开发排期、简历表述示例等)见:订阅到期提醒管理器_开发计划书.md

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages