fix: decouple AI completion from history save failures and improve history API errors

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-06-16 21:31:20 +08:00
parent 123a5cce6d
commit 187b08c3e1
8 changed files with 145 additions and 53 deletions
+8 -2
View File
@@ -16,7 +16,7 @@ import RegionSelect, {
} from "@/components/shared/region-select";
import { calculateBazi, type BaziChart } from "@/lib/calc/bazi";
import { streamAiCompletion } from "@/lib/ai/client-stream";
import { saveHistoryEntry } from "@/lib/history/storage";
import { saveHistoryEntrySafe } from "@/lib/history/storage";
export default function BaziForm() {
const [date, setDate] = useState(todaySolarYmd());
@@ -29,6 +29,7 @@ export default function BaziForm() {
const [chart, setChart] = useState<BaziChart | null>(null);
const [completion, setCompletion] = useState("");
const [error, setError] = useState("");
const [warning, setWarning] = useState("");
const [isLoading, setIsLoading] = useState(false);
const location = useRegionLocation(provinceCode, cityCode);
@@ -77,6 +78,7 @@ export default function BaziForm() {
}
setError("");
setWarning("");
setCompletion("");
setIsLoading(true);
@@ -92,7 +94,7 @@ export default function BaziForm() {
},
setCompletion,
);
await saveHistoryEntry({
const saveResult = await saveHistoryEntrySafe({
mode: "bazi",
title: "生辰八字解读",
question,
@@ -115,6 +117,9 @@ export default function BaziForm() {
: `${activeChart.pillars.year.ganZhi} ${activeChart.pillars.month.ganZhi} ${activeChart.pillars.day.ganZhi} ${activeChart.pillars.time.ganZhi}`,
},
});
if (!saveResult.ok) {
setWarning(saveResult.error);
}
} catch (err) {
setError(err instanceof Error ? err.message : String(err));
} finally {
@@ -137,6 +142,7 @@ export default function BaziForm() {
isLoading={isLoading}
onCompletion={handleAnalyze}
error={error}
warning={warning}
emptyHint="排盘后点击「AI 测算」获取解读"
downloadFilename={completion ? "生辰八字解读.md" : undefined}
downloadPreamble={downloadPreamble}
+8 -2
View File
@@ -23,7 +23,7 @@ import RegionSelect, {
import { calculateBazi, type BaziChart } from "@/lib/calc/bazi";
import type { GuaResult } from "@/lib/calc/hexagram";
import { streamAiCompletion } from "@/lib/ai/client-stream";
import { saveHistoryEntry } from "@/lib/history/storage";
import { saveHistoryEntrySafe } from "@/lib/history/storage";
export default function CombinedForm() {
const [birthDate, setBirthDate] = useState(todaySolarYmd());
@@ -45,6 +45,7 @@ export default function CombinedForm() {
const [chart, setChart] = useState<BaziChart | null>(null);
const [completion, setCompletion] = useState("");
const [error, setError] = useState("");
const [warning, setWarning] = useState("");
const [isLoading, setIsLoading] = useState(false);
const birthLocation = useRegionLocation(birthProvince, birthCity);
@@ -112,6 +113,7 @@ export default function CombinedForm() {
}
setError("");
setWarning("");
setCompletion("");
setIsLoading(true);
@@ -155,7 +157,7 @@ export default function CombinedForm() {
},
setCompletion,
);
await saveHistoryEntry({
const saveResult = await saveHistoryEntrySafe({
mode: "combined",
title: "综合测算解读",
question,
@@ -189,6 +191,9 @@ export default function CombinedForm() {
六爻: withHexagram && guaData ? guaData.result.guaTitle : "无",
},
});
if (!saveResult.ok) {
setWarning(saveResult.error);
}
} catch (e) {
setError(e instanceof Error ? e.message : String(e));
} finally {
@@ -211,6 +216,7 @@ export default function CombinedForm() {
isLoading={isLoading}
onCompletion={handleAnalyze}
error={error}
warning={warning}
emptyHint="填写完整信息后,点击「综合测算」"
downloadFilename={completion ? "综合测算解读.md" : undefined}
downloadPreamble={downloadPreamble}
+10 -2
View File
@@ -17,7 +17,7 @@ import RegionSelect, {
useRegionLocation,
} from "@/components/shared/region-select";
import { streamAiCompletion } from "@/lib/ai/client-stream";
import { saveHistoryEntry } from "@/lib/history/storage";
import { saveHistoryEntrySafe } from "@/lib/history/storage";
import type { GuaResult } from "@/lib/calc/hexagram";
import todayJson from "@/lib/data/today.json";
@@ -34,6 +34,7 @@ export default function LiuyaoForm() {
const [guaData, setGuaData] = useState<GuaResult | null>(null);
const [completion, setCompletion] = useState("");
const [error, setError] = useState("");
const [warning, setWarning] = useState("");
const [isLoading, setIsLoading] = useState(false);
const location = useRegionLocation(provinceCode, cityCode);
@@ -65,6 +66,7 @@ export default function LiuyaoForm() {
}
setError("");
setWarning("");
setCompletion("");
setIsLoading(true);
@@ -86,7 +88,7 @@ export default function LiuyaoForm() {
},
setCompletion,
);
await saveHistoryEntry({
const saveResult = await saveHistoryEntrySafe({
mode: "liuyao",
title: guaData!.result.guaTitle,
question,
@@ -104,6 +106,9 @@ export default function LiuyaoForm() {
卦象: guaData!.result.guaTitle,
},
});
if (!saveResult.ok) {
setWarning(saveResult.error);
}
} catch (e) {
setError(e instanceof Error ? e.message : String(e));
} finally {
@@ -122,6 +127,7 @@ export default function LiuyaoForm() {
setGuaData(null);
setCompletion("");
setError("");
setWarning("");
setIsLoading(false);
}
@@ -129,6 +135,7 @@ export default function LiuyaoForm() {
setGuaData(data);
setCompletion("");
setError("");
setWarning("");
}
const downloadPreamble =
@@ -145,6 +152,7 @@ export default function LiuyaoForm() {
isLoading={isLoading}
onCompletion={handleAnalyze}
error={error}
warning={warning}
emptyHint="完成起卦后,点击「AI 解读」"
downloadFilename={
completion && guaData