Files
wxserver/cloudfunctions/sendReminder/index.js
T
yuming 3965e542fc
部署到群晖 / deploy (push) Failing after 6m22s
接入自建后端 + Gitea CI/CD
- 新增 server/:Node + Express + SQLite + node-cron 实现登录、纪念日 CRUD 和定时订阅消息推送
- 新增 .gitea/workflows/deploy.yml:推送即触发群晖 Docker 部署,监听 15002
- utils/api.js:自动按 envVersion 切换本地/线上 BASE_URL
- app.js 与 add-anniversary.js 移除 wx.cloud 调用,改走自建后端
- cloudfunctions/ 暂保留以便回滚
- 一并提交此前未入库的首页 / 设置页 / 日历 / 万年历等改造

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-01 15:44:09 +08:00

198 lines
5.3 KiB
JavaScript

// 云函数:发送生日提醒
const cloud = require('wx-server-sdk')
cloud.init({
env: cloud.DYNAMIC_CURRENT_ENV
})
const db = cloud.database()
// 模板ID
const TEMPLATE_ID = '6J7Stt-lu7DKU6jblJ0nZGq_D81z5glnksf7qWfy5Yw'
/**
* 计算两个日期之间的天数差
*/
function getDaysUntil(targetDate) {
const today = new Date()
today.setHours(0, 0, 0, 0)
const target = new Date(targetDate)
target.setHours(0, 0, 0, 0)
const diffTime = target - today
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24))
return diffDays
}
/**
* 格式化日期
*/
function formatDate(date) {
const d = new Date(date)
const year = d.getFullYear()
const month = String(d.getMonth() + 1).padStart(2, '0')
const day = String(d.getDate()).padStart(2, '0')
return `${year}${month}${day}`
}
const TYPE_NAMES = {
birthday: '公历生日',
lunar_birthday: '农历生日',
wedding: '结婚纪念日',
engagement: '订婚纪念日',
other: '其他纪念日'
}
/**
* 获取类型名称
*/
function getTypeName(type, customName) {
if (type === 'other' && customName) return customName
return TYPE_NAMES[type] || '纪念日'
}
/**
* 获取今年的纪念日日期
*/
function getThisYearDate(anniversary) {
const today = new Date()
const currentYear = today.getFullYear()
// 使用公历日期计算
let thisYearDate = new Date(currentYear, anniversary.solarMonth - 1, anniversary.solarDay)
// 如果今年的已经过了,计算明年的
const daysUntil = getDaysUntil(thisYearDate)
if (daysUntil < 0) {
thisYearDate = new Date(currentYear + 1, anniversary.solarMonth - 1, anniversary.solarDay)
}
return thisYearDate
}
/**
* 主函数
*/
exports.main = async (event, context) => {
console.log('开始执行提醒任务...')
try {
// 获取所有启用提醒的纪念日
const anniversariesRes = await db.collection('anniversaries')
.where({
remindEnabled: true
})
.get()
console.log(`找到 ${anniversariesRes.data.length} 条启用提醒的纪念日`)
let successCount = 0
let failCount = 0
// 遍历每个纪念日
for (const anniversary of anniversariesRes.data) {
try {
// 计算今年的纪念日日期
const thisYearDate = getThisYearDate(anniversary)
const daysUntil = getDaysUntil(thisYearDate)
console.log(`${anniversary.personName}${getTypeName(anniversary.type, anniversary.customTypeName)},还有 ${daysUntil}`)
// 判断是否需要提醒
const shouldRemind = (
daysUntil === 0 || // 当天
daysUntil === anniversary.remindDays // 提前N天
)
if (shouldRemind) {
// 检查今天是否已经发送过提醒
const today = new Date()
today.setHours(0, 0, 0, 0)
const logRes = await db.collection('remind_logs')
.where({
anniversaryId: anniversary._id,
sendDate: db.command.gte(today)
})
.count()
if (logRes.total > 0) {
console.log(`今天已发送过提醒,跳过: ${anniversary.personName}`)
continue
}
// 发送订阅消息
const sendRes = await cloud.openapi.subscribeMessage.send({
touser: anniversary.openid,
page: 'pages/index/index',
data: {
name1: {
value: anniversary.personName
},
thing2: {
value: daysUntil === 0 ? '今天' : `还有${daysUntil}`
},
thing6: {
value: formatDate(thisYearDate)
},
thing5: {
value: anniversary.remark || '别忘了准备一份礼物哦!'
}
},
templateId: TEMPLATE_ID,
miniprogramState: 'formal' // 正式版
})
console.log(`发送成功: ${anniversary.personName}`, sendRes)
// 记录提醒日志
await db.collection('remind_logs').add({
data: {
anniversaryId: anniversary._id,
personName: anniversary.personName,
typeName: getTypeName(anniversary.type, anniversary.customTypeName),
daysUntil: daysUntil,
sendDate: new Date(),
status: 'success'
}
})
successCount++
}
} catch (err) {
console.error(`发送失败: ${anniversary.personName}`, err)
failCount++
// 记录失败日志
await db.collection('remind_logs').add({
data: {
anniversaryId: anniversary._id,
personName: anniversary.personName,
sendDate: new Date(),
status: 'failed',
error: err.message
}
})
}
}
console.log(`提醒任务完成: 成功${successCount}条,失败${failCount}`)
return {
success: true,
total: anniversariesRes.data.length,
successCount,
failCount
}
} catch (err) {
console.error('提醒任务执行失败:', err)
return {
success: false,
error: err.message
}
}
}