Skip to content

Commit 0661d42

Browse files
committed
Merge remote-tracking branch 'origin/develop_930' into develop_930
2 parents 4089c85 + 7f7f25d commit 0661d42

32 files changed

+1190
-1005
lines changed

frontend/src/app/App.tsx

Lines changed: 0 additions & 14 deletions
This file was deleted.

frontend/src/components/DetailHeader.tsx

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,11 @@ interface DetailHeaderProps<T> {
2626
operations: OperationItem[];
2727
}
2828

29-
const DetailHeader: React.FC<DetailHeaderProps<any>> = <T,>({
29+
function DetailHeader<T>({
3030
data,
3131
statistics,
3232
operations,
33-
}: DetailHeaderProps<T>) => {
33+
}: DetailHeaderProps<T>): React.ReactNode {
3434
return (
3535
<Card>
3636
<div className="flex items-start justify-between">
@@ -56,16 +56,20 @@ const DetailHeader: React.FC<DetailHeaderProps<any>> = <T,>({
5656
</Tag>
5757
)}
5858
</div>
59-
<p className="text-gray-700 mb-4">{data.description}</p>
60-
{data?.tags?.map((tag) => (
61-
<Tag
62-
key={tag.id}
63-
className="mr-1"
64-
style={{ background: tag.color }}
65-
>
66-
{tag.name}
67-
</Tag>
68-
))}
59+
<p className="text-gray-700 mb-2">{data.description}</p>
60+
{data?.tags && (
61+
<div className="flex flex-wrap mb-2">
62+
{data?.tags?.map((tag) => (
63+
<Tag
64+
key={tag.id}
65+
className="mr-1"
66+
style={{ background: tag.color }}
67+
>
68+
{tag.name}
69+
</Tag>
70+
))}
71+
</div>
72+
)}
6973
<div className="flex items-center gap-6 text-sm">
7074
{statistics.map((stat, idx) => (
7175
<div key={idx} className="flex items-center gap-1">
@@ -122,6 +126,6 @@ const DetailHeader: React.FC<DetailHeaderProps<any>> = <T,>({
122126
</div>
123127
</Card>
124128
);
125-
};
129+
}
126130

127131
export default DetailHeader;
Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
import React, { Component } from "react";
2+
import { Button, Modal } from "antd";
3+
4+
interface ErrorContextType {
5+
hasError: boolean;
6+
error: Error | null;
7+
errorInfo: { componentStack: string } | null;
8+
}
9+
10+
const ErrorContext = React.createContext<ErrorContextType>({
11+
hasError: false,
12+
error: null,
13+
errorInfo: null,
14+
});
15+
16+
interface ErrorBoundaryState {
17+
hasError: boolean;
18+
error: Error | null;
19+
errorInfo: { componentStack: string } | null;
20+
errorTimestamp: string | null;
21+
}
22+
23+
interface ErrorBoundaryProps {
24+
children?: React.ReactNode;
25+
onReset?: () => void;
26+
showDetails?: boolean;
27+
}
28+
29+
export default class ErrorBoundary extends Component<
30+
ErrorBoundaryProps,
31+
ErrorBoundaryState
32+
> {
33+
constructor(props: ErrorBoundaryProps) {
34+
super(props);
35+
this.state = {
36+
hasError: false,
37+
error: null,
38+
errorInfo: null,
39+
errorTimestamp: null,
40+
};
41+
}
42+
43+
static getDerivedStateFromError(error: any) {
44+
// 更新 state 使下一次渲染能够显示降级 UI
45+
return {
46+
hasError: true,
47+
error: error,
48+
errorTimestamp: new Date().toISOString(),
49+
};
50+
}
51+
52+
componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
53+
// 错误统计
54+
this.setState({
55+
error,
56+
errorInfo,
57+
hasError: true,
58+
});
59+
60+
// 在实际应用中,这里可以集成错误报告服务
61+
this.logErrorToService(error, errorInfo);
62+
63+
// 开发环境下在控制台显示详细错误
64+
if (process.env.NODE_ENV === "development") {
65+
console.error("ErrorBoundary 捕获到错误:", error);
66+
console.error("错误详情:", errorInfo);
67+
}
68+
}
69+
70+
logErrorToService = (error: Error, errorInfo: React.ErrorInfo) => {
71+
// 这里可以集成 Sentry、LogRocket 等错误监控服务
72+
const errorData = {
73+
error: error.toString(),
74+
errorInfo: errorInfo.componentStack,
75+
timestamp: this.state.errorTimestamp,
76+
url: window.location.href,
77+
userAgent: navigator.userAgent,
78+
};
79+
80+
// 模拟发送错误日志
81+
console.log("发送错误日志到监控服务:", errorData);
82+
83+
// 实际使用时取消注释并配置您的错误监控服务
84+
/*
85+
if (window.Sentry) {
86+
window.Sentry.captureException(error, { extra: errorInfo });
87+
}
88+
*/
89+
};
90+
91+
handleReset = () => {
92+
this.setState({
93+
hasError: false,
94+
error: null,
95+
errorInfo: null,
96+
errorTimestamp: null,
97+
});
98+
99+
// 可选:重新加载页面或执行其他恢复操作
100+
if (this.props.onReset) {
101+
this.props.onReset();
102+
}
103+
};
104+
105+
handleReload = () => {
106+
window.location.reload();
107+
};
108+
109+
handleGoHome = () => {
110+
window.location.href = "/";
111+
};
112+
113+
renderErrorDetails = () => {
114+
const { error, errorInfo } = this.state;
115+
116+
if (!this.props.showDetails) return null;
117+
118+
return (
119+
<div className="bg-gray-100 p-4 mt-4 text-left rounded">
120+
<div className="mt-2">
121+
<strong>错误信息:</strong>
122+
<pre className="bg-gray-600 px-4 py-2 rounded text-white overflow-auto">
123+
{error?.toString()}
124+
</pre>
125+
</div>
126+
{errorInfo && (
127+
<div className="mt-2">
128+
<strong>组件堆栈:</strong>
129+
<pre className="bg-gray-600 px-4 py-2 rounded text-white overflow-auto">
130+
{errorInfo.componentStack}
131+
</pre>
132+
</div>
133+
)}
134+
</div>
135+
);
136+
};
137+
138+
render() {
139+
if (this.state.hasError) {
140+
return (
141+
<Modal visible width={1000} footer={null} closable={false}>
142+
<div className="text-center p-6">
143+
<div className="text-3xl">⚠️</div>
144+
<h1 className="text-xl p-2">出了点问题</h1>
145+
<p className="text-sm text-gray-400">应用程序遇到了意外错误。</p>
146+
147+
<div className="flex justify-center gap-4 my-4">
148+
<Button onClick={this.handleReload}>刷新页面</Button>
149+
<Button type="primary" onClick={this.handleGoHome}>
150+
返回首页
151+
</Button>
152+
</div>
153+
154+
{this.renderErrorDetails()}
155+
156+
<div className="mt-4 border-t border-gray-100 pt-4 text-center">
157+
<p className="text-sm text-gray-500">
158+
如果问题持续存在,请联系技术支持
159+
</p>
160+
<small className="text-xs text-gray-400">
161+
错误 ID: {this.state.errorTimestamp}
162+
</small>
163+
</div>
164+
</div>
165+
</Modal>
166+
);
167+
}
168+
169+
return (
170+
<ErrorContext.Provider
171+
value={{
172+
hasError: this.state.hasError,
173+
error: this.state.error,
174+
errorInfo: this.state.errorInfo,
175+
}}
176+
>
177+
{this.props.children}
178+
</ErrorContext.Provider>
179+
);
180+
}
181+
}
182+
183+
export function withErrorBoundary(
184+
Component: React.ComponentType
185+
): React.ComponentType {
186+
return (props) => (
187+
<ErrorBoundary showDetails={process.env.NODE_ENV === "development"}>
188+
<Component {...props} />
189+
</ErrorBoundary>
190+
);
191+
}

frontend/src/mock/mock-apis.cjs

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -128,24 +128,19 @@ const MockAPI = {
128128
queryKnowledgeStatisticsUsingGet: "/knowledge/statistics", // 获取知识生成
129129

130130
// 算子市场
131-
createOperatorUsingPost: "/operators", // 创建算子
132-
uploadOperatorUsingPost: "/operators/upload", // 上传算子
133-
deleteCategoryUsingDelete: "/operators/categories/:categoryId", // 删除算子分类
134-
createCategoryUsingPost: "/operators/categories", // 创建算子分类
135-
queryCategoryTreeUsingGet: "/operators/categories/tree", // 获取算子分类树
136-
createLabelUsingPost: "/operators/labels", // 创建算子标签
137-
queryLabelsUsingGet: "/operators/labels", // 获取算子标签列表
138-
deleteLabelsUsingDelete: "/operators/labels", // 删除算子标签
139-
updateLabelByIdUsingPut: "/operators/labels/:labelId", // 更新算子标签
140-
queryOperatorsUsingGet: "/operators", // 获取算子列表
131+
queryOperatorsUsingPost: "/operators/list", // 获取算子列表
132+
queryCategoryTreeUsingGet: "/categories/tree", // 获取算子分类树
141133
queryOperatorByIdUsingGet: "/operators/:operatorId", // 根据ID获取算子详情
134+
createOperatorUsingPost: "/operators/create", // 创建算子
142135
updateOperatorByIdUsingPut: "/operators/:operatorId", // 更新算子
136+
uploadOperatorUsingPost: "/operators/upload", // 上传算子
137+
createLabelUsingPost: "/operators/labels", // 创建算子标签
138+
queryLabelsUsingGet: "/labels", // 获取算子标签列表
139+
deleteLabelsUsingDelete: "/labels", // 删除算子标签
140+
updateLabelByIdUsingPut: "/labels/:labelId", // 更新算子标签
143141
deleteOperatorByIdUsingDelete: "/operators/:operatorId", // 删除算子
144142
publishOperatorUsingPost: "/operators/:operatorId/publish", // 发布算子
145143
unpublishOperatorUsingPost: "/operators/:operatorId/unpublish", // 下架算子
146-
rateOperatorUsingPost: "/operators/:operatorId/rate", // 评分算子
147-
queryOperatorRatingsUsingGet: "/operators/:operatorId/ratings", // 获取算子评分列表
148-
queryOperatorStatisticsUsingGet: "/operators/statistics", // 获取算子统计信息
149144
};
150145

151146
module.exports = addMockPrefix("/api", MockAPI);

0 commit comments

Comments
 (0)