feat(rectification): add refinement packet without unique-minute claims
Surface D9/D10 change minutes, event-dasha match copy, dual-dasha conflict, and a post-adopt consult handoff so users can keep narrowing or start a reading from a representative time. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -33,6 +33,7 @@ export type ConversationalBirthTimeRectificationProps = Readonly<{
|
||||
onPendingChange?: (pending: boolean) => void;
|
||||
onProfileIncomplete?: () => void;
|
||||
onSaved?: (time: string, status: "accepted" | "confirmed") => void;
|
||||
onStartConsultation?: () => void;
|
||||
pendingConsultationQuestion?: string | null;
|
||||
onRestart?: () => void;
|
||||
}>;
|
||||
|
||||
@@ -101,6 +101,92 @@ function RectificationCandidateCards({
|
||||
);
|
||||
}
|
||||
|
||||
function RectificationRefinementPanel({
|
||||
result,
|
||||
}: Readonly<{ result: RectificationCandidateResult }>) {
|
||||
const transitions = result.windowTransitions;
|
||||
const ledger = result.eventDashaLedger;
|
||||
const agreement = result.dashaAgreement;
|
||||
const contrast = result.lagnaContrast;
|
||||
const nakshatra = result.nakshatraBoundary;
|
||||
const stage = result.precisionStage;
|
||||
if (
|
||||
transitions.length === 0
|
||||
&& ledger.length === 0
|
||||
&& !agreement
|
||||
&& !contrast
|
||||
&& !nakshatra?.near_boundary
|
||||
&& !stage
|
||||
) return null;
|
||||
return (
|
||||
<section className="rectification-refinement" aria-label="校正收窄观察">
|
||||
{stage && (
|
||||
<p className="rectification-refinement__stage">{stage.user_meaning}</p>
|
||||
)}
|
||||
{transitions.length > 0 && (
|
||||
<div>
|
||||
<strong>换升时刻</strong>
|
||||
<ul>
|
||||
{transitions.map((item) => (
|
||||
<li key={`${item.layer}-${item.at}`}>{item.user_meaning}</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
)}
|
||||
{contrast && (
|
||||
<div>
|
||||
<strong>两段本命上升</strong>
|
||||
<p>{contrast.user_meaning}</p>
|
||||
<ul>
|
||||
{contrast.intervals.map((interval) => (
|
||||
<li key={`${interval.start}-${interval.end}`}>
|
||||
{interval.start}-{interval.end}:{interval.lagna}
|
||||
{interval.lords.l1 ? `;一/四/七/十宫主 ${[interval.lords.l1, interval.lords.l4, interval.lords.l7, interval.lords.l10].filter(Boolean).join("、")}` : ""}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
)}
|
||||
{ledger.length > 0 && (
|
||||
<div>
|
||||
<strong>经历与大运对照</strong>
|
||||
<ul>
|
||||
{ledger.map((item) => (
|
||||
<li key={item.summary}>{item.user_meaning}</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
)}
|
||||
{agreement && (
|
||||
<p>{agreement.user_meaning}</p>
|
||||
)}
|
||||
{nakshatra?.near_boundary && nakshatra.user_meaning && (
|
||||
<div>
|
||||
<strong>交界节奏</strong>
|
||||
<p>{nakshatra.user_meaning}</p>
|
||||
</div>
|
||||
)}
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
function RectificationOosPanel({
|
||||
prompts,
|
||||
}: Readonly<{ prompts: RectificationCandidateResult["oosBlindPrompts"] }>) {
|
||||
if (prompts.length === 0) return null;
|
||||
return (
|
||||
<section className="rectification-refinement" aria-label="盘外对照">
|
||||
<strong>盘外对照</strong>
|
||||
<p>这些经历没有进入刚才的评分。若记得大概时间,可以补一条用来核对;不补也可以先看盘。</p>
|
||||
<ul>
|
||||
{prompts.map((item) => (
|
||||
<li key={item.domain}>{item.user_meaning}</li>
|
||||
))}
|
||||
</ul>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
type RectificationAgenticChatProps = Readonly<{
|
||||
caseId: string;
|
||||
sessionId: string;
|
||||
@@ -115,6 +201,7 @@ type RectificationAgenticChatProps = Readonly<{
|
||||
onPendingChange?: (pending: boolean) => void;
|
||||
onProfileIncomplete?: () => void;
|
||||
onSaved?: (time: string, status: "accepted" | "confirmed") => void;
|
||||
onStartConsultation?: () => void;
|
||||
pendingConsultationQuestion?: string | null;
|
||||
onRestart?: () => void;
|
||||
}>;
|
||||
@@ -212,6 +299,7 @@ export function RectificationAgenticChat(props: RectificationAgenticChatProps) {
|
||||
onPendingChange,
|
||||
onProfileIncomplete,
|
||||
onSaved,
|
||||
onStartConsultation,
|
||||
pendingConsultationQuestion,
|
||||
onRestart,
|
||||
} = props;
|
||||
@@ -637,10 +725,23 @@ export function RectificationAgenticChat(props: RectificationAgenticChatProps) {
|
||||
<RectificationHouseTableView table={candidateResult.houseTable} />
|
||||
</div>
|
||||
)}
|
||||
{candidateResult && <RectificationRefinementPanel result={candidateResult} />}
|
||||
{savedTime && (
|
||||
<p className="rectification-saved" role="status">
|
||||
{savedStatus === "confirmed" ? "已确认校正时间" : "当前排盘时间(代表性候选,还不能确认唯一分钟)"}:{savedTime}。后续排盘将使用该时间;你仍可继续补充事件或改选其他候选。
|
||||
</p>
|
||||
<div className="rectification-saved-wrap">
|
||||
<p className="rectification-saved" role="status">
|
||||
{savedStatus === "confirmed" ? "已确认校正时间" : "当前排盘时间(代表性候选,还不能确认唯一分钟)"}:{savedTime}。后续排盘将使用该时间;你仍可继续补充事件或改选其他候选。
|
||||
</p>
|
||||
{savedStatus === "accepted" && candidateResult && (
|
||||
<RectificationOosPanel prompts={candidateResult.oosBlindPrompts} />
|
||||
)}
|
||||
{savedStatus === "accepted" && onStartConsultation && (
|
||||
<div className="rectification-consult-handoff">
|
||||
<Button type="button" onClick={onStartConsultation}>
|
||||
用这个时间看盘
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{error && <p className="error-message" role="alert">{error}</p>}
|
||||
{readonly && (
|
||||
|
||||
Reference in New Issue
Block a user