fix: 修复确认生成报错导致React崩溃 - 递归提取嵌套错误对象
CI/CD Pipeline / Frontend Lint (push) Failing after 36h37m55s
CI/CD Pipeline / Validate Code Quality And Tests (push) Failing after 36h37m55s
CI/CD Pipeline / Production Browser E2E (push) Failing after 1695h12m34s
CI/CD Pipeline / Deploy Production (push) Failing after 1695h12m36s
CI/CD Pipeline / Build Production Runtime Images (push) Failing after 1695h12m38s
CI/CD Pipeline / Build & Push Staging (Watchtower auto-deploy) (push) Failing after 1695h12m38s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 1695h44m3s
CI/CD Pipeline / Frontend Lint (push) Failing after 36h37m55s
CI/CD Pipeline / Validate Code Quality And Tests (push) Failing after 36h37m55s
CI/CD Pipeline / Production Browser E2E (push) Failing after 1695h12m34s
CI/CD Pipeline / Deploy Production (push) Failing after 1695h12m36s
CI/CD Pipeline / Build Production Runtime Images (push) Failing after 1695h12m38s
CI/CD Pipeline / Build & Push Staging (Watchtower auto-deploy) (push) Failing after 1695h12m38s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 1695h44m3s
- client.ts: safeExtractString 升级为递归版本,处理 {code, message: {code, message}} 嵌套
- GeneratePage.tsx: catch块 extractString 升级为递归版本
- GeneratePage.tsx: 轮询错误路径 safeExtract 递归处理嵌套对象
- GeneratePage.tsx: 渲染处加 typeof 防御,确保不传对象给 React
- 修复 TS2304 变量名错误 (errorMsg → backendMsg)
This commit is contained in:
@@ -125,14 +125,19 @@ apiClient.interceptors.response.use(
|
||||
// 注意:后端返回的字段可能是对象 {code, message} 而非字符串,需要安全提取
|
||||
const data = error.response?.data;
|
||||
const rawServerMsg = data?.detail || data?.message || data?.msg;
|
||||
// 安全提取字符串:如果是对象则递归提取 message/msg/detail 字段
|
||||
// 安全提取字符串:递归处理嵌套对象(后端可能返回 {code, message: {code, message}} 等)
|
||||
const safeExtractString = (val: unknown): string => {
|
||||
if (typeof val === "string") return val;
|
||||
if (typeof val === "object" && val !== null) {
|
||||
if ("message" in val)
|
||||
return String((val as { message: unknown }).message);
|
||||
if ("msg" in val) return String((val as { msg: unknown }).msg);
|
||||
if ("detail" in val) return String((val as { detail: unknown }).detail);
|
||||
const obj = val as Record<string, unknown>;
|
||||
if (typeof obj.message === "string") return obj.message;
|
||||
if (typeof obj.msg === "string") return obj.msg;
|
||||
if (typeof obj.detail === "string") return obj.detail;
|
||||
// 嵌套对象:递归提取
|
||||
if (typeof obj.message === "object" && obj.message !== null)
|
||||
return safeExtractString(obj.message);
|
||||
if (typeof obj.msg === "object" && obj.msg !== null)
|
||||
return safeExtractString(obj.msg);
|
||||
return JSON.stringify(val);
|
||||
}
|
||||
return "";
|
||||
|
||||
@@ -542,15 +542,21 @@ const GeneratePage: React.FC = () => {
|
||||
(c: { status: string }) => c.status === "failed",
|
||||
)?.error_message ||
|
||||
"视频生成失败,请联系管理员或重试";
|
||||
// 安全提取字符串:如果是对象且有 message 属性,提取 message
|
||||
const errorMsg =
|
||||
typeof rawMsg === "string"
|
||||
? rawMsg
|
||||
: typeof rawMsg === "object" &&
|
||||
rawMsg !== null &&
|
||||
"message" in rawMsg
|
||||
? String((rawMsg as { message: unknown }).message)
|
||||
: JSON.stringify(rawMsg);
|
||||
// 安全提取字符串:递归处理嵌套对象(后端可能返回 {code, message: {code, message}} 等嵌套结构)
|
||||
const safeExtract = (val: unknown): string => {
|
||||
if (typeof val === "string") return val;
|
||||
if (typeof val === "object" && val !== null) {
|
||||
const obj = val as Record<string, unknown>;
|
||||
if (typeof obj.message === "string") return obj.message;
|
||||
if (typeof obj.msg === "string") return obj.msg;
|
||||
if (typeof obj.detail === "string") return obj.detail;
|
||||
if (obj.message && typeof obj.message === "object")
|
||||
return safeExtract(obj.message);
|
||||
return JSON.stringify(val);
|
||||
}
|
||||
return String(val ?? "");
|
||||
};
|
||||
const errorMsg = safeExtract(rawMsg);
|
||||
console.error("[生成失败] planId:", plan.id, "响应:", data);
|
||||
setGenerateError(errorMsg);
|
||||
message.error(errorMsg);
|
||||
@@ -596,15 +602,19 @@ const GeneratePage: React.FC = () => {
|
||||
};
|
||||
message?: string;
|
||||
};
|
||||
// 安全提取错误消息:后端可能返回对象 {code, message} 而非字符串
|
||||
// 安全提取错误消息:递归处理嵌套对象(后端可能返回 {code, message: {code, message}} 等)
|
||||
const extractString = (val: unknown): string => {
|
||||
if (typeof val === "string") return val;
|
||||
if (typeof val === "object" && val !== null) {
|
||||
if ("message" in val)
|
||||
return String((val as { message: unknown }).message);
|
||||
if ("msg" in val) return String((val as { msg: unknown }).msg);
|
||||
if ("detail" in val)
|
||||
return String((val as { detail: unknown }).detail);
|
||||
const obj = val as Record<string, unknown>;
|
||||
if (typeof obj.message === "string") return obj.message;
|
||||
if (typeof obj.msg === "string") return obj.msg;
|
||||
if (typeof obj.detail === "string") return obj.detail;
|
||||
// 嵌套对象:递归提取
|
||||
if (typeof obj.message === "object" && obj.message !== null)
|
||||
return extractString(obj.message);
|
||||
if (typeof obj.msg === "object" && obj.msg !== null)
|
||||
return extractString(obj.msg);
|
||||
return JSON.stringify(val);
|
||||
}
|
||||
return "";
|
||||
@@ -622,9 +632,25 @@ const GeneratePage: React.FC = () => {
|
||||
"完整错误:",
|
||||
axiosErr,
|
||||
);
|
||||
const errorMsg = backendMsg || "生成失败,请检查网络后重试或联系管理员";
|
||||
setGenerateError(errorMsg);
|
||||
message.error(errorMsg);
|
||||
// 确保 errorMsg 一定是字符串(后端可能返回 {code, message} 嵌套对象)
|
||||
const safeExtractErr = (val: unknown): string => {
|
||||
if (typeof val === "string") return val;
|
||||
if (typeof val === "object" && val !== null) {
|
||||
const obj = val as Record<string, unknown>;
|
||||
if (typeof obj.message === "string") return obj.message;
|
||||
if (typeof obj.msg === "string") return obj.msg;
|
||||
if (typeof obj.detail === "string") return obj.detail;
|
||||
// 嵌套对象:递归提取
|
||||
if (typeof obj.message === "object")
|
||||
return safeExtractErr(obj.message);
|
||||
return JSON.stringify(val);
|
||||
}
|
||||
return String(val ?? "");
|
||||
};
|
||||
const finalMsg =
|
||||
safeExtractErr(backendMsg) || "生成失败,请检查网络后重试或联系管理员";
|
||||
setGenerateError(finalMsg);
|
||||
message.error(finalMsg);
|
||||
}
|
||||
}, [
|
||||
title,
|
||||
@@ -1525,7 +1551,9 @@ const GeneratePage: React.FC = () => {
|
||||
生成失败
|
||||
</Text>
|
||||
<Text style={{ color: "var(--text-secondary)", fontSize: 12 }}>
|
||||
{generateError}
|
||||
{typeof generateError === "string"
|
||||
? generateError
|
||||
: JSON.stringify(generateError)}
|
||||
</Text>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user