245 lines
7.3 KiB
JavaScript
245 lines
7.3 KiB
JavaScript
|
|
const { getZodiacList } = require('./zodiacData');
|
|||
|
|
|
|||
|
|
// AI 配置
|
|||
|
|
const API_KEY = 'sk-f659b4c3aa954baaa6cbdbd5cae0b7d1';
|
|||
|
|
const BASE_URL = 'https://api.deepseek.com/chat/completions';
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 获取今日日期字符串 (YYYY-MM-DD)
|
|||
|
|
*/
|
|||
|
|
function getTodayStr() {
|
|||
|
|
const now = new Date();
|
|||
|
|
return `${now.getFullYear()}-${now.getMonth() + 1}-${now.getDate()}`;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 构建系统 Prompt
|
|||
|
|
*/
|
|||
|
|
function buildPrompt(zodiacName) {
|
|||
|
|
return `你是一位温暖、疗愈且富有洞察力的星座运势师。
|
|||
|
|
请根据今天的日期,为【${zodiacName}】生成一份专属运势。
|
|||
|
|
|
|||
|
|
【合规要求 - 极重要】
|
|||
|
|
1. 语言风格:温柔、诗意、治愈,仅供娱乐和心理参考。
|
|||
|
|
2. 禁止绝对化:不要使用“注定”、“一定会”、“必然”等词汇,使用“可能”、“倾向于”、“建议”等委婉表达。
|
|||
|
|
3. 禁止迷信承诺:严禁承诺具体的发财、升职、脱单结果。
|
|||
|
|
4. 禁止现实决策:严禁给出具体的医疗、法律、投资理财建议。
|
|||
|
|
5. 核心基调:通过细微的生活洞察,给人力量和抚慰,侧重心理状态疏导。
|
|||
|
|
|
|||
|
|
【输出结构】
|
|||
|
|
请严格按照以下 JSON 格式输出,不要包含 markdown 标记:
|
|||
|
|
{
|
|||
|
|
"keyword": "今日关键词 (2个字)",
|
|||
|
|
"core_energy": "核心能量 (15-20字,一句话概括)",
|
|||
|
|
"ratings": {
|
|||
|
|
"overall": 4, // 1-5的整数
|
|||
|
|
"love": 3,
|
|||
|
|
"career": 5,
|
|||
|
|
"wealth": 3
|
|||
|
|
},
|
|||
|
|
"fortune_text": {
|
|||
|
|
"love": "感情运势 (30-50字)",
|
|||
|
|
"career": "事业运势 (30-50字)",
|
|||
|
|
"wealth": "财运提醒 (30-50字)"
|
|||
|
|
},
|
|||
|
|
"lucky_elements": {
|
|||
|
|
"color": "颜色",
|
|||
|
|
"number": "数字",
|
|||
|
|
"time": "吉时 (如 15:00-17:00)"
|
|||
|
|
},
|
|||
|
|
"action": "行动建议 (20-30字)"
|
|||
|
|
}`;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 安全解析 JSON
|
|||
|
|
*/
|
|||
|
|
function safeJSONParse(text) {
|
|||
|
|
try {
|
|||
|
|
const cleanText = text.replace(/```json/g, '').replace(/```/g, '').trim();
|
|||
|
|
return JSON.parse(cleanText);
|
|||
|
|
} catch (e) {
|
|||
|
|
console.error('JSON解析失败:', e);
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 获取本地兜底数据 (适配新格式)
|
|||
|
|
*/
|
|||
|
|
function getLocalFallback(zodiacName) {
|
|||
|
|
const list = getZodiacList();
|
|||
|
|
const target = list.find(z => z.name === zodiacName);
|
|||
|
|
|
|||
|
|
if (target && target.fortunes && target.fortunes.length > 0) {
|
|||
|
|
const randomIdx = Math.floor(Math.random() * target.fortunes.length);
|
|||
|
|
const oldData = target.fortunes[randomIdx];
|
|||
|
|
|
|||
|
|
// 适配旧数据到新格式
|
|||
|
|
return {
|
|||
|
|
keyword: oldData.keyword,
|
|||
|
|
core_energy: oldData.today,
|
|||
|
|
ratings: {
|
|||
|
|
overall: 4,
|
|||
|
|
love: 3,
|
|||
|
|
career: 4,
|
|||
|
|
wealth: 3
|
|||
|
|
},
|
|||
|
|
fortune_text: {
|
|||
|
|
love: oldData.summary, // 暂用 summary 填充
|
|||
|
|
career: oldData.today,
|
|||
|
|
wealth: oldData.notice
|
|||
|
|
},
|
|||
|
|
lucky_elements: {
|
|||
|
|
color: "今日专属色",
|
|||
|
|
number: "7",
|
|||
|
|
time: "09:00-11:00"
|
|||
|
|
},
|
|||
|
|
action: oldData.action
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 获取星座运势 (优先缓存 -> AI -> 本地兜底)
|
|||
|
|
* @param {string} zodiacName 星座名称
|
|||
|
|
* @returns {Promise<object>} 运势数据对象
|
|||
|
|
*/
|
|||
|
|
async function fetchZodiacFortune(zodiacName) {
|
|||
|
|
const today = getTodayStr();
|
|||
|
|
const cacheKey = `zodiac_fortune_${zodiacName}_${today}`;
|
|||
|
|
|
|||
|
|
// 1. 检查缓存
|
|||
|
|
try {
|
|||
|
|
const cached = wx.getStorageSync(cacheKey);
|
|||
|
|
if (cached) {
|
|||
|
|
console.log(`[ZodiacAI] Hit cache for ${zodiacName}`);
|
|||
|
|
return cached;
|
|||
|
|
}
|
|||
|
|
} catch (e) {
|
|||
|
|
console.error('读取缓存失败:', e);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
console.log(`[ZodiacAI] Fetching AI for ${zodiacName}...`);
|
|||
|
|
|
|||
|
|
// 2. 调用 AI 接口
|
|||
|
|
try {
|
|||
|
|
const res = await new Promise((resolve, reject) => {
|
|||
|
|
wx.request({
|
|||
|
|
url: BASE_URL,
|
|||
|
|
method: 'POST',
|
|||
|
|
header: {
|
|||
|
|
'Content-Type': 'application/json',
|
|||
|
|
'Authorization': `Bearer ${API_KEY}`
|
|||
|
|
},
|
|||
|
|
data: {
|
|||
|
|
model: "deepseek-chat",
|
|||
|
|
messages: [
|
|||
|
|
{ role: "system", content: buildPrompt(zodiacName) },
|
|||
|
|
{ role: "user", content: `今天是 ${today},请解读。` }
|
|||
|
|
],
|
|||
|
|
temperature: 1.3 // 稍微提高创造性
|
|||
|
|
},
|
|||
|
|
timeout: 30000,
|
|||
|
|
success: resolve,
|
|||
|
|
fail: reject
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
if (res.statusCode === 200 && res.data.choices && res.data.choices[0]) {
|
|||
|
|
const content = res.data.choices[0].message.content;
|
|||
|
|
const parsedData = safeJSONParse(content);
|
|||
|
|
|
|||
|
|
if (parsedData) {
|
|||
|
|
// 3. 写入缓存 (成功才缓存)
|
|||
|
|
wx.setStorageSync(cacheKey, parsedData);
|
|||
|
|
return parsedData;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
console.warn('[ZodiacAI] AI response invalid, using fallback.');
|
|||
|
|
|
|||
|
|
} catch (err) {
|
|||
|
|
console.error('[ZodiacAI] Request failed:', err);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 4. 失败兜底 (返回本地数据)
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 获取今日星象概览 (每日更新一次)
|
|||
|
|
*/
|
|||
|
|
async function fetchDailyOverview() {
|
|||
|
|
const today = getTodayStr();
|
|||
|
|
const cacheKey = `daily_overview_${today}`;
|
|||
|
|
|
|||
|
|
// 1. 检查缓存
|
|||
|
|
try {
|
|||
|
|
const cached = wx.getStorageSync(cacheKey);
|
|||
|
|
if (cached) {
|
|||
|
|
return cached;
|
|||
|
|
}
|
|||
|
|
} catch (e) {
|
|||
|
|
console.error('读取缓存失败:', e);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const prompt = `你是一位专业占星师。请根据今天日期,生成一段通用的【今日星象概览】。
|
|||
|
|
【风格要求】
|
|||
|
|
- 客观、简练、有指导意义
|
|||
|
|
- 描述今天的月亮位置、主要行星相位(如水星三合木星等)及其对大众的影响
|
|||
|
|
|
|||
|
|
【输出格式】
|
|||
|
|
严格 JSON 格式:
|
|||
|
|
{
|
|||
|
|
"content": "星象描述 (40-60字)",
|
|||
|
|
"tags": ["标签1", "标签2", "标签3"] // 3个短标签,如:利于社交、适合学习、谨慎决策
|
|||
|
|
}`;
|
|||
|
|
|
|||
|
|
// 2. 调用 AI
|
|||
|
|
try {
|
|||
|
|
const res = await new Promise((resolve, reject) => {
|
|||
|
|
wx.request({
|
|||
|
|
url: BASE_URL,
|
|||
|
|
method: 'POST',
|
|||
|
|
header: {
|
|||
|
|
'Content-Type': 'application/json',
|
|||
|
|
'Authorization': `Bearer ${API_KEY}`
|
|||
|
|
},
|
|||
|
|
data: {
|
|||
|
|
model: "deepseek-chat",
|
|||
|
|
messages: [
|
|||
|
|
{ role: "system", content: prompt },
|
|||
|
|
{ role: "user", content: `今天是 ${today}。` }
|
|||
|
|
],
|
|||
|
|
temperature: 1.0
|
|||
|
|
},
|
|||
|
|
timeout: 30000,
|
|||
|
|
success: resolve,
|
|||
|
|
fail: reject
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
if (res.statusCode === 200 && res.data.choices) {
|
|||
|
|
const parsed = safeJSONParse(res.data.choices[0].message.content);
|
|||
|
|
if (parsed) {
|
|||
|
|
wx.setStorageSync(cacheKey, parsed);
|
|||
|
|
return parsed;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
} catch (err) {
|
|||
|
|
console.error('星象概览获取失败:', err);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 兜底数据
|
|||
|
|
return {
|
|||
|
|
content: "今日月亮能量温和,适合处理内心的情绪。水星状态良好,沟通效率较高。",
|
|||
|
|
tags: ["平稳", "沟通顺畅", "宜内省"]
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
module.exports = {
|
|||
|
|
fetchZodiacFortune,
|
|||
|
|
fetchDailyOverview
|
|||
|
|
};
|