{"repo": "1231hyper/tarot-web", "files": {"api/reading.js": {"5715431318453272b7c00c5162ec03762d85b41d": {"t": 1786068263.4333231, "n": 5198, "h": "bd74e574e16b4c2a", "c": "// ── 按牌阵生成专属提示词 ──────────────────────────────\nfunction buildPrompt(spreadId, layoutKey, cardInfo, cardCount) {\n const base = `你是一位资深塔罗牌占卜师,精通神秘学,擅长用诗意的语言解读塔罗牌阵。`;\n\n // 根据牌数动态调整字数要求和解读深度\n const lengthGuide = cardCount === 1\n ? \"60-80 字\"\n : cardCount <= 3\n ? \"100-150 字\"\n : cardCount <= 5\n ? \"150-200 字\"\n : \"200-300 字\";\n\n const prompts = {\n daily: {\n single: `${base}\n\n【单牌阵 · 今日指引】(共 1 张牌)\n\n${cardInfo}\n\n请用中文撰写一段 ${lengthGuide} 的综合解读,要求:\n1. 以神秘学风格开场,分析这张牌的象征元素与今日能量的呼应\n2. 结合牌面正逆位,给出今日核心建议与注意事项\n3. 聚焦于这一张牌的单一信息,不要提及\"多张牌\"或\"牌阵组合\"\n4. 语气温暖而有洞察力,适合快速阅读,像一封来自宇宙的便签`,\n\n three: `${base}\n\n【三牌阵 · 时间之流】(过去 → 现在 → 未来,共 3 张牌)\n\n${cardInfo}\n\n请用中文撰写一段 ${lengthGuide} 的综合解读,要求:\n1. 以神秘学风格开场,分析牌面象征与元素\n2. 结合过去→现在→未来的时间线,揭示内在联系与发展脉络\n3. 结尾给出 1-2 条实用的生活建议\n4. 语气温暖而有洞察力,避免过于宿命论`,\n },\n\n relationship: {\n relation3: `${base}\n\n【关系牌阵】(你的状态 / 对方状态 / 关系走向,共 3 张牌)\n\n${cardInfo}\n\n请用中文撰写一段 ${lengthGuide} 的综合解读,要求:\n1. 分析双方在关系中的能量状态与心理倾向\n2. 揭示两人互动中的核心张力或和谐点\n3. 结合关系走向牌给出建议\n4. 语气温暖客观,不偏不倚,避免宿命论`,\n\n relation4: `${base}\n\n【关系牌阵】(你的状态 / 对方状态 / 目前互动 / 未来发展,共 4 张牌)\n\n${cardInfo}\n\n请用中文撰写一段 ${lengthGuide} 的综合解读,要求:\n1. 分别分析双方在关系中的位置与能量\n2. 解读当前互动模式中的关键动力\n3. 结合最后一张牌给出关系发展趋势与实用建议\n4. 语气温暖而有同理心,避免过于判断性`,\n\n venus: `${base}\n\n【爱人之十字牌阵】(你的内心 / 对方的内心 / 你的外在 / 对方的外在 / 潜在阻碍,共 5 张牌)\n\n${cardInfo}\n\n请用中文撰写一段 ${lengthGuide} 的综合解读,要求:\n1. 深入剖析双方的内心真实想法与外在表现之间的差异\n2. 解读两人关系中的核心阻碍与突破方向\n3. 给出具体可行的关系改善建议\n4. 语气温暖深刻,富有同理心,避免过于悲观`,\n },\n\n career: {\n choice: `${base}\n\n【二选一牌阵】(目前状况 / 选择A现状 / 选择A结果 / 选择B现状 / 选择B结果,共 5 张牌)\n\n${cardInfo}\n\n请用中文撰写一段 ${lengthGuide} 的综合解读,要求:\n1. 先分析求问者当前的整体状况与心境\n2. 分别解读两个选择的阻碍与最终结果\n3. 对比两条路径的优劣,给出清晰的决策参考\n4. 语气理性而洞察,避免替求问者做决定`,\n },\n\n celtic: {\n celtic: `${base}\n\n【凯尔特十字牌阵】(核心问题 / 当前阻碍 / 潜意识基础 / 过去经历 / 短期未来 / 自我认知 / 外在环境 / 恐惧与希望 / 最终结果 / 综合建议,共 10 张牌)\n\n${cardInfo}\n\n请用中文撰写一段 ${lengthGuide} 的综合解读,要求:\n1. 以神秘学风格开场,整体把握牌阵的能量场\n2. 逐层分析:核心问题→阻碍→潜意识根源→过去影响→短期走向\n3. 解读自我认知与外在环境的互动,以及内心恐惧与希望的张力\n4. 综合所有牌面给出最终方向与 2-3 条具体建议\n5. 语气深邃而有洞察力,像一位智者的谆谆教诲`,\n },\n\n problem: {\n problem: `${base}\n\n【问题解决牌阵】(问题本质/盲点 / 导致原因 / 应采取行动 / 行动后走向,共 5 张牌)\n\n${cardInfo}\n\n请用中文撰写一段 ${lengthGuide} 的综合解读,要求:\n1. 以敏锐的视角揭示问题的本质与求问者可能忽视的盲点\n2. 分析导致问题的深层原因\n3. 给出具体、可操作的行动建议\n4. 结合最后一张牌展望行动后的积极走向\n5. 语气务实而鼓励,避免空泛的安慰`,\n },\n\n zodiac: {\n zodiac: `${base}\n\n【黄道十二宫牌阵】(自我 / 财务 / 沟通 / 家庭 / 恋爱 / 健康 / 婚姻 / 投资 / 进修 / 事业 / 人际 / 潜意识,共 12 张牌)\n\n${cardInfo}\n\n请用中文撰写一段 ${lengthGuide} 的综合解读,要求:\n1. 以神秘学风格开场,描绘整年/整体的能量画卷\n2. 按领域逐一简要点拨,每个领域 1-2 句核心建议\n3. 找出 2-3 个需要特别关注的领域并深入分析\n4. 结尾给出整体性的生活建议与鼓励\n5. 语气温暖而宏大,像一幅徐徐展开的星图`,\n },\n };\n\n const spreadPrompts = prompts[spreadId];\n if (!spreadPrompts) {\n return `${base}\\n\\n${cardInfo}\\n\\n请用中文撰写一段 ${lengthGuide} 的综合解读,聚焦于所给牌面信息。`;\n }\n const prompt = spreadPrompts[layoutKey] || Object.values(spreadPrompts)[0];\n return prompt;\n}\n\n// ── API Handler ──────────────────────────────────────\nexport default async function handler(req) {\n if (req.method !== \"POST\") {\n return new Response(JSON.stringify({ error: \"Method not allowed\" }), {\n status: 405,\n headers: { \"Content-Type\": \"application/json\" },\n });\n }\n\n let body;\n try {\n body = await req.json();\n } catch {\n return new Response(JSON.stringify({ error: \"Invalid JSON\" }), {\n status: 400,\n headers: { \"Content-Type\": \"application/json\" },\n });\n }\n\n const { cards, spreadId, layoutKey } = body;\n if (!Array.isArray(cards) || cards.length === 0) {\n return new Response(JSON.stringify({ error: \"缺少卡牌数据\" }), {\n status: 400,\n headers: { \"Content-Type\": \"application/json\" },\n });\n }\n\n const apiKey = process.env.DEEPSEEK_API_KEY;\n if (!apiKey) {\n return new Response(JSON.stringify({ error: \"服务未配置\" }), {\n status: 500,\n headers: { \"Content-Type\": \"application/json\" },\n });\n }\n\n const cardInfo = cards\n .map((c) => {\n const meaning = c.isReversed ? c.card.reversed : c.card.upright;\n return `【${c.position}】${c.card.name}(${c.orientation})\\n含义:${meaning}`;\n })\n .join(\"\\n\\n\");\n\n const prompt = buildPrompt(spreadId, layoutKey, cardInfo, cards.length);\n\n try {\n const res = await fetch(\"https://api.deepseek.com/v1/chat/completions\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify({\n model: \"deepseek-chat\",\n messages: [\n {\n role: \"system\",\n content:\n \"你是一位资深塔罗牌占卜师,精通神秘学,擅长用诗意的语言解读塔罗牌阵。\",\n },\n { role: \"user\", content: prompt },\n ],\n max_tokens: 400,\n temperature: 0.8,\n }),\n });\n\n if (!res.ok) {\n const errData = await res.json().catch(() => ({}));\n throw new Error(errData.error?.message || \"DeepSeek API 调用失败\");\n }\n\n const data = await res.json();\n const reading = data.choices?.[0]?.message?.content?.trim();\n\n return new Response(JSON.stringify({ reading }), {\n status: 200,\n headers: { \"Content-Type\": \"application/json\" },\n });\n } catch (err) {\n return new Response(\n JSON.stringify({ error: err.message || \"解读生成失败\" }),\n { status: 500, headers: { \"Content-Type\": \"application/json\" } }\n );\n }\n}\n"}}}}