feat(web): 重写自动起卦页面并修复数据解析

主要更改:
- 重写 AutoDivinationPage 与 ManualDivinationPage 设计一致
  - 每爻单独摇卦(3秒/爻)
  - 完整教程系统(首次进入自动触发)
  - 确认弹窗显示积分信息
  - 统一时间选择组件样式
  - 移除返回按钮

- ManualDivinationPage 添加确认弹窗
  - 点击开始解卦显示积分确认
  - 添加中英文翻译

- 修复干支信息和空亡信息解析
  - 完善 HistoryAgentOutput 类型定义
  - 重写 historyMessageToResultData 正确解析嵌套 ganzhi 对象
  - 修复 DivinationProcessingOverlay SSE 数据解析

- 统一历史列表图标
  - 添加 hexagram 图标(六爻卦象抽象)
  - Dashboard 和 HistoryListPage 使用相同图标

- 修复 DivinationResultPage 追问导航 threadId
This commit is contained in:
ZL-Q
2026-05-10 14:53:43 +08:00
parent dab3c766f2
commit 1fe17b03df
8 changed files with 904 additions and 154 deletions
+108 -34
View File
@@ -247,6 +247,46 @@ export interface HistoryAgentOutput {
gua_name?: string;
binaryCode?: string;
changedBinaryCode?: string;
targetGuaName?: string;
upperName?: string;
lowerName?: string;
divinationMethod?: string;
divinationTime?: string;
ganzhi?: {
yearGanZhi?: string;
monthGanZhi?: string;
dayGanZhi?: string;
timeGanZhi?: string;
yearKongWang?: string;
monthKongWang?: string;
dayKongWang?: string;
timeKongWang?: string;
yueJian?: string;
riChen?: string;
yuePo?: string;
riChong?: string;
};
wuXingStatuses?: Record<string, string>;
yaoInfoList?: Array<{
position?: number;
spiritName?: string;
relationName?: string;
tiganName?: string;
elementName?: string;
isYang?: boolean;
isChanging?: boolean;
specialMark?: string;
}>;
targetYaoInfoList?: Array<{
position?: number;
spiritName?: string;
relationName?: string;
tiganName?: string;
elementName?: string;
isYang?: boolean;
isChanging?: boolean;
specialMark?: string;
}>;
} | null;
}
@@ -343,55 +383,89 @@ export function historyMessageToResultData(message: HistoryMessage): DivinationR
const derived = output?.divination_derived;
if (!output || !derived) return null;
// Parse yao lines
const yaoLines: DivinationResultData['yaoLines'] = [];
const yaoInfoList = (derived as Record<string, unknown>).yaoInfoList;
if (Array.isArray(yaoInfoList)) {
yaoInfoList.forEach((item: Record<string, unknown>, idx: number) => {
if (Array.isArray(derived.yaoInfoList)) {
derived.yaoInfoList.forEach((item, idx) => {
// Determine YaoType based on isYang and isChanging
let type: YaoType = 'youngYang';
if (item.isYang === true && item.isChanging === true) {
type = 'oldYang';
} else if (item.isYang === false && item.isChanging === true) {
type = 'oldYin';
} else if (item.isYang === false && item.isChanging === false) {
type = 'youngYin';
}
yaoLines.push({
index: idx,
spirit: (item.spiritName as string) || '',
relation: (item.relationName as string) || '',
branch: (item.tiganName as string) || '',
element: (item.elementName as string) || '',
type: item.isYang ? 'youngYang' : 'youngYin',
mark: (item.specialMark as string) || '',
spirit: item.spiritName || '',
relation: item.relationName || '',
branch: item.tiganName || '',
element: item.elementName || '',
type,
mark: item.specialMark || '',
});
});
}
const ganzhiRaw = (derived as Record<string, unknown>).ganzhi as Record<string, string> || {};
// Parse target yao lines
const targetYaoLines: DivinationResultData['yaoLines'] = [];
if (Array.isArray(derived.targetYaoInfoList)) {
derived.targetYaoInfoList.forEach((item, idx) => {
let type: YaoType = 'youngYang';
if (item.isYang === true && item.isChanging === true) {
type = 'oldYang';
} else if (item.isYang === false && item.isChanging === true) {
type = 'oldYin';
} else if (item.isYang === false && item.isChanging === false) {
type = 'youngYin';
}
targetYaoLines.push({
index: idx,
spirit: item.spiritName || '',
relation: item.relationName || '',
branch: item.tiganName || '',
element: item.elementName || '',
type,
mark: item.specialMark || '',
});
});
}
// Parse ganzhi from nested object
const ganzhiSource = derived.ganzhi || {};
const ganzhi: DivinationResultData['ganzhi'] = {
yearGanZhi: ganzhiRaw.yearGanZhi || '',
monthGanZhi: ganzhiRaw.monthGanZhi || '',
dayGanZhi: ganzhiRaw.dayGanZhi || '',
timeGanZhi: ganzhiRaw.timeGanZhi || '',
yearKongWang: ganzhiRaw.yearKongWang || '',
monthKongWang: ganzhiRaw.monthKongWang || '',
dayKongWang: ganzhiRaw.dayKongWang || '',
timeKongWang: ganzhiRaw.timeKongWang || '',
yueJian: ganzhiRaw.yueJian || '',
riChen: ganzhiRaw.riChen || '',
yuePo: ganzhiRaw.yuePo || '',
riChong: ganzhiRaw.riChong || '',
yearGanZhi: ganzhiSource.yearGanZhi || '',
monthGanZhi: ganzhiSource.monthGanZhi || '',
dayGanZhi: ganzhiSource.dayGanZhi || '',
timeGanZhi: ganzhiSource.timeGanZhi || '',
yearKongWang: ganzhiSource.yearKongWang || '',
monthKongWang: ganzhiSource.monthKongWang || '',
dayKongWang: ganzhiSource.dayKongWang || '',
timeKongWang: ganzhiSource.timeKongWang || '',
yueJian: ganzhiSource.yueJian || '',
riChen: ganzhiSource.riChen || '',
yuePo: ganzhiSource.yuePo || '',
riChong: ganzhiSource.riChong || '',
};
const divinationTimeStr = (derived as Record<string, unknown>).divinationTime as string || '';
const divinationTimeStr = derived.divinationTime || '';
const divinationTime = parseChineseDate(divinationTimeStr);
return {
threadId: message.threadId,
params: {
method: ((derived as Record<string, unknown>).divinationMethod as string)?.includes('手动') ? 'manual' : 'auto',
questionType: (derived as Record<string, unknown>).questionType as string || '',
question: (derived as Record<string, unknown>).question as string || '',
method: derived.divinationMethod?.includes('手动') ? 'manual' : 'auto',
questionType: derived.questionType || '',
question: derived.question || '',
divinationTime,
},
binaryCode: (derived as Record<string, unknown>).binaryCode as string || '',
changedBinaryCode: (derived as Record<string, unknown>).changedBinaryCode as string || '',
guaName: (derived as Record<string, unknown>).guaName as string || '',
targetGuaName: (derived as Record<string, unknown>).targetGuaName as string || '',
upperName: (derived as Record<string, unknown>).upperName as string || '',
lowerName: (derived as Record<string, unknown>).lowerName as string || '',
binaryCode: derived.binaryCode || '',
changedBinaryCode: derived.changedBinaryCode || '',
guaName: derived.guaName || derived.gua_name || '',
targetGuaName: derived.targetGuaName || '',
upperName: derived.upperName || '',
lowerName: derived.lowerName || '',
signType: output.sign_level || '',
keywords: (output.keywords || []).join(' · '),
focusPoints: output.focus_points || [],
@@ -399,9 +473,9 @@ export function historyMessageToResultData(message: HistoryMessage): DivinationR
analysis: output.answer || '',
suggestion: (output.advice || []).join('\n'),
ganzhi,
wuXingStatus: (derived as Record<string, unknown>).wuXingStatuses as Record<string, string> || {},
wuXingStatus: derived.wuXingStatuses || {},
yaoLines,
targetYaoLines: [],
targetYaoLines,
status: (output.status as 'success' | 'failed' | 'refused') || 'success',
};
}