You've already forked DataMate
feat: fix the problem in the Operator Market frontend pages
This commit is contained in:
@@ -1,330 +1,330 @@
|
||||
import { BarChart, Circle, Grid, ImageIcon, Layers, Maximize, MousePointer, Move, Square, Target, Crop, RotateCcw, FileText, Tag, Heart, HelpCircle, BookOpen, MessageSquare, Users, Zap, Globe, Scissors } from "lucide-react";
|
||||
|
||||
// Define the AnnotationTask type if not imported from elsewhere
|
||||
interface AnnotationTask {
|
||||
id: string
|
||||
name: string
|
||||
completed: string
|
||||
completedCount: number
|
||||
skippedCount: number
|
||||
totalCount: number
|
||||
annotators: Array<{
|
||||
id: string
|
||||
name: string
|
||||
avatar?: string
|
||||
}>
|
||||
text: string
|
||||
status: "completed" | "in_progress" | "pending" | "skipped"
|
||||
project: string
|
||||
type: "图像分类" | "文本分类" | "目标检测" | "NER" | "语音识别" | "视频分析"
|
||||
datasetType: "text" | "image" | "video" | "audio"
|
||||
progress: number
|
||||
}
|
||||
|
||||
|
||||
export const mockTasks: AnnotationTask[] = [
|
||||
{
|
||||
id: "12345678",
|
||||
name: "图像分类标注任务",
|
||||
completed: "2024年1月20日 20:40",
|
||||
completedCount: 1,
|
||||
skippedCount: 0,
|
||||
totalCount: 2,
|
||||
annotators: [
|
||||
{ id: "1", name: "张三", avatar: "/placeholder-user.jpg" },
|
||||
{ id: "2", name: "李四", avatar: "/placeholder-user.jpg" },
|
||||
],
|
||||
text: "对产品图像进行分类标注,包含10个类别",
|
||||
status: "completed",
|
||||
project: "图像分类",
|
||||
type: "图像分类",
|
||||
datasetType: "image",
|
||||
progress: 100,
|
||||
},
|
||||
{
|
||||
id: "12345679",
|
||||
name: "文本情感分析标注",
|
||||
completed: "2024年1月20日 20:40",
|
||||
completedCount: 2,
|
||||
skippedCount: 0,
|
||||
totalCount: 2,
|
||||
annotators: [
|
||||
{ id: "1", name: "王五", avatar: "/placeholder-user.jpg" },
|
||||
{ id: "2", name: "赵六", avatar: "/placeholder-user.jpg" },
|
||||
],
|
||||
text: "对用户评论进行情感倾向标注",
|
||||
status: "completed",
|
||||
project: "文本分类",
|
||||
type: "文本分类",
|
||||
datasetType: "text",
|
||||
progress: 100,
|
||||
},
|
||||
{
|
||||
id: "12345680",
|
||||
name: "目标检测标注任务",
|
||||
completed: "2024年1月20日 20:40",
|
||||
completedCount: 1,
|
||||
skippedCount: 0,
|
||||
totalCount: 2,
|
||||
annotators: [{ id: "1", name: "孙七", avatar: "/placeholder-user.jpg" }],
|
||||
text: "对交通场景图像进行目标检测标注",
|
||||
status: "in_progress",
|
||||
project: "目标检测",
|
||||
type: "目标检测",
|
||||
datasetType: "image",
|
||||
progress: 50,
|
||||
},
|
||||
{
|
||||
id: "12345681",
|
||||
name: "命名实体识别标注",
|
||||
completed: "2024年1月20日 20:40",
|
||||
completedCount: 1,
|
||||
skippedCount: 0,
|
||||
totalCount: 2,
|
||||
annotators: [{ id: "1", name: "周八", avatar: "/placeholder-user.jpg" }],
|
||||
text: "对新闻文本进行命名实体识别标注",
|
||||
status: "in_progress",
|
||||
project: "NER",
|
||||
type: "NER",
|
||||
datasetType: "text",
|
||||
progress: 75,
|
||||
},
|
||||
{
|
||||
id: "12345682",
|
||||
name: "语音识别标注任务",
|
||||
completed: "2024年1月20日 20:40",
|
||||
completedCount: 1,
|
||||
skippedCount: 0,
|
||||
totalCount: 2,
|
||||
annotators: [{ id: "1", name: "吴九", avatar: "/placeholder-user.jpg" }],
|
||||
text: "对语音数据进行转录和标注",
|
||||
status: "in_progress",
|
||||
project: "语音识别",
|
||||
type: "语音识别",
|
||||
datasetType: "audio",
|
||||
progress: 25,
|
||||
},
|
||||
{
|
||||
id: "12345683",
|
||||
name: "视频动作识别标注",
|
||||
completed: "2024年1月20日 20:40",
|
||||
completedCount: 0,
|
||||
skippedCount: 2,
|
||||
totalCount: 2,
|
||||
annotators: [
|
||||
{ id: "1", name: "陈十", avatar: "/placeholder-user.jpg" },
|
||||
{ id: "2", name: "林十一", avatar: "/placeholder-user.jpg" },
|
||||
],
|
||||
text: "对视频中的人体动作进行识别和标注",
|
||||
status: "skipped",
|
||||
project: "视频分析",
|
||||
type: "视频分析",
|
||||
datasetType: "video",
|
||||
progress: 0,
|
||||
},
|
||||
]
|
||||
|
||||
// Define the Template type
|
||||
type Template = {
|
||||
id: string;
|
||||
name: string;
|
||||
category: string;
|
||||
description: string;
|
||||
type: string;
|
||||
preview?: string;
|
||||
icon: React.ReactNode;
|
||||
};
|
||||
|
||||
// 扩展的预制模板数据
|
||||
export const mockTemplates: Template[] = [
|
||||
// 计算机视觉模板
|
||||
{
|
||||
id: "cv-1",
|
||||
name: "目标检测",
|
||||
category: "Computer Vision",
|
||||
description: "使用边界框标注图像中的目标对象",
|
||||
type: "image",
|
||||
preview: "/placeholder.svg?height=120&width=180&text=Object+Detection",
|
||||
icon: <Square className="w-4 h-4" />,
|
||||
},
|
||||
{
|
||||
id: "cv-2",
|
||||
name: "语义分割(多边形)",
|
||||
category: "Computer Vision",
|
||||
description: "使用多边形精确标注图像中的区域",
|
||||
type: "image",
|
||||
preview: "/placeholder.svg?height=120&width=180&text=Polygon+Segmentation",
|
||||
icon: <Layers className="w-4 h-4" />,
|
||||
},
|
||||
{
|
||||
id: "cv-3",
|
||||
name: "语义分割(掩码)",
|
||||
category: "Computer Vision",
|
||||
description: "使用像素级掩码标注图像区域",
|
||||
type: "image",
|
||||
preview: "/placeholder.svg?height=120&width=180&text=Mask+Segmentation",
|
||||
icon: <Circle className="w-4 h-4" />,
|
||||
},
|
||||
{
|
||||
id: "cv-4",
|
||||
name: "关键点标注",
|
||||
category: "Computer Vision",
|
||||
description: "标注图像中的关键点位置",
|
||||
type: "image",
|
||||
preview: "/placeholder.svg?height=120&width=180&text=Keypoint+Labeling",
|
||||
icon: <MousePointer className="w-4 h-4" />,
|
||||
},
|
||||
{
|
||||
id: "cv-5",
|
||||
name: "图像分类",
|
||||
category: "Computer Vision",
|
||||
description: "为整个图像分配类别标签",
|
||||
type: "image",
|
||||
preview: "/placeholder.svg?height=120&width=180&text=Image+Classification",
|
||||
icon: <ImageIcon className="w-4 h-4" />,
|
||||
},
|
||||
{
|
||||
id: "cv-6",
|
||||
name: "实例分割",
|
||||
category: "Computer Vision",
|
||||
description: "区分同类别的不同实例对象",
|
||||
type: "image",
|
||||
preview: "/placeholder.svg?height=120&width=180&text=Instance+Segmentation",
|
||||
icon: <Target className="w-4 h-4" />,
|
||||
},
|
||||
{
|
||||
id: "cv-7",
|
||||
name: "全景分割",
|
||||
category: "Computer Vision",
|
||||
description: "结合语义分割和实例分割的全景标注",
|
||||
type: "image",
|
||||
preview: "/placeholder.svg?height=120&width=180&text=Panoptic+Segmentation",
|
||||
icon: <Grid className="w-4 h-4" />,
|
||||
},
|
||||
{
|
||||
id: "cv-8",
|
||||
name: "3D目标检测",
|
||||
category: "Computer Vision",
|
||||
description: "在3D空间中标注目标对象的位置和方向",
|
||||
type: "image",
|
||||
preview: "/placeholder.svg?height=120&width=180&text=3D+Object+Detection",
|
||||
icon: <Maximize className="w-4 h-4" />,
|
||||
},
|
||||
{
|
||||
id: "cv-9",
|
||||
name: "图像配对",
|
||||
category: "Computer Vision",
|
||||
description: "标注图像之间的对应关系",
|
||||
type: "image",
|
||||
preview: "/placeholder.svg?height=120&width=180&text=Image+Matching",
|
||||
icon: <Move className="w-4 h-4" />,
|
||||
},
|
||||
{
|
||||
id: "cv-10",
|
||||
name: "图像质量评估",
|
||||
category: "Computer Vision",
|
||||
description: "评估和标注图像质量等级",
|
||||
type: "image",
|
||||
preview: "/placeholder.svg?height=120&width=180&text=Quality+Assessment",
|
||||
icon: <BarChart className="w-4 h-4" />,
|
||||
},
|
||||
{
|
||||
id: "cv-11",
|
||||
name: "图像裁剪标注",
|
||||
category: "Computer Vision",
|
||||
description: "标注图像中需要裁剪的区域",
|
||||
type: "image",
|
||||
preview: "/placeholder.svg?height=120&width=180&text=Image+Cropping",
|
||||
icon: <Crop className="w-4 h-4" />,
|
||||
},
|
||||
{
|
||||
id: "cv-12",
|
||||
name: "图像旋转标注",
|
||||
category: "Computer Vision",
|
||||
description: "标注图像的正确方向角度",
|
||||
type: "image",
|
||||
preview: "/placeholder.svg?height=120&width=180&text=Image+Rotation",
|
||||
icon: <RotateCcw className="w-4 h-4" />,
|
||||
},
|
||||
// 自然语言处理模板
|
||||
{
|
||||
id: "nlp-1",
|
||||
name: "文本分类",
|
||||
category: "Natural Language Processing",
|
||||
description: "为文本分配类别标签",
|
||||
type: "text",
|
||||
icon: <FileText className="w-4 h-4" />,
|
||||
},
|
||||
{
|
||||
id: "nlp-2",
|
||||
name: "命名实体识别",
|
||||
category: "Natural Language Processing",
|
||||
description: "识别和标注文本中的实体",
|
||||
type: "text",
|
||||
icon: <Tag className="w-4 h-4" />,
|
||||
},
|
||||
{
|
||||
id: "nlp-3",
|
||||
name: "情感分析",
|
||||
category: "Natural Language Processing",
|
||||
description: "标注文本的情感倾向",
|
||||
type: "text",
|
||||
icon: <Heart className="w-4 h-4" />,
|
||||
},
|
||||
{
|
||||
id: "nlp-4",
|
||||
name: "问答标注",
|
||||
category: "Natural Language Processing",
|
||||
description: "标注问题和答案对",
|
||||
type: "text",
|
||||
icon: <HelpCircle className="w-4 h-4" />,
|
||||
},
|
||||
{
|
||||
id: "nlp-5",
|
||||
name: "文本摘要",
|
||||
category: "Natural Language Processing",
|
||||
description: "为长文本创建摘要标注",
|
||||
type: "text",
|
||||
icon: <BookOpen className="w-4 h-4" />,
|
||||
},
|
||||
{
|
||||
id: "nlp-6",
|
||||
name: "对话标注",
|
||||
category: "Natural Language Processing",
|
||||
description: "标注对话中的意图和实体",
|
||||
type: "text",
|
||||
icon: <MessageSquare className="w-4 h-4" />,
|
||||
},
|
||||
{
|
||||
id: "nlp-7",
|
||||
name: "关系抽取",
|
||||
category: "Natural Language Processing",
|
||||
description: "标注实体之间的关系",
|
||||
type: "text",
|
||||
icon: <Users className="w-4 h-4" />,
|
||||
},
|
||||
{
|
||||
id: "nlp-8",
|
||||
name: "文本相似度",
|
||||
category: "Natural Language Processing",
|
||||
description: "标注文本之间的相似度",
|
||||
type: "text",
|
||||
icon: <Zap className="w-4 h-4" />,
|
||||
},
|
||||
{
|
||||
id: "nlp-9",
|
||||
name: "语言检测",
|
||||
category: "Natural Language Processing",
|
||||
description: "识别和标注文本的语言类型",
|
||||
type: "text",
|
||||
icon: <Globe className="w-4 h-4" />,
|
||||
},
|
||||
{
|
||||
id: "nlp-10",
|
||||
name: "文本纠错",
|
||||
category: "Natural Language Processing",
|
||||
description: "标注文本中的错误并提供修正",
|
||||
type: "text",
|
||||
icon: <Scissors className="w-4 h-4" />,
|
||||
},
|
||||
import { BarChart, Circle, Grid, ImageIcon, Layers, Maximize, MousePointer, Move, Square, Target, Crop, RotateCcw, FileText, Tag, Heart, HelpCircle, BookOpen, MessageSquare, Users, Zap, Globe, Scissors } from "lucide-react";
|
||||
|
||||
// Define the AnnotationTask type if not imported from elsewhere
|
||||
interface AnnotationTask {
|
||||
id: string
|
||||
name: string
|
||||
completed: string
|
||||
completedCount: number
|
||||
skippedCount: number
|
||||
totalCount: number
|
||||
annotators: Array<{
|
||||
id: string
|
||||
name: string
|
||||
avatar?: string
|
||||
}>
|
||||
text: string
|
||||
status: "completed" | "in_progress" | "pending" | "skipped"
|
||||
project: string
|
||||
type: "图像分类" | "文本分类" | "目标检测" | "NER" | "语音识别" | "视频分析"
|
||||
datasetType: "text" | "image" | "video" | "audio"
|
||||
progress: number
|
||||
}
|
||||
|
||||
|
||||
export const mockTasks: AnnotationTask[] = [
|
||||
{
|
||||
id: "12345678",
|
||||
name: "图像分类标注任务",
|
||||
completed: "2024年1月20日 20:40",
|
||||
completedCount: 1,
|
||||
skippedCount: 0,
|
||||
totalCount: 2,
|
||||
annotators: [
|
||||
{ id: "1", name: "张三", avatar: "/placeholder-user.jpg" },
|
||||
{ id: "2", name: "李四", avatar: "/placeholder-user.jpg" },
|
||||
],
|
||||
text: "对产品图像进行分类标注,包含10个类别",
|
||||
status: "completed",
|
||||
project: "图像分类",
|
||||
type: "图像分类",
|
||||
datasetType: "image",
|
||||
progress: 100,
|
||||
},
|
||||
{
|
||||
id: "12345679",
|
||||
name: "文本情感分析标注",
|
||||
completed: "2024年1月20日 20:40",
|
||||
completedCount: 2,
|
||||
skippedCount: 0,
|
||||
totalCount: 2,
|
||||
annotators: [
|
||||
{ id: "1", name: "王五", avatar: "/placeholder-user.jpg" },
|
||||
{ id: "2", name: "赵六", avatar: "/placeholder-user.jpg" },
|
||||
],
|
||||
text: "对用户评论进行情感倾向标注",
|
||||
status: "completed",
|
||||
project: "文本分类",
|
||||
type: "文本分类",
|
||||
datasetType: "text",
|
||||
progress: 100,
|
||||
},
|
||||
{
|
||||
id: "12345680",
|
||||
name: "目标检测标注任务",
|
||||
completed: "2024年1月20日 20:40",
|
||||
completedCount: 1,
|
||||
skippedCount: 0,
|
||||
totalCount: 2,
|
||||
annotators: [{ id: "1", name: "孙七", avatar: "/placeholder-user.jpg" }],
|
||||
text: "对交通场景图像进行目标检测标注",
|
||||
status: "in_progress",
|
||||
project: "目标检测",
|
||||
type: "目标检测",
|
||||
datasetType: "image",
|
||||
progress: 50,
|
||||
},
|
||||
{
|
||||
id: "12345681",
|
||||
name: "命名实体识别标注",
|
||||
completed: "2024年1月20日 20:40",
|
||||
completedCount: 1,
|
||||
skippedCount: 0,
|
||||
totalCount: 2,
|
||||
annotators: [{ id: "1", name: "周八", avatar: "/placeholder-user.jpg" }],
|
||||
text: "对新闻文本进行命名实体识别标注",
|
||||
status: "in_progress",
|
||||
project: "NER",
|
||||
type: "NER",
|
||||
datasetType: "text",
|
||||
progress: 75,
|
||||
},
|
||||
{
|
||||
id: "12345682",
|
||||
name: "语音识别标注任务",
|
||||
completed: "2024年1月20日 20:40",
|
||||
completedCount: 1,
|
||||
skippedCount: 0,
|
||||
totalCount: 2,
|
||||
annotators: [{ id: "1", name: "吴九", avatar: "/placeholder-user.jpg" }],
|
||||
text: "对语音数据进行转录和标注",
|
||||
status: "in_progress",
|
||||
project: "语音识别",
|
||||
type: "语音识别",
|
||||
datasetType: "audio",
|
||||
progress: 25,
|
||||
},
|
||||
{
|
||||
id: "12345683",
|
||||
name: "视频动作识别标注",
|
||||
completed: "2024年1月20日 20:40",
|
||||
completedCount: 0,
|
||||
skippedCount: 2,
|
||||
totalCount: 2,
|
||||
annotators: [
|
||||
{ id: "1", name: "陈十", avatar: "/placeholder-user.jpg" },
|
||||
{ id: "2", name: "林十一", avatar: "/placeholder-user.jpg" },
|
||||
],
|
||||
text: "对视频中的人体动作进行识别和标注",
|
||||
status: "skipped",
|
||||
project: "视频分析",
|
||||
type: "视频分析",
|
||||
datasetType: "video",
|
||||
progress: 0,
|
||||
},
|
||||
]
|
||||
|
||||
// Define the Template type
|
||||
type Template = {
|
||||
id: string;
|
||||
name: string;
|
||||
category: string;
|
||||
description: string;
|
||||
type: string;
|
||||
preview?: string;
|
||||
icon: React.ReactNode;
|
||||
};
|
||||
|
||||
// 扩展的预制模板数据
|
||||
export const mockTemplates: Template[] = [
|
||||
// 计算机视觉模板
|
||||
{
|
||||
id: "cv-1",
|
||||
name: "目标检测",
|
||||
category: "Computer Vision",
|
||||
description: "使用边界框标注图像中的目标对象",
|
||||
type: "image",
|
||||
preview: "/placeholder.svg?height=120&width=180&text=Object+Detection",
|
||||
icon: <Square className="w-4 h-4" />,
|
||||
},
|
||||
{
|
||||
id: "cv-2",
|
||||
name: "语义分割(多边形)",
|
||||
category: "Computer Vision",
|
||||
description: "使用多边形精确标注图像中的区域",
|
||||
type: "image",
|
||||
preview: "/placeholder.svg?height=120&width=180&text=Polygon+Segmentation",
|
||||
icon: <Layers className="w-4 h-4" />,
|
||||
},
|
||||
{
|
||||
id: "cv-3",
|
||||
name: "语义分割(掩码)",
|
||||
category: "Computer Vision",
|
||||
description: "使用像素级掩码标注图像区域",
|
||||
type: "image",
|
||||
preview: "/placeholder.svg?height=120&width=180&text=Mask+Segmentation",
|
||||
icon: <Circle className="w-4 h-4" />,
|
||||
},
|
||||
{
|
||||
id: "cv-4",
|
||||
name: "关键点标注",
|
||||
category: "Computer Vision",
|
||||
description: "标注图像中的关键点位置",
|
||||
type: "image",
|
||||
preview: "/placeholder.svg?height=120&width=180&text=Keypoint+Labeling",
|
||||
icon: <MousePointer className="w-4 h-4" />,
|
||||
},
|
||||
{
|
||||
id: "cv-5",
|
||||
name: "图像分类",
|
||||
category: "Computer Vision",
|
||||
description: "为整个图像分配类别标签",
|
||||
type: "image",
|
||||
preview: "/placeholder.svg?height=120&width=180&text=Image+Classification",
|
||||
icon: <ImageIcon className="w-4 h-4" />,
|
||||
},
|
||||
{
|
||||
id: "cv-6",
|
||||
name: "实例分割",
|
||||
category: "Computer Vision",
|
||||
description: "区分同类别的不同实例对象",
|
||||
type: "image",
|
||||
preview: "/placeholder.svg?height=120&width=180&text=Instance+Segmentation",
|
||||
icon: <Target className="w-4 h-4" />,
|
||||
},
|
||||
{
|
||||
id: "cv-7",
|
||||
name: "全景分割",
|
||||
category: "Computer Vision",
|
||||
description: "结合语义分割和实例分割的全景标注",
|
||||
type: "image",
|
||||
preview: "/placeholder.svg?height=120&width=180&text=Panoptic+Segmentation",
|
||||
icon: <Grid className="w-4 h-4" />,
|
||||
},
|
||||
{
|
||||
id: "cv-8",
|
||||
name: "3D目标检测",
|
||||
category: "Computer Vision",
|
||||
description: "在3D空间中标注目标对象的位置和方向",
|
||||
type: "image",
|
||||
preview: "/placeholder.svg?height=120&width=180&text=3D+Object+Detection",
|
||||
icon: <Maximize className="w-4 h-4" />,
|
||||
},
|
||||
{
|
||||
id: "cv-9",
|
||||
name: "图像配对",
|
||||
category: "Computer Vision",
|
||||
description: "标注图像之间的对应关系",
|
||||
type: "image",
|
||||
preview: "/placeholder.svg?height=120&width=180&text=Image+Matching",
|
||||
icon: <Move className="w-4 h-4" />,
|
||||
},
|
||||
{
|
||||
id: "cv-10",
|
||||
name: "图像质量评估",
|
||||
category: "Computer Vision",
|
||||
description: "评估和标注图像质量等级",
|
||||
type: "image",
|
||||
preview: "/placeholder.svg?height=120&width=180&text=Quality+Assessment",
|
||||
icon: <BarChart className="w-4 h-4" />,
|
||||
},
|
||||
{
|
||||
id: "cv-11",
|
||||
name: "图像裁剪标注",
|
||||
category: "Computer Vision",
|
||||
description: "标注图像中需要裁剪的区域",
|
||||
type: "image",
|
||||
preview: "/placeholder.svg?height=120&width=180&text=Image+Cropping",
|
||||
icon: <Crop className="w-4 h-4" />,
|
||||
},
|
||||
{
|
||||
id: "cv-12",
|
||||
name: "图像旋转标注",
|
||||
category: "Computer Vision",
|
||||
description: "标注图像的正确方向角度",
|
||||
type: "image",
|
||||
preview: "/placeholder.svg?height=120&width=180&text=Image+Rotation",
|
||||
icon: <RotateCcw className="w-4 h-4" />,
|
||||
},
|
||||
// 自然语言处理模板
|
||||
{
|
||||
id: "nlp-1",
|
||||
name: "文本分类",
|
||||
category: "Natural Language Processing",
|
||||
description: "为文本分配类别标签",
|
||||
type: "text",
|
||||
icon: <FileText className="w-4 h-4" />,
|
||||
},
|
||||
{
|
||||
id: "nlp-2",
|
||||
name: "命名实体识别",
|
||||
category: "Natural Language Processing",
|
||||
description: "识别和标注文本中的实体",
|
||||
type: "text",
|
||||
icon: <Tag className="w-4 h-4" />,
|
||||
},
|
||||
{
|
||||
id: "nlp-3",
|
||||
name: "情感分析",
|
||||
category: "Natural Language Processing",
|
||||
description: "标注文本的情感倾向",
|
||||
type: "text",
|
||||
icon: <Heart className="w-4 h-4" />,
|
||||
},
|
||||
{
|
||||
id: "nlp-4",
|
||||
name: "问答标注",
|
||||
category: "Natural Language Processing",
|
||||
description: "标注问题和答案对",
|
||||
type: "text",
|
||||
icon: <HelpCircle className="w-4 h-4" />,
|
||||
},
|
||||
{
|
||||
id: "nlp-5",
|
||||
name: "文本摘要",
|
||||
category: "Natural Language Processing",
|
||||
description: "为长文本创建摘要标注",
|
||||
type: "text",
|
||||
icon: <BookOpen className="w-4 h-4" />,
|
||||
},
|
||||
{
|
||||
id: "nlp-6",
|
||||
name: "对话标注",
|
||||
category: "Natural Language Processing",
|
||||
description: "标注对话中的意图和实体",
|
||||
type: "text",
|
||||
icon: <MessageSquare className="w-4 h-4" />,
|
||||
},
|
||||
{
|
||||
id: "nlp-7",
|
||||
name: "关系抽取",
|
||||
category: "Natural Language Processing",
|
||||
description: "标注实体之间的关系",
|
||||
type: "text",
|
||||
icon: <Users className="w-4 h-4" />,
|
||||
},
|
||||
{
|
||||
id: "nlp-8",
|
||||
name: "文本相似度",
|
||||
category: "Natural Language Processing",
|
||||
description: "标注文本之间的相似度",
|
||||
type: "text",
|
||||
icon: <Zap className="w-4 h-4" />,
|
||||
},
|
||||
{
|
||||
id: "nlp-9",
|
||||
name: "语言检测",
|
||||
category: "Natural Language Processing",
|
||||
description: "识别和标注文本的语言类型",
|
||||
type: "text",
|
||||
icon: <Globe className="w-4 h-4" />,
|
||||
},
|
||||
{
|
||||
id: "nlp-10",
|
||||
name: "文本纠错",
|
||||
category: "Natural Language Processing",
|
||||
description: "标注文本中的错误并提供修正",
|
||||
type: "text",
|
||||
icon: <Scissors className="w-4 h-4" />,
|
||||
},
|
||||
]
|
||||
@@ -1,290 +1,290 @@
|
||||
// 预设评估维度配置
|
||||
export const presetEvaluationDimensions: EvaluationDimension[] = [
|
||||
{
|
||||
id: "answer_relevance",
|
||||
name: "回答相关性",
|
||||
description: "评估回答内容是否针对问题,是否切中要点",
|
||||
category: "accuracy",
|
||||
isEnabled: true,
|
||||
},
|
||||
{
|
||||
id: "content_quality",
|
||||
name: "内容质量",
|
||||
description: "评估内容的准确性、完整性和可读性",
|
||||
category: "quality",
|
||||
isEnabled: true,
|
||||
},
|
||||
{
|
||||
id: "information_completeness",
|
||||
name: "信息完整性",
|
||||
description: "评估信息是否完整,无缺失关键内容",
|
||||
category: "completeness",
|
||||
isEnabled: true,
|
||||
},
|
||||
{
|
||||
id: "language_fluency",
|
||||
name: "语言流畅性",
|
||||
description: "评估语言表达是否流畅自然",
|
||||
category: "quality",
|
||||
isEnabled: true,
|
||||
},
|
||||
{
|
||||
id: "factual_accuracy",
|
||||
name: "事实准确性",
|
||||
description: "评估内容中事实信息的准确性",
|
||||
category: "accuracy",
|
||||
isEnabled: true,
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
export const sliceOperators: SliceOperator[] = [
|
||||
{
|
||||
id: "paragraph-split",
|
||||
name: "段落分割",
|
||||
description: "按段落自然分割文档",
|
||||
type: "text",
|
||||
icon: "📄",
|
||||
params: { minLength: 50, maxLength: 1000 },
|
||||
},
|
||||
{
|
||||
id: "sentence-split",
|
||||
name: "句子分割",
|
||||
description: "按句子边界分割文档",
|
||||
type: "text",
|
||||
icon: "📝",
|
||||
params: { maxSentences: 5, overlap: 1 },
|
||||
},
|
||||
{
|
||||
id: "semantic-split",
|
||||
name: "语义分割",
|
||||
description: "基于语义相似度智能分割",
|
||||
type: "semantic",
|
||||
icon: "🧠",
|
||||
params: { threshold: 0.7, windowSize: 3 },
|
||||
},
|
||||
{
|
||||
id: "length-split",
|
||||
name: "长度分割",
|
||||
description: "按固定字符长度分割",
|
||||
type: "text",
|
||||
icon: "📏",
|
||||
params: { chunkSize: 512, overlap: 50 },
|
||||
},
|
||||
{
|
||||
id: "structure-split",
|
||||
name: "结构化分割",
|
||||
description: "按文档结构(标题、章节)分割",
|
||||
type: "structure",
|
||||
icon: "🏗️",
|
||||
params: { preserveHeaders: true, minSectionLength: 100 },
|
||||
},
|
||||
{
|
||||
id: "table-extract",
|
||||
name: "表格提取",
|
||||
description: "提取并单独处理表格内容",
|
||||
type: "structure",
|
||||
icon: "📊",
|
||||
params: { includeHeaders: true, mergeRows: false },
|
||||
},
|
||||
{
|
||||
id: "code-extract",
|
||||
name: "代码提取",
|
||||
description: "识别并提取代码块",
|
||||
type: "custom",
|
||||
icon: "💻",
|
||||
params: { languages: ["python", "javascript", "sql"], preserveIndentation: true },
|
||||
},
|
||||
{
|
||||
id: "qa-extract",
|
||||
name: "问答提取",
|
||||
description: "自动识别问答格式内容",
|
||||
type: "semantic",
|
||||
icon: "❓",
|
||||
params: { confidenceThreshold: 0.8, generateAnswers: true },
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
export const mockTasks: EvaluationTask[] = [
|
||||
{
|
||||
id: "1",
|
||||
name: "客服对话数据质量评估",
|
||||
datasetId: "1",
|
||||
datasetName: "客服对话数据集",
|
||||
evaluationType: "model",
|
||||
status: "completed",
|
||||
score: 85,
|
||||
progress: 100,
|
||||
createdAt: "2024-01-15 14:30",
|
||||
completedAt: "2024-01-15 14:45",
|
||||
description: "评估客服对话数据的质量,包括对话完整性、回复准确性等维度",
|
||||
dimensions: ["answer_relevance", "content_quality", "information_completeness"],
|
||||
customDimensions: [],
|
||||
sliceConfig: {
|
||||
threshold: 0.8,
|
||||
sampleCount: 100,
|
||||
method: "语义分割",
|
||||
},
|
||||
modelConfig: {
|
||||
url: "https://api.openai.com/v1/chat/completions",
|
||||
apiKey: "sk-***",
|
||||
prompt: "请从数据质量、标签准确性、标注一致性三个维度评估这个客服对话数据集...",
|
||||
temperature: 0.3,
|
||||
maxTokens: 2000,
|
||||
},
|
||||
metrics: {
|
||||
accuracy: 88,
|
||||
completeness: 92,
|
||||
consistency: 78,
|
||||
relevance: 85,
|
||||
},
|
||||
issues: [
|
||||
{ type: "重复数据", count: 23, severity: "medium" },
|
||||
{ type: "格式错误", count: 5, severity: "high" },
|
||||
{ type: "内容不完整", count: 12, severity: "low" },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
name: "产品评论人工评估",
|
||||
datasetId: "2",
|
||||
datasetName: "产品评论数据集",
|
||||
evaluationType: "manual",
|
||||
status: "pending",
|
||||
progress: 0,
|
||||
createdAt: "2024-01-15 15:20",
|
||||
description: "人工评估产品评论数据的情感标注准确性",
|
||||
dimensions: ["content_quality", "factual_accuracy"],
|
||||
customDimensions: [
|
||||
{
|
||||
id: "custom_1",
|
||||
name: "情感极性准确性",
|
||||
description: "评估情感标注的极性(正面/负面/中性)准确性",
|
||||
category: "custom",
|
||||
isCustom: true,
|
||||
isEnabled: true,
|
||||
},
|
||||
],
|
||||
sliceConfig: {
|
||||
threshold: 0.7,
|
||||
sampleCount: 50,
|
||||
method: "段落分割",
|
||||
},
|
||||
metrics: {
|
||||
accuracy: 0,
|
||||
completeness: 0,
|
||||
consistency: 0,
|
||||
relevance: 0,
|
||||
},
|
||||
issues: [],
|
||||
},
|
||||
{
|
||||
id: "3",
|
||||
name: "新闻分类数据评估",
|
||||
datasetId: "4",
|
||||
datasetName: "新闻分类数据集",
|
||||
evaluationType: "manual",
|
||||
status: "running",
|
||||
progress: 65,
|
||||
createdAt: "2024-01-15 16:10",
|
||||
description: "人工评估新闻分类数据集的标注质量",
|
||||
dimensions: ["content_quality", "information_completeness", "factual_accuracy"],
|
||||
customDimensions: [],
|
||||
sliceConfig: {
|
||||
threshold: 0.9,
|
||||
sampleCount: 80,
|
||||
method: "句子分割",
|
||||
},
|
||||
metrics: {
|
||||
accuracy: 82,
|
||||
completeness: 78,
|
||||
consistency: 85,
|
||||
relevance: 80,
|
||||
},
|
||||
issues: [{ type: "标注不一致", count: 15, severity: "medium" }],
|
||||
},
|
||||
]
|
||||
|
||||
// 模拟QA对数据
|
||||
export const mockQAPairs: QAPair[] = [
|
||||
{
|
||||
id: "qa_1",
|
||||
question: "这个产品的退货政策是什么?",
|
||||
answer: "我们提供7天无理由退货服务,商品需要保持原包装完整。",
|
||||
sliceId: "slice_1",
|
||||
score: 4.5,
|
||||
feedback: "回答准确且完整",
|
||||
},
|
||||
{
|
||||
id: "qa_2",
|
||||
question: "如何联系客服?",
|
||||
answer: "您可以通过在线客服、电话400-123-4567或邮箱service@company.com联系我们。",
|
||||
sliceId: "slice_2",
|
||||
score: 5.0,
|
||||
feedback: "提供了多种联系方式,非常全面",
|
||||
},
|
||||
{
|
||||
id: "qa_3",
|
||||
question: "配送时间需要多久?",
|
||||
answer: "一般情况下,我们会在1-3个工作日内发货,配送时间根据地区不同为2-7天。",
|
||||
sliceId: "slice_3",
|
||||
score: 4.0,
|
||||
feedback: "时间范围说明清楚",
|
||||
},
|
||||
]
|
||||
// 评估维度模板配置
|
||||
export const evaluationTemplates = {
|
||||
dialogue_text: {
|
||||
name: "对话文本评估",
|
||||
dimensions: [
|
||||
{
|
||||
id: "answer_relevance",
|
||||
name: "回答是否有针对性",
|
||||
description: "评估回答内容是否针对问题,是否切中要点",
|
||||
category: "accuracy" as const,
|
||||
isEnabled: true,
|
||||
},
|
||||
{
|
||||
id: "question_correctness",
|
||||
name: "问题是否正确",
|
||||
description: "评估问题表述是否清晰、准确、合理",
|
||||
category: "quality" as const,
|
||||
isEnabled: true,
|
||||
},
|
||||
{
|
||||
id: "answer_independence",
|
||||
name: "回答是否独立",
|
||||
description: "评估回答是否独立完整,不依赖外部信息",
|
||||
category: "completeness" as const,
|
||||
isEnabled: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
data_quality: {
|
||||
name: "数据质量评估",
|
||||
dimensions: [
|
||||
{
|
||||
id: "data_quality",
|
||||
name: "数据质量",
|
||||
description: "评估数据的整体质量,包括格式规范性、完整性等",
|
||||
category: "quality" as const,
|
||||
isEnabled: true,
|
||||
},
|
||||
{
|
||||
id: "label_accuracy",
|
||||
name: "标签准确性",
|
||||
description: "评估数据标签的准确性和一致性",
|
||||
category: "accuracy" as const,
|
||||
isEnabled: true,
|
||||
},
|
||||
{
|
||||
id: "data_completeness",
|
||||
name: "数据完整性",
|
||||
description: "评估数据集的完整性,是否存在缺失数据",
|
||||
category: "completeness" as const,
|
||||
isEnabled: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
// 预设评估维度配置
|
||||
export const presetEvaluationDimensions: EvaluationDimension[] = [
|
||||
{
|
||||
id: "answer_relevance",
|
||||
name: "回答相关性",
|
||||
description: "评估回答内容是否针对问题,是否切中要点",
|
||||
category: "accuracy",
|
||||
isEnabled: true,
|
||||
},
|
||||
{
|
||||
id: "content_quality",
|
||||
name: "内容质量",
|
||||
description: "评估内容的准确性、完整性和可读性",
|
||||
category: "quality",
|
||||
isEnabled: true,
|
||||
},
|
||||
{
|
||||
id: "information_completeness",
|
||||
name: "信息完整性",
|
||||
description: "评估信息是否完整,无缺失关键内容",
|
||||
category: "completeness",
|
||||
isEnabled: true,
|
||||
},
|
||||
{
|
||||
id: "language_fluency",
|
||||
name: "语言流畅性",
|
||||
description: "评估语言表达是否流畅自然",
|
||||
category: "quality",
|
||||
isEnabled: true,
|
||||
},
|
||||
{
|
||||
id: "factual_accuracy",
|
||||
name: "事实准确性",
|
||||
description: "评估内容中事实信息的准确性",
|
||||
category: "accuracy",
|
||||
isEnabled: true,
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
export const sliceOperators: SliceOperator[] = [
|
||||
{
|
||||
id: "paragraph-split",
|
||||
name: "段落分割",
|
||||
description: "按段落自然分割文档",
|
||||
type: "text",
|
||||
icon: "📄",
|
||||
params: { minLength: 50, maxLength: 1000 },
|
||||
},
|
||||
{
|
||||
id: "sentence-split",
|
||||
name: "句子分割",
|
||||
description: "按句子边界分割文档",
|
||||
type: "text",
|
||||
icon: "📝",
|
||||
params: { maxSentences: 5, overlap: 1 },
|
||||
},
|
||||
{
|
||||
id: "semantic-split",
|
||||
name: "语义分割",
|
||||
description: "基于语义相似度智能分割",
|
||||
type: "semantic",
|
||||
icon: "🧠",
|
||||
params: { threshold: 0.7, windowSize: 3 },
|
||||
},
|
||||
{
|
||||
id: "length-split",
|
||||
name: "长度分割",
|
||||
description: "按固定字符长度分割",
|
||||
type: "text",
|
||||
icon: "📏",
|
||||
params: { chunkSize: 512, overlap: 50 },
|
||||
},
|
||||
{
|
||||
id: "structure-split",
|
||||
name: "结构化分割",
|
||||
description: "按文档结构(标题、章节)分割",
|
||||
type: "structure",
|
||||
icon: "🏗️",
|
||||
params: { preserveHeaders: true, minSectionLength: 100 },
|
||||
},
|
||||
{
|
||||
id: "table-extract",
|
||||
name: "表格提取",
|
||||
description: "提取并单独处理表格内容",
|
||||
type: "structure",
|
||||
icon: "📊",
|
||||
params: { includeHeaders: true, mergeRows: false },
|
||||
},
|
||||
{
|
||||
id: "code-extract",
|
||||
name: "代码提取",
|
||||
description: "识别并提取代码块",
|
||||
type: "custom",
|
||||
icon: "💻",
|
||||
params: { languages: ["python", "javascript", "sql"], preserveIndentation: true },
|
||||
},
|
||||
{
|
||||
id: "qa-extract",
|
||||
name: "问答提取",
|
||||
description: "自动识别问答格式内容",
|
||||
type: "semantic",
|
||||
icon: "❓",
|
||||
params: { confidenceThreshold: 0.8, generateAnswers: true },
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
export const mockTasks: EvaluationTask[] = [
|
||||
{
|
||||
id: "1",
|
||||
name: "客服对话数据质量评估",
|
||||
datasetId: "1",
|
||||
datasetName: "客服对话数据集",
|
||||
evaluationType: "model",
|
||||
status: "completed",
|
||||
score: 85,
|
||||
progress: 100,
|
||||
createdAt: "2024-01-15 14:30",
|
||||
completedAt: "2024-01-15 14:45",
|
||||
description: "评估客服对话数据的质量,包括对话完整性、回复准确性等维度",
|
||||
dimensions: ["answer_relevance", "content_quality", "information_completeness"],
|
||||
customDimensions: [],
|
||||
sliceConfig: {
|
||||
threshold: 0.8,
|
||||
sampleCount: 100,
|
||||
method: "语义分割",
|
||||
},
|
||||
modelConfig: {
|
||||
url: "https://api.openai.com/v1/chat/completions",
|
||||
apiKey: "sk-***",
|
||||
prompt: "请从数据质量、标签准确性、标注一致性三个维度评估这个客服对话数据集...",
|
||||
temperature: 0.3,
|
||||
maxTokens: 2000,
|
||||
},
|
||||
metrics: {
|
||||
accuracy: 88,
|
||||
completeness: 92,
|
||||
consistency: 78,
|
||||
relevance: 85,
|
||||
},
|
||||
issues: [
|
||||
{ type: "重复数据", count: 23, severity: "medium" },
|
||||
{ type: "格式错误", count: 5, severity: "high" },
|
||||
{ type: "内容不完整", count: 12, severity: "low" },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
name: "产品评论人工评估",
|
||||
datasetId: "2",
|
||||
datasetName: "产品评论数据集",
|
||||
evaluationType: "manual",
|
||||
status: "pending",
|
||||
progress: 0,
|
||||
createdAt: "2024-01-15 15:20",
|
||||
description: "人工评估产品评论数据的情感标注准确性",
|
||||
dimensions: ["content_quality", "factual_accuracy"],
|
||||
customDimensions: [
|
||||
{
|
||||
id: "custom_1",
|
||||
name: "情感极性准确性",
|
||||
description: "评估情感标注的极性(正面/负面/中性)准确性",
|
||||
category: "custom",
|
||||
isCustom: true,
|
||||
isEnabled: true,
|
||||
},
|
||||
],
|
||||
sliceConfig: {
|
||||
threshold: 0.7,
|
||||
sampleCount: 50,
|
||||
method: "段落分割",
|
||||
},
|
||||
metrics: {
|
||||
accuracy: 0,
|
||||
completeness: 0,
|
||||
consistency: 0,
|
||||
relevance: 0,
|
||||
},
|
||||
issues: [],
|
||||
},
|
||||
{
|
||||
id: "3",
|
||||
name: "新闻分类数据评估",
|
||||
datasetId: "4",
|
||||
datasetName: "新闻分类数据集",
|
||||
evaluationType: "manual",
|
||||
status: "running",
|
||||
progress: 65,
|
||||
createdAt: "2024-01-15 16:10",
|
||||
description: "人工评估新闻分类数据集的标注质量",
|
||||
dimensions: ["content_quality", "information_completeness", "factual_accuracy"],
|
||||
customDimensions: [],
|
||||
sliceConfig: {
|
||||
threshold: 0.9,
|
||||
sampleCount: 80,
|
||||
method: "句子分割",
|
||||
},
|
||||
metrics: {
|
||||
accuracy: 82,
|
||||
completeness: 78,
|
||||
consistency: 85,
|
||||
relevance: 80,
|
||||
},
|
||||
issues: [{ type: "标注不一致", count: 15, severity: "medium" }],
|
||||
},
|
||||
]
|
||||
|
||||
// 模拟QA对数据
|
||||
export const mockQAPairs: QAPair[] = [
|
||||
{
|
||||
id: "qa_1",
|
||||
question: "这个产品的退货政策是什么?",
|
||||
answer: "我们提供7天无理由退货服务,商品需要保持原包装完整。",
|
||||
sliceId: "slice_1",
|
||||
score: 4.5,
|
||||
feedback: "回答准确且完整",
|
||||
},
|
||||
{
|
||||
id: "qa_2",
|
||||
question: "如何联系客服?",
|
||||
answer: "您可以通过在线客服、电话400-123-4567或邮箱service@company.com联系我们。",
|
||||
sliceId: "slice_2",
|
||||
score: 5.0,
|
||||
feedback: "提供了多种联系方式,非常全面",
|
||||
},
|
||||
{
|
||||
id: "qa_3",
|
||||
question: "配送时间需要多久?",
|
||||
answer: "一般情况下,我们会在1-3个工作日内发货,配送时间根据地区不同为2-7天。",
|
||||
sliceId: "slice_3",
|
||||
score: 4.0,
|
||||
feedback: "时间范围说明清楚",
|
||||
},
|
||||
]
|
||||
// 评估维度模板配置
|
||||
export const evaluationTemplates = {
|
||||
dialogue_text: {
|
||||
name: "对话文本评估",
|
||||
dimensions: [
|
||||
{
|
||||
id: "answer_relevance",
|
||||
name: "回答是否有针对性",
|
||||
description: "评估回答内容是否针对问题,是否切中要点",
|
||||
category: "accuracy" as const,
|
||||
isEnabled: true,
|
||||
},
|
||||
{
|
||||
id: "question_correctness",
|
||||
name: "问题是否正确",
|
||||
description: "评估问题表述是否清晰、准确、合理",
|
||||
category: "quality" as const,
|
||||
isEnabled: true,
|
||||
},
|
||||
{
|
||||
id: "answer_independence",
|
||||
name: "回答是否独立",
|
||||
description: "评估回答是否独立完整,不依赖外部信息",
|
||||
category: "completeness" as const,
|
||||
isEnabled: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
data_quality: {
|
||||
name: "数据质量评估",
|
||||
dimensions: [
|
||||
{
|
||||
id: "data_quality",
|
||||
name: "数据质量",
|
||||
description: "评估数据的整体质量,包括格式规范性、完整性等",
|
||||
category: "quality" as const,
|
||||
isEnabled: true,
|
||||
},
|
||||
{
|
||||
id: "label_accuracy",
|
||||
name: "标签准确性",
|
||||
description: "评估数据标签的准确性和一致性",
|
||||
category: "accuracy" as const,
|
||||
isEnabled: true,
|
||||
},
|
||||
{
|
||||
id: "data_completeness",
|
||||
name: "数据完整性",
|
||||
description: "评估数据集的完整性,是否存在缺失数据",
|
||||
category: "completeness" as const,
|
||||
isEnabled: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
@@ -1,254 +1,254 @@
|
||||
export const mockChunks = Array.from({ length: 23 }, (_, i) => ({
|
||||
id: i + 1,
|
||||
content: `这是第 ${
|
||||
i + 1
|
||||
} 个文档分块的内容示例。在实际应用中,这里会显示从原始文档中提取和分割的具体文本内容。用户可以在这里查看和编辑分块的内容,确保知识库的质量和准确性。这个分块包含了重要的业务信息和技术细节,需要仔细维护以确保检索的准确性。`,
|
||||
position: i + 1,
|
||||
tokens: Math.floor(Math.random() * 200) + 100,
|
||||
embedding: Array.from({ length: 1536 }, () => Math.random() - 0.5),
|
||||
similarity: (Math.random() * 0.3 + 0.7).toFixed(3),
|
||||
createdAt: "2024-01-22 10:35",
|
||||
updatedAt: "2024-01-22 10:35",
|
||||
vectorId: `vec_${i + 1}_${Math.random().toString(36).substr(2, 9)}`,
|
||||
sliceOperator: ["semantic-split", "paragraph-split", "table-extract"][
|
||||
Math.floor(Math.random() * 3)
|
||||
],
|
||||
parentChunkId: i > 0 ? Math.floor(Math.random() * i) + 1 : undefined,
|
||||
metadata: {
|
||||
source: "API文档.pdf",
|
||||
page: Math.floor(i / 5) + 1,
|
||||
section: `第${Math.floor(i / 3) + 1}章`,
|
||||
},
|
||||
}));
|
||||
|
||||
export const mockQAPairs = [
|
||||
{
|
||||
id: 1,
|
||||
question: "什么是API文档的主要用途?",
|
||||
answer:
|
||||
"API文档的主要用途是为开发者提供详细的接口说明,包括请求参数、响应格式和使用示例.",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
question: "如何正确使用这个API?",
|
||||
answer:
|
||||
"使用API时需要先获取访问令牌,然后按照文档中的格式发送请求,注意处理错误响应.",
|
||||
},
|
||||
];
|
||||
|
||||
export const sliceOperators: SliceOperator[] = [
|
||||
{
|
||||
id: "paragraph-split",
|
||||
name: "段落分割",
|
||||
description: "按段落自然分割文档",
|
||||
type: "text",
|
||||
icon: "📄",
|
||||
params: { minLength: 50, maxLength: 1000 },
|
||||
},
|
||||
{
|
||||
id: "sentence-split",
|
||||
name: "句子分割",
|
||||
description: "按句子边界分割文档",
|
||||
type: "text",
|
||||
icon: "📝",
|
||||
params: { maxSentences: 5, overlap: 1 },
|
||||
},
|
||||
{
|
||||
id: "semantic-split",
|
||||
name: "语义分割",
|
||||
description: "基于语义相似度智能分割",
|
||||
type: "semantic",
|
||||
icon: "🧠",
|
||||
params: { threshold: 0.7, windowSize: 3 },
|
||||
},
|
||||
{
|
||||
id: "length-split",
|
||||
name: "长度分割",
|
||||
description: "按固定字符长度分割",
|
||||
type: "text",
|
||||
icon: "📏",
|
||||
params: { chunkSize: 512, overlap: 50 },
|
||||
},
|
||||
{
|
||||
id: "structure-split",
|
||||
name: "结构化分割",
|
||||
description: "按文档结构(标题、章节)分割",
|
||||
type: "structure",
|
||||
icon: "🏗️",
|
||||
params: { preserveHeaders: true, minSectionLength: 100 },
|
||||
},
|
||||
{
|
||||
id: "table-extract",
|
||||
name: "表格提取",
|
||||
description: "提取并单独处理表格内容",
|
||||
type: "structure",
|
||||
icon: "📊",
|
||||
params: { includeHeaders: true, mergeRows: false },
|
||||
},
|
||||
{
|
||||
id: "code-extract",
|
||||
name: "代码提取",
|
||||
description: "识别并提取代码块",
|
||||
type: "custom",
|
||||
icon: "💻",
|
||||
params: {
|
||||
languages: ["python", "javascript", "sql"],
|
||||
preserveIndentation: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "qa-extract",
|
||||
name: "问答提取",
|
||||
description: "自动识别问答格式内容",
|
||||
type: "semantic",
|
||||
icon: "❓",
|
||||
params: { confidenceThreshold: 0.8, generateAnswers: true },
|
||||
},
|
||||
];
|
||||
|
||||
export const vectorDatabases = [
|
||||
{
|
||||
id: "pinecone",
|
||||
name: "Pinecone",
|
||||
description: "云端向量数据库,高性能检索",
|
||||
},
|
||||
{
|
||||
id: "weaviate",
|
||||
name: "Weaviate",
|
||||
description: "开源向量数据库,支持多模态",
|
||||
},
|
||||
{ id: "qdrant", name: "Qdrant", description: "高性能向量搜索引擎" },
|
||||
{ id: "chroma", name: "ChromaDB", description: "轻量级向量数据库" },
|
||||
{ id: "milvus", name: "Milvus", description: "分布式向量数据库" },
|
||||
{ id: "faiss", name: "FAISS", description: "Facebook AI 相似性搜索库" },
|
||||
];
|
||||
|
||||
export const mockKnowledgeBases: KnowledgeBase[] = [
|
||||
{
|
||||
id: 1,
|
||||
name: "产品技术文档库",
|
||||
description:
|
||||
"包含所有产品相关的技术文档和API说明,支持多种格式文档的智能解析和向量化处理",
|
||||
type: "unstructured",
|
||||
status: "ready",
|
||||
fileCount: 45,
|
||||
chunkCount: 1250,
|
||||
vectorCount: 1250,
|
||||
size: "2.3 GB",
|
||||
progress: 100,
|
||||
createdAt: "2024-01-15",
|
||||
lastUpdated: "2024-01-22",
|
||||
vectorDatabase: "pinecone",
|
||||
config: {
|
||||
embeddingModel: "text-embedding-3-large",
|
||||
llmModel: "gpt-4o",
|
||||
chunkSize: 512,
|
||||
overlap: 50,
|
||||
sliceMethod: "semantic",
|
||||
enableQA: true,
|
||||
vectorDimension: 1536,
|
||||
sliceOperators: ["semantic-split", "paragraph-split", "table-extract"],
|
||||
},
|
||||
files: [
|
||||
{
|
||||
id: 1,
|
||||
name: "API文档.pdf",
|
||||
type: "pdf",
|
||||
size: "2.5 MB",
|
||||
status: "completed",
|
||||
chunkCount: 156,
|
||||
progress: 100,
|
||||
uploadedAt: "2024-01-15",
|
||||
source: "upload",
|
||||
vectorizationStatus: "completed",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: "用户手册.docx",
|
||||
type: "docx",
|
||||
size: "1.8 MB",
|
||||
status: "disabled",
|
||||
chunkCount: 89,
|
||||
progress: 65,
|
||||
uploadedAt: "2024-01-22",
|
||||
source: "dataset",
|
||||
datasetId: "dataset-1",
|
||||
vectorizationStatus: "failed",
|
||||
},
|
||||
],
|
||||
vectorizationHistory: [
|
||||
{
|
||||
id: 1,
|
||||
timestamp: "2024-01-22 14:30:00",
|
||||
operation: "create",
|
||||
fileId: 1,
|
||||
fileName: "API文档.pdf",
|
||||
chunksProcessed: 156,
|
||||
vectorsGenerated: 156,
|
||||
status: "success",
|
||||
duration: "2m 15s",
|
||||
config: {
|
||||
embeddingModel: "text-embedding-3-large",
|
||||
chunkSize: 512,
|
||||
sliceMethod: "semantic",
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
timestamp: "2024-01-22 15:45:00",
|
||||
operation: "update",
|
||||
fileId: 2,
|
||||
fileName: "用户手册.docx",
|
||||
chunksProcessed: 89,
|
||||
vectorsGenerated: 0,
|
||||
status: "failed",
|
||||
duration: "0m 45s",
|
||||
config: {
|
||||
embeddingModel: "text-embedding-3-large",
|
||||
chunkSize: 512,
|
||||
sliceMethod: "semantic",
|
||||
},
|
||||
error: "向量化服务连接超时",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: "FAQ结构化知识库",
|
||||
description: "客服常见问题的结构化问答对,支持快速检索和智能匹配",
|
||||
type: "structured",
|
||||
status: "vectorizing",
|
||||
fileCount: 12,
|
||||
chunkCount: 890,
|
||||
vectorCount: 750,
|
||||
size: "156 MB",
|
||||
progress: 75,
|
||||
createdAt: "2024-01-20",
|
||||
lastUpdated: "2024-01-23",
|
||||
vectorDatabase: "weaviate",
|
||||
config: {
|
||||
embeddingModel: "text-embedding-ada-002",
|
||||
chunkSize: 256,
|
||||
overlap: 0,
|
||||
sliceMethod: "paragraph",
|
||||
enableQA: false,
|
||||
vectorDimension: 1536,
|
||||
sliceOperators: ["qa-extract", "paragraph-split"],
|
||||
},
|
||||
files: [
|
||||
{
|
||||
id: 3,
|
||||
name: "FAQ模板.xlsx",
|
||||
type: "xlsx",
|
||||
size: "450 KB",
|
||||
status: "vectorizing",
|
||||
chunkCount: 234,
|
||||
progress: 75,
|
||||
uploadedAt: "2024-01-20",
|
||||
source: "upload",
|
||||
vectorizationStatus: "processing",
|
||||
},
|
||||
],
|
||||
vectorizationHistory: [],
|
||||
},
|
||||
];
|
||||
export const mockChunks = Array.from({ length: 23 }, (_, i) => ({
|
||||
id: i + 1,
|
||||
content: `这是第 ${
|
||||
i + 1
|
||||
} 个文档分块的内容示例。在实际应用中,这里会显示从原始文档中提取和分割的具体文本内容。用户可以在这里查看和编辑分块的内容,确保知识库的质量和准确性。这个分块包含了重要的业务信息和技术细节,需要仔细维护以确保检索的准确性。`,
|
||||
position: i + 1,
|
||||
tokens: Math.floor(Math.random() * 200) + 100,
|
||||
embedding: Array.from({ length: 1536 }, () => Math.random() - 0.5),
|
||||
similarity: (Math.random() * 0.3 + 0.7).toFixed(3),
|
||||
createdAt: "2024-01-22 10:35",
|
||||
updatedAt: "2024-01-22 10:35",
|
||||
vectorId: `vec_${i + 1}_${Math.random().toString(36).substr(2, 9)}`,
|
||||
sliceOperator: ["semantic-split", "paragraph-split", "table-extract"][
|
||||
Math.floor(Math.random() * 3)
|
||||
],
|
||||
parentChunkId: i > 0 ? Math.floor(Math.random() * i) + 1 : undefined,
|
||||
metadata: {
|
||||
source: "API文档.pdf",
|
||||
page: Math.floor(i / 5) + 1,
|
||||
section: `第${Math.floor(i / 3) + 1}章`,
|
||||
},
|
||||
}));
|
||||
|
||||
export const mockQAPairs = [
|
||||
{
|
||||
id: 1,
|
||||
question: "什么是API文档的主要用途?",
|
||||
answer:
|
||||
"API文档的主要用途是为开发者提供详细的接口说明,包括请求参数、响应格式和使用示例.",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
question: "如何正确使用这个API?",
|
||||
answer:
|
||||
"使用API时需要先获取访问令牌,然后按照文档中的格式发送请求,注意处理错误响应.",
|
||||
},
|
||||
];
|
||||
|
||||
export const sliceOperators: SliceOperator[] = [
|
||||
{
|
||||
id: "paragraph-split",
|
||||
name: "段落分割",
|
||||
description: "按段落自然分割文档",
|
||||
type: "text",
|
||||
icon: "📄",
|
||||
params: { minLength: 50, maxLength: 1000 },
|
||||
},
|
||||
{
|
||||
id: "sentence-split",
|
||||
name: "句子分割",
|
||||
description: "按句子边界分割文档",
|
||||
type: "text",
|
||||
icon: "📝",
|
||||
params: { maxSentences: 5, overlap: 1 },
|
||||
},
|
||||
{
|
||||
id: "semantic-split",
|
||||
name: "语义分割",
|
||||
description: "基于语义相似度智能分割",
|
||||
type: "semantic",
|
||||
icon: "🧠",
|
||||
params: { threshold: 0.7, windowSize: 3 },
|
||||
},
|
||||
{
|
||||
id: "length-split",
|
||||
name: "长度分割",
|
||||
description: "按固定字符长度分割",
|
||||
type: "text",
|
||||
icon: "📏",
|
||||
params: { chunkSize: 512, overlap: 50 },
|
||||
},
|
||||
{
|
||||
id: "structure-split",
|
||||
name: "结构化分割",
|
||||
description: "按文档结构(标题、章节)分割",
|
||||
type: "structure",
|
||||
icon: "🏗️",
|
||||
params: { preserveHeaders: true, minSectionLength: 100 },
|
||||
},
|
||||
{
|
||||
id: "table-extract",
|
||||
name: "表格提取",
|
||||
description: "提取并单独处理表格内容",
|
||||
type: "structure",
|
||||
icon: "📊",
|
||||
params: { includeHeaders: true, mergeRows: false },
|
||||
},
|
||||
{
|
||||
id: "code-extract",
|
||||
name: "代码提取",
|
||||
description: "识别并提取代码块",
|
||||
type: "custom",
|
||||
icon: "💻",
|
||||
params: {
|
||||
languages: ["python", "javascript", "sql"],
|
||||
preserveIndentation: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "qa-extract",
|
||||
name: "问答提取",
|
||||
description: "自动识别问答格式内容",
|
||||
type: "semantic",
|
||||
icon: "❓",
|
||||
params: { confidenceThreshold: 0.8, generateAnswers: true },
|
||||
},
|
||||
];
|
||||
|
||||
export const vectorDatabases = [
|
||||
{
|
||||
id: "pinecone",
|
||||
name: "Pinecone",
|
||||
description: "云端向量数据库,高性能检索",
|
||||
},
|
||||
{
|
||||
id: "weaviate",
|
||||
name: "Weaviate",
|
||||
description: "开源向量数据库,支持多模态",
|
||||
},
|
||||
{ id: "qdrant", name: "Qdrant", description: "高性能向量搜索引擎" },
|
||||
{ id: "chroma", name: "ChromaDB", description: "轻量级向量数据库" },
|
||||
{ id: "milvus", name: "Milvus", description: "分布式向量数据库" },
|
||||
{ id: "faiss", name: "FAISS", description: "Facebook AI 相似性搜索库" },
|
||||
];
|
||||
|
||||
export const mockKnowledgeBases: KnowledgeBase[] = [
|
||||
{
|
||||
id: 1,
|
||||
name: "产品技术文档库",
|
||||
description:
|
||||
"包含所有产品相关的技术文档和API说明,支持多种格式文档的智能解析和向量化处理",
|
||||
type: "unstructured",
|
||||
status: "ready",
|
||||
fileCount: 45,
|
||||
chunkCount: 1250,
|
||||
vectorCount: 1250,
|
||||
size: "2.3 GB",
|
||||
progress: 100,
|
||||
createdAt: "2024-01-15",
|
||||
lastUpdated: "2024-01-22",
|
||||
vectorDatabase: "pinecone",
|
||||
config: {
|
||||
embeddingModel: "text-embedding-3-large",
|
||||
llmModel: "gpt-4o",
|
||||
chunkSize: 512,
|
||||
overlap: 50,
|
||||
sliceMethod: "semantic",
|
||||
enableQA: true,
|
||||
vectorDimension: 1536,
|
||||
sliceOperators: ["semantic-split", "paragraph-split", "table-extract"],
|
||||
},
|
||||
files: [
|
||||
{
|
||||
id: 1,
|
||||
name: "API文档.pdf",
|
||||
type: "pdf",
|
||||
size: "2.5 MB",
|
||||
status: "completed",
|
||||
chunkCount: 156,
|
||||
progress: 100,
|
||||
uploadedAt: "2024-01-15",
|
||||
source: "upload",
|
||||
vectorizationStatus: "completed",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: "用户手册.docx",
|
||||
type: "docx",
|
||||
size: "1.8 MB",
|
||||
status: "disabled",
|
||||
chunkCount: 89,
|
||||
progress: 65,
|
||||
uploadedAt: "2024-01-22",
|
||||
source: "dataset",
|
||||
datasetId: "dataset-1",
|
||||
vectorizationStatus: "failed",
|
||||
},
|
||||
],
|
||||
vectorizationHistory: [
|
||||
{
|
||||
id: 1,
|
||||
timestamp: "2024-01-22 14:30:00",
|
||||
operation: "create",
|
||||
fileId: 1,
|
||||
fileName: "API文档.pdf",
|
||||
chunksProcessed: 156,
|
||||
vectorsGenerated: 156,
|
||||
status: "success",
|
||||
duration: "2m 15s",
|
||||
config: {
|
||||
embeddingModel: "text-embedding-3-large",
|
||||
chunkSize: 512,
|
||||
sliceMethod: "semantic",
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
timestamp: "2024-01-22 15:45:00",
|
||||
operation: "update",
|
||||
fileId: 2,
|
||||
fileName: "用户手册.docx",
|
||||
chunksProcessed: 89,
|
||||
vectorsGenerated: 0,
|
||||
status: "failed",
|
||||
duration: "0m 45s",
|
||||
config: {
|
||||
embeddingModel: "text-embedding-3-large",
|
||||
chunkSize: 512,
|
||||
sliceMethod: "semantic",
|
||||
},
|
||||
error: "向量化服务连接超时",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: "FAQ结构化知识库",
|
||||
description: "客服常见问题的结构化问答对,支持快速检索和智能匹配",
|
||||
type: "structured",
|
||||
status: "vectorizing",
|
||||
fileCount: 12,
|
||||
chunkCount: 890,
|
||||
vectorCount: 750,
|
||||
size: "156 MB",
|
||||
progress: 75,
|
||||
createdAt: "2024-01-20",
|
||||
lastUpdated: "2024-01-23",
|
||||
vectorDatabase: "weaviate",
|
||||
config: {
|
||||
embeddingModel: "text-embedding-ada-002",
|
||||
chunkSize: 256,
|
||||
overlap: 0,
|
||||
sliceMethod: "paragraph",
|
||||
enableQA: false,
|
||||
vectorDimension: 1536,
|
||||
sliceOperators: ["qa-extract", "paragraph-split"],
|
||||
},
|
||||
files: [
|
||||
{
|
||||
id: 3,
|
||||
name: "FAQ模板.xlsx",
|
||||
type: "xlsx",
|
||||
size: "450 KB",
|
||||
status: "vectorizing",
|
||||
chunkCount: 234,
|
||||
progress: 75,
|
||||
uploadedAt: "2024-01-20",
|
||||
source: "upload",
|
||||
vectorizationStatus: "processing",
|
||||
},
|
||||
],
|
||||
vectorizationHistory: [],
|
||||
},
|
||||
];
|
||||
|
||||
@@ -1,167 +1,167 @@
|
||||
const { addMockPrefix } = require("./mock-core/util.cjs");
|
||||
|
||||
const MockAPI = {
|
||||
// 数据归集接口
|
||||
queryTasksUsingGet: "/data-collection/tasks", // 获取数据源任务列表
|
||||
createTaskUsingPost: "/data-collection/tasks", // 创建数据源任务
|
||||
queryTaskByIdUsingGet: "/data-collection/tasks/:id", // 根据ID获取数据源任务详情
|
||||
updateTaskByIdUsingPut: "/data-collection/tasks/:id", // 更新数据源任务
|
||||
queryDataXTemplatesUsingGet: "/data-collection/templates", // 获取DataX数据源模板列表
|
||||
deleteTaskByIdUsingDelete: "/data-collection/tasks/:id", // 删除数据源任务
|
||||
executeTaskByIdUsingPost: "/data-collection/tasks/:id/execute", // 执行数据源任务
|
||||
stopTaskByIdUsingPost: "/data-collection/tasks/:id/stop", // 停止数据源任务
|
||||
queryExecutionLogUsingPost: "/data-collection/executions", // 获取任务执行日志
|
||||
queryExecutionLogByIdUsingGet: "/data-collection/executions/:id", // 获取任务执行日志详情
|
||||
queryCollectionStatisticsUsingGet: "/data-collection/monitor/statistics", // 获取数据归集统计信息
|
||||
|
||||
// 数据管理接口
|
||||
queryDatasetsUsingGet: "/data-management/datasets", // 获取数据集列表
|
||||
createDatasetUsingPost: "/data-management/datasets", // 创建数据集
|
||||
queryDatasetByIdUsingGet: "/data-management/datasets/:id", // 根据ID获取数据集详情
|
||||
updateDatasetByIdUsingPut: "/data-management/datasets/:id", // 更新数据集
|
||||
deleteDatasetByIdUsingDelete: "/data-management/datasets/:id", // 删除数据集
|
||||
queryFilesUsingGet: "/data-management/datasets/:id/files", // 获取数据集文件列表
|
||||
uploadFileUsingPost: "/data-management/datasets/:id/files", // 添加数据集文件
|
||||
queryFileByIdUsingGet: "/data-management/datasets/:id/files/:fileId", // 获取数据集文件详情
|
||||
deleteFileByIdUsingDelete: "/data-management/datasets/:id/files/:fileId", // 删除数据集文件
|
||||
downloadFileByIdUsingGet:
|
||||
"/data-management/datasets/:id/files/:fileId/download", // 下载文件
|
||||
queryDatasetTypesUsingGet: "/data-management/dataset-types", // 获取数据集类型列表
|
||||
queryTagsUsingGet: "/data-management/tags", // 获取数据集标签列表
|
||||
createTagUsingPost: "/data-management/tags", // 创建数据集标签
|
||||
updateTagUsingPost: "/data-management/tags", // 更新数据集标签
|
||||
deleteTagUsingPost: "/data-management/tags", // 删除数据集标签
|
||||
queryDatasetStatisticsUsingGet: "/data-management/datasets/statistics", // 获取数据集统计信息
|
||||
preUploadFileUsingPost: "/data-management/datasets/:id/upload/pre-upload", // 预上传文件
|
||||
cancelUploadUsingPut: "/data-management/datasets/upload/cancel-upload/:id", // 取消上传
|
||||
uploadFileChunkUsingPost: "/data-management/datasets/:id/upload/chunk", // 上传切片
|
||||
|
||||
// 数据清洗接口
|
||||
queryCleaningTasksUsingGet: "/cleaning/tasks", // 获取清洗任务列表
|
||||
createCleaningTaskUsingPost: "/cleaning/tasks", // 创建清洗任务
|
||||
queryCleaningTaskByIdUsingGet: "/cleaning/tasks/:taskId", // 根据ID获取清洗任务详情
|
||||
deleteCleaningTaskByIdUsingDelete: "/cleaning/tasks/:taskId", // 删除清洗任务
|
||||
executeCleaningTaskUsingPost: "/cleaning/tasks/:taskId/execute", // 执行清洗任务
|
||||
stopCleaningTaskUsingPost: "/cleaning/tasks/:taskId/stop", // 停止清洗任务
|
||||
queryCleaningTemplatesUsingGet: "/cleaning/templates", // 获取清洗模板列表
|
||||
createCleaningTemplateUsingPost: "/cleaning/templates", // 创建清洗模板
|
||||
queryCleaningTemplateByIdUsingGet: "/cleaning/templates/:templateId", // 根据ID获取清洗模板详情
|
||||
updateCleaningTemplateByIdUsingPut: "/cleaning/templates/:templateId", // 根据ID更新清洗模板详情
|
||||
deleteCleaningTemplateByIdUsingDelete: "/cleaning/templates/:templateId", // 删除清洗模板
|
||||
|
||||
// 数据标注接口
|
||||
queryAnnotationTasksUsingGet: "/project/mappings/list", // 获取标注任务列表
|
||||
createAnnotationTaskUsingPost: "/project/create", // 创建标注任务
|
||||
syncAnnotationTaskByIdUsingPost: "/project/sync", // 同步标注任务
|
||||
deleteAnnotationTaskByIdUsingDelete: "/project/mappings", // 删除标注任务
|
||||
queryAnnotationTaskByIdUsingGet: "/annotation/tasks/:taskId", // 根据ID获取标注任务详情
|
||||
executeAnnotationTaskByIdUsingPost: "/annotation/tasks/:taskId/execute", // 执行标注任务
|
||||
stopAnnotationTaskByIdUsingPost: "/annotation/tasks/:taskId/stop", // 停止标注任务
|
||||
queryAnnotationDataUsingGet: "/annotation/data", // 获取标注数据列表
|
||||
submitAnnotationUsingPost: "/annotation/submit/:id", // 提交标注
|
||||
updateAnnotationUsingPut: "/annotation/update/:id", // 根据ID更新标注
|
||||
deleteAnnotationUsingDelete: "/annotation/delete/:id", // 根据ID删除标注
|
||||
startAnnotationTaskUsingPost: "/annotation/start/:taskId", // 开始标注任务
|
||||
pauseAnnotationTaskUsingPost: "/annotation/pause/:taskId", // 暂停标注任务
|
||||
resumeAnnotationTaskUsingPost: "/annotation/resume/:taskId", // 恢复标注任务
|
||||
completeAnnotationTaskUsingPost: "/annotation/complete/:taskId", // 完成标注任务
|
||||
getAnnotationTaskStatisticsUsingGet: "/annotation/statistics/:taskId", // 获取标注任务统计信息
|
||||
getAnnotationStatisticsUsingGet: "/annotation/statistics", // 获取标注统计信息
|
||||
queryAnnotationTemplatesUsingGet: "/annotation/templates", // 获取标注模板列表
|
||||
createAnnotationTemplateUsingPost: "/annotation/templates", // 创建标注模板
|
||||
queryAnnotationTemplateByIdUsingGet: "/annotation/templates/:templateId", // 根据ID获取标注模板详情
|
||||
queryAnnotatorsUsingGet: "/annotation/annotators", // 获取标注者列表
|
||||
assignAnnotatorUsingPost: "/annotation/annotators/:annotatorId", // 分配标注者
|
||||
|
||||
// 数据合成接口
|
||||
querySynthesisJobsUsingGet: "/synthesis/jobs", // 获取合成任务列表
|
||||
createSynthesisJobUsingPost: "/synthesis/jobs/create", // 创建合成任务
|
||||
querySynthesisJobByIdUsingGet: "/synthesis/jobs/:jobId", // 根据ID获取合成任务详情
|
||||
updateSynthesisJobByIdUsingPut: "/synthesis/jobs/:jobId", // 更新合成任务
|
||||
deleteSynthesisJobByIdUsingDelete: "/synthesis/jobs/:jobId", // 删除合成任务
|
||||
executeSynthesisJobUsingPost: "/synthesis/jobs/execute/:jobId", // 执行合成任务
|
||||
stopSynthesisJobByIdUsingPost: "/synthesis/jobs/stop/:jobId", // 停止合成任务
|
||||
querySynthesisTemplatesUsingGet: "/synthesis/templates", // 获取合成模板列表
|
||||
createSynthesisTemplateUsingPost: "/synthesis/templates/create", // 创建合成模板
|
||||
querySynthesisTemplateByIdUsingGet: "/synthesis/templates/:templateId", // 根据ID获取合成模板详情
|
||||
updateSynthesisTemplateByIdUsingPut: "/synthesis/templates/:templateId", // 更新合成模板
|
||||
deleteSynthesisTemplateByIdUsingDelete: "/synthesis/templates/:templateId", // 删除合成模板
|
||||
queryInstructionTemplatesUsingPost: "/synthesis/templates", // 获取指令模板列表
|
||||
createInstructionTemplateUsingPost: "/synthesis/templates/create", // 创建指令模板
|
||||
queryInstructionTemplateByIdUsingGet: "/synthesis/templates/:templateId", // 根据ID获取指令模板详情
|
||||
deleteInstructionTemplateByIdUsingDelete: "/synthesis/templates/:templateId", // 删除指令模板
|
||||
instructionTuningUsingPost: "/synthesis/instruction-tuning", // 指令微调
|
||||
cotDistillationUsingPost: "/synthesis/cot-distillation", // Cot蒸馏
|
||||
|
||||
// 数据配比接口
|
||||
createRatioTaskUsingPost: "/synthesis/ratio-task", // 创建配比任务
|
||||
queryRatioTasksUsingGet: "/synthesis/ratio-task", // 获取配比任务列表
|
||||
queryRatioTaskByIdUsingGet: "/synthesis/ratio-task/:taskId", // 根据ID获取配比任务详情
|
||||
deleteRatioTaskByIdUsingDelete: "/synthesis/ratio-task/:taskId", // 删除配比任务
|
||||
updateRatioTaskByIdUsingPut: "/synthesis/ratio-task/:taskId", // 更新配比任务
|
||||
executeRatioTaskByIdUsingPost: "/synthesis/ratio-task/:taskId/execute", // 执行配比任务
|
||||
stopRatioTaskByIdUsingPost: "/synthesis/ratio-task/:taskId/stop", // 停止配比任务
|
||||
queryRatioJobStatusUsingGet: "/synthesis/ratio-task/:taskId/status", // 获取配比任务状态
|
||||
queryRatioModelsUsingGet: "/synthesis/ratio-models", // 获取配比模型列表
|
||||
|
||||
// 数据评测接口
|
||||
queryEvaluationTasksUsingPost: "/evaluation/tasks", // 获取评测任务列表
|
||||
createEvaluationTaskUsingPost: "/evaluation/tasks/create", // 创建评测任务
|
||||
queryEvaluationTaskByIdUsingGet: "/evaluation/tasks/:taskId", // 根据ID获取评测任务详情
|
||||
updateEvaluationTaskByIdUsingPut: "/evaluation/tasks/:taskId", // 更新评测任务
|
||||
deleteEvaluationTaskByIdUsingDelete: "/evaluation/tasks/:taskId", // 删除评测任务
|
||||
executeEvaluationTaskByIdUsingPost: "/evaluation/tasks/:taskId/execute", // 执行评测任务
|
||||
stopEvaluationTaskByIdUsingPost: "/evaluation/tasks/:taskId/stop", // 停止评测任务
|
||||
queryEvaluationReportsUsingPost: "/evaluation/reports", // 获取评测报告列表
|
||||
queryEvaluationReportByIdUsingGet: "/evaluation/reports/:reportId", // 根据ID获取评测报告详情
|
||||
manualEvaluateUsingPost: "/evaluation/manual-evaluate", // 人工评测
|
||||
queryEvaluationStatisticsUsingGet: "/evaluation/statistics", // 获取评测统计信息
|
||||
evaluateDataQualityUsingPost: "/evaluation/data-quality", // 数据质量评测
|
||||
getQualityEvaluationByIdUsingGet: "/evaluation/data-quality/:id", // 根据ID获取数据质量评测详情
|
||||
evaluateCompatibilityUsingPost: "/evaluation/compatibility", // 兼容性评测
|
||||
evaluateValueUsingPost: "/evaluation/value", // 价值评测
|
||||
queryEvaluationReportsUsingGet: "/evaluation/reports", // 获取评测报告列表(简化版)
|
||||
getEvaluationReportByIdUsingGet: "/evaluation/reports/:reportId", // 根据ID获取评测报告详情(简化版)
|
||||
exportEvaluationReportUsingGet: "/evaluation/reports/:reportId/export", // 导出评测报告
|
||||
batchEvaluationUsingPost: "/evaluation/batch-evaluate", // 批量评测
|
||||
|
||||
// 知识生成接口
|
||||
queryKnowledgeBasesUsingPost: "/knowledge-base/list", // 获取知识库列表
|
||||
createKnowledgeBaseUsingPost: "/knowledge-base/create", // 创建知识库
|
||||
queryKnowledgeBaseByIdUsingGet: "/knowledge-base/:baseId", // 根据ID获取知识库详情
|
||||
updateKnowledgeBaseByIdUsingPut: "/knowledge-base/:baseId", // 更新知识库
|
||||
deleteKnowledgeBaseByIdUsingDelete: "/knowledge-base/:baseId", // 删除知识库
|
||||
addKnowledgeBaseFilesUsingPost: "/knowledge-base/:baseId/files", // 添加文件到知识库
|
||||
queryKnowledgeBaseFilesGet: "/knowledge-base/:baseId/files", // 根据ID获取知识生成文件列表
|
||||
queryKnowledgeBaseFilesByIdUsingGet:
|
||||
"/knowledge-base/:baseId/files/:fileId", // 根据ID获取知识生成文件详情
|
||||
deleteKnowledgeBaseTaskByIdUsingDelete: "/knowledge-base/:baseId/files/:id", // 删除知识生成文件
|
||||
|
||||
// 算子市场
|
||||
queryOperatorsUsingPost: "/operators/list", // 获取算子列表
|
||||
queryCategoryTreeUsingGet: "/categories/tree", // 获取算子分类树
|
||||
queryOperatorByIdUsingGet: "/operators/:id", // 根据ID获取算子详情
|
||||
createOperatorUsingPost: "/operators/create", // 创建算子
|
||||
updateOperatorByIdUsingPut: "/operators/:id", // 更新算子
|
||||
uploadOperatorUsingPost: "/operators/upload", // 上传算子
|
||||
uploadFileChunkUsingPost: "/operators/upload/chunk", // 上传切片
|
||||
preUploadOperatorUsingPost: "/operators/upload/pre-upload", // 预上传文件
|
||||
cancelUploadOperatorUsingPut: "/operators/upload/cancel-upload", // 取消上传
|
||||
|
||||
createLabelUsingPost: "/operators/labels", // 创建算子标签
|
||||
queryLabelsUsingGet: "/labels", // 获取算子标签列表
|
||||
deleteLabelsUsingDelete: "/labels", // 删除算子标签
|
||||
updateLabelByIdUsingPut: "/labels/:labelId", // 更新算子标签
|
||||
deleteOperatorByIdUsingDelete: "/operators/:operatorId", // 删除算子
|
||||
publishOperatorUsingPost: "/operators/:operatorId/publish", // 发布算子
|
||||
unpublishOperatorUsingPost: "/operators/:operatorId/unpublish", // 下架算子
|
||||
|
||||
// 设置接口
|
||||
queryModelsUsingGet: "/models/list", // 获取模型列表
|
||||
queryProvidersUsingGet: "/models/providers", // 获取模型提供商列表
|
||||
createModelUsingPost: "/models/create", // 创建模型
|
||||
updateModelUsingPut: "/models/:id", // 更新模型
|
||||
deleteModelUsingDelete: "/models/:id", // 删除模型
|
||||
};
|
||||
|
||||
module.exports = addMockPrefix("/api", MockAPI);
|
||||
const { addMockPrefix } = require("./mock-core/util.cjs");
|
||||
|
||||
const MockAPI = {
|
||||
// 数据归集接口
|
||||
queryTasksUsingGet: "/data-collection/tasks", // 获取数据源任务列表
|
||||
createTaskUsingPost: "/data-collection/tasks", // 创建数据源任务
|
||||
queryTaskByIdUsingGet: "/data-collection/tasks/:id", // 根据ID获取数据源任务详情
|
||||
updateTaskByIdUsingPut: "/data-collection/tasks/:id", // 更新数据源任务
|
||||
queryDataXTemplatesUsingGet: "/data-collection/templates", // 获取DataX数据源模板列表
|
||||
deleteTaskByIdUsingDelete: "/data-collection/tasks/:id", // 删除数据源任务
|
||||
executeTaskByIdUsingPost: "/data-collection/tasks/:id/execute", // 执行数据源任务
|
||||
stopTaskByIdUsingPost: "/data-collection/tasks/:id/stop", // 停止数据源任务
|
||||
queryExecutionLogUsingPost: "/data-collection/executions", // 获取任务执行日志
|
||||
queryExecutionLogByIdUsingGet: "/data-collection/executions/:id", // 获取任务执行日志详情
|
||||
queryCollectionStatisticsUsingGet: "/data-collection/monitor/statistics", // 获取数据归集统计信息
|
||||
|
||||
// 数据管理接口
|
||||
queryDatasetsUsingGet: "/data-management/datasets", // 获取数据集列表
|
||||
createDatasetUsingPost: "/data-management/datasets", // 创建数据集
|
||||
queryDatasetByIdUsingGet: "/data-management/datasets/:id", // 根据ID获取数据集详情
|
||||
updateDatasetByIdUsingPut: "/data-management/datasets/:id", // 更新数据集
|
||||
deleteDatasetByIdUsingDelete: "/data-management/datasets/:id", // 删除数据集
|
||||
queryFilesUsingGet: "/data-management/datasets/:id/files", // 获取数据集文件列表
|
||||
uploadFileUsingPost: "/data-management/datasets/:id/files", // 添加数据集文件
|
||||
queryFileByIdUsingGet: "/data-management/datasets/:id/files/:fileId", // 获取数据集文件详情
|
||||
deleteFileByIdUsingDelete: "/data-management/datasets/:id/files/:fileId", // 删除数据集文件
|
||||
downloadFileByIdUsingGet:
|
||||
"/data-management/datasets/:id/files/:fileId/download", // 下载文件
|
||||
queryDatasetTypesUsingGet: "/data-management/dataset-types", // 获取数据集类型列表
|
||||
queryTagsUsingGet: "/data-management/tags", // 获取数据集标签列表
|
||||
createTagUsingPost: "/data-management/tags", // 创建数据集标签
|
||||
updateTagUsingPost: "/data-management/tags", // 更新数据集标签
|
||||
deleteTagUsingPost: "/data-management/tags", // 删除数据集标签
|
||||
queryDatasetStatisticsUsingGet: "/data-management/datasets/statistics", // 获取数据集统计信息
|
||||
preUploadFileUsingPost: "/data-management/datasets/:id/upload/pre-upload", // 预上传文件
|
||||
cancelUploadUsingPut: "/data-management/datasets/upload/cancel-upload/:id", // 取消上传
|
||||
uploadFileChunkUsingPost: "/data-management/datasets/:id/upload/chunk", // 上传切片
|
||||
|
||||
// 数据清洗接口
|
||||
queryCleaningTasksUsingGet: "/cleaning/tasks", // 获取清洗任务列表
|
||||
createCleaningTaskUsingPost: "/cleaning/tasks", // 创建清洗任务
|
||||
queryCleaningTaskByIdUsingGet: "/cleaning/tasks/:taskId", // 根据ID获取清洗任务详情
|
||||
deleteCleaningTaskByIdUsingDelete: "/cleaning/tasks/:taskId", // 删除清洗任务
|
||||
executeCleaningTaskUsingPost: "/cleaning/tasks/:taskId/execute", // 执行清洗任务
|
||||
stopCleaningTaskUsingPost: "/cleaning/tasks/:taskId/stop", // 停止清洗任务
|
||||
queryCleaningTemplatesUsingGet: "/cleaning/templates", // 获取清洗模板列表
|
||||
createCleaningTemplateUsingPost: "/cleaning/templates", // 创建清洗模板
|
||||
queryCleaningTemplateByIdUsingGet: "/cleaning/templates/:templateId", // 根据ID获取清洗模板详情
|
||||
updateCleaningTemplateByIdUsingPut: "/cleaning/templates/:templateId", // 根据ID更新清洗模板详情
|
||||
deleteCleaningTemplateByIdUsingDelete: "/cleaning/templates/:templateId", // 删除清洗模板
|
||||
|
||||
// 数据标注接口
|
||||
queryAnnotationTasksUsingGet: "/project/mappings/list", // 获取标注任务列表
|
||||
createAnnotationTaskUsingPost: "/project/create", // 创建标注任务
|
||||
syncAnnotationTaskByIdUsingPost: "/project/sync", // 同步标注任务
|
||||
deleteAnnotationTaskByIdUsingDelete: "/project/mappings", // 删除标注任务
|
||||
queryAnnotationTaskByIdUsingGet: "/annotation/tasks/:taskId", // 根据ID获取标注任务详情
|
||||
executeAnnotationTaskByIdUsingPost: "/annotation/tasks/:taskId/execute", // 执行标注任务
|
||||
stopAnnotationTaskByIdUsingPost: "/annotation/tasks/:taskId/stop", // 停止标注任务
|
||||
queryAnnotationDataUsingGet: "/annotation/data", // 获取标注数据列表
|
||||
submitAnnotationUsingPost: "/annotation/submit/:id", // 提交标注
|
||||
updateAnnotationUsingPut: "/annotation/update/:id", // 根据ID更新标注
|
||||
deleteAnnotationUsingDelete: "/annotation/delete/:id", // 根据ID删除标注
|
||||
startAnnotationTaskUsingPost: "/annotation/start/:taskId", // 开始标注任务
|
||||
pauseAnnotationTaskUsingPost: "/annotation/pause/:taskId", // 暂停标注任务
|
||||
resumeAnnotationTaskUsingPost: "/annotation/resume/:taskId", // 恢复标注任务
|
||||
completeAnnotationTaskUsingPost: "/annotation/complete/:taskId", // 完成标注任务
|
||||
getAnnotationTaskStatisticsUsingGet: "/annotation/statistics/:taskId", // 获取标注任务统计信息
|
||||
getAnnotationStatisticsUsingGet: "/annotation/statistics", // 获取标注统计信息
|
||||
queryAnnotationTemplatesUsingGet: "/annotation/templates", // 获取标注模板列表
|
||||
createAnnotationTemplateUsingPost: "/annotation/templates", // 创建标注模板
|
||||
queryAnnotationTemplateByIdUsingGet: "/annotation/templates/:templateId", // 根据ID获取标注模板详情
|
||||
queryAnnotatorsUsingGet: "/annotation/annotators", // 获取标注者列表
|
||||
assignAnnotatorUsingPost: "/annotation/annotators/:annotatorId", // 分配标注者
|
||||
|
||||
// 数据合成接口
|
||||
querySynthesisJobsUsingGet: "/synthesis/jobs", // 获取合成任务列表
|
||||
createSynthesisJobUsingPost: "/synthesis/jobs/create", // 创建合成任务
|
||||
querySynthesisJobByIdUsingGet: "/synthesis/jobs/:jobId", // 根据ID获取合成任务详情
|
||||
updateSynthesisJobByIdUsingPut: "/synthesis/jobs/:jobId", // 更新合成任务
|
||||
deleteSynthesisJobByIdUsingDelete: "/synthesis/jobs/:jobId", // 删除合成任务
|
||||
executeSynthesisJobUsingPost: "/synthesis/jobs/execute/:jobId", // 执行合成任务
|
||||
stopSynthesisJobByIdUsingPost: "/synthesis/jobs/stop/:jobId", // 停止合成任务
|
||||
querySynthesisTemplatesUsingGet: "/synthesis/templates", // 获取合成模板列表
|
||||
createSynthesisTemplateUsingPost: "/synthesis/templates/create", // 创建合成模板
|
||||
querySynthesisTemplateByIdUsingGet: "/synthesis/templates/:templateId", // 根据ID获取合成模板详情
|
||||
updateSynthesisTemplateByIdUsingPut: "/synthesis/templates/:templateId", // 更新合成模板
|
||||
deleteSynthesisTemplateByIdUsingDelete: "/synthesis/templates/:templateId", // 删除合成模板
|
||||
queryInstructionTemplatesUsingPost: "/synthesis/templates", // 获取指令模板列表
|
||||
createInstructionTemplateUsingPost: "/synthesis/templates/create", // 创建指令模板
|
||||
queryInstructionTemplateByIdUsingGet: "/synthesis/templates/:templateId", // 根据ID获取指令模板详情
|
||||
deleteInstructionTemplateByIdUsingDelete: "/synthesis/templates/:templateId", // 删除指令模板
|
||||
instructionTuningUsingPost: "/synthesis/instruction-tuning", // 指令微调
|
||||
cotDistillationUsingPost: "/synthesis/cot-distillation", // Cot蒸馏
|
||||
|
||||
// 数据配比接口
|
||||
createRatioTaskUsingPost: "/synthesis/ratio-task", // 创建配比任务
|
||||
queryRatioTasksUsingGet: "/synthesis/ratio-task", // 获取配比任务列表
|
||||
queryRatioTaskByIdUsingGet: "/synthesis/ratio-task/:taskId", // 根据ID获取配比任务详情
|
||||
deleteRatioTaskByIdUsingDelete: "/synthesis/ratio-task/:taskId", // 删除配比任务
|
||||
updateRatioTaskByIdUsingPut: "/synthesis/ratio-task/:taskId", // 更新配比任务
|
||||
executeRatioTaskByIdUsingPost: "/synthesis/ratio-task/:taskId/execute", // 执行配比任务
|
||||
stopRatioTaskByIdUsingPost: "/synthesis/ratio-task/:taskId/stop", // 停止配比任务
|
||||
queryRatioJobStatusUsingGet: "/synthesis/ratio-task/:taskId/status", // 获取配比任务状态
|
||||
queryRatioModelsUsingGet: "/synthesis/ratio-models", // 获取配比模型列表
|
||||
|
||||
// 数据评测接口
|
||||
queryEvaluationTasksUsingPost: "/evaluation/tasks", // 获取评测任务列表
|
||||
createEvaluationTaskUsingPost: "/evaluation/tasks/create", // 创建评测任务
|
||||
queryEvaluationTaskByIdUsingGet: "/evaluation/tasks/:taskId", // 根据ID获取评测任务详情
|
||||
updateEvaluationTaskByIdUsingPut: "/evaluation/tasks/:taskId", // 更新评测任务
|
||||
deleteEvaluationTaskByIdUsingDelete: "/evaluation/tasks/:taskId", // 删除评测任务
|
||||
executeEvaluationTaskByIdUsingPost: "/evaluation/tasks/:taskId/execute", // 执行评测任务
|
||||
stopEvaluationTaskByIdUsingPost: "/evaluation/tasks/:taskId/stop", // 停止评测任务
|
||||
queryEvaluationReportsUsingPost: "/evaluation/reports", // 获取评测报告列表
|
||||
queryEvaluationReportByIdUsingGet: "/evaluation/reports/:reportId", // 根据ID获取评测报告详情
|
||||
manualEvaluateUsingPost: "/evaluation/manual-evaluate", // 人工评测
|
||||
queryEvaluationStatisticsUsingGet: "/evaluation/statistics", // 获取评测统计信息
|
||||
evaluateDataQualityUsingPost: "/evaluation/data-quality", // 数据质量评测
|
||||
getQualityEvaluationByIdUsingGet: "/evaluation/data-quality/:id", // 根据ID获取数据质量评测详情
|
||||
evaluateCompatibilityUsingPost: "/evaluation/compatibility", // 兼容性评测
|
||||
evaluateValueUsingPost: "/evaluation/value", // 价值评测
|
||||
queryEvaluationReportsUsingGet: "/evaluation/reports", // 获取评测报告列表(简化版)
|
||||
getEvaluationReportByIdUsingGet: "/evaluation/reports/:reportId", // 根据ID获取评测报告详情(简化版)
|
||||
exportEvaluationReportUsingGet: "/evaluation/reports/:reportId/export", // 导出评测报告
|
||||
batchEvaluationUsingPost: "/evaluation/batch-evaluate", // 批量评测
|
||||
|
||||
// 知识生成接口
|
||||
queryKnowledgeBasesUsingPost: "/knowledge-base/list", // 获取知识库列表
|
||||
createKnowledgeBaseUsingPost: "/knowledge-base/create", // 创建知识库
|
||||
queryKnowledgeBaseByIdUsingGet: "/knowledge-base/:baseId", // 根据ID获取知识库详情
|
||||
updateKnowledgeBaseByIdUsingPut: "/knowledge-base/:baseId", // 更新知识库
|
||||
deleteKnowledgeBaseByIdUsingDelete: "/knowledge-base/:baseId", // 删除知识库
|
||||
addKnowledgeBaseFilesUsingPost: "/knowledge-base/:baseId/files", // 添加文件到知识库
|
||||
queryKnowledgeBaseFilesGet: "/knowledge-base/:baseId/files", // 根据ID获取知识生成文件列表
|
||||
queryKnowledgeBaseFilesByIdUsingGet:
|
||||
"/knowledge-base/:baseId/files/:fileId", // 根据ID获取知识生成文件详情
|
||||
deleteKnowledgeBaseTaskByIdUsingDelete: "/knowledge-base/:baseId/files/:id", // 删除知识生成文件
|
||||
|
||||
// 算子市场
|
||||
queryOperatorsUsingPost: "/operators/list", // 获取算子列表
|
||||
queryCategoryTreeUsingGet: "/categories/tree", // 获取算子分类树
|
||||
queryOperatorByIdUsingGet: "/operators/:id", // 根据ID获取算子详情
|
||||
createOperatorUsingPost: "/operators/create", // 创建算子
|
||||
updateOperatorByIdUsingPut: "/operators/:id", // 更新算子
|
||||
uploadOperatorUsingPost: "/operators/upload", // 上传算子
|
||||
uploadFileChunkUsingPost: "/operators/upload/chunk", // 上传切片
|
||||
preUploadOperatorUsingPost: "/operators/upload/pre-upload", // 预上传文件
|
||||
cancelUploadOperatorUsingPut: "/operators/upload/cancel-upload", // 取消上传
|
||||
|
||||
createLabelUsingPost: "/operators/labels", // 创建算子标签
|
||||
queryLabelsUsingGet: "/labels", // 获取算子标签列表
|
||||
deleteLabelsUsingDelete: "/labels", // 删除算子标签
|
||||
updateLabelByIdUsingPut: "/labels/:labelId", // 更新算子标签
|
||||
deleteOperatorByIdUsingDelete: "/operators/:operatorId", // 删除算子
|
||||
publishOperatorUsingPost: "/operators/:operatorId/publish", // 发布算子
|
||||
unpublishOperatorUsingPost: "/operators/:operatorId/unpublish", // 下架算子
|
||||
|
||||
// 设置接口
|
||||
queryModelsUsingGet: "/models/list", // 获取模型列表
|
||||
queryProvidersUsingGet: "/models/providers", // 获取模型提供商列表
|
||||
createModelUsingPost: "/models/create", // 创建模型
|
||||
updateModelUsingPut: "/models/:id", // 更新模型
|
||||
deleteModelUsingDelete: "/models/:id", // 删除模型
|
||||
};
|
||||
|
||||
module.exports = addMockPrefix("/api", MockAPI);
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
const fs = require('fs');
|
||||
|
||||
function loadAllMockModules(router, pathDir) {
|
||||
if (!fs.existsSync(pathDir)) {
|
||||
throw new Error(`Mock directory ${pathDir} does not exist.`);
|
||||
}
|
||||
|
||||
const files = fs.readdirSync(pathDir);
|
||||
files.forEach(file => {
|
||||
const filePath = `${pathDir}/${file}`;
|
||||
if(fs.lstatSync(filePath).isDirectory()) {
|
||||
loadAllMockModules(router, filePath);
|
||||
} else {
|
||||
let fileNameModule = file.replace('/\.js\b$/', '');
|
||||
let module = require(`${pathDir}/${fileNameModule}`);
|
||||
if(typeof module === 'function' && module.length === 1) {
|
||||
module(router);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
loadAllMockModules,
|
||||
const fs = require('fs');
|
||||
|
||||
function loadAllMockModules(router, pathDir) {
|
||||
if (!fs.existsSync(pathDir)) {
|
||||
throw new Error(`Mock directory ${pathDir} does not exist.`);
|
||||
}
|
||||
|
||||
const files = fs.readdirSync(pathDir);
|
||||
files.forEach(file => {
|
||||
const filePath = `${pathDir}/${file}`;
|
||||
if(fs.lstatSync(filePath).isDirectory()) {
|
||||
loadAllMockModules(router, filePath);
|
||||
} else {
|
||||
let fileNameModule = file.replace('/\.js\b$/', '');
|
||||
let module = require(`${pathDir}/${fileNameModule}`);
|
||||
if(typeof module === 'function' && module.length === 1) {
|
||||
module(router);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
loadAllMockModules,
|
||||
};
|
||||
@@ -1,63 +1,63 @@
|
||||
const path = require("path");
|
||||
const Mock = require("mockjs");
|
||||
const session = require("express-session");
|
||||
const FileStore = require("session-file-store")(session);
|
||||
|
||||
const { isFunction } = require("lodash");
|
||||
|
||||
const argv = require("minimist")(process.argv.slice(2));
|
||||
const isDev = (argv.env || "development") === "development";
|
||||
const TOKEN_KEY = isDev ? "X-Auth-Token" : "X-Csrf-Token";
|
||||
|
||||
const setSessionUser = (req, getLoginInfo) => {
|
||||
if (!isFunction(getLoginInfo)) {
|
||||
throw new Error("getLoginInfo must be a function");
|
||||
}
|
||||
|
||||
if (!req.session?.users) {
|
||||
req.session.users = {};
|
||||
}
|
||||
|
||||
let token = req.get(TOKEN_KEY);
|
||||
const { users } = req.session;
|
||||
if (!token || !users[token]) {
|
||||
token = Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, "");
|
||||
const userInfo = getLoginInfo(req) || {};
|
||||
users[token] = user;
|
||||
}
|
||||
return token;
|
||||
};
|
||||
|
||||
const getSessionUser = (req) => {
|
||||
const token = req.get(TOKEN_KEY);
|
||||
if (token && req.session?.users) {
|
||||
return req.session.users[token];
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const genExpressSession = () => {
|
||||
return session({
|
||||
name: "demo.name",
|
||||
secret: "demo.secret",
|
||||
resave: true,
|
||||
saveUninitialized: true,
|
||||
cookie: {
|
||||
maxAge: 60 * 60 * 1e3,
|
||||
expires: new Date(Date.now() + 60 * 60 * 1e3),
|
||||
}, // 1 hour
|
||||
store: new FileStore({
|
||||
path: path.join(__dirname, "../sessions"),
|
||||
retries: 0,
|
||||
keyFunction: (secret, sessionId) => {
|
||||
return secret + sessionId;
|
||||
},
|
||||
}),
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
setSessionUser,
|
||||
getSessionUser,
|
||||
genExpressSession,
|
||||
};
|
||||
const path = require("path");
|
||||
const Mock = require("mockjs");
|
||||
const session = require("express-session");
|
||||
const FileStore = require("session-file-store")(session);
|
||||
|
||||
const { isFunction } = require("lodash");
|
||||
|
||||
const argv = require("minimist")(process.argv.slice(2));
|
||||
const isDev = (argv.env || "development") === "development";
|
||||
const TOKEN_KEY = isDev ? "X-Auth-Token" : "X-Csrf-Token";
|
||||
|
||||
const setSessionUser = (req, getLoginInfo) => {
|
||||
if (!isFunction(getLoginInfo)) {
|
||||
throw new Error("getLoginInfo must be a function");
|
||||
}
|
||||
|
||||
if (!req.session?.users) {
|
||||
req.session.users = {};
|
||||
}
|
||||
|
||||
let token = req.get(TOKEN_KEY);
|
||||
const { users } = req.session;
|
||||
if (!token || !users[token]) {
|
||||
token = Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, "");
|
||||
const userInfo = getLoginInfo(req) || {};
|
||||
users[token] = user;
|
||||
}
|
||||
return token;
|
||||
};
|
||||
|
||||
const getSessionUser = (req) => {
|
||||
const token = req.get(TOKEN_KEY);
|
||||
if (token && req.session?.users) {
|
||||
return req.session.users[token];
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const genExpressSession = () => {
|
||||
return session({
|
||||
name: "demo.name",
|
||||
secret: "demo.secret",
|
||||
resave: true,
|
||||
saveUninitialized: true,
|
||||
cookie: {
|
||||
maxAge: 60 * 60 * 1e3,
|
||||
expires: new Date(Date.now() + 60 * 60 * 1e3),
|
||||
}, // 1 hour
|
||||
store: new FileStore({
|
||||
path: path.join(__dirname, "../sessions"),
|
||||
retries: 0,
|
||||
keyFunction: (secret, sessionId) => {
|
||||
return secret + sessionId;
|
||||
},
|
||||
}),
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
setSessionUser,
|
||||
getSessionUser,
|
||||
genExpressSession,
|
||||
};
|
||||
|
||||
@@ -1,30 +1,30 @@
|
||||
|
||||
function log(message, type = "log", provided = 'console') {
|
||||
const providedFn = globalThis[provided] || console;
|
||||
if (providedFn && typeof providedFn[type] === 'function') {
|
||||
const invokeMethod = providedFn[type ?? 'log'];
|
||||
invokeMethod.call(providedFn, message);
|
||||
}
|
||||
}
|
||||
|
||||
function addMockPrefix(urlPrefix, api) {
|
||||
const newMockApi = {};
|
||||
Object.keys(api).map(apiKey=>{
|
||||
newMockApi[apiKey] = urlPrefix + api[apiKey];
|
||||
});
|
||||
|
||||
return new Proxy(newMockApi, {
|
||||
get(target, prop) {
|
||||
if (prop in target) {
|
||||
return target[prop];
|
||||
} else {
|
||||
throw new Error(`API ${String(prop)} is not defined.`);
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
log,
|
||||
addMockPrefix,
|
||||
|
||||
function log(message, type = "log", provided = 'console') {
|
||||
const providedFn = globalThis[provided] || console;
|
||||
if (providedFn && typeof providedFn[type] === 'function') {
|
||||
const invokeMethod = providedFn[type ?? 'log'];
|
||||
invokeMethod.call(providedFn, message);
|
||||
}
|
||||
}
|
||||
|
||||
function addMockPrefix(urlPrefix, api) {
|
||||
const newMockApi = {};
|
||||
Object.keys(api).map(apiKey=>{
|
||||
newMockApi[apiKey] = urlPrefix + api[apiKey];
|
||||
});
|
||||
|
||||
return new Proxy(newMockApi, {
|
||||
get(target, prop) {
|
||||
if (prop in target) {
|
||||
return target[prop];
|
||||
} else {
|
||||
throw new Error(`API ${String(prop)} is not defined.`);
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
log,
|
||||
addMockPrefix,
|
||||
};
|
||||
@@ -1,13 +1,13 @@
|
||||
const errorHandle = (err, req, res, next) => {
|
||||
if(res.headersSent) {
|
||||
return next(err);
|
||||
}
|
||||
console.error('Server Error:', err.message);
|
||||
res.status(500).json({
|
||||
code: '500',
|
||||
msg: 'Internal Server Error',
|
||||
data: null,
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = errorHandle;
|
||||
const errorHandle = (err, req, res, next) => {
|
||||
if(res.headersSent) {
|
||||
return next(err);
|
||||
}
|
||||
console.error('Server Error:', err.message);
|
||||
res.status(500).json({
|
||||
code: '500',
|
||||
msg: 'Internal Server Error',
|
||||
data: null,
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = errorHandle;
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
const setHeader = require('./set-header-middleware.cjs');
|
||||
const strongMatch = require('./strong-match-middleware.cjs');
|
||||
const sendJSON = require('./send-json-middleawre.cjs');
|
||||
const errorHandle = require('./error-handle-middleware.cjs');
|
||||
|
||||
module.exports = {
|
||||
setHeader,
|
||||
strongMatch,
|
||||
sendJSON,
|
||||
errorHandle,
|
||||
const setHeader = require('./set-header-middleware.cjs');
|
||||
const strongMatch = require('./strong-match-middleware.cjs');
|
||||
const sendJSON = require('./send-json-middleawre.cjs');
|
||||
const errorHandle = require('./error-handle-middleware.cjs');
|
||||
|
||||
module.exports = {
|
||||
setHeader,
|
||||
strongMatch,
|
||||
sendJSON,
|
||||
errorHandle,
|
||||
};
|
||||
@@ -1,18 +1,18 @@
|
||||
const sendJSON = (req, res, next) => {
|
||||
res.sendJSON = (
|
||||
data = null,
|
||||
{ code = '0', msg = 'success', statusCode = 200, timeout = 0 } = {}
|
||||
) => {
|
||||
const timer = setTimeout(() => {
|
||||
res.status(statusCode).json({
|
||||
code,
|
||||
msg,
|
||||
data,
|
||||
});
|
||||
clearTimeout(timer);
|
||||
}, timeout);
|
||||
};
|
||||
next();
|
||||
};
|
||||
|
||||
const sendJSON = (req, res, next) => {
|
||||
res.sendJSON = (
|
||||
data = null,
|
||||
{ code = '0', msg = 'success', statusCode = 200, timeout = 0 } = {}
|
||||
) => {
|
||||
const timer = setTimeout(() => {
|
||||
res.status(statusCode).json({
|
||||
code,
|
||||
msg,
|
||||
data,
|
||||
});
|
||||
clearTimeout(timer);
|
||||
}, timeout);
|
||||
};
|
||||
next();
|
||||
};
|
||||
|
||||
module.exports = sendJSON;
|
||||
@@ -1,14 +1,14 @@
|
||||
const setHeader = (req, res, next) => {
|
||||
res.set({
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Access-Control-Allow-Methods': 'GET,POST,PUT,DELETE,OPTIONS',
|
||||
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
|
||||
'Content-Security-Policy': "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src *; font-src 'self';",
|
||||
'X-Content-Type-Options': 'nosniff',
|
||||
'X-Frame-Options': 'SAMEORIGIN',
|
||||
'X-XSS-Protection': '1; mode=block',
|
||||
});
|
||||
next();
|
||||
};
|
||||
|
||||
const setHeader = (req, res, next) => {
|
||||
res.set({
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Access-Control-Allow-Methods': 'GET,POST,PUT,DELETE,OPTIONS',
|
||||
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
|
||||
'Content-Security-Policy': "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src *; font-src 'self';",
|
||||
'X-Content-Type-Options': 'nosniff',
|
||||
'X-Frame-Options': 'SAMEORIGIN',
|
||||
'X-XSS-Protection': '1; mode=block',
|
||||
});
|
||||
next();
|
||||
};
|
||||
|
||||
module.exports = setHeader;
|
||||
@@ -1,13 +1,13 @@
|
||||
const API = require('../mock-apis.cjs');
|
||||
|
||||
const strongMatch = (req, res, next) => {
|
||||
res.strongMatch = () => {
|
||||
const { url } = req;
|
||||
const index = url.indexOf('?');
|
||||
const targetUrl = index !== -1 ? url.substring(0, index) : url;
|
||||
const isExistedUrl = Object.values(API).includes(targetUrl);
|
||||
return isExistedUrl;
|
||||
};
|
||||
next();
|
||||
};
|
||||
const API = require('../mock-apis.cjs');
|
||||
|
||||
const strongMatch = (req, res, next) => {
|
||||
res.strongMatch = () => {
|
||||
const { url } = req;
|
||||
const index = url.indexOf('?');
|
||||
const targetUrl = index !== -1 ? url.substring(0, index) : url;
|
||||
const isExistedUrl = Object.values(API).includes(targetUrl);
|
||||
return isExistedUrl;
|
||||
};
|
||||
next();
|
||||
};
|
||||
module.exports = strongMatch;
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,232 +1,232 @@
|
||||
const Mock = require("mockjs");
|
||||
const API = require("../mock-apis.cjs");
|
||||
const { Random } = Mock;
|
||||
|
||||
// 生成模拟数据归集统计信息
|
||||
function dataXTemplate() {
|
||||
return {
|
||||
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
name: Mock.Random.ctitle(5, 15),
|
||||
sourceType: Mock.Random.csentence(3, 10),
|
||||
targetType: Mock.Random.csentence(3, 10),
|
||||
description: Mock.Random.csentence(5, 20),
|
||||
version: `v${Mock.Random.integer(1, 5)}.${Mock.Random.integer(
|
||||
0,
|
||||
9
|
||||
)}.${Mock.Random.integer(0, 9)}`,
|
||||
isSystem: Mock.Random.boolean(),
|
||||
createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
|
||||
updatedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
|
||||
};
|
||||
}
|
||||
|
||||
const templateList = new Array(20).fill(null).map(dataXTemplate);
|
||||
|
||||
// 生成模拟任务数据
|
||||
function taskItem() {
|
||||
return {
|
||||
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
name: Mock.Random.ctitle(5, 20),
|
||||
description: Mock.Random.csentence(5, 20),
|
||||
syncMode: Mock.Random.pick(["ONCE", "SCHEDULED"]),
|
||||
config: {
|
||||
query: "SELECT * FROM table WHERE condition",
|
||||
batchSize: Mock.Random.integer(100, 1000),
|
||||
frequency: Mock.Random.integer(1, 60), // in minutes
|
||||
},
|
||||
scheduleExpression: "0 0 * * *", // cron expression
|
||||
lastExecutionId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
status: Mock.Random.pick([
|
||||
"DRAFT",
|
||||
"READY",
|
||||
"RUNNING",
|
||||
"FAILED",
|
||||
"STOPPED",
|
||||
"SUCCESS",
|
||||
]),
|
||||
createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
|
||||
updatedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
|
||||
sourceDataSourceId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
sourceDataSourceName: Mock.Random.ctitle(5, 20),
|
||||
targetDataSourceId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
targetDataSourceName: Mock.Random.ctitle(5, 20),
|
||||
};
|
||||
}
|
||||
|
||||
const taskList = new Array(50).fill(null).map(taskItem);
|
||||
|
||||
// 生成模拟任务执行日志数据
|
||||
function executionLogItem() {
|
||||
return {
|
||||
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
taskName: Mock.Random.ctitle(5, 20),
|
||||
dataSource: Mock.Random.ctitle(5, 15),
|
||||
startTime: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
|
||||
endTime: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
|
||||
status: Mock.Random.pick(["SUCCESS", "FAILED", "RUNNING"]),
|
||||
triggerType: Mock.Random.pick(["MANUAL", "SCHEDULED", "API"]),
|
||||
duration: Mock.Random.integer(1, 120),
|
||||
retryCount: Mock.Random.integer(0, 5),
|
||||
recordsProcessed: Mock.Random.integer(100, 10000),
|
||||
processId: Mock.Random.integer(1000, 9999),
|
||||
errorMessage: Mock.Random.boolean() ? "" : Mock.Random.csentence(5, 20),
|
||||
};
|
||||
}
|
||||
|
||||
const executionLogList = new Array(100).fill(null).map(executionLogItem);
|
||||
|
||||
module.exports = function (router) {
|
||||
// 获取任务列表
|
||||
router.get(API.queryTasksUsingGet, (req, res) => {
|
||||
const { keyword, status, page = 0, size = 10 } = req.query;
|
||||
let filteredTasks = taskList;
|
||||
if (keyword) {
|
||||
filteredTasks = filteredTasks.filter((task) =>
|
||||
task.name.includes(keyword)
|
||||
);
|
||||
}
|
||||
if (status && status.length > 0) {
|
||||
filteredTasks = filteredTasks.filter((task) =>
|
||||
status.includes(task.status)
|
||||
);
|
||||
}
|
||||
const startIndex = page * size;
|
||||
const endIndex = startIndex + size;
|
||||
const paginatedTasks = filteredTasks.slice(startIndex, endIndex);
|
||||
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Success",
|
||||
data: {
|
||||
totalElements: filteredTasks.length,
|
||||
page,
|
||||
size,
|
||||
content: paginatedTasks,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
router.get(API.queryDataXTemplatesUsingGet, (req, res) => {
|
||||
const { keyword, page = 0, size = 10 } = req.query;
|
||||
let filteredTemplates = templateList;
|
||||
if (keyword) {
|
||||
filteredTemplates = filteredTemplates.filter((template) =>
|
||||
template.name.includes(keyword)
|
||||
);
|
||||
}
|
||||
const startIndex = page * size;
|
||||
const endIndex = startIndex + size;
|
||||
const paginatedTemplates = filteredTemplates.slice(startIndex, endIndex);
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Success",
|
||||
data: {
|
||||
content: paginatedTemplates,
|
||||
totalElements: filteredTemplates.length,
|
||||
page,
|
||||
size,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
// 创建任务
|
||||
router.post(API.createTaskUsingPost, (req, res) => {
|
||||
taskList.unshift(taskItem()); // 添加一个新的任务到列表开头
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "任务创建成功",
|
||||
data: {
|
||||
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
// 更新任务
|
||||
router.post(API.updateTaskByIdUsingPut, (req, res) => {
|
||||
const { id } = req.body;
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Data source task updated successfully",
|
||||
data: taskList.find((task) => task.id === id),
|
||||
});
|
||||
});
|
||||
|
||||
// 删除任务
|
||||
router.post(API.deleteTaskByIdUsingDelete, (req, res) => {
|
||||
const { id } = req.body;
|
||||
const index = taskList.findIndex((task) => task.id === id);
|
||||
if (index !== -1) {
|
||||
taskList.splice(index, 1);
|
||||
}
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Data source task deleted successfully",
|
||||
data: null,
|
||||
});
|
||||
});
|
||||
|
||||
// 执行任务
|
||||
router.post(API.executeTaskByIdUsingPost, (req, res) => {
|
||||
console.log("Received request to execute task", req.body);
|
||||
const { id } = req.body;
|
||||
console.log("Executing task with ID:", id);
|
||||
taskList.find((task) => task.id === id).status = "RUNNING";
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Data source task execution started",
|
||||
data: null,
|
||||
});
|
||||
});
|
||||
|
||||
// 停止任务
|
||||
router.post(API.stopTaskByIdUsingPost, (req, res) => {
|
||||
const { id } = req.body;
|
||||
const task = taskList.find((task) => task.id === id);
|
||||
if (task) {
|
||||
task.status = "STOPPED";
|
||||
}
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Data source task stopped successfully",
|
||||
data: null,
|
||||
});
|
||||
});
|
||||
|
||||
// 获取任务执行日志
|
||||
router.post(API.queryExecutionLogUsingPost, (req, res) => {
|
||||
const { keyword, page = 1, size = 10, status } = req.body;
|
||||
let filteredLogs = executionLogList;
|
||||
if (keyword) {
|
||||
filteredLogs = filteredLogs.filter((log) =>
|
||||
log.taskName.includes(keyword)
|
||||
);
|
||||
}
|
||||
if (status && status.length > 0) {
|
||||
filteredLogs = filteredLogs.filter((log) => status.includes(log.status));
|
||||
}
|
||||
const startIndex = (page - 1) * size;
|
||||
const endIndex = startIndex + size;
|
||||
const paginatedLogs = filteredLogs.slice(startIndex, endIndex);
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Success",
|
||||
data: {
|
||||
totalElements: filteredLogs.length,
|
||||
page,
|
||||
size,
|
||||
results: paginatedLogs,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
// 获取任务执行日志详情
|
||||
router.post(API.queryExecutionLogByIdUsingGet, (req, res) => {
|
||||
const { id } = req.body;
|
||||
const log = executionLogList.find((log) => log.id === id);
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Success",
|
||||
data: log,
|
||||
});
|
||||
});
|
||||
};
|
||||
const Mock = require("mockjs");
|
||||
const API = require("../mock-apis.cjs");
|
||||
const { Random } = Mock;
|
||||
|
||||
// 生成模拟数据归集统计信息
|
||||
function dataXTemplate() {
|
||||
return {
|
||||
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
name: Mock.Random.ctitle(5, 15),
|
||||
sourceType: Mock.Random.csentence(3, 10),
|
||||
targetType: Mock.Random.csentence(3, 10),
|
||||
description: Mock.Random.csentence(5, 20),
|
||||
version: `v${Mock.Random.integer(1, 5)}.${Mock.Random.integer(
|
||||
0,
|
||||
9
|
||||
)}.${Mock.Random.integer(0, 9)}`,
|
||||
isSystem: Mock.Random.boolean(),
|
||||
createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
|
||||
updatedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
|
||||
};
|
||||
}
|
||||
|
||||
const templateList = new Array(20).fill(null).map(dataXTemplate);
|
||||
|
||||
// 生成模拟任务数据
|
||||
function taskItem() {
|
||||
return {
|
||||
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
name: Mock.Random.ctitle(5, 20),
|
||||
description: Mock.Random.csentence(5, 20),
|
||||
syncMode: Mock.Random.pick(["ONCE", "SCHEDULED"]),
|
||||
config: {
|
||||
query: "SELECT * FROM table WHERE condition",
|
||||
batchSize: Mock.Random.integer(100, 1000),
|
||||
frequency: Mock.Random.integer(1, 60), // in minutes
|
||||
},
|
||||
scheduleExpression: "0 0 * * *", // cron expression
|
||||
lastExecutionId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
status: Mock.Random.pick([
|
||||
"DRAFT",
|
||||
"READY",
|
||||
"RUNNING",
|
||||
"FAILED",
|
||||
"STOPPED",
|
||||
"SUCCESS",
|
||||
]),
|
||||
createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
|
||||
updatedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
|
||||
sourceDataSourceId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
sourceDataSourceName: Mock.Random.ctitle(5, 20),
|
||||
targetDataSourceId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
targetDataSourceName: Mock.Random.ctitle(5, 20),
|
||||
};
|
||||
}
|
||||
|
||||
const taskList = new Array(50).fill(null).map(taskItem);
|
||||
|
||||
// 生成模拟任务执行日志数据
|
||||
function executionLogItem() {
|
||||
return {
|
||||
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
taskName: Mock.Random.ctitle(5, 20),
|
||||
dataSource: Mock.Random.ctitle(5, 15),
|
||||
startTime: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
|
||||
endTime: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
|
||||
status: Mock.Random.pick(["SUCCESS", "FAILED", "RUNNING"]),
|
||||
triggerType: Mock.Random.pick(["MANUAL", "SCHEDULED", "API"]),
|
||||
duration: Mock.Random.integer(1, 120),
|
||||
retryCount: Mock.Random.integer(0, 5),
|
||||
recordsProcessed: Mock.Random.integer(100, 10000),
|
||||
processId: Mock.Random.integer(1000, 9999),
|
||||
errorMessage: Mock.Random.boolean() ? "" : Mock.Random.csentence(5, 20),
|
||||
};
|
||||
}
|
||||
|
||||
const executionLogList = new Array(100).fill(null).map(executionLogItem);
|
||||
|
||||
module.exports = function (router) {
|
||||
// 获取任务列表
|
||||
router.get(API.queryTasksUsingGet, (req, res) => {
|
||||
const { keyword, status, page = 0, size = 10 } = req.query;
|
||||
let filteredTasks = taskList;
|
||||
if (keyword) {
|
||||
filteredTasks = filteredTasks.filter((task) =>
|
||||
task.name.includes(keyword)
|
||||
);
|
||||
}
|
||||
if (status && status.length > 0) {
|
||||
filteredTasks = filteredTasks.filter((task) =>
|
||||
status.includes(task.status)
|
||||
);
|
||||
}
|
||||
const startIndex = page * size;
|
||||
const endIndex = startIndex + size;
|
||||
const paginatedTasks = filteredTasks.slice(startIndex, endIndex);
|
||||
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Success",
|
||||
data: {
|
||||
totalElements: filteredTasks.length,
|
||||
page,
|
||||
size,
|
||||
content: paginatedTasks,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
router.get(API.queryDataXTemplatesUsingGet, (req, res) => {
|
||||
const { keyword, page = 0, size = 10 } = req.query;
|
||||
let filteredTemplates = templateList;
|
||||
if (keyword) {
|
||||
filteredTemplates = filteredTemplates.filter((template) =>
|
||||
template.name.includes(keyword)
|
||||
);
|
||||
}
|
||||
const startIndex = page * size;
|
||||
const endIndex = startIndex + size;
|
||||
const paginatedTemplates = filteredTemplates.slice(startIndex, endIndex);
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Success",
|
||||
data: {
|
||||
content: paginatedTemplates,
|
||||
totalElements: filteredTemplates.length,
|
||||
page,
|
||||
size,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
// 创建任务
|
||||
router.post(API.createTaskUsingPost, (req, res) => {
|
||||
taskList.unshift(taskItem()); // 添加一个新的任务到列表开头
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "任务创建成功",
|
||||
data: {
|
||||
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
// 更新任务
|
||||
router.post(API.updateTaskByIdUsingPut, (req, res) => {
|
||||
const { id } = req.body;
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Data source task updated successfully",
|
||||
data: taskList.find((task) => task.id === id),
|
||||
});
|
||||
});
|
||||
|
||||
// 删除任务
|
||||
router.post(API.deleteTaskByIdUsingDelete, (req, res) => {
|
||||
const { id } = req.body;
|
||||
const index = taskList.findIndex((task) => task.id === id);
|
||||
if (index !== -1) {
|
||||
taskList.splice(index, 1);
|
||||
}
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Data source task deleted successfully",
|
||||
data: null,
|
||||
});
|
||||
});
|
||||
|
||||
// 执行任务
|
||||
router.post(API.executeTaskByIdUsingPost, (req, res) => {
|
||||
console.log("Received request to execute task", req.body);
|
||||
const { id } = req.body;
|
||||
console.log("Executing task with ID:", id);
|
||||
taskList.find((task) => task.id === id).status = "RUNNING";
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Data source task execution started",
|
||||
data: null,
|
||||
});
|
||||
});
|
||||
|
||||
// 停止任务
|
||||
router.post(API.stopTaskByIdUsingPost, (req, res) => {
|
||||
const { id } = req.body;
|
||||
const task = taskList.find((task) => task.id === id);
|
||||
if (task) {
|
||||
task.status = "STOPPED";
|
||||
}
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Data source task stopped successfully",
|
||||
data: null,
|
||||
});
|
||||
});
|
||||
|
||||
// 获取任务执行日志
|
||||
router.post(API.queryExecutionLogUsingPost, (req, res) => {
|
||||
const { keyword, page = 1, size = 10, status } = req.body;
|
||||
let filteredLogs = executionLogList;
|
||||
if (keyword) {
|
||||
filteredLogs = filteredLogs.filter((log) =>
|
||||
log.taskName.includes(keyword)
|
||||
);
|
||||
}
|
||||
if (status && status.length > 0) {
|
||||
filteredLogs = filteredLogs.filter((log) => status.includes(log.status));
|
||||
}
|
||||
const startIndex = (page - 1) * size;
|
||||
const endIndex = startIndex + size;
|
||||
const paginatedLogs = filteredLogs.slice(startIndex, endIndex);
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Success",
|
||||
data: {
|
||||
totalElements: filteredLogs.length,
|
||||
page,
|
||||
size,
|
||||
results: paginatedLogs,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
// 获取任务执行日志详情
|
||||
router.post(API.queryExecutionLogByIdUsingGet, (req, res) => {
|
||||
const { id } = req.body;
|
||||
const log = executionLogList.find((log) => log.id === id);
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Success",
|
||||
data: log,
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,435 +1,435 @@
|
||||
const Mock = require("mockjs");
|
||||
const API = require("../mock-apis.cjs");
|
||||
|
||||
function tagItem() {
|
||||
return {
|
||||
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
name: Mock.Random.word(3, 10),
|
||||
description: Mock.Random.csentence(5, 20),
|
||||
color: Mock.Random.color(),
|
||||
usageCount: Mock.Random.integer(0, 100),
|
||||
};
|
||||
}
|
||||
const tagList = new Array(20).fill(null).map((_, index) => tagItem(index));
|
||||
|
||||
function datasetItem() {
|
||||
return {
|
||||
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
name: Mock.Random.ctitle(5, 20),
|
||||
datasetType: Mock.Random.pick(["TEXT", "IMAGE", "AUDIO", "VIDEO"]),
|
||||
status: Mock.Random.pick(["DRAFT","ACTIVE", "INACTIVE", "PROCESSING"]),
|
||||
tags: Mock.Random.shuffle(tagList).slice(0, Mock.Random.integer(1, 3)),
|
||||
totalSize: Mock.Random.integer(1024, 1024 * 1024 * 1024), // in bytes
|
||||
description: Mock.Random.cparagraph(1, 3),
|
||||
createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
|
||||
updatedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
|
||||
createdBy: Mock.Random.cname(),
|
||||
updatedBy: Mock.Random.cname(),
|
||||
};
|
||||
}
|
||||
|
||||
const datasetList = new Array(50)
|
||||
.fill(null)
|
||||
.map((_, index) => datasetItem(index));
|
||||
|
||||
function datasetFileItem() {
|
||||
return {
|
||||
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
fileName:
|
||||
Mock.Random.word(5, 15) +
|
||||
"." +
|
||||
Mock.Random.pick(["csv", "json", "xml", "parquet", "avro"]),
|
||||
originName:
|
||||
Mock.Random.word(5, 15) +
|
||||
"." +
|
||||
Mock.Random.pick(["csv", "json", "xml", "parquet", "avro"]),
|
||||
fileType: Mock.Random.pick(["CSV", "JSON", "XML", "Parquet", "Avro"]),
|
||||
size: Mock.Random.integer(1024, 1024 * 1024 * 1024), // in bytes
|
||||
type: Mock.Random.pick(["CSV", "JSON", "XML", "Parquet", "Avro"]),
|
||||
status: Mock.Random.pick(["UPLOADED", "PROCESSING", "COMPLETED", "ERROR"]),
|
||||
description: Mock.Random.csentence(5, 20),
|
||||
filePath: "/path/to/file/" + Mock.Random.word(5, 10),
|
||||
uploadedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
|
||||
uploadedBy: Mock.Random.cname(),
|
||||
};
|
||||
}
|
||||
|
||||
const datasetFileList = new Array(200)
|
||||
.fill(null)
|
||||
.map((_, index) => datasetFileItem(index));
|
||||
|
||||
const datasetStatistics = {
|
||||
count: {
|
||||
text: 10,
|
||||
image: 34,
|
||||
audio: 23,
|
||||
video: 5,
|
||||
},
|
||||
size: {
|
||||
text: "120 MB",
|
||||
image: "3.4 GB",
|
||||
audio: "2.3 GB",
|
||||
video: "15 GB",
|
||||
},
|
||||
totalDatasets: datasetList.length,
|
||||
totalFiles: datasetFileList.length,
|
||||
completedFiles: datasetFileList.filter((file) => file.status === "COMPLETED")
|
||||
.length,
|
||||
totalSize: datasetFileList.reduce((acc, file) => acc + file.size, 0), // in bytes
|
||||
completionRate:
|
||||
datasetFileList.length === 0
|
||||
? 0
|
||||
: Math.round(
|
||||
(datasetFileList.filter((file) => file.status === "COMPLETED")
|
||||
.length /
|
||||
datasetFileList.length) *
|
||||
100
|
||||
), // percentage
|
||||
};
|
||||
|
||||
const datasetTypes = [
|
||||
{
|
||||
code: "PRETRAIN",
|
||||
name: "预训练数据集",
|
||||
description: "用于模型预训练的大规模数据集",
|
||||
supportedFormats: ["txt", "json", "csv", "parquet"],
|
||||
icon: "brain",
|
||||
},
|
||||
{
|
||||
code: "FINE_TUNE",
|
||||
name: "微调数据集",
|
||||
description: "用于模型微调的专业数据集",
|
||||
supportedFormats: ["json", "csv", "xlsx"],
|
||||
icon: "tune",
|
||||
},
|
||||
{
|
||||
code: "EVAL",
|
||||
name: "评估数据集",
|
||||
description: "用于模型评估的标准数据集",
|
||||
supportedFormats: ["json", "csv", "xml"],
|
||||
icon: "assessment",
|
||||
},
|
||||
];
|
||||
|
||||
module.exports = { datasetList };
|
||||
module.exports = function (router) {
|
||||
// 获取数据统计信息
|
||||
router.get(API.queryDatasetStatisticsUsingGet, (req, res) => {
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Success",
|
||||
data: datasetStatistics,
|
||||
});
|
||||
});
|
||||
|
||||
// 创建数据
|
||||
router.post(API.createDatasetUsingPost, (req, res) => {
|
||||
const newDataset = {
|
||||
...req.body,
|
||||
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
status: "ACTIVE",
|
||||
fileCount: 0,
|
||||
totalSize: 0,
|
||||
completionRate: 0,
|
||||
createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
|
||||
updatedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
|
||||
createdBy: "Admin",
|
||||
updatedBy: "Admin",
|
||||
tags: tagList.filter((tag) => req.body?.tagIds?.includes?.(tag.id)),
|
||||
};
|
||||
datasetList.unshift(newDataset); // Add to the beginning of the list
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Dataset created successfully",
|
||||
data: newDataset,
|
||||
});
|
||||
});
|
||||
|
||||
// 获取数据集列表
|
||||
router.get(API.queryDatasetsUsingGet, (req, res) => {
|
||||
const { page = 0, size = 10, keyword, type, status, tags } = req.query;
|
||||
console.log("Received query params:", req.query);
|
||||
|
||||
let filteredDatasets = datasetList;
|
||||
if (keyword) {
|
||||
console.log("filter keyword:", keyword);
|
||||
|
||||
filteredDatasets = filteredDatasets.filter(
|
||||
(dataset) =>
|
||||
dataset.name.includes(keyword) ||
|
||||
dataset.description.includes(keyword)
|
||||
);
|
||||
}
|
||||
if (type) {
|
||||
filteredDatasets = filteredDatasets.filter(
|
||||
(dataset) => dataset.datasetType === type
|
||||
);
|
||||
}
|
||||
if (status) {
|
||||
console.log("filter status:", status);
|
||||
filteredDatasets = filteredDatasets.filter(
|
||||
(dataset) => dataset.status === status
|
||||
);
|
||||
}
|
||||
if (tags && tags.length > 0) {
|
||||
console.log("filter tags:", tags);
|
||||
filteredDatasets = filteredDatasets.filter((dataset) =>
|
||||
tags.every((tag) => dataset.tags.some((t) => t.name === tag))
|
||||
);
|
||||
}
|
||||
|
||||
const totalElements = filteredDatasets.length;
|
||||
const paginatedDatasets = filteredDatasets.slice(
|
||||
page * size,
|
||||
(page + 1) * size
|
||||
);
|
||||
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Success",
|
||||
data: {
|
||||
totalElements,
|
||||
page,
|
||||
size,
|
||||
content: paginatedDatasets,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
// 根据ID获取数据集详情
|
||||
router.get(API.queryDatasetByIdUsingGet, (req, res) => {
|
||||
const { id } = req.params;
|
||||
|
||||
const dataset = datasetList.find((d) => d.id === id);
|
||||
if (dataset) {
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Success",
|
||||
data: dataset,
|
||||
});
|
||||
} else {
|
||||
res.status(404).send({
|
||||
code: "1",
|
||||
msg: "Dataset not found",
|
||||
data: null,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 更新数据集
|
||||
router.put(API.updateDatasetByIdUsingPut, (req, res) => {
|
||||
const { id } = req.params;
|
||||
let { tags } = req.body;
|
||||
|
||||
const index = datasetList.findIndex((d) => d.id === id);
|
||||
tags = [...datasetList[index].tags.map((tag) => tag.name), ...tags];
|
||||
if (index !== -1) {
|
||||
datasetList[index] = {
|
||||
...datasetList[index],
|
||||
...req.body,
|
||||
tags: tagList.filter((tag) => tags?.includes?.(tag.name)),
|
||||
updatedAt: new Date().toISOString(),
|
||||
updatedBy: "Admin",
|
||||
};
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Dataset updated successfully",
|
||||
data: datasetList[index],
|
||||
});
|
||||
} else {
|
||||
res.status(404).send({
|
||||
code: "1",
|
||||
msg: "Dataset not found",
|
||||
data: null,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 删除数据集
|
||||
router.delete(API.deleteDatasetByIdUsingDelete, (req, res) => {
|
||||
const { datasetId } = req.params;
|
||||
const index = datasetList.findIndex((d) => d.id === datasetId);
|
||||
|
||||
if (index !== -1) {
|
||||
datasetList.splice(index, 1);
|
||||
res.status(204).send();
|
||||
} else {
|
||||
res.status(404).send({
|
||||
code: "1",
|
||||
msg: "Dataset not found",
|
||||
data: null,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 获取数据集文件列表
|
||||
router.get(API.queryFilesUsingGet, (req, res) => {
|
||||
const { datasetId } = req.params;
|
||||
const { page = 0, size = 20, fileType, status } = req.query;
|
||||
|
||||
let filteredFiles = datasetFileList;
|
||||
|
||||
if (fileType) {
|
||||
filteredFiles = filteredFiles.filter(
|
||||
(file) => file.fileType === fileType
|
||||
);
|
||||
}
|
||||
|
||||
if (status) {
|
||||
filteredFiles = filteredFiles.filter((file) => file.status === status);
|
||||
}
|
||||
|
||||
const startIndex = page * size;
|
||||
const endIndex = startIndex + parseInt(size);
|
||||
const pageData = filteredFiles.slice(startIndex, endIndex);
|
||||
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Success",
|
||||
data: {
|
||||
content: pageData,
|
||||
page: parseInt(page),
|
||||
size: parseInt(size),
|
||||
totalElements: filteredFiles.length,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
// 上传文件到数据集
|
||||
router.post(API.uploadFileUsingPost, (req, res) => {
|
||||
const { datasetId } = req.params;
|
||||
const newFile = {
|
||||
...datasetFileItem(),
|
||||
...req.body,
|
||||
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
uploadedAt: new Date().toISOString(),
|
||||
uploadedBy: "Admin",
|
||||
};
|
||||
|
||||
datasetFileList.push(newFile);
|
||||
|
||||
res.status(201).send({
|
||||
code: "0",
|
||||
msg: "File uploaded successfully",
|
||||
data: newFile,
|
||||
});
|
||||
});
|
||||
|
||||
// 获取文件详情
|
||||
router.get(API.queryFileByIdUsingGet, (req, res) => {
|
||||
const { datasetId, fileId } = req.params;
|
||||
const file = datasetFileList.find((f) => f.id === fileId);
|
||||
|
||||
if (file) {
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Success",
|
||||
data: file,
|
||||
});
|
||||
} else {
|
||||
res.status(404).send({
|
||||
code: "1",
|
||||
msg: "File not found",
|
||||
data: null,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 删除文件
|
||||
router.delete(API.deleteFileByIdUsingDelete, (req, res) => {
|
||||
const { datasetId, fileId } = req.params;
|
||||
const index = datasetFileList.findIndex((f) => f.id === fileId);
|
||||
|
||||
if (index !== -1) {
|
||||
datasetFileList.splice(index, 1);
|
||||
res.status(204).send();
|
||||
} else {
|
||||
res.status(404).send({
|
||||
code: "1",
|
||||
msg: "File not found",
|
||||
data: null,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 下载文件
|
||||
router.get(API.downloadFileByIdUsingGet, (req, res) => {
|
||||
const { datasetId, fileId } = req.params;
|
||||
const file = datasetFileList.find((f) => f.id === fileId);
|
||||
|
||||
if (file) {
|
||||
res.setHeader(
|
||||
"Content-Disposition",
|
||||
`attachment; filename="${file.fileName}"`
|
||||
);
|
||||
res.setHeader("Content-Type", "application/octet-stream");
|
||||
res.send(`Mock file content for ${file.fileName}`);
|
||||
} else {
|
||||
res.status(404).send({
|
||||
code: "1",
|
||||
msg: "File not found",
|
||||
data: null,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 获取数据集类型列表
|
||||
router.get(API.queryDatasetTypesUsingGet, (req, res) => {
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Success",
|
||||
data: datasetTypes,
|
||||
});
|
||||
});
|
||||
|
||||
// 获取标签列表
|
||||
router.get(API.queryTagsUsingGet, (req, res) => {
|
||||
const { keyword } = req.query;
|
||||
let filteredTags = tagList;
|
||||
|
||||
if (keyword) {
|
||||
filteredTags = tagList.filter((tag) =>
|
||||
tag.name.toLowerCase().includes(keyword.toLowerCase())
|
||||
);
|
||||
}
|
||||
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Success",
|
||||
data: filteredTags,
|
||||
});
|
||||
});
|
||||
|
||||
// 创建标签
|
||||
router.post(API.createTagUsingPost, (req, res) => {
|
||||
const newTag = {
|
||||
...tagItem(),
|
||||
...req.body,
|
||||
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
usageCount: 0,
|
||||
};
|
||||
|
||||
tagList.push(newTag);
|
||||
|
||||
res.status(201).send({
|
||||
code: "0",
|
||||
msg: "Tag created successfully",
|
||||
data: newTag,
|
||||
});
|
||||
});
|
||||
|
||||
router.post(API.preUploadFileUsingPost, (req, res) => {
|
||||
res.status(201).send(Mock.Random.guid());
|
||||
});
|
||||
|
||||
// 上传
|
||||
router.post(API.uploadFileChunkUsingPost, (req, res) => {
|
||||
res.status(500).send({ message: "Simulated upload failure" });
|
||||
// res.status(201).send({ data: "success" });
|
||||
});
|
||||
|
||||
// 取消上传
|
||||
router.put(API.cancelUploadUsingPut, (req, res) => {
|
||||
res.status(201).send({ data: "success" });
|
||||
});
|
||||
};
|
||||
const Mock = require("mockjs");
|
||||
const API = require("../mock-apis.cjs");
|
||||
|
||||
function tagItem() {
|
||||
return {
|
||||
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
name: Mock.Random.word(3, 10),
|
||||
description: Mock.Random.csentence(5, 20),
|
||||
color: Mock.Random.color(),
|
||||
usageCount: Mock.Random.integer(0, 100),
|
||||
};
|
||||
}
|
||||
const tagList = new Array(20).fill(null).map((_, index) => tagItem(index));
|
||||
|
||||
function datasetItem() {
|
||||
return {
|
||||
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
name: Mock.Random.ctitle(5, 20),
|
||||
datasetType: Mock.Random.pick(["TEXT", "IMAGE", "AUDIO", "VIDEO"]),
|
||||
status: Mock.Random.pick(["DRAFT","ACTIVE", "INACTIVE", "PROCESSING"]),
|
||||
tags: Mock.Random.shuffle(tagList).slice(0, Mock.Random.integer(1, 3)),
|
||||
totalSize: Mock.Random.integer(1024, 1024 * 1024 * 1024), // in bytes
|
||||
description: Mock.Random.cparagraph(1, 3),
|
||||
createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
|
||||
updatedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
|
||||
createdBy: Mock.Random.cname(),
|
||||
updatedBy: Mock.Random.cname(),
|
||||
};
|
||||
}
|
||||
|
||||
const datasetList = new Array(50)
|
||||
.fill(null)
|
||||
.map((_, index) => datasetItem(index));
|
||||
|
||||
function datasetFileItem() {
|
||||
return {
|
||||
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
fileName:
|
||||
Mock.Random.word(5, 15) +
|
||||
"." +
|
||||
Mock.Random.pick(["csv", "json", "xml", "parquet", "avro"]),
|
||||
originName:
|
||||
Mock.Random.word(5, 15) +
|
||||
"." +
|
||||
Mock.Random.pick(["csv", "json", "xml", "parquet", "avro"]),
|
||||
fileType: Mock.Random.pick(["CSV", "JSON", "XML", "Parquet", "Avro"]),
|
||||
size: Mock.Random.integer(1024, 1024 * 1024 * 1024), // in bytes
|
||||
type: Mock.Random.pick(["CSV", "JSON", "XML", "Parquet", "Avro"]),
|
||||
status: Mock.Random.pick(["UPLOADED", "PROCESSING", "COMPLETED", "ERROR"]),
|
||||
description: Mock.Random.csentence(5, 20),
|
||||
filePath: "/path/to/file/" + Mock.Random.word(5, 10),
|
||||
uploadedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
|
||||
uploadedBy: Mock.Random.cname(),
|
||||
};
|
||||
}
|
||||
|
||||
const datasetFileList = new Array(200)
|
||||
.fill(null)
|
||||
.map((_, index) => datasetFileItem(index));
|
||||
|
||||
const datasetStatistics = {
|
||||
count: {
|
||||
text: 10,
|
||||
image: 34,
|
||||
audio: 23,
|
||||
video: 5,
|
||||
},
|
||||
size: {
|
||||
text: "120 MB",
|
||||
image: "3.4 GB",
|
||||
audio: "2.3 GB",
|
||||
video: "15 GB",
|
||||
},
|
||||
totalDatasets: datasetList.length,
|
||||
totalFiles: datasetFileList.length,
|
||||
completedFiles: datasetFileList.filter((file) => file.status === "COMPLETED")
|
||||
.length,
|
||||
totalSize: datasetFileList.reduce((acc, file) => acc + file.size, 0), // in bytes
|
||||
completionRate:
|
||||
datasetFileList.length === 0
|
||||
? 0
|
||||
: Math.round(
|
||||
(datasetFileList.filter((file) => file.status === "COMPLETED")
|
||||
.length /
|
||||
datasetFileList.length) *
|
||||
100
|
||||
), // percentage
|
||||
};
|
||||
|
||||
const datasetTypes = [
|
||||
{
|
||||
code: "PRETRAIN",
|
||||
name: "预训练数据集",
|
||||
description: "用于模型预训练的大规模数据集",
|
||||
supportedFormats: ["txt", "json", "csv", "parquet"],
|
||||
icon: "brain",
|
||||
},
|
||||
{
|
||||
code: "FINE_TUNE",
|
||||
name: "微调数据集",
|
||||
description: "用于模型微调的专业数据集",
|
||||
supportedFormats: ["json", "csv", "xlsx"],
|
||||
icon: "tune",
|
||||
},
|
||||
{
|
||||
code: "EVAL",
|
||||
name: "评估数据集",
|
||||
description: "用于模型评估的标准数据集",
|
||||
supportedFormats: ["json", "csv", "xml"],
|
||||
icon: "assessment",
|
||||
},
|
||||
];
|
||||
|
||||
module.exports = { datasetList };
|
||||
module.exports = function (router) {
|
||||
// 获取数据统计信息
|
||||
router.get(API.queryDatasetStatisticsUsingGet, (req, res) => {
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Success",
|
||||
data: datasetStatistics,
|
||||
});
|
||||
});
|
||||
|
||||
// 创建数据
|
||||
router.post(API.createDatasetUsingPost, (req, res) => {
|
||||
const newDataset = {
|
||||
...req.body,
|
||||
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
status: "ACTIVE",
|
||||
fileCount: 0,
|
||||
totalSize: 0,
|
||||
completionRate: 0,
|
||||
createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
|
||||
updatedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
|
||||
createdBy: "Admin",
|
||||
updatedBy: "Admin",
|
||||
tags: tagList.filter((tag) => req.body?.tagIds?.includes?.(tag.id)),
|
||||
};
|
||||
datasetList.unshift(newDataset); // Add to the beginning of the list
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Dataset created successfully",
|
||||
data: newDataset,
|
||||
});
|
||||
});
|
||||
|
||||
// 获取数据集列表
|
||||
router.get(API.queryDatasetsUsingGet, (req, res) => {
|
||||
const { page = 0, size = 10, keyword, type, status, tags } = req.query;
|
||||
console.log("Received query params:", req.query);
|
||||
|
||||
let filteredDatasets = datasetList;
|
||||
if (keyword) {
|
||||
console.log("filter keyword:", keyword);
|
||||
|
||||
filteredDatasets = filteredDatasets.filter(
|
||||
(dataset) =>
|
||||
dataset.name.includes(keyword) ||
|
||||
dataset.description.includes(keyword)
|
||||
);
|
||||
}
|
||||
if (type) {
|
||||
filteredDatasets = filteredDatasets.filter(
|
||||
(dataset) => dataset.datasetType === type
|
||||
);
|
||||
}
|
||||
if (status) {
|
||||
console.log("filter status:", status);
|
||||
filteredDatasets = filteredDatasets.filter(
|
||||
(dataset) => dataset.status === status
|
||||
);
|
||||
}
|
||||
if (tags && tags.length > 0) {
|
||||
console.log("filter tags:", tags);
|
||||
filteredDatasets = filteredDatasets.filter((dataset) =>
|
||||
tags.every((tag) => dataset.tags.some((t) => t.name === tag))
|
||||
);
|
||||
}
|
||||
|
||||
const totalElements = filteredDatasets.length;
|
||||
const paginatedDatasets = filteredDatasets.slice(
|
||||
page * size,
|
||||
(page + 1) * size
|
||||
);
|
||||
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Success",
|
||||
data: {
|
||||
totalElements,
|
||||
page,
|
||||
size,
|
||||
content: paginatedDatasets,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
// 根据ID获取数据集详情
|
||||
router.get(API.queryDatasetByIdUsingGet, (req, res) => {
|
||||
const { id } = req.params;
|
||||
|
||||
const dataset = datasetList.find((d) => d.id === id);
|
||||
if (dataset) {
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Success",
|
||||
data: dataset,
|
||||
});
|
||||
} else {
|
||||
res.status(404).send({
|
||||
code: "1",
|
||||
msg: "Dataset not found",
|
||||
data: null,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 更新数据集
|
||||
router.put(API.updateDatasetByIdUsingPut, (req, res) => {
|
||||
const { id } = req.params;
|
||||
let { tags } = req.body;
|
||||
|
||||
const index = datasetList.findIndex((d) => d.id === id);
|
||||
tags = [...datasetList[index].tags.map((tag) => tag.name), ...tags];
|
||||
if (index !== -1) {
|
||||
datasetList[index] = {
|
||||
...datasetList[index],
|
||||
...req.body,
|
||||
tags: tagList.filter((tag) => tags?.includes?.(tag.name)),
|
||||
updatedAt: new Date().toISOString(),
|
||||
updatedBy: "Admin",
|
||||
};
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Dataset updated successfully",
|
||||
data: datasetList[index],
|
||||
});
|
||||
} else {
|
||||
res.status(404).send({
|
||||
code: "1",
|
||||
msg: "Dataset not found",
|
||||
data: null,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 删除数据集
|
||||
router.delete(API.deleteDatasetByIdUsingDelete, (req, res) => {
|
||||
const { datasetId } = req.params;
|
||||
const index = datasetList.findIndex((d) => d.id === datasetId);
|
||||
|
||||
if (index !== -1) {
|
||||
datasetList.splice(index, 1);
|
||||
res.status(204).send();
|
||||
} else {
|
||||
res.status(404).send({
|
||||
code: "1",
|
||||
msg: "Dataset not found",
|
||||
data: null,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 获取数据集文件列表
|
||||
router.get(API.queryFilesUsingGet, (req, res) => {
|
||||
const { datasetId } = req.params;
|
||||
const { page = 0, size = 20, fileType, status } = req.query;
|
||||
|
||||
let filteredFiles = datasetFileList;
|
||||
|
||||
if (fileType) {
|
||||
filteredFiles = filteredFiles.filter(
|
||||
(file) => file.fileType === fileType
|
||||
);
|
||||
}
|
||||
|
||||
if (status) {
|
||||
filteredFiles = filteredFiles.filter((file) => file.status === status);
|
||||
}
|
||||
|
||||
const startIndex = page * size;
|
||||
const endIndex = startIndex + parseInt(size);
|
||||
const pageData = filteredFiles.slice(startIndex, endIndex);
|
||||
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Success",
|
||||
data: {
|
||||
content: pageData,
|
||||
page: parseInt(page),
|
||||
size: parseInt(size),
|
||||
totalElements: filteredFiles.length,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
// 上传文件到数据集
|
||||
router.post(API.uploadFileUsingPost, (req, res) => {
|
||||
const { datasetId } = req.params;
|
||||
const newFile = {
|
||||
...datasetFileItem(),
|
||||
...req.body,
|
||||
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
uploadedAt: new Date().toISOString(),
|
||||
uploadedBy: "Admin",
|
||||
};
|
||||
|
||||
datasetFileList.push(newFile);
|
||||
|
||||
res.status(201).send({
|
||||
code: "0",
|
||||
msg: "File uploaded successfully",
|
||||
data: newFile,
|
||||
});
|
||||
});
|
||||
|
||||
// 获取文件详情
|
||||
router.get(API.queryFileByIdUsingGet, (req, res) => {
|
||||
const { datasetId, fileId } = req.params;
|
||||
const file = datasetFileList.find((f) => f.id === fileId);
|
||||
|
||||
if (file) {
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Success",
|
||||
data: file,
|
||||
});
|
||||
} else {
|
||||
res.status(404).send({
|
||||
code: "1",
|
||||
msg: "File not found",
|
||||
data: null,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 删除文件
|
||||
router.delete(API.deleteFileByIdUsingDelete, (req, res) => {
|
||||
const { datasetId, fileId } = req.params;
|
||||
const index = datasetFileList.findIndex((f) => f.id === fileId);
|
||||
|
||||
if (index !== -1) {
|
||||
datasetFileList.splice(index, 1);
|
||||
res.status(204).send();
|
||||
} else {
|
||||
res.status(404).send({
|
||||
code: "1",
|
||||
msg: "File not found",
|
||||
data: null,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 下载文件
|
||||
router.get(API.downloadFileByIdUsingGet, (req, res) => {
|
||||
const { datasetId, fileId } = req.params;
|
||||
const file = datasetFileList.find((f) => f.id === fileId);
|
||||
|
||||
if (file) {
|
||||
res.setHeader(
|
||||
"Content-Disposition",
|
||||
`attachment; filename="${file.fileName}"`
|
||||
);
|
||||
res.setHeader("Content-Type", "application/octet-stream");
|
||||
res.send(`Mock file content for ${file.fileName}`);
|
||||
} else {
|
||||
res.status(404).send({
|
||||
code: "1",
|
||||
msg: "File not found",
|
||||
data: null,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 获取数据集类型列表
|
||||
router.get(API.queryDatasetTypesUsingGet, (req, res) => {
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Success",
|
||||
data: datasetTypes,
|
||||
});
|
||||
});
|
||||
|
||||
// 获取标签列表
|
||||
router.get(API.queryTagsUsingGet, (req, res) => {
|
||||
const { keyword } = req.query;
|
||||
let filteredTags = tagList;
|
||||
|
||||
if (keyword) {
|
||||
filteredTags = tagList.filter((tag) =>
|
||||
tag.name.toLowerCase().includes(keyword.toLowerCase())
|
||||
);
|
||||
}
|
||||
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Success",
|
||||
data: filteredTags,
|
||||
});
|
||||
});
|
||||
|
||||
// 创建标签
|
||||
router.post(API.createTagUsingPost, (req, res) => {
|
||||
const newTag = {
|
||||
...tagItem(),
|
||||
...req.body,
|
||||
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
usageCount: 0,
|
||||
};
|
||||
|
||||
tagList.push(newTag);
|
||||
|
||||
res.status(201).send({
|
||||
code: "0",
|
||||
msg: "Tag created successfully",
|
||||
data: newTag,
|
||||
});
|
||||
});
|
||||
|
||||
router.post(API.preUploadFileUsingPost, (req, res) => {
|
||||
res.status(201).send(Mock.Random.guid());
|
||||
});
|
||||
|
||||
// 上传
|
||||
router.post(API.uploadFileChunkUsingPost, (req, res) => {
|
||||
res.status(500).send({ message: "Simulated upload failure" });
|
||||
// res.status(201).send({ data: "success" });
|
||||
});
|
||||
|
||||
// 取消上传
|
||||
router.put(API.cancelUploadUsingPut, (req, res) => {
|
||||
res.status(201).send({ data: "success" });
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,220 +1,220 @@
|
||||
|
||||
const Mock = require("mockjs");
|
||||
const API = require("../mock-apis.cjs");
|
||||
|
||||
function ratioJobItem() {
|
||||
return {
|
||||
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
name: Mock.Random.ctitle(5, 15),
|
||||
description: Mock.Random.csentence(10, 30),
|
||||
status: Mock.Random.pick(["PENDING", "RUNNING", "COMPLETED", "FAILED", "PAUSED"]),
|
||||
totals: Mock.Random.integer(1000, 10000),
|
||||
ratio_method: Mock.Random.pick(["DATASET", "TAG"]),
|
||||
target_dataset_id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
target_dataset_name: Mock.Random.ctitle(3, 8),
|
||||
config: [
|
||||
{
|
||||
datasetId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
counts: Mock.Random.integer(100, 1000).toString(),
|
||||
filter_conditions: "",
|
||||
},
|
||||
{
|
||||
datasetId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
counts: Mock.Random.integer(100, 1000).toString(),
|
||||
filter_conditions: "",
|
||||
},
|
||||
],
|
||||
created_at: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
|
||||
updated_at: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
|
||||
};
|
||||
}
|
||||
|
||||
const ratioJobList = new Array(20).fill(null).map(ratioJobItem);
|
||||
|
||||
|
||||
module.exports = function (router) {
|
||||
// 获取配比任务列表
|
||||
router.get(API.queryRatioTasksUsingGet, (req, res) => {
|
||||
const { page = 0, size = 10, status } = req.query;
|
||||
let filteredJobs = ratioJobList;
|
||||
if (status) {
|
||||
filteredJobs = ratioJobList.filter((job) => job.status === status);
|
||||
}
|
||||
const startIndex = page * size;
|
||||
const endIndex = startIndex + parseInt(size);
|
||||
const pageData = filteredJobs.slice(startIndex, endIndex);
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Success",
|
||||
data: {
|
||||
content: pageData,
|
||||
totalElements: filteredJobs.length,
|
||||
totalPages: Math.ceil(filteredJobs.length / size),
|
||||
size: parseInt(size),
|
||||
number: parseInt(page),
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
// 创建配比任务
|
||||
router.post(API.createRatioTaskUsingPost, (req, res) => {
|
||||
const newJob = {
|
||||
...ratioJobItem(),
|
||||
...req.body,
|
||||
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
status: "PENDING",
|
||||
createdAt: new Date().toISOString(),
|
||||
};
|
||||
ratioJobList.push(newJob);
|
||||
res.status(201).send({
|
||||
code: "0",
|
||||
msg: "Ratio job created successfully",
|
||||
data: newJob,
|
||||
});
|
||||
});
|
||||
|
||||
// 获取配比任务详情
|
||||
router.get(API.queryRatioTaskByIdUsingGet, (req, res) => {
|
||||
const { taskId } = req.params;
|
||||
const job = ratioJobList.find((j) => j.id === taskId);
|
||||
if (job) {
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Success",
|
||||
data: job,
|
||||
});
|
||||
} else {
|
||||
res.status(404).send({
|
||||
code: "1",
|
||||
msg: "Ratio job not found",
|
||||
data: null,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 删除配比任务
|
||||
router.delete(API.deleteRatioTaskByIdUsingDelete, (req, res) => {
|
||||
const { taskId } = req.params;
|
||||
const index = ratioJobList.findIndex((j) => j.id === taskId);
|
||||
if (index !== -1) {
|
||||
ratioJobList.splice(index, 1);
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Ratio job deleted successfully",
|
||||
data: null,
|
||||
});
|
||||
} else {
|
||||
res.status(404).send({
|
||||
code: "1",
|
||||
msg: "Ratio job not found",
|
||||
data: null,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 更新配比任务
|
||||
router.put(API.updateRatioTaskByIdUsingPut, (req, res) => {
|
||||
const { taskId } = req.params;
|
||||
const index = ratioJobList.findIndex((j) => j.id === taskId);
|
||||
if (index !== -1) {
|
||||
ratioJobList[index] = {
|
||||
...ratioJobList[index],
|
||||
...req.body,
|
||||
updatedAt: new Date().toISOString(),
|
||||
};
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Ratio job updated successfully",
|
||||
data: ratioJobList[index],
|
||||
});
|
||||
} else {
|
||||
res.status(404).send({
|
||||
code: "1",
|
||||
msg: "Ratio job not found",
|
||||
data: null,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 执行配比任务
|
||||
router.post(API.executeRatioTaskByIdUsingPost, (req, res) => {
|
||||
const { taskId } = req.params;
|
||||
const job = ratioJobList.find((j) => j.id === taskId);
|
||||
if (job) {
|
||||
job.status = "RUNNING";
|
||||
job.startedAt = new Date().toISOString();
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Ratio job execution started",
|
||||
data: {
|
||||
executionId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
status: "RUNNING",
|
||||
message: "Job execution started successfully",
|
||||
},
|
||||
});
|
||||
} else {
|
||||
res.status(404).send({
|
||||
code: "1",
|
||||
msg: "Ratio job not found",
|
||||
data: null,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 停止配比任务
|
||||
router.post(API.stopRatioTaskByIdUsingPost, (req, res) => {
|
||||
const { taskId } = req.params;
|
||||
const job = ratioJobList.find((j) => j.id === taskId);
|
||||
if (job) {
|
||||
job.status = "STOPPED";
|
||||
job.finishedAt = new Date().toISOString();
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Ratio job stopped successfully",
|
||||
data: null,
|
||||
});
|
||||
} else {
|
||||
res.status(404).send({
|
||||
code: "1",
|
||||
msg: "Ratio job not found",
|
||||
data: null,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 获取配比任务状态
|
||||
router.get(API.queryRatioJobStatusUsingGet, (req, res) => {
|
||||
const { taskId } = req.params;
|
||||
const job = ratioJobList.find((j) => j.id === taskId);
|
||||
if (job) {
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Success",
|
||||
data: {
|
||||
status: job.status,
|
||||
progress: job.progress,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
res.status(404).send({
|
||||
code: "1",
|
||||
msg: "Ratio job not found",
|
||||
data: null,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 获取配比模型列表
|
||||
router.get(API.queryRatioModelsUsingGet, (req, res) => {
|
||||
const models = [
|
||||
{ id: "model1", name: "均匀分配模型", description: "将目标数量均匀分配到各数据集。" },
|
||||
{ id: "model2", name: "标签优先模型", description: "优先满足标签配比需求。" },
|
||||
{ id: "model3", name: "自定义模型", description: "支持自定义分配逻辑。" },
|
||||
];
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Success",
|
||||
data: models,
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const Mock = require("mockjs");
|
||||
const API = require("../mock-apis.cjs");
|
||||
|
||||
function ratioJobItem() {
|
||||
return {
|
||||
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
name: Mock.Random.ctitle(5, 15),
|
||||
description: Mock.Random.csentence(10, 30),
|
||||
status: Mock.Random.pick(["PENDING", "RUNNING", "COMPLETED", "FAILED", "PAUSED"]),
|
||||
totals: Mock.Random.integer(1000, 10000),
|
||||
ratio_method: Mock.Random.pick(["DATASET", "TAG"]),
|
||||
target_dataset_id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
target_dataset_name: Mock.Random.ctitle(3, 8),
|
||||
config: [
|
||||
{
|
||||
datasetId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
counts: Mock.Random.integer(100, 1000).toString(),
|
||||
filter_conditions: "",
|
||||
},
|
||||
{
|
||||
datasetId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
counts: Mock.Random.integer(100, 1000).toString(),
|
||||
filter_conditions: "",
|
||||
},
|
||||
],
|
||||
created_at: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
|
||||
updated_at: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
|
||||
};
|
||||
}
|
||||
|
||||
const ratioJobList = new Array(20).fill(null).map(ratioJobItem);
|
||||
|
||||
|
||||
module.exports = function (router) {
|
||||
// 获取配比任务列表
|
||||
router.get(API.queryRatioTasksUsingGet, (req, res) => {
|
||||
const { page = 0, size = 10, status } = req.query;
|
||||
let filteredJobs = ratioJobList;
|
||||
if (status) {
|
||||
filteredJobs = ratioJobList.filter((job) => job.status === status);
|
||||
}
|
||||
const startIndex = page * size;
|
||||
const endIndex = startIndex + parseInt(size);
|
||||
const pageData = filteredJobs.slice(startIndex, endIndex);
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Success",
|
||||
data: {
|
||||
content: pageData,
|
||||
totalElements: filteredJobs.length,
|
||||
totalPages: Math.ceil(filteredJobs.length / size),
|
||||
size: parseInt(size),
|
||||
number: parseInt(page),
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
// 创建配比任务
|
||||
router.post(API.createRatioTaskUsingPost, (req, res) => {
|
||||
const newJob = {
|
||||
...ratioJobItem(),
|
||||
...req.body,
|
||||
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
status: "PENDING",
|
||||
createdAt: new Date().toISOString(),
|
||||
};
|
||||
ratioJobList.push(newJob);
|
||||
res.status(201).send({
|
||||
code: "0",
|
||||
msg: "Ratio job created successfully",
|
||||
data: newJob,
|
||||
});
|
||||
});
|
||||
|
||||
// 获取配比任务详情
|
||||
router.get(API.queryRatioTaskByIdUsingGet, (req, res) => {
|
||||
const { taskId } = req.params;
|
||||
const job = ratioJobList.find((j) => j.id === taskId);
|
||||
if (job) {
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Success",
|
||||
data: job,
|
||||
});
|
||||
} else {
|
||||
res.status(404).send({
|
||||
code: "1",
|
||||
msg: "Ratio job not found",
|
||||
data: null,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 删除配比任务
|
||||
router.delete(API.deleteRatioTaskByIdUsingDelete, (req, res) => {
|
||||
const { taskId } = req.params;
|
||||
const index = ratioJobList.findIndex((j) => j.id === taskId);
|
||||
if (index !== -1) {
|
||||
ratioJobList.splice(index, 1);
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Ratio job deleted successfully",
|
||||
data: null,
|
||||
});
|
||||
} else {
|
||||
res.status(404).send({
|
||||
code: "1",
|
||||
msg: "Ratio job not found",
|
||||
data: null,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 更新配比任务
|
||||
router.put(API.updateRatioTaskByIdUsingPut, (req, res) => {
|
||||
const { taskId } = req.params;
|
||||
const index = ratioJobList.findIndex((j) => j.id === taskId);
|
||||
if (index !== -1) {
|
||||
ratioJobList[index] = {
|
||||
...ratioJobList[index],
|
||||
...req.body,
|
||||
updatedAt: new Date().toISOString(),
|
||||
};
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Ratio job updated successfully",
|
||||
data: ratioJobList[index],
|
||||
});
|
||||
} else {
|
||||
res.status(404).send({
|
||||
code: "1",
|
||||
msg: "Ratio job not found",
|
||||
data: null,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 执行配比任务
|
||||
router.post(API.executeRatioTaskByIdUsingPost, (req, res) => {
|
||||
const { taskId } = req.params;
|
||||
const job = ratioJobList.find((j) => j.id === taskId);
|
||||
if (job) {
|
||||
job.status = "RUNNING";
|
||||
job.startedAt = new Date().toISOString();
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Ratio job execution started",
|
||||
data: {
|
||||
executionId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
status: "RUNNING",
|
||||
message: "Job execution started successfully",
|
||||
},
|
||||
});
|
||||
} else {
|
||||
res.status(404).send({
|
||||
code: "1",
|
||||
msg: "Ratio job not found",
|
||||
data: null,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 停止配比任务
|
||||
router.post(API.stopRatioTaskByIdUsingPost, (req, res) => {
|
||||
const { taskId } = req.params;
|
||||
const job = ratioJobList.find((j) => j.id === taskId);
|
||||
if (job) {
|
||||
job.status = "STOPPED";
|
||||
job.finishedAt = new Date().toISOString();
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Ratio job stopped successfully",
|
||||
data: null,
|
||||
});
|
||||
} else {
|
||||
res.status(404).send({
|
||||
code: "1",
|
||||
msg: "Ratio job not found",
|
||||
data: null,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 获取配比任务状态
|
||||
router.get(API.queryRatioJobStatusUsingGet, (req, res) => {
|
||||
const { taskId } = req.params;
|
||||
const job = ratioJobList.find((j) => j.id === taskId);
|
||||
if (job) {
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Success",
|
||||
data: {
|
||||
status: job.status,
|
||||
progress: job.progress,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
res.status(404).send({
|
||||
code: "1",
|
||||
msg: "Ratio job not found",
|
||||
data: null,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 获取配比模型列表
|
||||
router.get(API.queryRatioModelsUsingGet, (req, res) => {
|
||||
const models = [
|
||||
{ id: "model1", name: "均匀分配模型", description: "将目标数量均匀分配到各数据集。" },
|
||||
{ id: "model2", name: "标签优先模型", description: "优先满足标签配比需求。" },
|
||||
{ id: "model3", name: "自定义模型", description: "支持自定义分配逻辑。" },
|
||||
];
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Success",
|
||||
data: models,
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,176 +1,176 @@
|
||||
const Mock = require("mockjs");
|
||||
const API = require("../mock-apis.cjs");
|
||||
|
||||
// 知识库数据
|
||||
function KnowledgeBaseItem() {
|
||||
return {
|
||||
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
name: Mock.Random.ctitle(5, 15),
|
||||
description: Mock.Random.csentence(10, 30),
|
||||
createdBy: Mock.Random.cname(),
|
||||
updatedBy: Mock.Random.cname(),
|
||||
embeddingModel: Mock.Random.pick([
|
||||
"text-embedding-ada-002",
|
||||
"text-embedding-3-small",
|
||||
"text-embedding-3-large",
|
||||
]),
|
||||
chatModel: Mock.Random.pick(["gpt-3.5-turbo", "gpt-4", "gpt-4-32k"]),
|
||||
createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
|
||||
updatedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
|
||||
};
|
||||
}
|
||||
|
||||
const knowledgeBaseList = new Array(50).fill(null).map(KnowledgeBaseItem);
|
||||
|
||||
function fileItem() {
|
||||
return {
|
||||
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
|
||||
updatedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
|
||||
createdBy: Mock.Random.cname(),
|
||||
updatedBy: Mock.Random.cname(),
|
||||
knowledgeBaseId: Mock.Random.pick(knowledgeBaseList).id,
|
||||
fileId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
fileName: Mock.Random.ctitle(5, 15),
|
||||
chunkCount: Mock.Random.integer(1, 100),
|
||||
metadata: {},
|
||||
status: Mock.Random.pick([
|
||||
"UNPROCESSED",
|
||||
"PROCESSING",
|
||||
"PROCESSED",
|
||||
"PROCESS_FAILED",
|
||||
]),
|
||||
};
|
||||
}
|
||||
|
||||
const fileList = new Array(20).fill(null).map(fileItem);
|
||||
|
||||
module.exports = function (router) {
|
||||
// 获取知识库列表
|
||||
router.post(API.queryKnowledgeBasesUsingPost, (req, res) => {
|
||||
const { page = 0, size, keyword } = req.body;
|
||||
let filteredList = knowledgeBaseList;
|
||||
if (keyword) {
|
||||
filteredList = knowledgeBaseList.filter(
|
||||
(kb) => kb.name.includes(keyword) || kb.description.includes(keyword)
|
||||
);
|
||||
}
|
||||
const start = page * size;
|
||||
const end = start + size;
|
||||
const totalElements = filteredList.length;
|
||||
const paginatedList = filteredList.slice(start, end);
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Success",
|
||||
data: {
|
||||
totalElements,
|
||||
page,
|
||||
size,
|
||||
content: paginatedList,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
// 创建知识库
|
||||
router.post(API.createKnowledgeBaseUsingPost, (req, res) => {
|
||||
const item = KnowledgeBaseItem();
|
||||
knowledgeBaseList.unshift(item);
|
||||
res.status(201).send(item);
|
||||
});
|
||||
|
||||
// 获取知识库详情
|
||||
router.get(API.queryKnowledgeBaseByIdUsingGet, (req, res) => {
|
||||
const id = req.params.baseId;
|
||||
const item =
|
||||
knowledgeBaseList.find((kb) => kb.id === id) || KnowledgeBaseItem();
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Success",
|
||||
data: item,
|
||||
});
|
||||
});
|
||||
|
||||
// 更新知识库
|
||||
router.put(API.updateKnowledgeBaseByIdUsingPut, (req, res) => {
|
||||
const id = req.params.baseId;
|
||||
const idx = knowledgeBaseList.findIndex((kb) => kb.id === id);
|
||||
if (idx >= 0) {
|
||||
knowledgeBaseList[idx] = { ...knowledgeBaseList[idx], ...req.body };
|
||||
res.status(201).send(knowledgeBaseList[idx]);
|
||||
} else {
|
||||
res.status(404).send({ message: "Not found" });
|
||||
}
|
||||
});
|
||||
|
||||
// 删除知识库
|
||||
router.delete(API.deleteKnowledgeBaseByIdUsingDelete, (req, res) => {
|
||||
const id = req.params.baseId;
|
||||
const idx = knowledgeBaseList.findIndex((kb) => kb.id === id);
|
||||
if (idx >= 0) {
|
||||
knowledgeBaseList.splice(idx, 1);
|
||||
res.status(201).send({ success: true });
|
||||
} else {
|
||||
res.status(404).send({ message: "Not found" });
|
||||
}
|
||||
});
|
||||
|
||||
// 添加文件到知识库
|
||||
router.post(API.addKnowledgeBaseFilesUsingPost, (req, res) => {
|
||||
const file = Mock.mock({
|
||||
id: "@guid",
|
||||
name: "@ctitle(5,15)",
|
||||
size: "@integer(1000,1000000)",
|
||||
status: "uploaded",
|
||||
createdAt: "@datetime",
|
||||
});
|
||||
res.status(201).send(file);
|
||||
});
|
||||
|
||||
// 获取知识生成文件详情
|
||||
router.get(API.queryKnowledgeBaseFilesGet, (req, res) => {
|
||||
const { keyword, page, size } = req.query;
|
||||
let filteredList = fileList;
|
||||
if (keyword) {
|
||||
filteredList = fileList.filter((file) => file.fileName.includes(keyword));
|
||||
}
|
||||
const start = page * size;
|
||||
const end = start + size;
|
||||
const totalElements = filteredList.length;
|
||||
const paginatedList = filteredList.slice(start, end);
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Success",
|
||||
data: {
|
||||
totalElements,
|
||||
page,
|
||||
size,
|
||||
content: paginatedList,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
router.get(API.queryKnowledgeBaseFilesByIdUsingGet, (req, res) => {
|
||||
const { baseId, fileId } = req.params;
|
||||
const item =
|
||||
fileList.find(
|
||||
(file) => file.knowledgeBaseId === baseId && file.id === fileId
|
||||
) || fileItem();
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Success",
|
||||
data: item,
|
||||
});
|
||||
});
|
||||
|
||||
// 删除知识生成文件
|
||||
router.delete(API.deleteKnowledgeBaseTaskByIdUsingDelete, (req, res) => {
|
||||
const { id } = req.params;
|
||||
const idx = fileList.findIndex((file) => file.id === id);
|
||||
if (idx >= 0) {
|
||||
fileList.splice(idx, 1);
|
||||
res.status(200).send({ success: true });
|
||||
return;
|
||||
}
|
||||
res.status(404).send({ message: "Not found" });
|
||||
});
|
||||
};
|
||||
const Mock = require("mockjs");
|
||||
const API = require("../mock-apis.cjs");
|
||||
|
||||
// 知识库数据
|
||||
function KnowledgeBaseItem() {
|
||||
return {
|
||||
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
name: Mock.Random.ctitle(5, 15),
|
||||
description: Mock.Random.csentence(10, 30),
|
||||
createdBy: Mock.Random.cname(),
|
||||
updatedBy: Mock.Random.cname(),
|
||||
embeddingModel: Mock.Random.pick([
|
||||
"text-embedding-ada-002",
|
||||
"text-embedding-3-small",
|
||||
"text-embedding-3-large",
|
||||
]),
|
||||
chatModel: Mock.Random.pick(["gpt-3.5-turbo", "gpt-4", "gpt-4-32k"]),
|
||||
createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
|
||||
updatedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
|
||||
};
|
||||
}
|
||||
|
||||
const knowledgeBaseList = new Array(50).fill(null).map(KnowledgeBaseItem);
|
||||
|
||||
function fileItem() {
|
||||
return {
|
||||
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
|
||||
updatedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
|
||||
createdBy: Mock.Random.cname(),
|
||||
updatedBy: Mock.Random.cname(),
|
||||
knowledgeBaseId: Mock.Random.pick(knowledgeBaseList).id,
|
||||
fileId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
fileName: Mock.Random.ctitle(5, 15),
|
||||
chunkCount: Mock.Random.integer(1, 100),
|
||||
metadata: {},
|
||||
status: Mock.Random.pick([
|
||||
"UNPROCESSED",
|
||||
"PROCESSING",
|
||||
"PROCESSED",
|
||||
"PROCESS_FAILED",
|
||||
]),
|
||||
};
|
||||
}
|
||||
|
||||
const fileList = new Array(20).fill(null).map(fileItem);
|
||||
|
||||
module.exports = function (router) {
|
||||
// 获取知识库列表
|
||||
router.post(API.queryKnowledgeBasesUsingPost, (req, res) => {
|
||||
const { page = 0, size, keyword } = req.body;
|
||||
let filteredList = knowledgeBaseList;
|
||||
if (keyword) {
|
||||
filteredList = knowledgeBaseList.filter(
|
||||
(kb) => kb.name.includes(keyword) || kb.description.includes(keyword)
|
||||
);
|
||||
}
|
||||
const start = page * size;
|
||||
const end = start + size;
|
||||
const totalElements = filteredList.length;
|
||||
const paginatedList = filteredList.slice(start, end);
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Success",
|
||||
data: {
|
||||
totalElements,
|
||||
page,
|
||||
size,
|
||||
content: paginatedList,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
// 创建知识库
|
||||
router.post(API.createKnowledgeBaseUsingPost, (req, res) => {
|
||||
const item = KnowledgeBaseItem();
|
||||
knowledgeBaseList.unshift(item);
|
||||
res.status(201).send(item);
|
||||
});
|
||||
|
||||
// 获取知识库详情
|
||||
router.get(API.queryKnowledgeBaseByIdUsingGet, (req, res) => {
|
||||
const id = req.params.baseId;
|
||||
const item =
|
||||
knowledgeBaseList.find((kb) => kb.id === id) || KnowledgeBaseItem();
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Success",
|
||||
data: item,
|
||||
});
|
||||
});
|
||||
|
||||
// 更新知识库
|
||||
router.put(API.updateKnowledgeBaseByIdUsingPut, (req, res) => {
|
||||
const id = req.params.baseId;
|
||||
const idx = knowledgeBaseList.findIndex((kb) => kb.id === id);
|
||||
if (idx >= 0) {
|
||||
knowledgeBaseList[idx] = { ...knowledgeBaseList[idx], ...req.body };
|
||||
res.status(201).send(knowledgeBaseList[idx]);
|
||||
} else {
|
||||
res.status(404).send({ message: "Not found" });
|
||||
}
|
||||
});
|
||||
|
||||
// 删除知识库
|
||||
router.delete(API.deleteKnowledgeBaseByIdUsingDelete, (req, res) => {
|
||||
const id = req.params.baseId;
|
||||
const idx = knowledgeBaseList.findIndex((kb) => kb.id === id);
|
||||
if (idx >= 0) {
|
||||
knowledgeBaseList.splice(idx, 1);
|
||||
res.status(201).send({ success: true });
|
||||
} else {
|
||||
res.status(404).send({ message: "Not found" });
|
||||
}
|
||||
});
|
||||
|
||||
// 添加文件到知识库
|
||||
router.post(API.addKnowledgeBaseFilesUsingPost, (req, res) => {
|
||||
const file = Mock.mock({
|
||||
id: "@guid",
|
||||
name: "@ctitle(5,15)",
|
||||
size: "@integer(1000,1000000)",
|
||||
status: "uploaded",
|
||||
createdAt: "@datetime",
|
||||
});
|
||||
res.status(201).send(file);
|
||||
});
|
||||
|
||||
// 获取知识生成文件详情
|
||||
router.get(API.queryKnowledgeBaseFilesGet, (req, res) => {
|
||||
const { keyword, page, size } = req.query;
|
||||
let filteredList = fileList;
|
||||
if (keyword) {
|
||||
filteredList = fileList.filter((file) => file.fileName.includes(keyword));
|
||||
}
|
||||
const start = page * size;
|
||||
const end = start + size;
|
||||
const totalElements = filteredList.length;
|
||||
const paginatedList = filteredList.slice(start, end);
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Success",
|
||||
data: {
|
||||
totalElements,
|
||||
page,
|
||||
size,
|
||||
content: paginatedList,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
router.get(API.queryKnowledgeBaseFilesByIdUsingGet, (req, res) => {
|
||||
const { baseId, fileId } = req.params;
|
||||
const item =
|
||||
fileList.find(
|
||||
(file) => file.knowledgeBaseId === baseId && file.id === fileId
|
||||
) || fileItem();
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Success",
|
||||
data: item,
|
||||
});
|
||||
});
|
||||
|
||||
// 删除知识生成文件
|
||||
router.delete(API.deleteKnowledgeBaseTaskByIdUsingDelete, (req, res) => {
|
||||
const { id } = req.params;
|
||||
const idx = fileList.findIndex((file) => file.id === id);
|
||||
if (idx >= 0) {
|
||||
fileList.splice(idx, 1);
|
||||
res.status(200).send({ success: true });
|
||||
return;
|
||||
}
|
||||
res.status(404).send({ message: "Not found" });
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,150 +1,150 @@
|
||||
const Mock = require("mockjs");
|
||||
const API = require("../mock-apis.cjs");
|
||||
|
||||
// 算子标签数据
|
||||
function labelItem() {
|
||||
return {
|
||||
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
name: Mock.Random.pick([
|
||||
"数据清洗",
|
||||
"特征选择",
|
||||
"分类算法",
|
||||
"聚类算法",
|
||||
"回归分析",
|
||||
"深度神经网络",
|
||||
"卷积神经网络",
|
||||
"循环神经网络",
|
||||
"注意力机制",
|
||||
"文本分析",
|
||||
"图像处理",
|
||||
"语音识别",
|
||||
"推荐算法",
|
||||
"异常检测",
|
||||
"优化算法",
|
||||
"集成学习",
|
||||
"迁移学习",
|
||||
"强化学习",
|
||||
"联邦学习",
|
||||
]),
|
||||
usageCount: Mock.Random.integer(1, 500),
|
||||
createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
|
||||
};
|
||||
}
|
||||
|
||||
const labelList = new Array(50).fill(null).map(labelItem);
|
||||
|
||||
module.exports = function (router) {
|
||||
router.post(API.preUploadOperatorUsingPost, (req, res) => {
|
||||
res.status(201).send(Mock.Random.guid());
|
||||
});
|
||||
|
||||
// 上传切片
|
||||
router.post(API.uploadFileChunkUsingPost, (req, res) => {
|
||||
// res.status(500).send({ message: "Simulated upload failure" });
|
||||
res.status(201).send({ data: "success" });
|
||||
});
|
||||
|
||||
// 取消上传
|
||||
router.put(API.cancelUploadOperatorUsingPut, (req, res) => {
|
||||
res.status(201).send({ data: "success" });
|
||||
});
|
||||
|
||||
router.post(API.uploadOperatorUsingPost, (req, res) => {
|
||||
res.status(201).send({
|
||||
code: "0",
|
||||
msg: "Upload successful",
|
||||
data: {
|
||||
operatorId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
// 其他返回数据
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
// 获取算子标签列表
|
||||
router.get(API.queryLabelsUsingGet, (req, res) => {
|
||||
const { page = 0, size = 20, keyword = "" } = req.query;
|
||||
|
||||
let filteredLabels = labelList;
|
||||
|
||||
if (keyword) {
|
||||
filteredLabels = labelList.filter((label) =>
|
||||
label.name.toLowerCase().includes(keyword.toLowerCase())
|
||||
);
|
||||
}
|
||||
|
||||
const startIndex = page * size;
|
||||
const endIndex = startIndex + parseInt(size);
|
||||
const pageData = filteredLabels.slice(startIndex, endIndex);
|
||||
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Success",
|
||||
data: {
|
||||
content: pageData,
|
||||
totalElements: filteredLabels.length,
|
||||
totalPages: Math.ceil(filteredLabels.length / size),
|
||||
size: parseInt(size),
|
||||
number: parseInt(page),
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
// 创建标签
|
||||
router.post(API.createLabelUsingPost, (req, res) => {
|
||||
const { name } = req.body;
|
||||
|
||||
const newLabel = {
|
||||
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
name,
|
||||
usageCount: 0,
|
||||
createdAt: new Date().toISOString(),
|
||||
};
|
||||
|
||||
labelList.push(newLabel);
|
||||
|
||||
res.status(201).send({
|
||||
code: "0",
|
||||
msg: "Label created successfully",
|
||||
data: newLabel,
|
||||
});
|
||||
});
|
||||
|
||||
// 批量删除标签
|
||||
router.delete(API.deleteLabelsUsingDelete, (req, res) => {
|
||||
const labelIds = req.body; // 数组形式的标签ID列表
|
||||
|
||||
let deletedCount = 0;
|
||||
labelIds.forEach((labelId) => {
|
||||
const index = labelList.findIndex((label) => label.id === labelId);
|
||||
if (index !== -1) {
|
||||
labelList.splice(index, 1);
|
||||
deletedCount++;
|
||||
}
|
||||
});
|
||||
|
||||
res.status(204).send();
|
||||
});
|
||||
|
||||
// 更新标签
|
||||
router.put(API.updateLabelByIdUsingPut, (req, res) => {
|
||||
const { id } = req.params;
|
||||
const updates = req.body; // 数组形式的更新数据
|
||||
|
||||
updates.forEach((update) => {
|
||||
const index = labelList.findIndex((label) => label.id === update.id);
|
||||
if (index !== -1) {
|
||||
labelList[index] = {
|
||||
...labelList[index],
|
||||
...update,
|
||||
updatedAt: new Date().toISOString(),
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Labels updated successfully",
|
||||
data: null,
|
||||
});
|
||||
});
|
||||
};
|
||||
const Mock = require("mockjs");
|
||||
const API = require("../mock-apis.cjs");
|
||||
|
||||
// 算子标签数据
|
||||
function labelItem() {
|
||||
return {
|
||||
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
name: Mock.Random.pick([
|
||||
"数据清洗",
|
||||
"特征选择",
|
||||
"分类算法",
|
||||
"聚类算法",
|
||||
"回归分析",
|
||||
"深度神经网络",
|
||||
"卷积神经网络",
|
||||
"循环神经网络",
|
||||
"注意力机制",
|
||||
"文本分析",
|
||||
"图像处理",
|
||||
"语音识别",
|
||||
"推荐算法",
|
||||
"异常检测",
|
||||
"优化算法",
|
||||
"集成学习",
|
||||
"迁移学习",
|
||||
"强化学习",
|
||||
"联邦学习",
|
||||
]),
|
||||
usageCount: Mock.Random.integer(1, 500),
|
||||
createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
|
||||
};
|
||||
}
|
||||
|
||||
const labelList = new Array(50).fill(null).map(labelItem);
|
||||
|
||||
module.exports = function (router) {
|
||||
router.post(API.preUploadOperatorUsingPost, (req, res) => {
|
||||
res.status(201).send(Mock.Random.guid());
|
||||
});
|
||||
|
||||
// 上传切片
|
||||
router.post(API.uploadFileChunkUsingPost, (req, res) => {
|
||||
// res.status(500).send({ message: "Simulated upload failure" });
|
||||
res.status(201).send({ data: "success" });
|
||||
});
|
||||
|
||||
// 取消上传
|
||||
router.put(API.cancelUploadOperatorUsingPut, (req, res) => {
|
||||
res.status(201).send({ data: "success" });
|
||||
});
|
||||
|
||||
router.post(API.uploadOperatorUsingPost, (req, res) => {
|
||||
res.status(201).send({
|
||||
code: "0",
|
||||
msg: "Upload successful",
|
||||
data: {
|
||||
operatorId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
// 其他返回数据
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
// 获取算子标签列表
|
||||
router.get(API.queryLabelsUsingGet, (req, res) => {
|
||||
const { page = 0, size = 20, keyword = "" } = req.query;
|
||||
|
||||
let filteredLabels = labelList;
|
||||
|
||||
if (keyword) {
|
||||
filteredLabels = labelList.filter((label) =>
|
||||
label.name.toLowerCase().includes(keyword.toLowerCase())
|
||||
);
|
||||
}
|
||||
|
||||
const startIndex = page * size;
|
||||
const endIndex = startIndex + parseInt(size);
|
||||
const pageData = filteredLabels.slice(startIndex, endIndex);
|
||||
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Success",
|
||||
data: {
|
||||
content: pageData,
|
||||
totalElements: filteredLabels.length,
|
||||
totalPages: Math.ceil(filteredLabels.length / size),
|
||||
size: parseInt(size),
|
||||
number: parseInt(page),
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
// 创建标签
|
||||
router.post(API.createLabelUsingPost, (req, res) => {
|
||||
const { name } = req.body;
|
||||
|
||||
const newLabel = {
|
||||
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
name,
|
||||
usageCount: 0,
|
||||
createdAt: new Date().toISOString(),
|
||||
};
|
||||
|
||||
labelList.push(newLabel);
|
||||
|
||||
res.status(201).send({
|
||||
code: "0",
|
||||
msg: "Label created successfully",
|
||||
data: newLabel,
|
||||
});
|
||||
});
|
||||
|
||||
// 批量删除标签
|
||||
router.delete(API.deleteLabelsUsingDelete, (req, res) => {
|
||||
const labelIds = req.body; // 数组形式的标签ID列表
|
||||
|
||||
let deletedCount = 0;
|
||||
labelIds.forEach((labelId) => {
|
||||
const index = labelList.findIndex((label) => label.id === labelId);
|
||||
if (index !== -1) {
|
||||
labelList.splice(index, 1);
|
||||
deletedCount++;
|
||||
}
|
||||
});
|
||||
|
||||
res.status(204).send();
|
||||
});
|
||||
|
||||
// 更新标签
|
||||
router.put(API.updateLabelByIdUsingPut, (req, res) => {
|
||||
const { id } = req.params;
|
||||
const updates = req.body; // 数组形式的更新数据
|
||||
|
||||
updates.forEach((update) => {
|
||||
const index = labelList.findIndex((label) => label.id === update.id);
|
||||
if (index !== -1) {
|
||||
labelList[index] = {
|
||||
...labelList[index],
|
||||
...update,
|
||||
updatedAt: new Date().toISOString(),
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Labels updated successfully",
|
||||
data: null,
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,177 +1,177 @@
|
||||
const Mock = require("mockjs");
|
||||
const API = require("../mock-apis.cjs");
|
||||
|
||||
// 算子标签数据
|
||||
function ModelItem() {
|
||||
return {
|
||||
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
modelName: Mock.Random.pick([
|
||||
"数据清洗",
|
||||
"特征选择",
|
||||
"分类算法",
|
||||
"聚类算法",
|
||||
"回归分析",
|
||||
"深度神经网络",
|
||||
"卷积神经网络",
|
||||
"循环神经网络",
|
||||
"注意力机制",
|
||||
"文本分析",
|
||||
"图像处理",
|
||||
"语音识别",
|
||||
"推荐算法",
|
||||
"异常检测",
|
||||
"优化算法",
|
||||
"集成学习",
|
||||
"迁移学习",
|
||||
"强化学习",
|
||||
"联邦学习",
|
||||
]),
|
||||
provider: Mock.Random.pick([
|
||||
"OpenAI",
|
||||
"Anthropic",
|
||||
"Cohere",
|
||||
"AI21 Labs",
|
||||
"Hugging Face",
|
||||
"Google Cloud AI",
|
||||
"Microsoft Azure AI",
|
||||
"Amazon Web Services AI",
|
||||
"IBM Watson",
|
||||
"Alibaba Cloud AI",
|
||||
]),
|
||||
type: Mock.Random.pick(["CHAT", "EMBEDDING"]),
|
||||
usageCount: Mock.Random.integer(1, 500),
|
||||
createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
|
||||
updatedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
|
||||
};
|
||||
}
|
||||
|
||||
const modelList = new Array(50).fill(null).map(ModelItem);
|
||||
|
||||
function ProviderItem(provider) {
|
||||
return {
|
||||
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
provider,
|
||||
baseUrl: Mock.Random.url("https") + "/v1/models",
|
||||
createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
|
||||
};
|
||||
}
|
||||
|
||||
const ProviderList = [
|
||||
"OpenAI",
|
||||
"Anthropic",
|
||||
"Cohere",
|
||||
"AI21 Labs",
|
||||
"Hugging Face",
|
||||
"Google Cloud AI",
|
||||
"Microsoft Azure AI",
|
||||
"Amazon Web Services AI",
|
||||
"IBM Watson",
|
||||
"Alibaba Cloud AI",
|
||||
].map(ProviderItem);
|
||||
|
||||
module.exports = function (router) {
|
||||
// 获取模型列表
|
||||
router.get(API.queryModelsUsingGet, (req, res) => {
|
||||
const {
|
||||
page = 0,
|
||||
size = 20,
|
||||
keyword = "",
|
||||
provider = "",
|
||||
type = "",
|
||||
} = req.query;
|
||||
|
||||
let filteredModels = modelList;
|
||||
|
||||
if (keyword) {
|
||||
filteredModels = modelList.filter((model) =>
|
||||
model.modelName.toLowerCase().includes(keyword.toLowerCase())
|
||||
);
|
||||
}
|
||||
if (provider && provider !== "all") {
|
||||
filteredModels = filteredModels.filter(
|
||||
(model) => model.provider === provider
|
||||
);
|
||||
}
|
||||
if (type && type !== "all") {
|
||||
filteredModels = filteredModels.filter((model) => model.type === type);
|
||||
}
|
||||
|
||||
const startIndex = page * size;
|
||||
const endIndex = startIndex + parseInt(size);
|
||||
const pageData = filteredModels.slice(startIndex, endIndex);
|
||||
|
||||
res.status(201).send({
|
||||
code: "0",
|
||||
msg: "Success",
|
||||
data: {
|
||||
content: pageData,
|
||||
totalElements: filteredModels.length,
|
||||
totalPages: Math.ceil(filteredModels.length / size),
|
||||
size: parseInt(size),
|
||||
number: parseInt(page),
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
// 获取模型提供商列表
|
||||
router.get(API.queryProvidersUsingGet, (req, res) => {
|
||||
res.status(201).send({
|
||||
code: "0",
|
||||
msg: "success",
|
||||
data: ProviderList,
|
||||
});
|
||||
});
|
||||
|
||||
// 创建模型
|
||||
router.post(API.createModelUsingPost, (req, res) => {
|
||||
const { ...modelData } = req.body;
|
||||
const newModel = {
|
||||
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
...modelData,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
};
|
||||
modelList.unshift(newModel);
|
||||
res.status(201).send({
|
||||
code: "0",
|
||||
msg: "success",
|
||||
data: newModel,
|
||||
});
|
||||
});
|
||||
|
||||
// 删除模型
|
||||
router.delete(API.deleteModelUsingDelete, (req, res) => {
|
||||
const { id } = req.params;
|
||||
|
||||
const index = modelList.findIndex((model) => model.id === id);
|
||||
if (index !== -1) {
|
||||
modelList.splice(index, 1);
|
||||
}
|
||||
|
||||
res.status(204).send({
|
||||
code: "0",
|
||||
msg: "success",
|
||||
data: null,
|
||||
});
|
||||
});
|
||||
|
||||
// 更新模型
|
||||
router.put(API.updateModelUsingPut, (req, res) => {
|
||||
const { id, ...update } = req.params;
|
||||
|
||||
const index = modelList.findIndex((model) => model.id === id);
|
||||
if (index !== -1) {
|
||||
modelList[index] = {
|
||||
...modelList[index],
|
||||
...update,
|
||||
updatedAt: new Date().toISOString(),
|
||||
};
|
||||
}
|
||||
|
||||
res.status(201).send({
|
||||
code: "0",
|
||||
msg: "success",
|
||||
data: null,
|
||||
});
|
||||
});
|
||||
};
|
||||
const Mock = require("mockjs");
|
||||
const API = require("../mock-apis.cjs");
|
||||
|
||||
// 算子标签数据
|
||||
function ModelItem() {
|
||||
return {
|
||||
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
modelName: Mock.Random.pick([
|
||||
"数据清洗",
|
||||
"特征选择",
|
||||
"分类算法",
|
||||
"聚类算法",
|
||||
"回归分析",
|
||||
"深度神经网络",
|
||||
"卷积神经网络",
|
||||
"循环神经网络",
|
||||
"注意力机制",
|
||||
"文本分析",
|
||||
"图像处理",
|
||||
"语音识别",
|
||||
"推荐算法",
|
||||
"异常检测",
|
||||
"优化算法",
|
||||
"集成学习",
|
||||
"迁移学习",
|
||||
"强化学习",
|
||||
"联邦学习",
|
||||
]),
|
||||
provider: Mock.Random.pick([
|
||||
"OpenAI",
|
||||
"Anthropic",
|
||||
"Cohere",
|
||||
"AI21 Labs",
|
||||
"Hugging Face",
|
||||
"Google Cloud AI",
|
||||
"Microsoft Azure AI",
|
||||
"Amazon Web Services AI",
|
||||
"IBM Watson",
|
||||
"Alibaba Cloud AI",
|
||||
]),
|
||||
type: Mock.Random.pick(["CHAT", "EMBEDDING"]),
|
||||
usageCount: Mock.Random.integer(1, 500),
|
||||
createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
|
||||
updatedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
|
||||
};
|
||||
}
|
||||
|
||||
const modelList = new Array(50).fill(null).map(ModelItem);
|
||||
|
||||
function ProviderItem(provider) {
|
||||
return {
|
||||
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
provider,
|
||||
baseUrl: Mock.Random.url("https") + "/v1/models",
|
||||
createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
|
||||
};
|
||||
}
|
||||
|
||||
const ProviderList = [
|
||||
"OpenAI",
|
||||
"Anthropic",
|
||||
"Cohere",
|
||||
"AI21 Labs",
|
||||
"Hugging Face",
|
||||
"Google Cloud AI",
|
||||
"Microsoft Azure AI",
|
||||
"Amazon Web Services AI",
|
||||
"IBM Watson",
|
||||
"Alibaba Cloud AI",
|
||||
].map(ProviderItem);
|
||||
|
||||
module.exports = function (router) {
|
||||
// 获取模型列表
|
||||
router.get(API.queryModelsUsingGet, (req, res) => {
|
||||
const {
|
||||
page = 0,
|
||||
size = 20,
|
||||
keyword = "",
|
||||
provider = "",
|
||||
type = "",
|
||||
} = req.query;
|
||||
|
||||
let filteredModels = modelList;
|
||||
|
||||
if (keyword) {
|
||||
filteredModels = modelList.filter((model) =>
|
||||
model.modelName.toLowerCase().includes(keyword.toLowerCase())
|
||||
);
|
||||
}
|
||||
if (provider && provider !== "all") {
|
||||
filteredModels = filteredModels.filter(
|
||||
(model) => model.provider === provider
|
||||
);
|
||||
}
|
||||
if (type && type !== "all") {
|
||||
filteredModels = filteredModels.filter((model) => model.type === type);
|
||||
}
|
||||
|
||||
const startIndex = page * size;
|
||||
const endIndex = startIndex + parseInt(size);
|
||||
const pageData = filteredModels.slice(startIndex, endIndex);
|
||||
|
||||
res.status(201).send({
|
||||
code: "0",
|
||||
msg: "Success",
|
||||
data: {
|
||||
content: pageData,
|
||||
totalElements: filteredModels.length,
|
||||
totalPages: Math.ceil(filteredModels.length / size),
|
||||
size: parseInt(size),
|
||||
number: parseInt(page),
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
// 获取模型提供商列表
|
||||
router.get(API.queryProvidersUsingGet, (req, res) => {
|
||||
res.status(201).send({
|
||||
code: "0",
|
||||
msg: "success",
|
||||
data: ProviderList,
|
||||
});
|
||||
});
|
||||
|
||||
// 创建模型
|
||||
router.post(API.createModelUsingPost, (req, res) => {
|
||||
const { ...modelData } = req.body;
|
||||
const newModel = {
|
||||
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
...modelData,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
};
|
||||
modelList.unshift(newModel);
|
||||
res.status(201).send({
|
||||
code: "0",
|
||||
msg: "success",
|
||||
data: newModel,
|
||||
});
|
||||
});
|
||||
|
||||
// 删除模型
|
||||
router.delete(API.deleteModelUsingDelete, (req, res) => {
|
||||
const { id } = req.params;
|
||||
|
||||
const index = modelList.findIndex((model) => model.id === id);
|
||||
if (index !== -1) {
|
||||
modelList.splice(index, 1);
|
||||
}
|
||||
|
||||
res.status(204).send({
|
||||
code: "0",
|
||||
msg: "success",
|
||||
data: null,
|
||||
});
|
||||
});
|
||||
|
||||
// 更新模型
|
||||
router.put(API.updateModelUsingPut, (req, res) => {
|
||||
const { id, ...update } = req.params;
|
||||
|
||||
const index = modelList.findIndex((model) => model.id === id);
|
||||
if (index !== -1) {
|
||||
modelList[index] = {
|
||||
...modelList[index],
|
||||
...update,
|
||||
updatedAt: new Date().toISOString(),
|
||||
};
|
||||
}
|
||||
|
||||
res.status(201).send({
|
||||
code: "0",
|
||||
msg: "success",
|
||||
data: null,
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,58 +1,58 @@
|
||||
const express = require('express');
|
||||
const fs = require('fs-extra');
|
||||
const path = require('path');
|
||||
const bodyParser = require('body-parser');
|
||||
const { genExpressSession } = require('./mock-core/session-helper.cjs');
|
||||
const {
|
||||
setHeader,
|
||||
sendJSON,
|
||||
strongMatch,
|
||||
errorHandle,
|
||||
} = require('./mock-middleware/index.cjs');
|
||||
|
||||
|
||||
const { loadAllMockModules } = require('./mock-core/module-loader.cjs');
|
||||
const { log } = require('./mock-core/util.cjs');
|
||||
|
||||
const app = express();
|
||||
const router = express.Router();
|
||||
|
||||
const argv = require('minimist')(process.argv.slice(2));
|
||||
const deployUrl = argv['deploy-url'] || '/';
|
||||
const deployPath = argv['deploy-path'] || '/';
|
||||
const port = argv.port || 8002;
|
||||
const env = argv.env || 'development';
|
||||
|
||||
// app静态文件实际目录
|
||||
const deployAppPath = path.join(__dirname, deployPath);
|
||||
preStartCheck(deployAppPath);
|
||||
|
||||
app.use(setHeader);
|
||||
|
||||
// 提供静态文件服务
|
||||
app.use(deployUrl, express.static(deployAppPath));
|
||||
app.use(bodyParser.json({limit: '1mb'}));
|
||||
app.use(bodyParser.urlencoded({ extended: false, limit: '1mb' }));
|
||||
app.use(sendJSON);
|
||||
app.use(strongMatch);
|
||||
app.use(genExpressSession());
|
||||
|
||||
const mockDir = path.join(__dirname, '/mock-seed');
|
||||
loadAllMockModules(router, mockDir);
|
||||
app.use(deployUrl, router);
|
||||
app.use(errorHandle);
|
||||
|
||||
app.get('/', (req, res) => {
|
||||
res.sendFile('default response', { root: deployAppPath });
|
||||
});
|
||||
|
||||
app.listen(port, function() {
|
||||
log(`Mock server is running at http://localhost:${port}${deployUrl} in ${env} mode`);
|
||||
})
|
||||
|
||||
function preStartCheck(deployAppPath) {
|
||||
if(!fs.existsSync(deployAppPath)) {
|
||||
log(`Error: The path ${deployAppPath} does not exist. Please build the frontend application first.`, 'error');
|
||||
process.exit(1);
|
||||
}
|
||||
const express = require('express');
|
||||
const fs = require('fs-extra');
|
||||
const path = require('path');
|
||||
const bodyParser = require('body-parser');
|
||||
const { genExpressSession } = require('./mock-core/session-helper.cjs');
|
||||
const {
|
||||
setHeader,
|
||||
sendJSON,
|
||||
strongMatch,
|
||||
errorHandle,
|
||||
} = require('./mock-middleware/index.cjs');
|
||||
|
||||
|
||||
const { loadAllMockModules } = require('./mock-core/module-loader.cjs');
|
||||
const { log } = require('./mock-core/util.cjs');
|
||||
|
||||
const app = express();
|
||||
const router = express.Router();
|
||||
|
||||
const argv = require('minimist')(process.argv.slice(2));
|
||||
const deployUrl = argv['deploy-url'] || '/';
|
||||
const deployPath = argv['deploy-path'] || '/';
|
||||
const port = argv.port || 8002;
|
||||
const env = argv.env || 'development';
|
||||
|
||||
// app静态文件实际目录
|
||||
const deployAppPath = path.join(__dirname, deployPath);
|
||||
preStartCheck(deployAppPath);
|
||||
|
||||
app.use(setHeader);
|
||||
|
||||
// 提供静态文件服务
|
||||
app.use(deployUrl, express.static(deployAppPath));
|
||||
app.use(bodyParser.json({limit: '1mb'}));
|
||||
app.use(bodyParser.urlencoded({ extended: false, limit: '1mb' }));
|
||||
app.use(sendJSON);
|
||||
app.use(strongMatch);
|
||||
app.use(genExpressSession());
|
||||
|
||||
const mockDir = path.join(__dirname, '/mock-seed');
|
||||
loadAllMockModules(router, mockDir);
|
||||
app.use(deployUrl, router);
|
||||
app.use(errorHandle);
|
||||
|
||||
app.get('/', (req, res) => {
|
||||
res.sendFile('default response', { root: deployAppPath });
|
||||
});
|
||||
|
||||
app.listen(port, function() {
|
||||
log(`Mock server is running at http://localhost:${port}${deployUrl} in ${env} mode`);
|
||||
})
|
||||
|
||||
function preStartCheck(deployAppPath) {
|
||||
if(!fs.existsSync(deployAppPath)) {
|
||||
log(`Error: The path ${deployAppPath} does not exist. Please build the frontend application first.`, 'error');
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
@@ -1,22 +1,22 @@
|
||||
{
|
||||
"restartable": "rs",
|
||||
"ignore": [
|
||||
".git",
|
||||
"node_modules/**/node_modules",
|
||||
"dist",
|
||||
"build",
|
||||
"*.test.js",
|
||||
"*.spec.js"
|
||||
],
|
||||
"verbose": true,
|
||||
"watch": ["*.cjs"],
|
||||
"exec": "node --inspect=0.0.0.0:9229 mock.cjs",
|
||||
"ext": "js,cjs,json",
|
||||
"execMap": {
|
||||
"js": "node --harmony"
|
||||
},
|
||||
"env": {
|
||||
"NODE_ENV": "development"
|
||||
},
|
||||
"signal": "SIGTERM"
|
||||
}
|
||||
{
|
||||
"restartable": "rs",
|
||||
"ignore": [
|
||||
".git",
|
||||
"node_modules/**/node_modules",
|
||||
"dist",
|
||||
"build",
|
||||
"*.test.js",
|
||||
"*.spec.js"
|
||||
],
|
||||
"verbose": true,
|
||||
"watch": ["*.cjs"],
|
||||
"exec": "node --inspect=0.0.0.0:9229 mock.cjs",
|
||||
"ext": "js,cjs,json",
|
||||
"execMap": {
|
||||
"js": "node --harmony"
|
||||
},
|
||||
"env": {
|
||||
"NODE_ENV": "development"
|
||||
},
|
||||
"signal": "SIGTERM"
|
||||
}
|
||||
|
||||
@@ -1,209 +1,209 @@
|
||||
// Add mock files data
|
||||
export const mockFiles = [
|
||||
{ id: "file1", name: "dataset_part_001.jsonl", size: "2.5MB", type: "JSONL" },
|
||||
{ id: "file2", name: "dataset_part_002.jsonl", size: "2.3MB", type: "JSONL" },
|
||||
{ id: "file3", name: "dataset_part_003.jsonl", size: "2.7MB", type: "JSONL" },
|
||||
{ id: "file4", name: "training_data.txt", size: "1.8MB", type: "TXT" },
|
||||
{ id: "file5", name: "validation_set.csv", size: "856KB", type: "CSV" },
|
||||
{ id: "file6", name: "test_samples.json", size: "1.2MB", type: "JSON" },
|
||||
{ id: "file7", name: "raw_text_001.txt", size: "3.1MB", type: "TXT" },
|
||||
{ id: "file8", name: "raw_text_002.txt", size: "2.9MB", type: "TXT" },
|
||||
];
|
||||
|
||||
export const mockSynthesisTasks: SynthesisTask[] = [
|
||||
{
|
||||
id: 1,
|
||||
name: "文字生成问答对_判断题",
|
||||
type: "qa",
|
||||
status: "completed",
|
||||
progress: 100,
|
||||
sourceDataset: "orig_20250724_64082",
|
||||
targetCount: 1000,
|
||||
generatedCount: 1000,
|
||||
createdAt: "2025-01-20",
|
||||
template: "判断题生成模板",
|
||||
estimatedTime: "已完成",
|
||||
quality: 95,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: "知识蒸馏数据集",
|
||||
type: "distillation",
|
||||
status: "running",
|
||||
progress: 65,
|
||||
sourceDataset: "teacher_model_outputs",
|
||||
targetCount: 5000,
|
||||
generatedCount: 3250,
|
||||
createdAt: "2025-01-22",
|
||||
template: "蒸馏模板v2",
|
||||
estimatedTime: "剩余 15 分钟",
|
||||
quality: 88,
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: "多模态对话生成",
|
||||
type: "multimodal",
|
||||
status: "failed",
|
||||
progress: 25,
|
||||
sourceDataset: "image_text_pairs",
|
||||
targetCount: 2000,
|
||||
generatedCount: 500,
|
||||
createdAt: "2025-01-23",
|
||||
template: "多模态对话模板",
|
||||
errorMessage: "模型API调用失败,请检查配置",
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: "金融问答数据生成",
|
||||
type: "qa",
|
||||
status: "pending",
|
||||
progress: 0,
|
||||
sourceDataset: "financial_qa_dataset",
|
||||
targetCount: 800,
|
||||
generatedCount: 0,
|
||||
createdAt: "2025-01-24",
|
||||
template: "金融问答模板",
|
||||
estimatedTime: "等待开始",
|
||||
quality: 0,
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: "医疗文本蒸馏",
|
||||
type: "distillation",
|
||||
status: "paused",
|
||||
progress: 45,
|
||||
sourceDataset: "medical_corpus",
|
||||
targetCount: 3000,
|
||||
generatedCount: 1350,
|
||||
createdAt: "2025-01-21",
|
||||
template: "医疗蒸馏模板",
|
||||
estimatedTime: "已暂停",
|
||||
quality: 92,
|
||||
},
|
||||
];
|
||||
|
||||
export const mockTemplates: Template[] = [
|
||||
{
|
||||
id: 1,
|
||||
name: "判断题生成模板",
|
||||
type: "preset",
|
||||
category: "问答对生成",
|
||||
prompt: `根据给定的文本内容,生成一个判断题。
|
||||
|
||||
文本内容:{text}
|
||||
|
||||
请按照以下格式生成:
|
||||
1. 判断题:[基于文本内容的判断题]
|
||||
2. 答案:[对/错]
|
||||
3. 解释:[简要解释为什么这个答案是正确的]
|
||||
|
||||
要求:
|
||||
- 判断题应该基于文本的核心内容
|
||||
- 答案必须明确且有依据
|
||||
- 解释要简洁清晰`,
|
||||
variables: ["text"],
|
||||
description: "根据文本内容生成判断题,适用于教育和培训场景",
|
||||
usageCount: 156,
|
||||
lastUsed: "2025-01-20",
|
||||
quality: 95,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: "选择题生成模板",
|
||||
type: "preset",
|
||||
category: "问答对生成",
|
||||
prompt: `基于以下文本,创建一个多选题:
|
||||
|
||||
{text}
|
||||
|
||||
请按照以下格式生成:
|
||||
问题:[基于文本的问题]
|
||||
A. [选项A]
|
||||
B. [选项B]
|
||||
C. [选项C]
|
||||
D. [选项D]
|
||||
正确答案:[A/B/C/D]
|
||||
解析:[详细解释]
|
||||
|
||||
要求:
|
||||
- 问题要有一定难度
|
||||
- 选项要有迷惑性
|
||||
- 正确答案要有充分依据`,
|
||||
variables: ["text"],
|
||||
description: "生成多选题的标准模板,适用于考试和评估",
|
||||
usageCount: 89,
|
||||
lastUsed: "2025-01-19",
|
||||
quality: 92,
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: "知识蒸馏模板",
|
||||
type: "preset",
|
||||
category: "蒸馏数据集",
|
||||
prompt: `作为学生模型,学习教师模型的输出:
|
||||
|
||||
输入:{input}
|
||||
教师输出:{teacher_output}
|
||||
|
||||
请模仿教师模型的推理过程和输出格式,生成相似质量的回答。
|
||||
|
||||
要求:
|
||||
- 保持教师模型的推理逻辑
|
||||
- 输出格式要一致
|
||||
- 质量要接近教师模型水平`,
|
||||
variables: ["input", "teacher_output"],
|
||||
description: "用于知识蒸馏的模板,帮助小模型学习大模型的能力",
|
||||
usageCount: 234,
|
||||
lastUsed: "2025-01-22",
|
||||
quality: 88,
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: "金融问答模板",
|
||||
type: "custom",
|
||||
category: "问答对生成",
|
||||
prompt: `基于金融领域知识,生成专业问答对:
|
||||
|
||||
参考内容:{content}
|
||||
|
||||
生成格式:
|
||||
问题:[专业的金融问题]
|
||||
答案:[准确的专业回答]
|
||||
关键词:[相关金融术语]
|
||||
|
||||
要求:
|
||||
- 问题具有实用性
|
||||
- 答案准确专业
|
||||
- 符合金融行业标准`,
|
||||
variables: ["content"],
|
||||
description: "专门用于金融领域的问答对生成",
|
||||
usageCount: 45,
|
||||
lastUsed: "2025-01-18",
|
||||
quality: 89,
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: "医疗蒸馏模板",
|
||||
type: "custom",
|
||||
category: "蒸馏数据集",
|
||||
prompt: `医疗知识蒸馏模板:
|
||||
|
||||
原始医疗文本:{medical_text}
|
||||
专家标注:{expert_annotation}
|
||||
|
||||
生成医疗知识点:
|
||||
1. 核心概念:[提取关键医疗概念]
|
||||
2. 临床意义:[说明临床应用价值]
|
||||
3. 注意事项:[重要提醒和禁忌]
|
||||
|
||||
要求:
|
||||
- 确保医疗信息准确性
|
||||
- 遵循医疗伦理规范
|
||||
- 适合医学教育使用`,
|
||||
variables: ["medical_text", "expert_annotation"],
|
||||
description: "医疗领域专用的知识蒸馏模板",
|
||||
usageCount: 67,
|
||||
lastUsed: "2025-01-21",
|
||||
quality: 94,
|
||||
},
|
||||
];
|
||||
// Add mock files data
|
||||
export const mockFiles = [
|
||||
{ id: "file1", name: "dataset_part_001.jsonl", size: "2.5MB", type: "JSONL" },
|
||||
{ id: "file2", name: "dataset_part_002.jsonl", size: "2.3MB", type: "JSONL" },
|
||||
{ id: "file3", name: "dataset_part_003.jsonl", size: "2.7MB", type: "JSONL" },
|
||||
{ id: "file4", name: "training_data.txt", size: "1.8MB", type: "TXT" },
|
||||
{ id: "file5", name: "validation_set.csv", size: "856KB", type: "CSV" },
|
||||
{ id: "file6", name: "test_samples.json", size: "1.2MB", type: "JSON" },
|
||||
{ id: "file7", name: "raw_text_001.txt", size: "3.1MB", type: "TXT" },
|
||||
{ id: "file8", name: "raw_text_002.txt", size: "2.9MB", type: "TXT" },
|
||||
];
|
||||
|
||||
export const mockSynthesisTasks: SynthesisTask[] = [
|
||||
{
|
||||
id: 1,
|
||||
name: "文字生成问答对_判断题",
|
||||
type: "qa",
|
||||
status: "completed",
|
||||
progress: 100,
|
||||
sourceDataset: "orig_20250724_64082",
|
||||
targetCount: 1000,
|
||||
generatedCount: 1000,
|
||||
createdAt: "2025-01-20",
|
||||
template: "判断题生成模板",
|
||||
estimatedTime: "已完成",
|
||||
quality: 95,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: "知识蒸馏数据集",
|
||||
type: "distillation",
|
||||
status: "running",
|
||||
progress: 65,
|
||||
sourceDataset: "teacher_model_outputs",
|
||||
targetCount: 5000,
|
||||
generatedCount: 3250,
|
||||
createdAt: "2025-01-22",
|
||||
template: "蒸馏模板v2",
|
||||
estimatedTime: "剩余 15 分钟",
|
||||
quality: 88,
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: "多模态对话生成",
|
||||
type: "multimodal",
|
||||
status: "failed",
|
||||
progress: 25,
|
||||
sourceDataset: "image_text_pairs",
|
||||
targetCount: 2000,
|
||||
generatedCount: 500,
|
||||
createdAt: "2025-01-23",
|
||||
template: "多模态对话模板",
|
||||
errorMessage: "模型API调用失败,请检查配置",
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: "金融问答数据生成",
|
||||
type: "qa",
|
||||
status: "pending",
|
||||
progress: 0,
|
||||
sourceDataset: "financial_qa_dataset",
|
||||
targetCount: 800,
|
||||
generatedCount: 0,
|
||||
createdAt: "2025-01-24",
|
||||
template: "金融问答模板",
|
||||
estimatedTime: "等待开始",
|
||||
quality: 0,
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: "医疗文本蒸馏",
|
||||
type: "distillation",
|
||||
status: "paused",
|
||||
progress: 45,
|
||||
sourceDataset: "medical_corpus",
|
||||
targetCount: 3000,
|
||||
generatedCount: 1350,
|
||||
createdAt: "2025-01-21",
|
||||
template: "医疗蒸馏模板",
|
||||
estimatedTime: "已暂停",
|
||||
quality: 92,
|
||||
},
|
||||
];
|
||||
|
||||
export const mockTemplates: Template[] = [
|
||||
{
|
||||
id: 1,
|
||||
name: "判断题生成模板",
|
||||
type: "preset",
|
||||
category: "问答对生成",
|
||||
prompt: `根据给定的文本内容,生成一个判断题。
|
||||
|
||||
文本内容:{text}
|
||||
|
||||
请按照以下格式生成:
|
||||
1. 判断题:[基于文本内容的判断题]
|
||||
2. 答案:[对/错]
|
||||
3. 解释:[简要解释为什么这个答案是正确的]
|
||||
|
||||
要求:
|
||||
- 判断题应该基于文本的核心内容
|
||||
- 答案必须明确且有依据
|
||||
- 解释要简洁清晰`,
|
||||
variables: ["text"],
|
||||
description: "根据文本内容生成判断题,适用于教育和培训场景",
|
||||
usageCount: 156,
|
||||
lastUsed: "2025-01-20",
|
||||
quality: 95,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: "选择题生成模板",
|
||||
type: "preset",
|
||||
category: "问答对生成",
|
||||
prompt: `基于以下文本,创建一个多选题:
|
||||
|
||||
{text}
|
||||
|
||||
请按照以下格式生成:
|
||||
问题:[基于文本的问题]
|
||||
A. [选项A]
|
||||
B. [选项B]
|
||||
C. [选项C]
|
||||
D. [选项D]
|
||||
正确答案:[A/B/C/D]
|
||||
解析:[详细解释]
|
||||
|
||||
要求:
|
||||
- 问题要有一定难度
|
||||
- 选项要有迷惑性
|
||||
- 正确答案要有充分依据`,
|
||||
variables: ["text"],
|
||||
description: "生成多选题的标准模板,适用于考试和评估",
|
||||
usageCount: 89,
|
||||
lastUsed: "2025-01-19",
|
||||
quality: 92,
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: "知识蒸馏模板",
|
||||
type: "preset",
|
||||
category: "蒸馏数据集",
|
||||
prompt: `作为学生模型,学习教师模型的输出:
|
||||
|
||||
输入:{input}
|
||||
教师输出:{teacher_output}
|
||||
|
||||
请模仿教师模型的推理过程和输出格式,生成相似质量的回答。
|
||||
|
||||
要求:
|
||||
- 保持教师模型的推理逻辑
|
||||
- 输出格式要一致
|
||||
- 质量要接近教师模型水平`,
|
||||
variables: ["input", "teacher_output"],
|
||||
description: "用于知识蒸馏的模板,帮助小模型学习大模型的能力",
|
||||
usageCount: 234,
|
||||
lastUsed: "2025-01-22",
|
||||
quality: 88,
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: "金融问答模板",
|
||||
type: "custom",
|
||||
category: "问答对生成",
|
||||
prompt: `基于金融领域知识,生成专业问答对:
|
||||
|
||||
参考内容:{content}
|
||||
|
||||
生成格式:
|
||||
问题:[专业的金融问题]
|
||||
答案:[准确的专业回答]
|
||||
关键词:[相关金融术语]
|
||||
|
||||
要求:
|
||||
- 问题具有实用性
|
||||
- 答案准确专业
|
||||
- 符合金融行业标准`,
|
||||
variables: ["content"],
|
||||
description: "专门用于金融领域的问答对生成",
|
||||
usageCount: 45,
|
||||
lastUsed: "2025-01-18",
|
||||
quality: 89,
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: "医疗蒸馏模板",
|
||||
type: "custom",
|
||||
category: "蒸馏数据集",
|
||||
prompt: `医疗知识蒸馏模板:
|
||||
|
||||
原始医疗文本:{medical_text}
|
||||
专家标注:{expert_annotation}
|
||||
|
||||
生成医疗知识点:
|
||||
1. 核心概念:[提取关键医疗概念]
|
||||
2. 临床意义:[说明临床应用价值]
|
||||
3. 注意事项:[重要提醒和禁忌]
|
||||
|
||||
要求:
|
||||
- 确保医疗信息准确性
|
||||
- 遵循医疗伦理规范
|
||||
- 适合医学教育使用`,
|
||||
variables: ["medical_text", "expert_annotation"],
|
||||
description: "医疗领域专用的知识蒸馏模板",
|
||||
usageCount: 67,
|
||||
lastUsed: "2025-01-21",
|
||||
quality: 94,
|
||||
},
|
||||
];
|
||||
|
||||
Reference in New Issue
Block a user