新增塔罗牌占卜模块

- 新增后端TaLuoController控制器,实现塔罗牌占卜API
- 包含78张塔罗牌数据(22张大阿卡纳+56张小阿卡纳)
- 支持三种牌阵:单张牌、三张牌阵、凯尔特十字牌阵
- 新增前端塔罗牌UI界面
- 在首页添加塔罗牌入口,位于占星术模块下方
- 支持正位逆位解读
- 修复CommonUtil.java中过时的CORBA导入
This commit is contained in:
H1d3rOne committed 2026-03-06 05:01:00 +08:00
1 parent d5be5b7429
commit 3a8ee8f702
6 files changed
+936 -1

No files matched your search

@@ -0,0 +1,320 @@
package xuan.controller;
import org.springframework.web.bind.annotation.*;
import java.util.*;
@RestController
@RequestMapping("/api/taluo")
public class TaLuoController {
private static final List<Map<String, Object>> MAJOR_ARCANA = Arrays.asList(
createCard(0, "愚者", "The Fool", "新的开始、冒险、天真、自由", "鲁莽、冲动、不负责任", "代表新的旅程和无限可能"),
createCard(1, "魔术师", "The Magician", "创造力、技能、意志力、自信", "欺骗、操纵、缺乏计划", "代表运用技能实现目标"),
createCard(2, "女祭司", "The High Priestess", "直觉、神秘、潜意识、智慧", "隐藏的真相、表面化、无知", "代表内在智慧和直觉"),
createCard(3, "女皇", "The Empress", "丰饶、母性、创造力、自然", "依赖、过度保护、创造力受阻", "代表丰盛和滋养"),
createCard(4, "皇帝", "The Emperor", "权威、结构、控制、父亲形象", "专制、僵化、控制欲过强", "代表秩序和领导力"),
createCard(5, "教皇", "The Hierophant", "传统、信仰、教育、精神指导", "教条主义、叛逆、打破传统", "代表精神指引和传统价值"),
createCard(6, "恋人", "The Lovers", "爱情、和谐、选择、价值观", "不和谐、失衡、错误选择", "代表爱情和重要抉择"),
createCard(7, "战车", "The Chariot", "意志力、胜利、决心、控制", "失控、侵略性、缺乏方向", "代表通过决心获得胜利"),
createCard(8, "力量", "Strength", "勇气、耐心、内在力量、同情心", "自我怀疑、软弱、缺乏自信", "代表内在的勇气和力量"),
createCard(9, "隐士", "The Hermit", "内省、寻求真理、孤独、智慧", "孤立、孤独、拒绝帮助", "代表寻求内在智慧"),
createCard(10, "命运之轮", "Wheel of Fortune", "命运、转折点、循环、机遇", "厄运、抗拒改变、失控", "代表命运的转变"),
createCard(11, "正义", "Justice", "公正、真理、因果、法律", "不公正、不诚实、逃避责任", "代表公正和平衡"),
createCard(12, "倒吊人", "The Hanged Man", "牺牲、等待、新视角、放下", "拖延、抗拒、无谓牺牲", "代表通过牺牲获得洞察"),
createCard(13, "死神", "Death", "结束、转变、重生、放下过去", "抗拒改变、停滞、恐惧", "代表结束和新的开始"),
createCard(14, "节制", "Temperance", "平衡、耐心、适度、和谐", "失衡、过度、缺乏耐心", "代表平衡和调和"),
createCard(15, "恶魔", "The Devil", "束缚、诱惑、物质主义、阴暗面", "解脱、打破束缚、面对阴影", "代表被物质束缚"),
createCard(16, "塔", "The Tower", "突变、毁灭、觉醒、真相揭露", "逃避改变、恐惧灾难、延迟崩溃", "代表突然的改变和觉醒"),
createCard(17, "星星", "The Star", "希望、灵感、宁静、更新", "绝望、缺乏信心、失去希望", "代表希望和灵感"),
createCard(18, "月亮", "The Moon", "幻觉、恐惧、潜意识、直觉", "困惑、恐惧、逃避现实", "代表潜意识和幻觉"),
createCard(19, "太阳", "The Sun", "成功、快乐、活力、积极", "暂时的挫折、过度乐观、自负", "代表成功和快乐"),
createCard(20, "审判", "Judgement", "重生、觉醒、召唤、反思", "自我怀疑、拒绝改变、逃避审判", "代表觉醒和重生"),
createCard(21, "世界", "The World", "完成、成就、整合、圆满", "未完成、缺乏闭合、延迟成功", "代表完成和圆满")
);
private static final List<Map<String, Object>> MINOR_ARCANA = createMinorArcana();
private static Map<String, Object> createCard(int number, String name, String englishName,
String uprightMeaning, String reversedMeaning, String description) {
Map<String, Object> card = new HashMap<>();
card.put("number", number);
card.put("name", name);
card.put("englishName", englishName);
card.put("uprightMeaning", uprightMeaning);
card.put("reversedMeaning", reversedMeaning);
card.put("description", description);
card.put("type", number < 22 ? "major" : "minor");
return card;
}
private static List<Map<String, Object>> createMinorArcana() {
List<Map<String, Object>> cards = new ArrayList<>();
String[] suits = {"权杖", "圣杯", "宝剑", "星币"};
String[] suitMeanings = {"行动与创造", "情感与关系", "思想与沟通", "物质与现实"};
String[] ranks = {"Ace", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "侍从", "骑士", "王后", "国王"};
int cardNumber = 22;
for (int suitIndex = 0; suitIndex < suits.length; suitIndex++) {
String suit = suits[suitIndex];
String suitMeaning = suitMeanings[suitIndex];
for (int rankIndex = 0; rankIndex < ranks.length; rankIndex++) {
String rank = ranks[rankIndex];
String cardName = suit + rank;
Map<String, Object> card = new HashMap<>();
card.put("number", cardNumber++);
card.put("name", cardName);
card.put("englishName", rank + " of " + getSuitEnglish(suit));
card.put("suit", suit);
card.put("rank", rank);
card.put("uprightMeaning", generateUprightMeaning(suit, rank, suitMeaning));
card.put("reversedMeaning", generateReversedMeaning(suit, rank, suitMeaning));
card.put("description", suitMeaning + "领域的" + getRankDescription(rank));
card.put("type", "minor");
cards.add(card);
}
}
return cards;
}
private static String getSuitEnglish(String suit) {
switch (suit) {
case "权杖": return "Wands";
case "圣杯": return "Cups";
case "宝剑": return "Swords";
case "星币": return "Pentacles";
default: return suit;
}
}
private static String getRankDescription(String rank) {
switch (rank) {
case "Ace": return "新的开始";
case "Two": return "选择与平衡";
case "Three": return "发展与创造";
case "Four": return "稳定与基础";
case "Five": return "冲突与挑战";
case "Six": return "和谐与胜利";
case "Seven": return "评估与选择";
case "Eight": return "行动与速度";
case "Nine": return "接近完成";
case "Ten": return "完成与圆满";
case "侍从": return "学习与探索";
case "骑士": return "行动与追求";
case "王后": return "内在智慧";
case "国王": return "掌控与权威";
default: return rank;
}
}
private static String generateUprightMeaning(String suit, String rank, String suitMeaning) {
return suitMeaning + "方面的" + getRankDescription(rank) + ",正位时能量流动顺畅";
}
private static String generateReversedMeaning(String suit, String rank, String suitMeaning) {
return suitMeaning + "方面的" + getRankDescription(rank) + ",逆位时需要反思调整";
}
@PostMapping("/divine")
public Map<String, Object> divine(@RequestBody TaLuoRequest request) {
Map<String, Object> result = new HashMap<>();
try {
String spreadType = request.getSpreadType() != null ? request.getSpreadType() : "single";
int cardCount = getCardCount(spreadType);
List<Map<String, Object>> allCards = new ArrayList<>();
allCards.addAll(MAJOR_ARCANA);
allCards.addAll(MINOR_ARCANA);
Collections.shuffle(allCards, new Random());
List<Map<String, Object>> selectedCards = new ArrayList<>();
for (int i = 0; i < cardCount; i++) {
Map<String, Object> card = new HashMap<>(allCards.get(i));
boolean isReversed = new Random().nextBoolean();
card.put("isReversed", isReversed);
card.put("position", i + 1);
card.put("positionMeaning", getPositionMeaning(spreadType, i + 1));
selectedCards.add(card);
}
Map<String, Object> data = new HashMap<>();
data.put("spreadType", spreadType);
data.put("spreadName", getSpreadName(spreadType));
data.put("question", request.getQuestion());
data.put("cards", selectedCards);
data.put("interpretation", generateInterpretation(selectedCards, spreadType, request.getQuestion()));
data.put("timestamp", new Date());
result.put("success", true);
result.put("data", data);
} catch (Exception e) {
result.put("success", false);
result.put("error", e.getMessage());
}
return result;
}
private int getCardCount(String spreadType) {
switch (spreadType) {
case "single": return 1;
case "three": return 3;
case "celtic": return 10;
default: return 1;
}
}
private String getSpreadName(String spreadType) {
switch (spreadType) {
case "single": return "单张牌占卜";
case "three": return "三张牌阵";
case "celtic": return "凯尔特十字牌阵";
default: return "单张牌占卜";
}
}
private String getPositionMeaning(String spreadType, int position) {
if ("single".equals(spreadType)) {
return "当前指引";
} else if ("three".equals(spreadType)) {
switch (position) {
case 1: return "过去";
case 2: return "现在";
case 3: return "未来";
default: return "未知";
}
} else if ("celtic".equals(spreadType)) {
switch (position) {
case 1: return "现状";
case 2: return "阻碍";
case 3: return "目标";
case 4: return "根源";
case 5: return "过去";
case 6: return "未来";
case 7: return "自我";
case 8: return "环境";
case 9: return "希望与恐惧";
case 10: return "结果";
default: return "未知";
}
}
return "未知";
}
private String generateInterpretation(List<Map<String, Object>> cards, String spreadType, String question) {
StringBuilder interpretation = new StringBuilder();
if ("single".equals(spreadType)) {
Map<String, Object> card = cards.get(0);
String name = (String) card.get("name");
boolean isReversed = (Boolean) card.get("isReversed");
String meaning = isReversed ? (String) card.get("reversedMeaning") : (String) card.get("uprightMeaning");
interpretation.append("您抽到的牌是【").append(name).append("】");
interpretation.append(isReversed ? "(逆位)" : "(正位)").append("。\n\n");
interpretation.append("牌义解读:").append(meaning).append("。\n\n");
interpretation.append((String) card.get("description"));
} else if ("three".equals(spreadType)) {
interpretation.append("三张牌阵解读:\n\n");
for (Map<String, Object> card : cards) {
String name = (String) card.get("name");
boolean isReversed = (Boolean) card.get("isReversed");
String position = (String) card.get("positionMeaning");
String meaning = isReversed ? (String) card.get("reversedMeaning") : (String) card.get("uprightMeaning");
interpretation.append("【").append(position).append("】");
interpretation.append(name).append(isReversed ? "(逆位)" : "(正位)").append("\n");
interpretation.append(meaning).append("\n\n");
}
interpretation.append("综合解读:从过去到现在再到未来,牌面展示了事情的发展脉络。");
} else if ("celtic".equals(spreadType)) {
interpretation.append("凯尔特十字牌阵解读:\n\n");
interpretation.append("核心区域(位置1-6):\n");
for (int i = 0; i < 6; i++) {
Map<String, Object> card = cards.get(i);
String name = (String) card.get("name");
boolean isReversed = (Boolean) card.get("isReversed");
String position = (String) card.get("positionMeaning");
String meaning = isReversed ? (String) card.get("reversedMeaning") : (String) card.get("uprightMeaning");
interpretation.append("【").append(position).append("】");
interpretation.append(name).append(isReversed ? "(逆位)" : "(正位)").append(":");
interpretation.append(meaning).append("\n");
}
interpretation.append("\n延伸区域(位置7-10):\n");
for (int i = 6; i < 10; i++) {
Map<String, Object> card = cards.get(i);
String name = (String) card.get("name");
boolean isReversed = (Boolean) card.get("isReversed");
String position = (String) card.get("positionMeaning");
String meaning = isReversed ? (String) card.get("reversedMeaning") : (String) card.get("uprightMeaning");
interpretation.append("【").append(position).append("】");
interpretation.append(name).append(isReversed ? "(逆位)" : "(正位)").append(":");
interpretation.append(meaning).append("\n");
}
interpretation.append("\n综合解读:凯尔特十字牌阵为您提供了全方位的视角,帮助您深入理解问题的各个方面。");
}
return interpretation.toString();
}
@GetMapping("/cards")
public Map<String, Object> getAllCards() {
Map<String, Object> result = new HashMap<>();
try {
List<Map<String, Object>> allCards = new ArrayList<>();
allCards.addAll(MAJOR_ARCANA);
allCards.addAll(MINOR_ARCANA);
result.put("success", true);
result.put("data", allCards);
} catch (Exception e) {
result.put("success", false);
result.put("error", e.getMessage());
}
return result;
}
@GetMapping("/card/{number}")
public Map<String, Object> getCard(@PathVariable int number) {
Map<String, Object> result = new HashMap<>();
try {
List<Map<String, Object>> allCards = new ArrayList<>();
allCards.addAll(MAJOR_ARCANA);
allCards.addAll(MINOR_ARCANA);
if (number >= 0 && number < allCards.size()) {
result.put("success", true);
result.put("data", allCards.get(number));
} else {
result.put("success", false);
result.put("error", "Card not found");
}
} catch (Exception e) {
result.put("success", false);
result.put("error", e.getMessage());
}
return result;
}
public static class TaLuoRequest {
private String question;
private String spreadType;
public String getQuestion() { return question; }
public void setQuestion(String question) { this.question = question; }
public String getSpreadType() { return spreadType; }
public void setSpreadType(String spreadType) { this.spreadType = spreadType; }
}
}