新增 /api/subscribe 接口:授权上报与风险查询

- grantQuota/getQuotaStatus 从 index.js 导出供测试直接调用
- app.listen 加 require.main 守卫,避免测试 require 本文件时
  真的起服务占用端口、cron 定时器让进程无法退出
This commit is contained in:
yuming
2026-08-15 17:55:40 +08:00
parent 3a61b7952b
commit b1949ac73e
2 changed files with 105 additions and 5 deletions
+47 -5
View File
@@ -4,6 +4,8 @@ const express = require('express')
const db = require('./db')
const wx = require('./wx')
const reminder = require('./reminder')
const quota = require('./quota')
const atRisk = require('./atRisk')
const app = express()
app.use(express.json({ limit: '1mb' }))
@@ -221,6 +223,39 @@ function getPersons(openid) {
return { success: true, data: rows }
}
// ---- 订阅额度 ----
// 前端授权成功后上报。纯累加、不去重:微信侧确实每次授权都 +1,如实记录即可。
function grantQuota(openid, data) {
const count = (data && data.count) || 1
return { success: true, balance: quota.grant(openid, count) }
}
// 首页查询:返回余额和「哪几个人的提醒有风险」
function getQuotaStatus(openid) {
const balance = quota.getBalance(openid)
const rows = db.prepare('SELECT * FROM anniversaries WHERE openid = ? AND remindEnabled = 1').all(openid)
const { atRiskCount, atRiskNames } = atRisk.computeAtRisk(rows.map(normalize), balance)
return { success: true, balance, atRiskCount, atRiskNames }
}
app.post('/api/subscribe', (req, res) => {
try {
const openid = req.headers['x-openid'] || req.body.openid
if (!openid) return res.json({ success: false, error: '缺少 openid' })
const { action, data } = req.body
switch (action) {
case 'grant': return res.json(grantQuota(openid, data))
case 'get': return res.json(getQuotaStatus(openid))
default: return res.json({ success: false, error: '未知操作' })
}
} catch (err) {
console.error('订阅额度操作失败:', err.message)
res.json({ success: false, error: err.message })
}
})
// 手动触发提醒任务(便于调试,无需等到定点)
app.post('/api/reminder/run', async (req, res) => {
try {
@@ -231,10 +266,17 @@ app.post('/api/reminder/run', async (req, res) => {
}
})
module.exports = { grantQuota, getQuotaStatus }
// ---- 启动 ----
const PORT = process.env.PORT || 3000
app.listen(PORT, () => {
console.log(`生日提醒后端已启动,监听 ${PORT}`)
reminder.start()
})
// 只在直接执行本文件(node src/index.js / npm start)时才真正监听端口、注册定时任务。
// 测试用 require('../src/index') 只是拿函数引用,不需要(也不能)真的起服务——
// 否则会占住端口且 cron 定时器让进程一直不退出,测试永远卡住。
if (require.main === module) {
const PORT = process.env.PORT || 3000
app.listen(PORT, () => {
console.log(`生日提醒后端已启动,监听 ${PORT}`)
reminder.start()
})
}