1412 lines
56 KiB
JavaScript
1412 lines
56 KiB
JavaScript
// ===== 积分系统开关 =====
|
||
// 上架时设置为 true, 测试时设置为 false
|
||
const ENABLE_POINTS = false;
|
||
// =========================
|
||
|
||
// AI 配置 (建议后续迁移至后端以保证 API Key 安全)
|
||
const DEEPSEEK_API_KEY = 'sk-f659b4c3aa954baaa6cbdbd5cae0b7d1'; // 请在此处替换您的 API Key
|
||
const DEEPSEEK_BASE_URL = 'https://api.deepseek.com/chat/completions';
|
||
|
||
// --- 数据导入 ---
|
||
const { minorArcana } = require('../../data/tarot/index');
|
||
const { getQuestionType } = require('../../utils/questionType');
|
||
const { generateSpreadStory } = require('../../utils/spreadStory');
|
||
const { validateQuestion, scoreQuestion } = require('../../utils/questionFilter');
|
||
const { safeAIRequest } = require('../../utils/aiRequestManager');
|
||
const { hasEnough, deductPoints } = require('../../utils/pointsManager');
|
||
|
||
// --- Prompt 模板定义 ---
|
||
|
||
// 1. 基础版模板:平静、清晰、节制
|
||
const TAROT_PROMPT_BASE = `你是一位克制、温和、不制造依赖的塔罗解读者。
|
||
你的角色不是预测未来,而是陪伴当下的人理解此刻的状态。
|
||
|
||
【解读边界】
|
||
- 不给命令,不下结论,不使用“你应该”“结果是”“一定会”
|
||
- 不预测具体事件或时间,不制造焦虑或依赖
|
||
|
||
【语言风格】
|
||
- 平静、清晰、节制
|
||
- 使用“可能 / 正在 / 也许 / 可以感受到”
|
||
- 像是轻声说明,而不是说服或劝导,避免情绪渲染与神秘化表达
|
||
|
||
【解读结构】
|
||
1. 用 1–2 句话描绘这张牌当下呈现的状态氛围
|
||
2. 结合关键词与核心含义,解释它可能对应的内在状态
|
||
3. 用一句自然收口的话结束,不引导行动
|
||
|
||
【输出要求】
|
||
- 总字数 120–180 字
|
||
- 只输出解读文本,不使用标题、编号、分段符号`;
|
||
|
||
// 2. 深夜版模板:更慢、更柔和、允许留白
|
||
const TAROT_PROMPT_NIGHT = `你是一位安静、克制、不制造依赖的塔罗解读者。
|
||
此刻的解读更像一次低声的陪伴,而不是解释或分析。
|
||
|
||
【解读边界】
|
||
- 不给建议,不下判断,不使用“你应该”“结果是”“接下来会”
|
||
- 不预测未来事件或变化,不放大情绪,不渲染痛苦
|
||
|
||
【语言风格】
|
||
- 更慢、更柔和
|
||
- 使用“也许 / 正在 / 像是 / 仿佛”
|
||
- 允许留白,不急着说清楚一切,文字像夜晚一样安静
|
||
|
||
【解读结构】
|
||
1. 先用一句贴近当下感受的描述开头
|
||
2. 围绕关键词展开,但重点放在“感受本身”
|
||
3. 用一句轻微、可停住的句子结束,不指向下一步
|
||
|
||
【输出要求】
|
||
- 只输出解读文本`;
|
||
|
||
|
||
// 3. 增强版模板:解读稳定器 + 高关联性结构化解读
|
||
const TAROT_PROMPT_ENHANCED = `📏 解读稳定规则(高优先级执行)
|
||
|
||
你必须保持解读风格稳定、具体且一致,不允许出现质量波动。
|
||
|
||
【一、解读长度控制】
|
||
• 整体长度:400~700 字(不少于 300 字,不超过 900 字)
|
||
• 各模块建议:
|
||
- 问题回应:2~3句
|
||
- 牌面分析:每张牌2句以内
|
||
- 当前状态:2~3句
|
||
- 发展趋势:2~3句
|
||
- 行动建议:3~5条短句
|
||
• 禁止:超长段落、大段心理学科普、冗长比喻
|
||
|
||
【二、结构稳定规则(必须严格执行)】
|
||
输出必须包含且仅包含以下5个部分,不允许新增其他模块:
|
||
1. 问题回应
|
||
2. 牌面分析
|
||
3. 当前状态
|
||
4. 发展趋势
|
||
5. 行动建议
|
||
|
||
【三、解读深度控制】
|
||
每段必须包含至少一个:情境描述、心理状态、行为倾向、关系互动
|
||
禁止:单纯解释牌意、抽象空话、能量类泛词堆叠
|
||
|
||
【四、情绪语气稳定器】
|
||
• 必须:温和、理解用户、提供支持
|
||
• 避免:过度肯定(一定会)、绝对否定(绝不会)、命令式建议、恐吓式预测
|
||
• 推荐句式:"你当前可能正在经历…" "这可能让你感到…" "可以尝试…"
|
||
|
||
【五、百科化防护规则(非常重要)】
|
||
禁止出现:"通常这张牌代表…" "根据牌义…" "在传统塔罗中…"
|
||
如果出现类似内容,必须立即转化为与用户问题相关的情境说明。
|
||
|
||
【六、参考牌义权重限制】
|
||
信息优先级:用户问题 > 提问领域 > 抽到的牌 > 参考牌义
|
||
参考牌义只能用于理解,不允许复述或改写复述。
|
||
|
||
【七、质量自检(生成前内部执行)】
|
||
在输出前检查:
|
||
✓ 开头是否回应问题
|
||
✓ 是否逐张牌关联问题
|
||
✓ 是否包含可执行建议
|
||
✓ 是否出现百科语句
|
||
✓ 是否结构完整
|
||
|
||
---
|
||
|
||
🎯 角色设定
|
||
|
||
你是一位专业、温和、具有洞察力的塔罗解读师。
|
||
你的解读必须围绕用户提出的问题展开,而不是输出通用牌义。
|
||
|
||
⚠️ 本次解读优先级:
|
||
用户问题 > 提问领域 > 抽到的牌 > 参考牌义
|
||
|
||
🧭 解读核心要求(非常重要)
|
||
|
||
1️⃣ 解读必须紧密围绕「用户问题」展开
|
||
2️⃣ 开头第一句话必须直接回应用户的问题情境
|
||
3️⃣ 每一张牌都要说明它与该问题的具体关系
|
||
4️⃣ 禁止输出通用百科式牌义解释
|
||
5️⃣ 必须结合提问领域进行情境化分析
|
||
6️⃣ 解读重点放在状态、趋势与建议,而非绝对预测
|
||
|
||
🎨 语言风格要求
|
||
|
||
• 温和、具体、有针对性
|
||
• 使用"你当前的情况可能是…"
|
||
• 避免绝对判断和命令式语气
|
||
• 不要出现:"根据牌义来说…" "通常这张牌代表…"
|
||
|
||
🚫 禁止行为
|
||
|
||
• 不要复述参考牌义原文
|
||
• 不要脱离用户问题进行泛泛而谈
|
||
• 不要写百科解释
|
||
• 不要生成医疗、法律、金融建议
|
||
|
||
📤 输出格式
|
||
|
||
请严格按照以下 JSON 格式输出,不要包含任何其他说明性文字:
|
||
{
|
||
"theme": "直接回应用户问题的核心主题(必须提及问题关键词)",
|
||
"status": "用户在这个问题上的当前状态",
|
||
"influence": "影响这个问题的潜在因素",
|
||
"advice": "温和、可执行的个人成长建议",
|
||
"positions": [
|
||
{
|
||
"posName": "位置名称",
|
||
"posMeaning": "解释这张牌如何影响该问题情境(60-100字,必须联系问题)"
|
||
}
|
||
]
|
||
}`;
|
||
|
||
// 牌阵配置 - 包含所有可用牌阵
|
||
const SPREADS = [
|
||
{
|
||
"id": "one_card_guidance",
|
||
"name": "单张指引",
|
||
"cardCount": 1,
|
||
"cost": 1,
|
||
"positions": ["当下的指引"],
|
||
"description": "为你此刻的状态提供一个温和而清晰的方向提示",
|
||
"tags": ["综合"],
|
||
"aiSchema": ["core_theme", "current_state", "action_advice"]
|
||
},
|
||
{
|
||
"id": "three_time_flow",
|
||
"name": "过去·现在·未来",
|
||
"cardCount": 3,
|
||
"cost": 3,
|
||
"positions": ["过去", "现在", "未来"],
|
||
"description": "帮助你理解事情的发展过程与可能走向",
|
||
"tags": ["综合", "决策"],
|
||
"aiSchema": ["core_theme", "current_state", "potential_influence", "action_advice"]
|
||
},
|
||
{
|
||
"id": "three_problem_solution",
|
||
"name": "问题·阻碍·建议",
|
||
"cardCount": 3,
|
||
"cost": 3,
|
||
"positions": ["问题核心", "当前阻碍", "行动建议"],
|
||
"description": "聚焦关键问题,找出当下最可行的应对方式",
|
||
"tags": ["决策"],
|
||
"aiSchema": ["core_theme", "current_state", "action_advice"]
|
||
},
|
||
{
|
||
"id": "love_spark",
|
||
"name": "爱情火花",
|
||
"cardCount": 3,
|
||
"cost": 3,
|
||
"positions": ["你的感受", "对方的感受", "关系潜力"],
|
||
"description": "探索彼此的真实感受与这段关系的可能性",
|
||
"tags": ["爱情"],
|
||
"aiSchema": ["core_theme", "current_state", "potential_influence", "action_advice"]
|
||
},
|
||
{
|
||
"id": "two_choice_decision",
|
||
"name": "二选一抉择",
|
||
"cardCount": 4,
|
||
"cost": 4,
|
||
"positions": ["选择A的发展", "选择A的结果", "选择B的发展", "选择B的结果"],
|
||
"description": "对比两种选择的潜在走向,辅助理性决策",
|
||
"tags": ["决策"],
|
||
"aiSchema": ["core_theme", "potential_influence", "action_advice"]
|
||
},
|
||
{
|
||
"id": "relationship_healing",
|
||
"name": "关系修复",
|
||
"cardCount": 4,
|
||
"cost": 4,
|
||
"positions": ["问题根源", "你的责任", "对方的责任", "修复方向"],
|
||
"description": "深入理解关系裂痕,找到和解与修复的路径",
|
||
"tags": ["爱情"],
|
||
"aiSchema": ["core_theme", "current_state", "potential_influence", "action_advice"]
|
||
},
|
||
{
|
||
"id": "five_situation_analysis",
|
||
"name": "现状分析",
|
||
"cardCount": 5,
|
||
"cost": 5,
|
||
"positions": ["现状", "内在因素", "外在影响", "行动方向", "可能结果"],
|
||
"description": "从内外层面拆解局势,明确下一步行动",
|
||
"tags": ["事业", "综合"],
|
||
"aiSchema": ["core_theme", "current_state", "potential_influence", "action_advice"]
|
||
},
|
||
{
|
||
"id": "relationship_spread",
|
||
"name": "关系洞察",
|
||
"cardCount": 5,
|
||
"cost": 5,
|
||
"positions": ["你的位置", "对方的位置", "关系现状", "隐藏影响", "未来趋势"],
|
||
"description": "理解一段关系中的互动模式与发展方向",
|
||
"tags": ["爱情"],
|
||
"aiSchema": ["core_theme", "current_state", "potential_influence", "action_advice"]
|
||
},
|
||
{
|
||
"id": "destiny_connection",
|
||
"name": "缘分探索",
|
||
"cardCount": 5,
|
||
"cost": 5,
|
||
"positions": ["前世因缘", "今生相遇", "情感纽带", "考验挑战", "缘分走向"],
|
||
"description": "探索两人之间的灵性连接与命运安排",
|
||
"tags": ["爱情"],
|
||
"aiSchema": ["core_theme", "current_state", "potential_influence", "action_advice"]
|
||
},
|
||
{
|
||
"id": "career_breakthrough",
|
||
"name": "职场突破",
|
||
"cardCount": 5,
|
||
"cost": 5,
|
||
"positions": ["当前困境", "优势资源", "潜在机会", "需要克服", "突破方向"],
|
||
"description": "识别职场瓶颈,找到突破与晋升的关键",
|
||
"tags": ["事业"],
|
||
"aiSchema": ["core_theme", "current_state", "potential_influence", "action_advice"]
|
||
},
|
||
{
|
||
"id": "timeline_spread",
|
||
"name": "时间之流",
|
||
"cardCount": 5,
|
||
"cost": 5,
|
||
"positions": ["远古根源", "过去影响", "当下状态", "近期发展", "未来趋势"],
|
||
"description": "追溯事件的时间线,看清发展脉络",
|
||
"tags": ["综合"],
|
||
"aiSchema": ["core_theme", "current_state", "potential_influence", "action_advice"]
|
||
},
|
||
{
|
||
"id": "diamond_spread",
|
||
"name": "钻石牌阵",
|
||
"cardCount": 5,
|
||
"cost": 5,
|
||
"positions": ["问题本质", "过去原因", "未来发展", "外部资源", "最佳行动"],
|
||
"description": "多角度剖析问题,找到解决之道",
|
||
"tags": ["决策"],
|
||
"aiSchema": ["core_theme", "current_state", "potential_influence", "action_advice"]
|
||
},
|
||
{
|
||
"id": "career_planning",
|
||
"name": "事业规划",
|
||
"cardCount": 6,
|
||
"cost": 6,
|
||
"positions": ["当前位置", "核心优势", "发展方向", "潜在障碍", "贵人助力", "长期目标"],
|
||
"description": "全面规划职业发展路径,明确长期目标",
|
||
"tags": ["事业"],
|
||
"aiSchema": ["core_theme", "current_state", "potential_influence", "action_advice"]
|
||
},
|
||
{
|
||
"id": "wealth_analysis",
|
||
"name": "财运分析",
|
||
"cardCount": 6,
|
||
"cost": 6,
|
||
"positions": ["财务现状", "收入来源", "支出模式", "投资机会", "财务风险", "财富增长"],
|
||
"description": "深入分析财务状况,找到财富增长的路径",
|
||
"tags": ["事业"],
|
||
"aiSchema": ["core_theme", "current_state", "potential_influence", "action_advice"]
|
||
},
|
||
{
|
||
"id": "spiritual_guidance",
|
||
"name": "灵性指引",
|
||
"cardCount": 7,
|
||
"cost": 7,
|
||
"positions": ["当前能量", "内在阻碍", "潜在天赋", "灵性课题", "指导建议", "未来机遇", "最高指引"],
|
||
"description": "深入探索内在世界,获得灵性层面的启发",
|
||
"tags": ["深度"],
|
||
"aiSchema": ["core_theme", "current_state", "potential_influence", "action_advice"]
|
||
},
|
||
{
|
||
"id": "horseshoe_spread",
|
||
"name": "马蹄铁牌阵",
|
||
"cardCount": 7,
|
||
"cost": 7,
|
||
"positions": ["过去", "现在", "未来", "你的态度", "他人影响", "障碍", "最终结果"],
|
||
"description": "全面了解情况的来龙去脉与未来走向",
|
||
"tags": ["综合"],
|
||
"aiSchema": ["core_theme", "current_state", "potential_influence", "action_advice"]
|
||
},
|
||
{
|
||
"id": "celtic_cross",
|
||
"name": "凯尔特十字",
|
||
"cardCount": 10,
|
||
"cost": 10,
|
||
"positions": ["现状", "挑战", "根基", "过去", "可能性", "近期未来", "你的态度", "外部影响", "希望与恐惧", "最终结果"],
|
||
"description": "最经典的综合牌阵,深度解析生命议题",
|
||
"tags": ["深度"],
|
||
"aiSchema": ["core_theme", "current_state", "potential_influence", "action_advice"]
|
||
},
|
||
{
|
||
"id": "tree_of_life",
|
||
"name": "生命之树",
|
||
"cardCount": 10,
|
||
"cost": 10,
|
||
"positions": ["王冠", "智慧", "理解", "慈悲", "严厉", "美丽", "胜利", "荣耀", "基础", "王国"],
|
||
"description": "基于卡巴拉生命之树的深度灵性探索",
|
||
"tags": ["深度"],
|
||
"aiSchema": ["core_theme", "current_state", "potential_influence", "action_advice"]
|
||
},
|
||
// 新增爱情牌阵
|
||
{
|
||
"id": "lover_pyramid",
|
||
"name": "恋人金字塔",
|
||
"cardCount": 4,
|
||
"cost": 4,
|
||
"positions": ["核心关系", "你的状态", "对方状态", "未来发展"],
|
||
"description": "适合恋人关系 & 互动解析",
|
||
"tags": ["爱情"],
|
||
"aiSchema": ["core_theme", "current_state", "potential_influence", "action_advice"]
|
||
},
|
||
{
|
||
"id": "new_love",
|
||
"name": "新爱牌阵",
|
||
"cardCount": 3,
|
||
"cost": 3,
|
||
"positions": ["当前状态", "遇见契机", "发展方向"],
|
||
"description": "适合新的感情 & 遇见新欢,为单身的你或刚分手的你带来新爱提示",
|
||
"tags": ["爱情"],
|
||
"aiSchema": ["core_theme", "current_state", "action_advice"]
|
||
},
|
||
{
|
||
"id": "relationship_basic",
|
||
"name": "人际关系牌阵",
|
||
"cardCount": 3,
|
||
"cost": 3,
|
||
"positions": ["你的想法", "对方想法", "关系走向"],
|
||
"description": "适合梳理关系 & 拉近距离,回溯结识初衷,梳理人际关系,拉近彼此距离",
|
||
"tags": ["爱情"],
|
||
"aiSchema": ["core_theme", "current_state", "action_advice"]
|
||
},
|
||
{
|
||
"id": "love_tree_spread",
|
||
"name": "爱情树牌阵",
|
||
"cardCount": 5,
|
||
"cost": 5,
|
||
"positions": ["核心问题", "过去影响", "现在状况", "未来趋势", "最终结果"],
|
||
"description": "适合深度求爱 & 寻找症结,解析前因后果,回溯爱情过往,探究本源核心",
|
||
"tags": ["爱情"],
|
||
"aiSchema": ["core_theme", "current_state", "potential_influence", "action_advice"]
|
||
},
|
||
{
|
||
"id": "love_cross_spread",
|
||
"name": "爱情大十字",
|
||
"cardCount": 5,
|
||
"cost": 5,
|
||
"positions": ["你的状态", "对方状态", "过去影响", "现在情况", "未来发展"],
|
||
"description": "适合解析两性关系 & 爱情状况,基于洞悉彼此关系中的情感状况并分析结果",
|
||
"tags": ["爱情"],
|
||
"aiSchema": ["core_theme", "current_state", "potential_influence", "action_advice"]
|
||
},
|
||
{
|
||
"id": "mr_right",
|
||
"name": "真命天子牌阵",
|
||
"cardCount": 5,
|
||
"cost": 5,
|
||
"positions": ["内心期待", "现实阻碍", "理想对象", "行动建议", "遇见时机"],
|
||
"description": "单身探索有缘人 & 合适对象,探索内心的想法,改善外在的行为,遇到适合的人",
|
||
"tags": ["爱情"],
|
||
"aiSchema": ["core_theme", "current_state", "potential_influence", "action_advice"]
|
||
},
|
||
{
|
||
"id": "search_lover",
|
||
"name": "寻找对象牌阵",
|
||
"cardCount": 5,
|
||
"cost": 5,
|
||
"positions": ["当前状态", "优势特质", "改进方向", "寻找方式", "目标确定"],
|
||
"description": "适合寻找意中人 & 有缘人,睁全宫中人的愿景,帮助自己确定目标",
|
||
"tags": ["爱情"],
|
||
"aiSchema": ["core_theme", "current_state", "potential_influence", "action_advice"]
|
||
},
|
||
{
|
||
"id": "inspiration_correspondence",
|
||
"name": "灵感对应牌阵",
|
||
"cardCount": 6,
|
||
"cost": 6,
|
||
"positions": ["情感现状", "内心需求", "对方感受", "互动方式", "发展建议", "最终走向"],
|
||
"description": "适合情感困惑 & 人际关系,增长解析指缘联接或情感互动,帮您交融状态",
|
||
"tags": ["爱情"],
|
||
"aiSchema": ["core_theme", "current_state", "potential_influence", "action_advice"]
|
||
},
|
||
{
|
||
"id": "gypsy_spread",
|
||
"name": "吉普赛牌阵",
|
||
"cardCount": 5,
|
||
"cost": 5,
|
||
"positions": ["你的想法", "对方想法", "过去经历", "现在状况", "未来发展"],
|
||
"description": "适合情侣分析 & 关系延展,探索彼此内心想法,找到合适的相处方式",
|
||
"tags": ["爱情"],
|
||
"aiSchema": ["core_theme", "current_state", "potential_influence", "action_advice"]
|
||
},
|
||
{
|
||
"id": "venus_spread",
|
||
"name": "维纳斯牌阵",
|
||
"cardCount": 8,
|
||
"cost": 8,
|
||
"positions": ["你的状态", "对方状态", "关系开始", "当前情况", "核心问题", "最终结果", "外部影响", "内在感受"],
|
||
"description": "适合爱情发展 & 判断走向,全面的爱情解析牌阵,深入分析两性关系",
|
||
"tags": ["爱情"],
|
||
"aiSchema": ["core_theme", "current_state", "potential_influence", "action_advice"]
|
||
},
|
||
{
|
||
"id": "lover_tree",
|
||
"name": "恋人之树牌阵",
|
||
"cardCount": 7,
|
||
"cost": 7,
|
||
"positions": ["你的行为", "对方行为", "你的想法", "对方想法", "你的感受", "对方感受", "关系走向"],
|
||
"description": "适合探究对方心理 & 行为模式,对比情侣间的行为差异,进而根据事实做出判断",
|
||
"tags": ["爱情"],
|
||
"aiSchema": ["core_theme", "current_state", "potential_influence", "action_advice"]
|
||
},
|
||
{
|
||
"id": "marriage_spread",
|
||
"name": "婚姻牌阵",
|
||
"cardCount": 7,
|
||
"cost": 7,
|
||
"positions": ["婚姻基础", "你的期望", "对方期望", "核心问题", "外部影响", "内在感受", "未来走向"],
|
||
"description": "适合婚姻状况 & 内在剖析,针对婚姻状况和期望进行解析,通过细致分析把握婚姻走向",
|
||
"tags": ["爱情"],
|
||
"aiSchema": ["core_theme", "current_state", "potential_influence", "action_advice"]
|
||
},
|
||
// 新增事业牌阵
|
||
{
|
||
"id": "golden_triangle",
|
||
"name": "金三角牌阵",
|
||
"cardCount": 3,
|
||
"cost": 3,
|
||
"positions": ["问题核心", "左侧因素", "右侧因素"],
|
||
"description": "适合财富探索 & 问题解析,清楚审视整个问题的来龙去脉,进而做出正确决策",
|
||
"tags": ["事业", "财富"],
|
||
"aiSchema": ["core_theme", "current_state", "action_advice"]
|
||
},
|
||
{
|
||
"id": "success_star",
|
||
"name": "成功之星牌阵",
|
||
"cardCount": 3,
|
||
"cost": 3,
|
||
"positions": ["当前位置", "行动方向", "成功目标"],
|
||
"description": "适合走位辨路 & 累积行动,锁定目标破除阻碍,告诉星光,心有明月再出发",
|
||
"tags": ["事业"],
|
||
"aiSchema": ["core_theme", "current_state", "action_advice"]
|
||
},
|
||
{
|
||
"id": "career_pyramid",
|
||
"name": "事业金字塔",
|
||
"cardCount": 4,
|
||
"cost": 4,
|
||
"positions": ["核心优势", "需要改进", "外部机会", "未来发展"],
|
||
"description": "适合解析财富运势 & 提升财商,明晰自我的优缺点,帮助自己除弊趋利在事业中获得优势",
|
||
"tags": ["事业"],
|
||
"aiSchema": ["core_theme", "current_state", "potential_influence", "action_advice"]
|
||
},
|
||
{
|
||
"id": "wealth_tree",
|
||
"name": "财富之树牌阵",
|
||
"cardCount": 5,
|
||
"cost": 5,
|
||
"positions": ["财务基础", "收入来源", "支出状况", "当前状态", "未来趋势"],
|
||
"description": "适合事业发展 & 状态评估,通过对财富的梳理,健全适合自己的财务模式",
|
||
"tags": ["事业", "财富"],
|
||
"aiSchema": ["core_theme", "current_state", "potential_influence", "action_advice"]
|
||
},
|
||
{
|
||
"id": "x_opportunity",
|
||
"name": "X时机牌阵",
|
||
"cardCount": 5,
|
||
"cost": 5,
|
||
"positions": ["当前时机", "有利因素", "不利因素", "行动建议", "结果预测"],
|
||
"description": "适合时机捕捉 & 临场决策,以事物处理时机为主线轴,牵挂问题解决的成功概率",
|
||
"tags": ["事业", "决策"],
|
||
"aiSchema": ["core_theme", "current_state", "potential_influence", "action_advice"]
|
||
},
|
||
{
|
||
"id": "job_interview",
|
||
"name": "面试求职牌阵",
|
||
"cardCount": 5,
|
||
"cost": 5,
|
||
"positions": ["自我状态", "优势展现", "需要注意", "面试官印象", "录用可能"],
|
||
"description": "适合解析应聘面试 & 求职状况,洞察对方需求与自我留言,有效提高面试成功率",
|
||
"tags": ["事业"],
|
||
"aiSchema": ["core_theme", "current_state", "potential_influence", "action_advice"]
|
||
},
|
||
{
|
||
"id": "work_problems",
|
||
"name": "工作问题牌阵",
|
||
"cardCount": 6,
|
||
"cost": 6,
|
||
"positions": ["问题核心", "上级态度", "同事关系", "个人能力", "外部环境", "解决方案"],
|
||
"description": "适合聚焦目标 & 优化路径,当你明确自己的目标,全世界都会为你让路",
|
||
"tags": ["事业"],
|
||
"aiSchema": ["core_theme", "current_state", "potential_influence", "action_advice"]
|
||
},
|
||
{
|
||
"id": "turbulent_finances",
|
||
"name": "财富波浪牌阵",
|
||
"cardCount": 6,
|
||
"cost": 6,
|
||
"positions": ["财务起点", "第一波动", "稳定期", "第二波动", "调整期", "未来趋势"],
|
||
"description": "适合借力打力 & 多空对比,追问本质,结合正反两方面的分析,做出理智判断",
|
||
"tags": ["事业", "财富"],
|
||
"aiSchema": ["core_theme", "current_state", "potential_influence", "action_advice"]
|
||
},
|
||
{
|
||
"id": "desired_job",
|
||
"name": "期望的工作",
|
||
"cardCount": 6,
|
||
"cost": 6,
|
||
"positions": ["理想工作", "个人优势", "需要提升", "寻找方向", "关键因素", "实现可能"],
|
||
"description": "适合评估工作前景 & 关联因素,剖析工作前景,理清相关因素,给出明确的思路",
|
||
"tags": ["事业"],
|
||
"aiSchema": ["core_theme", "current_state", "potential_influence", "action_advice"]
|
||
},
|
||
// 新增决策牌阵
|
||
{
|
||
"id": "two_options",
|
||
"name": "二个选择牌阵",
|
||
"cardCount": 3,
|
||
"cost": 3,
|
||
"positions": ["选项A", "选项B", "建议方向"],
|
||
"description": "适合评测选项 & 做出抉择,在两难的处境中给出建议,选出适合自己的抉择",
|
||
"tags": ["决策"],
|
||
"aiSchema": ["core_theme", "current_state", "action_advice"]
|
||
},
|
||
{
|
||
"id": "three_options",
|
||
"name": "三个选择牌阵",
|
||
"cardCount": 3,
|
||
"cost": 3,
|
||
"positions": ["当前状况", "参考方向一", "参考方向二"],
|
||
"description": "提供参考方向 & 行动指向,遇到3个选择时,给你提供参考的方向",
|
||
"tags": ["决策"],
|
||
"aiSchema": ["core_theme", "current_state", "action_advice"]
|
||
},
|
||
{
|
||
"id": "daily_tree",
|
||
"name": "每日树牌阵",
|
||
"cardCount": 4,
|
||
"cost": 4,
|
||
"positions": ["今日核心", "需要注意", "有利因素", "行动建议"],
|
||
"description": "适长当日难题 & 当日解决,天天没烦恼,解决每天遇到的问题",
|
||
"tags": ["综合"],
|
||
"aiSchema": ["core_theme", "current_state", "action_advice"]
|
||
},
|
||
{
|
||
"id": "weigh_two",
|
||
"name": "二选一牌阵",
|
||
"cardCount": 5,
|
||
"cost": 5,
|
||
"positions": ["当前状况", "选项A优势", "选项B优势", "选项A劣势", "选项B劣势"],
|
||
"description": "主要用于抉择 & 判断,二选一,适用于二种情况选择其中一种",
|
||
"tags": ["决策"],
|
||
"aiSchema": ["core_theme", "current_state", "potential_influence", "action_advice"]
|
||
},
|
||
{
|
||
"id": "comparing_choices",
|
||
"name": "比较选择牌阵",
|
||
"cardCount": 6,
|
||
"cost": 6,
|
||
"positions": ["选项A现状", "选项A发展", "选项A结果", "选项B现状", "选项B发展", "选项B结果"],
|
||
"description": "适合判断情势 & 决定方向,多层面聚焦两个方向,更多的线索更多的细节",
|
||
"tags": ["决策"],
|
||
"aiSchema": ["core_theme", "current_state", "potential_influence", "action_advice"]
|
||
},
|
||
{
|
||
"id": "weigh_three",
|
||
"name": "三选一牌阵",
|
||
"cardCount": 7,
|
||
"cost": 7,
|
||
"positions": ["当前状况", "选项A优势", "选项B优势", "选项A劣势", "选项C优势", "选项C劣势", "选项B劣势"],
|
||
"description": "适合事情抉择 & 选择评估,对利弊关系进行分析判断,权衡利弊,做出最终的选择",
|
||
"tags": ["决策"],
|
||
"aiSchema": ["core_theme", "current_state", "potential_influence", "action_advice"]
|
||
},
|
||
// 新增深度探索牌阵
|
||
{
|
||
"id": "mind_body_spirit",
|
||
"name": "身心灵牌阵",
|
||
"cardCount": 4,
|
||
"cost": 4,
|
||
"positions": ["身体", "心智", "灵性", "整体状态"],
|
||
"description": "适合自我探索 & 了解自己,透彻审视自我,更直切明了自身成长路径",
|
||
"tags": ["成长", "综合"],
|
||
"aiSchema": ["core_theme", "current_state", "action_advice"]
|
||
},
|
||
{
|
||
"id": "four_elements",
|
||
"name": "四元素牌阵",
|
||
"cardCount": 4,
|
||
"cost": 4,
|
||
"positions": ["感性", "理性", "物质", "行动"],
|
||
"description": "适合问题探索 & 多方解析,从感性、理性、物质、行动四方面分析,进而接近实质",
|
||
"tags": ["探索", "综合"],
|
||
"aiSchema": ["core_theme", "current_state", "action_advice"]
|
||
},
|
||
{
|
||
"id": "self_discovery",
|
||
"name": "自我探索牌阵",
|
||
"cardCount": 4,
|
||
"cost": 4,
|
||
"positions": ["核心自我", "潜能", "优势", "需要提升"],
|
||
"description": "适合认识自我 & 提升潜能,开发自身潜力,提高对自己的认识",
|
||
"tags": ["探索", "成长"],
|
||
"aiSchema": ["core_theme", "current_state", "action_advice"]
|
||
},
|
||
{
|
||
"id": "know_yourself",
|
||
"name": "认识你自己",
|
||
"cardCount": 5,
|
||
"cost": 5,
|
||
"positions": ["核心自我", "思想", "行为", "情感", "环境影响"],
|
||
"description": "适合自我剖析 & 境况认知,人无时无刻不受环境的影响,在各种关系的交织中成长",
|
||
"tags": ["成长", "综合"],
|
||
"aiSchema": ["core_theme", "current_state", "potential_influence", "action_advice"]
|
||
},
|
||
{
|
||
"id": "your_breakthrough",
|
||
"name": "你的突破牌阵",
|
||
"cardCount": 5,
|
||
"cost": 5,
|
||
"positions": ["当前困境", "阻碍因素", "突破点", "行动方向", "预期结果"],
|
||
"description": "适合打破僵环 & 突破自我,识别固定模式,突破往复循环",
|
||
"tags": ["成长"],
|
||
"aiSchema": ["core_theme", "current_state", "potential_influence", "action_advice"]
|
||
},
|
||
{
|
||
"id": "elemental_cross",
|
||
"name": "元素十字牌阵",
|
||
"cardCount": 6,
|
||
"cost": 6,
|
||
"positions": ["核心问题", "火元素", "水元素", "风元素", "土元素", "解决方案"],
|
||
"description": "主要用于带入问题 & 解决问题,根据现实情况全面运用四元素能提升自己",
|
||
"tags": ["探索", "综合"],
|
||
"aiSchema": ["core_theme", "current_state", "potential_influence", "action_advice"]
|
||
},
|
||
{
|
||
"id": "wheel_spread",
|
||
"name": "车轮牌阵",
|
||
"cardCount": 7,
|
||
"cost": 7,
|
||
"positions": ["中心", "过去", "现在", "未来", "机会", "挑战", "结果"],
|
||
"description": "适合专注自我 & 探寻改变,有时走出循环照顾的舒适圈,有所改变时,才能成长",
|
||
"tags": ["成长"],
|
||
"aiSchema": ["core_theme", "current_state", "potential_influence", "action_advice"]
|
||
},
|
||
{
|
||
"id": "seven_planets",
|
||
"name": "七行星牌阵",
|
||
"cardCount": 7,
|
||
"cost": 7,
|
||
"positions": ["核心", "月亮", "水星", "金星", "太阳", "火星", "木星"],
|
||
"description": "适合审视目前状态 & 了解自己,综合分析当下状况,全面的了解自己",
|
||
"tags": ["成长", "综合"],
|
||
"aiSchema": ["core_theme", "current_state", "potential_influence", "action_advice"]
|
||
},
|
||
{
|
||
"id": "dream_mirror",
|
||
"name": "梦镜牌阵",
|
||
"cardCount": 7,
|
||
"cost": 7,
|
||
"positions": ["梦境表象", "潜意识", "情感", "符号", "启示", "行动", "整合"],
|
||
"description": "适合分析梦境 & 获得启迪,梦像一面镜子,解读梦境,是理解自己的渠道",
|
||
"tags": ["探索"],
|
||
"aiSchema": ["core_theme", "current_state", "potential_influence", "action_advice"]
|
||
}
|
||
];
|
||
|
||
|
||
|
||
|
||
Page({
|
||
data: {
|
||
todayDate: '', // 用于存储今天的日期
|
||
// 1. 状态管理: spread_select, idle, shuffling, drawing, flipping, revealed
|
||
state: 'spread_select', // 初始进入牌阵选择
|
||
selectedSpread: null,
|
||
question: '', // 用户输入的问题
|
||
questionType: '综合问题', // 问题类型
|
||
questionQuality: null, // 问题质量评分
|
||
drawnCardIndices: [], // 用户选中的牌索引
|
||
drawnCards: [], // 实际抽到的牌对象
|
||
revealedCount: 0, // 已翻开的数量
|
||
|
||
cardBackImage: '/images/beimian.png',
|
||
spreads: SPREADS,
|
||
|
||
// 牌阵筛选状态
|
||
activeTag: '全部',
|
||
filteredSpreads: SPREADS,
|
||
spreadTags: ['全部', '综合', '爱情', '事业', '决策', '深度', '成长', '探索'],
|
||
|
||
// 动画数据
|
||
deckAnimation: {},
|
||
cardAnimation: {},
|
||
infoAnimation: {},
|
||
guideAnimation: {},
|
||
|
||
// AI 解读相关
|
||
aiResult: null,
|
||
isAiLoading: false,
|
||
aiLoadingText: '正在抽取牌面…', // 动态加载提示
|
||
spreadStory: '',
|
||
|
||
// 3. 前缀文案列表(随机抽取)
|
||
prefixList: [
|
||
"今天,这张牌提醒你:",
|
||
"此刻,宇宙传递的信息:",
|
||
"这张牌想告诉你:",
|
||
"请收下这份指引:"
|
||
],
|
||
|
||
// 2. 完整的 22 张大阿尔卡那牌组(包含逆位含义)
|
||
cardList: [
|
||
{
|
||
name: "愚者",
|
||
keyword: "新的开始",
|
||
meaning: "放下恐惧,勇敢迈出第一步,世界充满无限可能。",
|
||
reversedMeaning: "也许有些太冲动了?停下来检查一下背包,确保安全再出发。",
|
||
energy: "外放",
|
||
image: "/images/yuzhe.png"
|
||
},
|
||
{
|
||
name: "魔术师",
|
||
keyword: "创造力",
|
||
meaning: "你拥有实现目标所需的一切资源,现在是行动的时候。",
|
||
reversedMeaning: "你是否低估了自己的能力?或者在犹豫不决?相信自己,工具就在手边。",
|
||
energy: "外放",
|
||
image: "/images/moshushi.png"
|
||
},
|
||
{
|
||
name: "女祭司",
|
||
keyword: "直觉",
|
||
meaning: "倾听内心的声音,答案就在你潜意识的深处。",
|
||
reversedMeaning: "暂时听不见内心的声音了吗?别急着向外寻找,先让自己静下来。",
|
||
energy: "内敛",
|
||
image: "/images/nvjishi.png"
|
||
},
|
||
{
|
||
name: "皇后",
|
||
keyword: "丰饶",
|
||
meaning: "享受生活的美好,去创造、去关爱,收获也是一种能力。",
|
||
reversedMeaning: "是否忽略了对自己的关爱?或者有些过度保护?给彼此一点呼吸的空间。",
|
||
energy: "柔和",
|
||
image: "/images/nvhuang.png"
|
||
},
|
||
{
|
||
name: "皇帝",
|
||
keyword: "秩序",
|
||
meaning: "建立规则和结构,理性地掌控局面,承担起责任。",
|
||
reversedMeaning: "有时候太固执会让人疲惫,适度放权,弹性也是一种力量。",
|
||
energy: "坚实",
|
||
image: "/images/huangdi.png"
|
||
},
|
||
{
|
||
name: "教皇",
|
||
keyword: "指引",
|
||
meaning: "寻求传统智慧的帮助,或者成为他人的精神导师。",
|
||
reversedMeaning: "不必拘泥于陈规旧矩,试着打破常规,寻找适合你自己的那条路。",
|
||
energy: "庄重",
|
||
image: "/images/jiaohuang.png"
|
||
},
|
||
{
|
||
name: "恋人",
|
||
keyword: "选择",
|
||
meaning: "跟随你的心,在关系中寻找和谐,做出忠于自我的决定。",
|
||
reversedMeaning: "现在的关系是否有些失衡?先爱自己,才能更好地爱别人。",
|
||
energy: "柔和",
|
||
image: "/images/lianren.png"
|
||
},
|
||
{
|
||
name: "战车",
|
||
keyword: "意志",
|
||
meaning: "认准目标,克服相反的力量,胜利属于坚持到底的人。",
|
||
reversedMeaning: "感觉失去了方向控制?慢下来,重新调整导航,欲速则不达。",
|
||
energy: "激进",
|
||
image: "/images/zhanche.png"
|
||
},
|
||
{
|
||
name: "力量",
|
||
keyword: "勇气",
|
||
meaning: "真正的力量是温柔的坚持,用耐心驯服内心的野兽。",
|
||
reversedMeaning: "不要怀疑自己的韧性,面对内心的软弱并不是坏事,那是温柔的开始。",
|
||
energy: "柔和",
|
||
image: "/images/liliang.png"
|
||
},
|
||
{
|
||
name: "隐士",
|
||
keyword: "内省",
|
||
meaning: "暂时远离喧嚣,向内探索,寻找属于你自己的光。",
|
||
reversedMeaning: "`是不是一个人待太久了?试着走出洞穴,和外界建立一点连接吧。",
|
||
energy: "潜沉",
|
||
image: "/images/yinzhe.png"
|
||
},
|
||
{
|
||
name: "命运之轮",
|
||
keyword: "转折",
|
||
meaning: "改变是永恒的,顺势而为,抓住出现在你面前的机会。",
|
||
reversedMeaning: "运气暂时不在你这边,但没关系,低谷正是蓄力反弹的好时机。",
|
||
energy: "流转",
|
||
image: "/images/mingyunzhilun.png"
|
||
},
|
||
{
|
||
name: "正义",
|
||
keyword: "因果",
|
||
meaning: "诚实面对真相,所有的决定都会带来相应的结果。",
|
||
reversedMeaning: "即使结果不尽如人意,也要问心无愧。对自己诚实,比什么都重要。",
|
||
energy: "平衡",
|
||
image: "/images/zhengyi.png"
|
||
},
|
||
{
|
||
name: "倒吊人",
|
||
keyword: "换位",
|
||
meaning: "换一个角度看世界,有时候牺牲是为了更大的获得。",
|
||
reversedMeaning: "挣扎只会更累,不如彻底放松,换个角度看世界,也许心结就解开了。",
|
||
energy: "停滞",
|
||
image: "/images/daodiaoren.png"
|
||
},
|
||
{
|
||
name: "死神",
|
||
keyword: "新生",
|
||
meaning: "结束是为了新的开始,彻底告别过去,才能拥抱未来。",
|
||
reversedMeaning: "还在紧抓着过去不放吗?只有腾出双手,才能接住新的礼物。",
|
||
energy: "决绝",
|
||
image: "/images/sishen.png"
|
||
},
|
||
{
|
||
name: "节制",
|
||
keyword: "平衡",
|
||
meaning: "在极端之间寻找中庸之道,融合对立,通过耐心获得疗愈。",
|
||
reversedMeaning: "是不是有些失衡了?在这忙乱的世界里,找回你内心的节奏和中点。",
|
||
energy: "融合",
|
||
image: "/images/jiezhi.png"
|
||
},
|
||
{
|
||
name: "恶魔",
|
||
keyword: "束缚",
|
||
meaning: "觉察那些控制你的欲望或习惯,唯有觉知才能带来解脱。",
|
||
reversedMeaning: "别被眼前的诱惑蒙蔽,或者感觉被束缚。其实锁链是松的,你随时可以走。",
|
||
energy: "沉重",
|
||
image: "/images/emo.png"
|
||
},
|
||
{
|
||
name: "高塔",
|
||
keyword: "崩塌",
|
||
meaning: "不要害怕突如其来的剧变,它在摧毁虚假的根基,让你重建真实。",
|
||
reversedMeaning: "废墟中反而能看清地基。既然倒了,正好可以按照你真正想要的样子重建。",
|
||
energy: "剧烈",
|
||
image: "/images/ta.png"
|
||
},
|
||
{
|
||
name: "星星",
|
||
keyword: "希望",
|
||
meaning: "黑暗之后必有星光,保持信心,未来充满治愈与灵感。",
|
||
reversedMeaning: "暂时看不见星星也没关系,它们还在那里。给自己一点信心,黎明就在前方。",
|
||
energy: "明亮",
|
||
image: "/images/xingxing.png"
|
||
},
|
||
{
|
||
name: "月亮",
|
||
keyword: "幻象",
|
||
meaning: "直面内心的不安与迷茫,并非所有事情都如表象般真实。",
|
||
reversedMeaning: "恐惧只是长长的影子,别被它吓住。随着天亮,迷雾终会散去。",
|
||
energy: "幽静",
|
||
image: "/images/yueliang.png"
|
||
},
|
||
{
|
||
name: "太阳",
|
||
keyword: "喜悦",
|
||
meaning: "快乐、成功与活力,尽情地发光热,享受当下的幸福。",
|
||
reversedMeaning: "乌云暂时遮住了阳光,但这只是暂时的。保持乐观,你心里的光谁也偷不走。",
|
||
energy: "灼热",
|
||
image: "/images/taiyang.png"
|
||
},
|
||
{
|
||
name: "审判",
|
||
keyword: "觉醒",
|
||
meaning: "听到内心的召唤,回顾过往,做出决定,获得新生。",
|
||
reversedMeaning: "不要对他人的评价太敏感,也不要自我怀疑。如果你准备好了,就出发吧。",
|
||
energy: "回响",
|
||
image: "/images/shenpan.png"
|
||
},
|
||
{
|
||
name: "世界",
|
||
keyword: "圆满",
|
||
meaning: "一段旅程的完美终点,成就感与整合,准备开始新的循环。",
|
||
reversedMeaning: "机遇还没完全成熟,再耐心一点点。检查一下还有什么细节没完成?",
|
||
energy: "圆融",
|
||
image: "/images/shijie.png"
|
||
}
|
||
],
|
||
// 合并大牌和小牌
|
||
allCards: [],
|
||
aiResult: null,
|
||
|
||
// 塔罗低语 - 分类问题库
|
||
tarotWhispersBank: {
|
||
'爱情': [
|
||
{ text: '我们的关系会如何发展?' },
|
||
{ text: '这段感情值得继续吗?' },
|
||
{ text: '对方对我是什么感觉?' },
|
||
{ text: 'TA是我的灵魂伴侣吗?' },
|
||
{ text: '我们之间的问题能解决吗?' },
|
||
{ text: '这段关系的未来如何?' },
|
||
{ text: '我该如何改善这段关系?' },
|
||
{ text: '我们的缘分有多深?' }
|
||
],
|
||
'事业': [
|
||
{ text: '我是否应该换工作?' },
|
||
{ text: '这个合作值得继续吗?' },
|
||
{ text: '我的事业发展方向是什么?' },
|
||
{ text: '现在适合创业吗?' },
|
||
{ text: '我的职场瓶颈在哪里?' },
|
||
{ text: '如何提升我的职场竞争力?' },
|
||
{ text: '这个投资机会如何?' },
|
||
{ text: '我的财运走势怎样?' }
|
||
],
|
||
'决策': [
|
||
{ text: '我应该选择A还是B?' },
|
||
{ text: '现在是做这个决定的好时机吗?' },
|
||
{ text: '这个选择会带来什么结果?' },
|
||
{ text: '我该如何做出正确的决定?' },
|
||
{ text: '这条路适合我吗?' },
|
||
{ text: '我需要考虑哪些因素?' },
|
||
{ text: '放弃还是坚持?' },
|
||
{ text: '改变会带来什么?' }
|
||
],
|
||
'综合': [
|
||
{ text: '我现在的状态如何?' },
|
||
{ text: '我需要关注什么?' },
|
||
{ text: '未来会发生什么?' },
|
||
{ text: '我的人生方向是什么?' },
|
||
{ text: '如何突破当前困境?' },
|
||
{ text: '我的优势是什么?' },
|
||
{ text: '什么在阻碍我?' },
|
||
{ text: '我该如何成长?' }
|
||
],
|
||
'深度': [
|
||
{ text: '我的灵性课题是什么?' },
|
||
{ text: '我的人生使命是什么?' },
|
||
{ text: '如何找到内心的平静?' },
|
||
{ text: '我需要学习什么?' },
|
||
{ text: '我的潜能在哪里?' },
|
||
{ text: '如何实现灵性成长?' },
|
||
{ text: '我的生命意义是什么?' },
|
||
{ text: '宇宙想告诉我什么?' }
|
||
]
|
||
},
|
||
tarotWhispers: [
|
||
{ text: '我们的关系会如何发展?' },
|
||
{ text: '这段感情值得继续吗?' },
|
||
{ text: '我是否应该换工作?' },
|
||
{ text: '这个合作值得继续吗?' },
|
||
{ text: '我应该选择A还是B?' },
|
||
{ text: '现在是做这个决定的好时机吗?' },
|
||
{ text: '我现在的状态如何?' },
|
||
{ text: '我需要关注什么?' }
|
||
],
|
||
selectedWhisperIndex: -1
|
||
},
|
||
|
||
onLoad: function () {
|
||
// 获取当前日期
|
||
const now = new Date();
|
||
const year = now.getFullYear();
|
||
const month = (now.getMonth() + 1).toString().padStart(2, '0');
|
||
const day = now.getDate().toString().padStart(2, '0');
|
||
const dateStr = `${year}-${month}-${day}`;
|
||
|
||
this.setData({
|
||
todayDate: dateStr,
|
||
allCards: [...this.data.cardList, ...minorArcana]
|
||
});
|
||
|
||
console.log(`塔罗牌已就位,共 ${this.data.allCards.length} 张。`)
|
||
},
|
||
|
||
// --- 1. 选择牌阵 ---
|
||
selectSpread: function (e) {
|
||
const id = e.currentTarget.dataset.id;
|
||
const spread = this.data.spreads.find(s => s.id === id);
|
||
|
||
// 检查积分是否足够 (可通过ENABLE_POINTS开关控制)
|
||
if (ENABLE_POINTS && !hasEnough(spread.cost)) {
|
||
wx.showModal({
|
||
title: '积分不足',
|
||
content: `当前牌阵需要 ${spread.cost} 积分,您的积分不足,请稍后再来`,
|
||
showCancel: false,
|
||
confirmText: '知道了'
|
||
});
|
||
return;
|
||
}
|
||
|
||
// 根据牌阵标签更新塔罗低语
|
||
const primaryTag = spread.tags[0]; // 使用第一个标签作为主分类
|
||
const whispers = this.data.tarotWhispersBank[primaryTag] || this.data.tarotWhispersBank['综合'];
|
||
|
||
this.setData({
|
||
selectedSpread: spread,
|
||
tarotWhispers: whispers,
|
||
selectedWhisperIndex: -1, // 重置选中状态
|
||
state: 'asking' // 先进入提问状态
|
||
});
|
||
},
|
||
|
||
// --- 牌阵标签筛选 ---
|
||
filterSpreads: function (e) {
|
||
const tag = e.currentTarget.dataset.tag;
|
||
let filtered = SPREADS;
|
||
|
||
if (tag !== '全部') {
|
||
filtered = SPREADS.filter(spread =>
|
||
spread.tags && spread.tags.includes(tag)
|
||
);
|
||
}
|
||
|
||
this.setData({
|
||
activeTag: tag,
|
||
filteredSpreads: filtered
|
||
});
|
||
},
|
||
|
||
// --- 1.5 确认问题并开始洗牌 ---
|
||
confirmQuestion: function () {
|
||
const question = this.data.question.trim();
|
||
console.log('confirmQuestion 被调用,问题:', question);
|
||
|
||
// 新增:过滤验证
|
||
const filterResult = validateQuestion(question);
|
||
console.log('过滤结果:', filterResult);
|
||
|
||
if (filterResult.status === 'reject') {
|
||
console.log('触发拒绝弹窗');
|
||
// 显示拒绝弹窗
|
||
wx.showModal({
|
||
title: '温馨提示',
|
||
content: filterResult.reason,
|
||
showCancel: false,
|
||
confirmText: '我知道了'
|
||
});
|
||
return;
|
||
}
|
||
|
||
if (filterResult.status === 'rewrite') {
|
||
console.log('触发改写建议弹窗');
|
||
// 显示改写建议弹窗 - 简化版本
|
||
const firstSuggestion = filterResult.suggestions[0];
|
||
const modalContent = `${filterResult.reason}\n\n${firstSuggestion}`;
|
||
console.log('弹窗内容:', modalContent);
|
||
|
||
wx.showModal({
|
||
title: '提问建议',
|
||
content: modalContent,
|
||
confirmText: '使用建议',
|
||
cancelText: '继续提问',
|
||
success: (res) => {
|
||
console.log('弹窗回调:', res);
|
||
if (res.confirm) {
|
||
// 使用建议问题
|
||
this.setData({
|
||
question: firstSuggestion,
|
||
questionQuality: scoreQuestion(firstSuggestion)
|
||
});
|
||
}
|
||
// 无论选择哪个,都继续流程
|
||
this.proceedToShuffle();
|
||
},
|
||
fail: (err) => {
|
||
console.error('弹窗显示失败:', err);
|
||
// 即使弹窗失败,也继续流程
|
||
this.proceedToShuffle();
|
||
}
|
||
});
|
||
return;
|
||
}
|
||
|
||
console.log('通过验证,继续流程');
|
||
// pass 状态:直接继续
|
||
this.proceedToShuffle();
|
||
},
|
||
|
||
// 抽离洗牌逻辑
|
||
proceedToShuffle: function () {
|
||
const questionType = getQuestionType(this.data.question);
|
||
this.setData({
|
||
questionType: questionType,
|
||
state: 'shuffling'
|
||
});
|
||
|
||
// 模拟洗牌感应 2.5s
|
||
setTimeout(() => {
|
||
this.setData({ state: 'drawing' });
|
||
}, 2500);
|
||
},
|
||
|
||
// 输入问题
|
||
onQuestionInput: function (e) {
|
||
const question = e.detail.value;
|
||
const quality = scoreQuestion(question);
|
||
this.setData({
|
||
question: question,
|
||
questionQuality: quality
|
||
});
|
||
},
|
||
|
||
// 选择塔罗低语
|
||
selectWhisper: function (e) {
|
||
const index = e.currentTarget.dataset.index;
|
||
const question = e.currentTarget.dataset.question;
|
||
const quality = scoreQuestion(question);
|
||
|
||
// 震动反馈
|
||
wx.vibrateShort({
|
||
type: 'light'
|
||
});
|
||
|
||
this.setData({
|
||
question: question,
|
||
questionQuality: quality,
|
||
selectedWhisperIndex: index
|
||
});
|
||
},
|
||
|
||
// --- 2. 抽牌逻辑 ---
|
||
onCardTap: function (e) {
|
||
const index = e.currentTarget.dataset.index;
|
||
let { drawnCardIndices, selectedSpread } = this.data;
|
||
|
||
if (drawnCardIndices.includes(index)) {
|
||
drawnCardIndices = drawnCardIndices.filter(i => i !== index);
|
||
} else if (drawnCardIndices.length < selectedSpread.cardCount) {
|
||
drawnCardIndices.push(index);
|
||
}
|
||
|
||
this.setData({ drawnCardIndices });
|
||
},
|
||
|
||
// --- 3. 确认开启 ---
|
||
confirmDraw: function () {
|
||
const { drawnCardIndices, allCards, selectedSpread } = this.data;
|
||
const drawnCards = drawnCardIndices.map(() => {
|
||
const randomIndex = Math.floor(Math.random() * allCards.length);
|
||
const card = Object.assign({}, allCards[randomIndex]);
|
||
card.isReversed = Math.random() >= 0.5;
|
||
// 如果这张牌没有图片(如小牌),使用背面图作为占位符,或保持原有逻辑
|
||
if (!card.image) {
|
||
card.image = this.data.cardBackImage;
|
||
}
|
||
return card;
|
||
});
|
||
|
||
// 扣除积分(只扣一次,可通过ENABLE_POINTS开关控制)
|
||
if (ENABLE_POINTS) {
|
||
deductPoints(selectedSpread.cost);
|
||
console.log(`[积分系统] 占卜消耗 ${selectedSpread.cost} 积分`);
|
||
} else {
|
||
console.log(`[积分系统] 测试模式,跳过积分扣除`);
|
||
}
|
||
|
||
this.setData({
|
||
drawnCards,
|
||
state: 'flipping',
|
||
revealedCount: 0
|
||
});
|
||
},
|
||
|
||
// --- 4. 逐一翻牌 ---
|
||
revealNext: function (e) {
|
||
const index = e.currentTarget.dataset.index;
|
||
if (index === this.data.revealedCount) {
|
||
const nextCount = index + 1;
|
||
this.setData({
|
||
revealedCount: nextCount
|
||
});
|
||
|
||
// 如果全部翻开,触发解读
|
||
if (nextCount === this.data.selectedSpread.cardCount) {
|
||
this.setData({ state: 'revealed' });
|
||
this.showInterpretation();
|
||
}
|
||
}
|
||
},
|
||
|
||
// --- 展示解读内容 ---
|
||
showInterpretation: function () {
|
||
const infoAnim = wx.createAnimation({
|
||
duration: 800,
|
||
timingFunction: 'ease'
|
||
});
|
||
infoAnim.opacity(1).translateY(0).step();
|
||
this.setData({ infoAnimation: infoAnim.export() });
|
||
|
||
// 异步获取 AI 解读
|
||
this.fetchAiInterpretation();
|
||
},
|
||
|
||
// --- 获取 AI 解读主逻辑 ---
|
||
fetchAiInterpretation: async function () {
|
||
const { drawnCards, selectedSpread, question, questionType } = this.data;
|
||
if (!drawnCards.length) return;
|
||
|
||
this.setData({
|
||
isAiLoading: true,
|
||
aiResult: null,
|
||
aiLoadingText: '正在抽取牌面…'
|
||
});
|
||
|
||
// 1. 构建卡牌信息
|
||
const cardDetails = drawnCards.map((card, index) => {
|
||
return `位置[${selectedSpread.positions[index]}]:${card.name} (${card.isReversed ? '逆位' : '正位'}),关键词:${card.keyword || (card.keywords ? card.keywords.join(',') : '')}`;
|
||
}).join('\n');
|
||
|
||
// 2. 构建参考牌义(供 AI 理解用)
|
||
const cardMeanings = drawnCards.map((card, index) => {
|
||
const meaning = card.isReversed ? (card.reversedMeaning || card.description) : (card.meaning || card.description);
|
||
return `${card.name} (${card.isReversed ? '逆位' : '正位'}):${meaning}`;
|
||
}).join('\n');
|
||
|
||
// 3. 构建完整的用户提示
|
||
const userPrompt = `📥 输入信息
|
||
|
||
用户问题:
|
||
${question || '未指定具体问题'}
|
||
|
||
提问领域:
|
||
${questionType}
|
||
|
||
牌阵:
|
||
${selectedSpread.name}
|
||
|
||
抽到的牌:
|
||
${cardDetails}
|
||
|
||
参考牌义(内部理解用):
|
||
${cardMeanings}
|
||
|
||
⚠️ 参考牌义仅用于理解,不允许逐字复述。请严格围绕用户的问题进行解读。`;
|
||
|
||
console.log("正在获取深度解读...");
|
||
console.log("用户问题:", question);
|
||
console.log("提问领域:", questionType);
|
||
|
||
// 4. 使用稳态请求管理器
|
||
const result = await safeAIRequest({
|
||
url: DEEPSEEK_BASE_URL,
|
||
header: {
|
||
'Authorization': `Bearer ${DEEPSEEK_API_KEY}`,
|
||
'Content-Type': 'application/json'
|
||
},
|
||
data: {
|
||
model: "deepseek-chat",
|
||
messages: [
|
||
{ role: "system", content: TAROT_PROMPT_ENHANCED },
|
||
{ role: "user", content: userPrompt }
|
||
],
|
||
stream: false,
|
||
response_format: { type: "json_object" }
|
||
},
|
||
drawnCards,
|
||
spread: selectedSpread,
|
||
onProgress: (text) => {
|
||
this.setData({ aiLoadingText: text });
|
||
}
|
||
});
|
||
|
||
// 5. 处理结果
|
||
if (result.status === 'blocked') {
|
||
wx.showToast({
|
||
title: result.message,
|
||
icon: 'none',
|
||
duration: 2000
|
||
});
|
||
this.setData({ isAiLoading: false });
|
||
return;
|
||
}
|
||
|
||
// 6. 生成整体趋势
|
||
const spreadStory = generateSpreadStory(drawnCards);
|
||
|
||
// 7. 更新数据
|
||
this.setData({
|
||
aiResult: result.data,
|
||
spreadStory: spreadStory,
|
||
isAiLoading: false
|
||
});
|
||
|
||
// 8. 如果是 fallback,显示提示
|
||
if (result.status === 'fallback' && result.error) {
|
||
wx.showToast({
|
||
title: 'AI 解读失败,已使用备用解读',
|
||
icon: 'none',
|
||
duration: 3000
|
||
});
|
||
}
|
||
},
|
||
|
||
handleAiFallback: function () {
|
||
// 构建一个基础的回退对象
|
||
const fallback = {
|
||
theme: "能量感应受阻",
|
||
status: "当前思绪可能较为杂乱",
|
||
influence: "外界干扰或网络波动",
|
||
advice: "建议深呼吸,稍后再次尝试开启心灵对话",
|
||
positions: this.data.drawnCards.map((card, index) => ({
|
||
posName: this.data.selectedSpread.positions[index],
|
||
posMeaning: `${card.name}${card.isReversed ? '(逆位)' : '(正位)'}:${card.isReversed ? (card.reversedMeaning || card.description) : (card.meaning || card.description)}`
|
||
}))
|
||
};
|
||
this.setData({
|
||
aiResult: fallback,
|
||
isAiLoading: false
|
||
});
|
||
},
|
||
|
||
resetSpread: function () {
|
||
this.setData({
|
||
state: 'spread_select',
|
||
selectedSpread: null,
|
||
drawnCardIndices: [],
|
||
drawnCards: [],
|
||
revealedCount: 0,
|
||
aiResult: null
|
||
});
|
||
},
|
||
|
||
// --- 导航优化:统一返回逻辑 ---
|
||
handleBack: function () {
|
||
// 根据当前状态返回到上一个状态
|
||
const currentState = this.data.state;
|
||
|
||
if (currentState === 'asking') {
|
||
// 从提问页返回到牌阵选择页
|
||
this.setData({
|
||
state: 'spread_select',
|
||
question: '',
|
||
questionQuality: null,
|
||
selectedWhisperIndex: -1
|
||
});
|
||
} else if (currentState === 'shuffling' || currentState === 'drawing' || currentState === 'flipping') {
|
||
// 从洗牌/选牌/翻牌页返回到提问页
|
||
this.setData({
|
||
state: 'asking',
|
||
drawnCardIndices: [],
|
||
drawnCards: [],
|
||
revealedCount: 0
|
||
});
|
||
} else if (currentState === 'revealed') {
|
||
// 从解读页返回到牌阵选择页(重新开始)
|
||
this.setData({
|
||
state: 'spread_select',
|
||
question: '',
|
||
questionQuality: null,
|
||
selectedWhisperIndex: -1,
|
||
drawnCardIndices: [],
|
||
drawnCards: [],
|
||
revealedCount: 0,
|
||
aiResult: null
|
||
});
|
||
} else if (currentState === 'spread_select') {
|
||
// 从牌阵选择页返回到主页
|
||
wx.navigateBack({
|
||
delta: 1
|
||
});
|
||
} else {
|
||
// 其他状态直接返回主页
|
||
wx.navigateBack({
|
||
delta: 1
|
||
});
|
||
}
|
||
}
|
||
})
|