feat(cloud): 实现微信云函数 - 订阅管理与每日运势推送
- subscribe: 用户订阅/取消订阅/查询订阅状态 - daily-push: 定时查询订阅用户、生成运势、发送订阅消息 - push-test: 推送调试云函数 - 定时触发器配置,每日 7:00/12:00/18:00 推送
This commit is contained in:
@@ -0,0 +1,210 @@
|
||||
// 云函数算法辅助模块
|
||||
// 包含运势生成所需的纯函数,适配 Node.js 环境
|
||||
|
||||
// 星曜吉凶定义
|
||||
const StarNature = {
|
||||
JI: 'JI',
|
||||
XIONG: 'XIONG',
|
||||
ZHONGHE: 'ZHONGHE',
|
||||
}
|
||||
|
||||
// 四化类型
|
||||
const TransformationType = {
|
||||
LU: 'LU',
|
||||
QUAN: 'QUAN',
|
||||
KE: 'KE',
|
||||
JI: 'JI',
|
||||
}
|
||||
|
||||
// 宫位类型
|
||||
const PalaceType = {
|
||||
MING: 'MING',
|
||||
XIONG: 'XIONG',
|
||||
FUQI: 'FUQI',
|
||||
CAI: 'CAI',
|
||||
JILU: 'JILU',
|
||||
QIAN: 'QIAN',
|
||||
GUANLU: 'GUANLU',
|
||||
TUDI: 'TUDI',
|
||||
FUBEN: 'FUBEN',
|
||||
FU: 'FU',
|
||||
SHEN: 'SHEN',
|
||||
ZINV: 'ZINV',
|
||||
}
|
||||
|
||||
// 地支序数
|
||||
const BRANCH_INDEX = {
|
||||
ZI: 1, CHOU: 2, YIN: 3, MAO: 4,
|
||||
CHEN: 5, SI: 6, WU: 7, WEI: 8,
|
||||
SHEN: 9, YOU: 10, XU: 11, HAI: 12,
|
||||
}
|
||||
|
||||
// 地支颜色映射
|
||||
const BRANCH_COLOR_MAP = {
|
||||
ZI: '黑色', CHOU: '黄色', YIN: '绿色', MAO: '绿色',
|
||||
CHEN: '黄色', SI: '红色', WU: '红色', WEI: '黄色',
|
||||
SHEN: '白色', YOU: '白色', XU: '黄色', HAI: '黑色',
|
||||
}
|
||||
|
||||
// 幸运颜色列表
|
||||
const LUCKY_COLORS = ['红色', '黄色', '蓝色', '绿色', '紫色', '金色', '白色', '黑色']
|
||||
|
||||
/**
|
||||
* 根据生辰信息和当前日期生成推送内容
|
||||
* @param {Object} birthInfo - 用户生辰信息
|
||||
* @param {Date} date - 当前日期
|
||||
* @returns {Object} 运势内容
|
||||
*/
|
||||
function generatePushContent(birthInfo, date) {
|
||||
// 基于生辰信息计算基础运势
|
||||
const baseScore = calculateBaseScore(birthInfo, date)
|
||||
const dailyScore = applyDailyAdjustment(baseScore, date)
|
||||
|
||||
const overallScore = clampScore(dailyScore)
|
||||
const overallLuck = determineLuckLevel(overallScore)
|
||||
|
||||
// 各维度运势
|
||||
const careerScore = clampScore(overallScore + getDimensionOffset(date, 'career'))
|
||||
const wealthScore = clampScore(overallScore + getDimensionOffset(date, 'wealth'))
|
||||
const relationshipScore = clampScore(overallScore + getDimensionOffset(date, 'relationship'))
|
||||
const healthScore = clampScore(overallScore + getDimensionOffset(date, 'health'))
|
||||
|
||||
const luckyColor = calculateLuckyColor(birthInfo, date)
|
||||
const luckyNumber = calculateLuckyNumber(birthInfo, date)
|
||||
|
||||
return {
|
||||
overallScore,
|
||||
overallLuck,
|
||||
careerAdvice: generateDimensionAdvice('事业', careerScore),
|
||||
wealthAdvice: generateDimensionAdvice('财运', wealthScore),
|
||||
relationshipAdvice: generateDimensionAdvice('感情', relationshipScore),
|
||||
healthAdvice: generateDimensionAdvice('健康', healthScore),
|
||||
luckyColor,
|
||||
luckyNumber,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算基础运势分数
|
||||
*/
|
||||
function calculateBaseScore(birthInfo, date) {
|
||||
// 根据出生月份和日期计算基础分
|
||||
const birthMonth = birthInfo.birthHour != null
|
||||
? (birthInfo.birthHour % 12) + 1
|
||||
: (date.getMonth() + 1)
|
||||
const birthDay = parseInt(birthInfo.birthDate.split('-')[2] || '15')
|
||||
|
||||
// 基础分 50-70
|
||||
const baseScore = 50 + (birthMonth * 3 + birthDay) % 21
|
||||
return baseScore
|
||||
}
|
||||
|
||||
/**
|
||||
* 应用每日调整
|
||||
*/
|
||||
function applyDailyAdjustment(baseScore, date) {
|
||||
const dayOfMonth = date.getDate()
|
||||
const month = date.getMonth() + 1
|
||||
|
||||
// 月相调整
|
||||
let adjustment = 0
|
||||
if (dayOfMonth <= 7) adjustment += 2
|
||||
else if (dayOfMonth <= 14) adjustment += 1
|
||||
else if (dayOfMonth <= 21) adjustment -= 1
|
||||
else adjustment -= 2
|
||||
|
||||
// 季节调整
|
||||
if (month >= 3 && month <= 5) adjustment += 1 // 春季
|
||||
else if (month >= 9 && month <= 11) adjustment -= 1 // 秋季
|
||||
|
||||
return baseScore + adjustment
|
||||
}
|
||||
|
||||
/**
|
||||
* 各维度偏移
|
||||
*/
|
||||
function getDimensionOffset(date, dimension) {
|
||||
const dayOfMonth = date.getDate()
|
||||
const month = date.getMonth() + 1
|
||||
|
||||
switch (dimension) {
|
||||
case 'career':
|
||||
return (dayOfMonth % 5 === 0) ? 5 : (dayOfMonth % 3 === 0) ? 2 : 0
|
||||
case 'wealth':
|
||||
return (dayOfMonth % 7 === 0) ? 5 : (dayOfMonth % 2 === 0) ? 2 : 0
|
||||
case 'relationship':
|
||||
return (dayOfMonth % 4 === 0) ? 3 : (month % 2 === 0) ? 1 : 0
|
||||
case 'health':
|
||||
return (dayOfMonth % 6 === 0) ? 3 : (month % 3 === 0) ? 1 : 0
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成各维度建议
|
||||
*/
|
||||
function generateDimensionAdvice(name, score) {
|
||||
if (score >= 80) {
|
||||
return `${name}运势吉显,宜把握良机`
|
||||
} else if (score >= 65) {
|
||||
return `${name}运势平顺,稳中求进`
|
||||
} else if (score >= 50) {
|
||||
return `${name}运势一般,谨慎行事`
|
||||
} else {
|
||||
return `${name}运势欠佳,宜静待时机`
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算幸运色
|
||||
*/
|
||||
function calculateLuckyColor(birthInfo, date) {
|
||||
const birthMonth = parseInt(birthInfo.birthDate.split('-')[1] || '1')
|
||||
const baseIndex = (birthMonth - 1) % LUCKY_COLORS.length
|
||||
const dayOffset = date.getDate() % 3
|
||||
const colorIndex = (baseIndex + dayOffset) % LUCKY_COLORS.length
|
||||
return LUCKY_COLORS[colorIndex]
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算幸运数字
|
||||
*/
|
||||
function calculateLuckyNumber(birthInfo, date) {
|
||||
const dayOfMonth = date.getDate()
|
||||
const month = date.getMonth() + 1
|
||||
const birthDay = parseInt(birthInfo.birthDate.split('-')[2] || '15')
|
||||
let num = (dayOfMonth + month + birthDay) % 9
|
||||
if (num === 0) num = 9
|
||||
return String(num)
|
||||
}
|
||||
|
||||
/**
|
||||
* 确定运势等级
|
||||
*/
|
||||
function determineLuckLevel(score) {
|
||||
if (score >= 90) return '大吉'
|
||||
if (score >= 80) return '吉'
|
||||
if (score >= 70) return '中吉'
|
||||
if (score >= 60) return '平'
|
||||
if (score >= 50) return '中平'
|
||||
if (score >= 40) return '小凶'
|
||||
return '凶'
|
||||
}
|
||||
|
||||
/**
|
||||
* 限制分数范围
|
||||
*/
|
||||
function clampScore(score) {
|
||||
return Math.max(0, Math.min(100, Math.floor(score)))
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
generatePushContent,
|
||||
determineLuckLevel,
|
||||
calculateLuckyColor,
|
||||
calculateLuckyNumber,
|
||||
PalaceType,
|
||||
StarNature,
|
||||
TransformationType,
|
||||
}
|
||||
Reference in New Issue
Block a user