优化(前端): 清理资料研究导入冲突并实施全功能路由懒加载与错误边界
This commit is contained in:
parent
00aa5e3238
commit
d5e338ad97
@ -118,7 +118,6 @@ export async function 发起拆书(
|
||||
输入: { config_id: string; reason?: string | null },
|
||||
) {
|
||||
if (!输入.config_id.trim()) throw new Error("请明确指定已启用的分析配置。");
|
||||
const { 客户端 } = await import("../../接口/生成/客户端");
|
||||
const { data, error } = await 客户端.POST(
|
||||
"/api/v1/sources/{source_id}/analyses",
|
||||
{
|
||||
@ -136,7 +135,6 @@ export async function 发起拆书(
|
||||
}
|
||||
|
||||
export async function 恢复拆书(taskId: string) {
|
||||
const { 客户端 } = await import("../../接口/生成/客户端");
|
||||
const { data, error } = await 客户端.POST(
|
||||
"/api/v1/analyses/{task_id}/resume",
|
||||
{
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
/** 资料对照页:来源版本原文、清理候选对照与榜单快照(含失败态)。 */
|
||||
import { useState } from "react";
|
||||
import { 客户端 } from "../../接口/生成/客户端";
|
||||
import { useMuse来源列表, useMuse版本原文 } from "./数据";
|
||||
import { Ui反馈状态 } from "../../界面/反馈状态";
|
||||
import { useMuse作者会话 } from "../../应用/作者会话";
|
||||
@ -14,12 +15,12 @@ export function Ui资料页() {
|
||||
|
||||
async function 生成并应用(sourceId: string, revision: number) {
|
||||
try {
|
||||
const { data, error } = await (await import("../../接口/生成/客户端")).客户端.POST(
|
||||
const { data, error } = await 客户端.POST(
|
||||
"/api/v1/sources/{source_id}/versions/{revision}/clean-candidates",
|
||||
{ params: { path: { source_id: sourceId, revision } } },
|
||||
);
|
||||
if (!data) throw new Error((error as { message?: string })?.message ?? "生成失败");
|
||||
const apply = await (await import("../../接口/生成/客户端")).客户端.POST(
|
||||
const apply = await 客户端.POST(
|
||||
"/api/v1/clean-candidates/{candidate_id}/apply",
|
||||
{ params: { path: { candidate_id: (data as { candidate_id: string }).candidate_id } } },
|
||||
);
|
||||
|
||||
@ -1,76 +1,186 @@
|
||||
import { lazy, Suspense } from "react";
|
||||
import { Navigate, Route, Routes } from "react-router-dom";
|
||||
import { Ui审校页, Ui声音页, Ui规则页 } from "../功能/审校修订";
|
||||
import { Ui任务列表 } from "../功能/任务运行";
|
||||
import { Ui实验页 } from "../功能/效果评测";
|
||||
import {
|
||||
Ui作品首页,
|
||||
Ui作品档案,
|
||||
Ui探索工作区,
|
||||
Ui规划工作区,
|
||||
} from "../功能/作品规划";
|
||||
import { Ui候选审阅页, Ui正文页 } from "../功能/正文写作";
|
||||
import { Ui资料页, Ui拆书工作区, Ui榜单与选题页 } from "../功能/资料研究";
|
||||
import { Ui世界资料页, Ui人物关系页, Ui时间与伏笔页 } from "../功能/故事世界";
|
||||
import { Ui方法库页, Ui方法详情, Ui版本绑定 } from "../功能/知识方法";
|
||||
import { Ui偏好页, Ui反馈对照, Ui改进提案页 } from "../功能/作者经验";
|
||||
import {
|
||||
Ui全书整理页,
|
||||
Ui定稿导出页,
|
||||
Ui连载计划页,
|
||||
Ui读者反馈页,
|
||||
} from "../功能/交付连载";
|
||||
import { Ui连接与模型页, Ui数据管理页, Ui备份恢复页 } from "../功能/系统管理";
|
||||
import { Ui反馈状态 } from "../界面/反馈状态";
|
||||
import { Ui页面错误边界 } from "./页面错误边界";
|
||||
|
||||
// 首屏核心静态保留:轻量作品列表
|
||||
import { Ui作品首页 } from "../功能/作品规划/作品首页";
|
||||
|
||||
// 其余功能页路由级懒加载(精准具体页面入口,避免聚合出口产生重叠打包)
|
||||
const Ui探索工作区 = lazy(() =>
|
||||
import("../功能/作品规划/探索工作区").then((m) => ({ default: m.Ui探索工作区 })),
|
||||
);
|
||||
const Ui作品档案 = lazy(() =>
|
||||
import("../功能/作品规划/作品档案").then((m) => ({ default: m.Ui作品档案 })),
|
||||
);
|
||||
const Ui规划工作区 = lazy(() =>
|
||||
import("../功能/作品规划/规划工作区").then((m) => ({ default: m.Ui规划工作区 })),
|
||||
);
|
||||
|
||||
// 正文写作与审阅(含富文本编辑器重依赖)
|
||||
const Ui正文页 = lazy(() =>
|
||||
import("../功能/正文写作/正文页").then((m) => ({ default: m.Ui正文页 })),
|
||||
);
|
||||
const Ui候选审阅页 = lazy(() =>
|
||||
import("../功能/正文写作/候选审阅").then((m) => ({ default: m.Ui候选审阅页 })),
|
||||
);
|
||||
|
||||
// 审校修订
|
||||
const Ui审校页 = lazy(() =>
|
||||
import("../功能/审校修订/审校页").then((m) => ({ default: m.Ui审校页 })),
|
||||
);
|
||||
const Ui声音页 = lazy(() =>
|
||||
import("../功能/审校修订/声音档案").then((m) => ({ default: m.Ui声音页 })),
|
||||
);
|
||||
const Ui规则页 = lazy(() =>
|
||||
import("../功能/审校修订/规则页").then((m) => ({ default: m.Ui规则页 })),
|
||||
);
|
||||
|
||||
// 任务运行与效果评测
|
||||
const Ui任务列表 = lazy(() =>
|
||||
import("../功能/任务运行/任务列表").then((m) => ({ default: m.Ui任务列表 })),
|
||||
);
|
||||
const Ui实验页 = lazy(() =>
|
||||
import("../功能/效果评测/实验页").then((m) => ({ default: m.Ui实验页 })),
|
||||
);
|
||||
|
||||
// 故事世界
|
||||
const Ui世界资料页 = lazy(() =>
|
||||
import("../功能/故事世界/世界资料页").then((m) => ({ default: m.Ui世界资料页 })),
|
||||
);
|
||||
const Ui人物关系页 = lazy(() =>
|
||||
import("../功能/故事世界/人物关系页").then((m) => ({ default: m.Ui人物关系页 })),
|
||||
);
|
||||
const Ui时间与伏笔页 = lazy(() =>
|
||||
import("../功能/故事世界/时间与伏笔页").then((m) => ({ default: m.Ui时间与伏笔页 })),
|
||||
);
|
||||
|
||||
// 资料研究
|
||||
const Ui资料页 = lazy(() =>
|
||||
import("../功能/资料研究/资料页").then((m) => ({ default: m.Ui资料页 })),
|
||||
);
|
||||
const Ui拆书工作区 = lazy(() =>
|
||||
import("../功能/资料研究/拆书工作区").then((m) => ({ default: m.Ui拆书工作区 })),
|
||||
);
|
||||
const Ui榜单与选题页 = lazy(() =>
|
||||
import("../功能/资料研究/榜单与选题页").then((m) => ({ default: m.Ui榜单与选题页 })),
|
||||
);
|
||||
|
||||
// 知识方法
|
||||
const Ui方法库页 = lazy(() =>
|
||||
import("../功能/知识方法/方法库页").then((m) => ({ default: m.Ui方法库页 })),
|
||||
);
|
||||
const Ui方法详情 = lazy(() =>
|
||||
import("../功能/知识方法/方法详情").then((m) => ({ default: m.Ui方法详情 })),
|
||||
);
|
||||
const Ui版本绑定 = lazy(() =>
|
||||
import("../功能/知识方法/版本绑定").then((m) => ({ default: m.Ui版本绑定 })),
|
||||
);
|
||||
|
||||
// 交付连载
|
||||
const Ui全书整理页 = lazy(() =>
|
||||
import("../功能/交付连载/全书整理页").then((m) => ({ default: m.Ui全书整理页 })),
|
||||
);
|
||||
const Ui定稿导出页 = lazy(() =>
|
||||
import("../功能/交付连载/定稿导出页").then((m) => ({ default: m.Ui定稿导出页 })),
|
||||
);
|
||||
const Ui连载计划页 = lazy(() =>
|
||||
import("../功能/交付连载/连载计划页").then((m) => ({ default: m.Ui连载计划页 })),
|
||||
);
|
||||
const Ui读者反馈页 = lazy(() =>
|
||||
import("../功能/交付连载/读者反馈页").then((m) => ({ default: m.Ui读者反馈页 })),
|
||||
);
|
||||
|
||||
// 系统管理
|
||||
const Ui连接与模型页 = lazy(() =>
|
||||
import("../功能/系统管理/连接与模型页").then((m) => ({ default: m.Ui连接与模型页 })),
|
||||
);
|
||||
const Ui数据管理页 = lazy(() =>
|
||||
import("../功能/系统管理/数据管理页").then((m) => ({ default: m.Ui数据管理页 })),
|
||||
);
|
||||
const Ui备份恢复页 = lazy(() =>
|
||||
import("../功能/系统管理/备份恢复页").then((m) => ({ default: m.Ui备份恢复页 })),
|
||||
);
|
||||
|
||||
// 作者经验
|
||||
const Ui偏好页 = lazy(() =>
|
||||
import("../功能/作者经验/偏好页").then((m) => ({ default: m.Ui偏好页 })),
|
||||
);
|
||||
const Ui反馈对照 = lazy(() =>
|
||||
import("../功能/作者经验/反馈对照").then((m) => ({ default: m.Ui反馈对照 })),
|
||||
);
|
||||
const Ui改进提案页 = lazy(() =>
|
||||
import("../功能/作者经验/改进提案页").then((m) => ({ default: m.Ui改进提案页 })),
|
||||
);
|
||||
|
||||
export function Ui页面路由() {
|
||||
return (
|
||||
<Routes>
|
||||
<Route path="/works" element={<Ui作品首页 />} />
|
||||
<Route path="/explorations/:draft_id?" element={<Ui探索工作区 />} />
|
||||
<Route path="/works/:work_id/profile" element={<Ui作品档案 />} />
|
||||
<Route path="/works/:work_id/plans" element={<Ui规划工作区 />} />
|
||||
<Route path="/works/:work_id/write/:chapter_id?" element={<Ui正文页 />} />
|
||||
<Route
|
||||
path="/works/:work_id/candidates/:chapter_id"
|
||||
element={<Ui候选审阅页 />}
|
||||
/>
|
||||
<Route path="/works/:work_id/review" element={<Ui审校页 />} />
|
||||
<Route path="/works/:work_id/voice" element={<Ui声音页 />} />
|
||||
<Route path="/works/:work_id/delivery" element={<Ui全书整理页 />} />
|
||||
<Route
|
||||
path="/works/:work_id/delivery/export/:delivery_id?"
|
||||
element={<Ui定稿导出页 />}
|
||||
/>
|
||||
<Route path="/works/:work_id/serial" element={<Ui连载计划页 />} />
|
||||
<Route
|
||||
path="/works/:work_id/reader-feedback"
|
||||
element={<Ui读者反馈页 />}
|
||||
/>
|
||||
<Route path="/review-rules" element={<Ui规则页 />} />
|
||||
<Route path="/tasks" element={<Ui任务列表 />} />
|
||||
<Route path="/evaluations/:experiment_id?" element={<Ui实验页 />} />
|
||||
<Route path="/works/:work_id/world" element={<Ui世界资料页壳 />} />
|
||||
<Route
|
||||
path="/works/:work_id/world/relations"
|
||||
element={<Ui人物关系页壳 />}
|
||||
/>
|
||||
<Route
|
||||
path="/works/:work_id/world/timeline"
|
||||
element={<Ui时间与伏笔页Shell />}
|
||||
/>
|
||||
<Route path="/sources" element={<Ui资料页 />} />
|
||||
<Route path="/research" element={<Ui拆书工作区 />} />
|
||||
<Route path="/rankings" element={<Ui榜单与选题页 />} />
|
||||
<Route path="/methods" element={<Ui方法库页Shell />} />
|
||||
<Route path="/methods/:method_id" element={<Ui方法详情壳 />} />
|
||||
<Route path="/works/:work_id/methods" element={<Ui版本绑定壳 />} />
|
||||
<Route path="/system" element={<Ui连接与模型页 />} />
|
||||
<Route path="/system/data" element={<Ui数据管理页 />} />
|
||||
<Route path="/system/backups" element={<Ui备份恢复页 />} />
|
||||
<Route path="/preferences" element={<Ui偏好页 />} />
|
||||
<Route path="/feedback/:feedback_id" element={<Ui反馈对照 />} />
|
||||
<Route path="/improvements/:improvement_id?" element={<Ui改进提案页 />} />
|
||||
<Route path="*" element={<Navigate to="/works" replace />} />
|
||||
</Routes>
|
||||
<Ui页面错误边界>
|
||||
<Suspense
|
||||
fallback={
|
||||
<main className="content">
|
||||
<div className="page-heading">
|
||||
<Ui反馈状态 message="正在载入页面组件…" />
|
||||
</div>
|
||||
</main>
|
||||
}
|
||||
>
|
||||
<Routes>
|
||||
<Route path="/works" element={<Ui作品首页 />} />
|
||||
<Route path="/explorations/:draft_id?" element={<Ui探索工作区 />} />
|
||||
<Route path="/works/:work_id/profile" element={<Ui作品档案 />} />
|
||||
<Route path="/works/:work_id/plans" element={<Ui规划工作区 />} />
|
||||
<Route
|
||||
path="/works/:work_id/write/:chapter_id?"
|
||||
element={<Ui正文页 />}
|
||||
/>
|
||||
<Route
|
||||
path="/works/:work_id/candidates/:chapter_id"
|
||||
element={<Ui候选审阅页 />}
|
||||
/>
|
||||
<Route path="/works/:work_id/review" element={<Ui审校页 />} />
|
||||
<Route path="/works/:work_id/voice" element={<Ui声音页 />} />
|
||||
<Route path="/works/:work_id/delivery" element={<Ui全书整理页 />} />
|
||||
<Route
|
||||
path="/works/:work_id/delivery/export/:delivery_id?"
|
||||
element={<Ui定稿导出页 />}
|
||||
/>
|
||||
<Route path="/works/:work_id/serial" element={<Ui连载计划页 />} />
|
||||
<Route
|
||||
path="/works/:work_id/reader-feedback"
|
||||
element={<Ui读者反馈页 />}
|
||||
/>
|
||||
<Route path="/review-rules" element={<Ui规则页 />} />
|
||||
<Route path="/tasks" element={<Ui任务列表 />} />
|
||||
<Route path="/evaluations/:experiment_id?" element={<Ui实验页 />} />
|
||||
<Route path="/works/:work_id/world" element={<Ui世界资料页壳 />} />
|
||||
<Route
|
||||
path="/works/:work_id/world/relations"
|
||||
element={<Ui人物关系页壳 />}
|
||||
/>
|
||||
<Route
|
||||
path="/works/:work_id/world/timeline"
|
||||
element={<Ui时间与伏笔页Shell />}
|
||||
/>
|
||||
<Route path="/sources" element={<Ui资料页 />} />
|
||||
<Route path="/research" element={<Ui拆书工作区 />} />
|
||||
<Route path="/rankings" element={<Ui榜单与选题页 />} />
|
||||
<Route path="/methods" element={<Ui方法库页Shell />} />
|
||||
<Route path="/methods/:method_id" element={<Ui方法详情壳 />} />
|
||||
<Route path="/works/:work_id/methods" element={<Ui版本绑定壳 />} />
|
||||
<Route path="/system" element={<Ui连接与模型页 />} />
|
||||
<Route path="/system/data" element={<Ui数据管理页 />} />
|
||||
<Route path="/system/backups" element={<Ui备份恢复页 />} />
|
||||
<Route path="/preferences" element={<Ui偏好页 />} />
|
||||
<Route path="/feedback/:feedback_id" element={<Ui反馈对照 />} />
|
||||
<Route
|
||||
path="/improvements/:improvement_id?"
|
||||
element={<Ui改进提案页 />}
|
||||
/>
|
||||
<Route path="*" element={<Navigate to="/works" replace />} />
|
||||
</Routes>
|
||||
</Suspense>
|
||||
</Ui页面错误边界>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
62
web/src/应用/页面错误边界.tsx
Normal file
62
web/src/应用/页面错误边界.tsx
Normal file
@ -0,0 +1,62 @@
|
||||
import { Component, type ErrorInfo, type ReactNode } from "react";
|
||||
import { Ui反馈状态 } from "../界面/反馈状态";
|
||||
|
||||
interface Props {
|
||||
children: ReactNode;
|
||||
}
|
||||
|
||||
interface State {
|
||||
hasError: boolean;
|
||||
error: Error | null;
|
||||
}
|
||||
|
||||
export class Ui页面错误边界 extends Component<Props, State> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
this.state = { hasError: false, error: null };
|
||||
}
|
||||
|
||||
static getDerivedStateFromError(error: Error): State {
|
||||
return { hasError: true, error };
|
||||
}
|
||||
|
||||
componentDidCatch(error: Error, errorInfo: ErrorInfo) {
|
||||
console.error("页面加载或渲染失败:", error, errorInfo);
|
||||
}
|
||||
|
||||
重试 = () => {
|
||||
this.setState({ hasError: false, error: null });
|
||||
};
|
||||
|
||||
render() {
|
||||
if (this.state.hasError) {
|
||||
return (
|
||||
<main className="content">
|
||||
<div className="page-heading">
|
||||
<div>
|
||||
<p className="eyebrow">加载受阻</p>
|
||||
<h1>页面未正常载入</h1>
|
||||
<p className="muted">可能是网络暂时中断或应用版本已更新。</p>
|
||||
</div>
|
||||
</div>
|
||||
<Ui反馈状态
|
||||
error
|
||||
message={
|
||||
this.state.error?.message ||
|
||||
"页面组件加载失败,请尝试重新载入。"
|
||||
}
|
||||
/>
|
||||
<div style={{ marginTop: "1rem", display: "flex", gap: "0.5rem" }}>
|
||||
<button className="primary" onClick={this.重试}>
|
||||
重新尝试加载
|
||||
</button>
|
||||
<button onClick={() => window.location.assign("/works")}>
|
||||
返回作品首页
|
||||
</button>
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
return this.props.children;
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user