init datamate

This commit is contained in:
Dallas98
2025-10-21 23:00:48 +08:00
commit 1c97afed7d
692 changed files with 135442 additions and 0 deletions

View File

@@ -0,0 +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" />,
},
]

View File

@@ -0,0 +1,56 @@
import {
DatabaseOutlined,
BarChartOutlined,
FileTextOutlined,
ThunderboltOutlined,
PictureOutlined,
CalculatorOutlined,
SwapOutlined,
} from "@ant-design/icons";
import { FileImage, FileText, Music, Repeat, Video } from "lucide-react";
// 模板类型选项
export const templateTypes = [
{
value: "text",
label: "文本",
icon: FileText,
description: "处理文本数据的清洗模板",
},
{
value: "image",
label: "图片",
icon: FileImage,
description: "处理图像数据的清洗模板",
},
{
value: "video",
label: "视频",
icon: Video,
description: "处理视频数据的清洗模板",
},
{
value: "audio",
label: "音频",
icon: Music,
description: "处理音频数据的清洗模板",
},
{
value: "image-to-text",
label: "图片转文本",
icon: Repeat,
description: "图像识别转文本的处理模板",
},
];
// 算子分类
export const OPERATOR_CATEGORIES = {
data: { name: "数据清洗", icon: <DatabaseOutlined />, color: "#1677ff" },
ml: { name: "机器学习", icon: <ThunderboltOutlined />, color: "#722ed1" },
vision: { name: "计算机视觉", icon: <PictureOutlined />, color: "#52c41a" },
nlp: { name: "自然语言处理", icon: <FileTextOutlined />, color: "#faad14" },
analysis: { name: "数据分析", icon: <BarChartOutlined />, color: "#f5222d" },
transform: { name: "数据转换", icon: <SwapOutlined />, color: "#13c2c2" },
io: { name: "输入输出", icon: <FileTextOutlined />, color: "#595959" },
math: { name: "数学计算", icon: <CalculatorOutlined />, color: "#fadb14" },
};

View File

@@ -0,0 +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,
},
],
},
}

View File

@@ -0,0 +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: [],
},
];

View File

@@ -0,0 +1,149 @@
const { addMockPrefix } = require("./mock-core/util.cjs");
const MockAPI = {
// 数据归集接口
queryTasksUsingPost: "/data-collection/tasks", // 获取数据源任务列表
createTaskUsingPost: "/data-collection/tasks/create", // 创建数据源任务
queryTaskByIdUsingGet: "/data-collection/tasks/:id", // 根据ID获取数据源任务详情
updateTaskByIdUsingPut: "/data-collection/tasks/:id", // 更新数据源任务
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蒸馏
queryOperatorsUsingPost: "/synthesis/operators", // 获取操作列表
// 数据评测接口
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/bases", // 获取知识库列表
createKnowledgeBaseUsingPost: "/knowledge/bases/create", // 创建知识库
queryKnowledgeBaseByIdUsingGet: "/knowledge/bases/:baseId", // 根据ID获取知识库详情
updateKnowledgeBaseByIdUsingPut: "/knowledge/bases/:baseId", // 更新知识库
deleteKnowledgeBaseByIdUsingDelete: "/knowledge/bases/:baseId", // 删除知识库
queryKnowledgeGenerationTasksUsingPost: "/knowledge/tasks", // 获取知识生成任务列表
createKnowledgeGenerationTaskUsingPost: "/knowledge/tasks/create", // 创建知识生成任务
queryKnowledgeGenerationTaskByIdUsingGet: "/knowledge/tasks/:taskId", // 根据ID获取知识生成任务详情
updateKnowledgeGenerationTaskByIdUsingPut: "/knowledge/tasks/:taskId", // 更新知识生成任务
deleteKnowledgeGenerationTaskByIdUsingDelete: "/knowledge/tasks/:taskId", // 删除知识生成任务
executeKnowledgeGenerationTaskByIdUsingPost:
"/knowledge/tasks/:taskId/execute", // 执行知识生成任务
stopKnowledgeGenerationTaskByIdUsingPost: "/knowledge/tasks/:taskId/stop", // 停止知识生成任务
queryKnowledgeStatisticsUsingGet: "/knowledge/statistics", // 获取知识生成
// 算子市场
queryOperatorsUsingPost: "/operators/list", // 获取算子列表
queryCategoryTreeUsingGet: "/categories/tree", // 获取算子分类树
queryOperatorByIdUsingGet: "/operators/:operatorId", // 根据ID获取算子详情
createOperatorUsingPost: "/operators/create", // 创建算子
updateOperatorByIdUsingPut: "/operators/:operatorId", // 更新算子
uploadOperatorUsingPost: "/operators/upload", // 上传算子
createLabelUsingPost: "/operators/labels", // 创建算子标签
queryLabelsUsingGet: "/labels", // 获取算子标签列表
deleteLabelsUsingDelete: "/labels", // 删除算子标签
updateLabelByIdUsingPut: "/labels/:labelId", // 更新算子标签
deleteOperatorByIdUsingDelete: "/operators/:operatorId", // 删除算子
publishOperatorUsingPost: "/operators/:operatorId/publish", // 发布算子
unpublishOperatorUsingPost: "/operators/:operatorId/unpublish", // 下架算子
};
module.exports = addMockPrefix("/api", MockAPI);

View File

@@ -0,0 +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,
};

View File

@@ -0,0 +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,
};

View File

@@ -0,0 +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,
};

View File

@@ -0,0 +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;

View File

@@ -0,0 +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,
};

View File

@@ -0,0 +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();
};
module.exports = sendJSON;

View File

@@ -0,0 +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();
};
module.exports = setHeader;

View File

@@ -0,0 +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();
};
module.exports = strongMatch;

View File

@@ -0,0 +1,618 @@
const Mock = require("mockjs");
const API = require("../mock-apis.cjs");
// 标注任务数据
function annotationTaskItem() {
return {
source_dataset_id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
mapping_id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
labelling_project_id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
labelling_project_name: Mock.Random.ctitle(5, 20),
created_at: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
last_updated_at: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
deleted_at: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
// id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
// name: Mock.Random.ctitle(5, 20),
// description: Mock.Random.csentence(5, 30),
// type: Mock.Random.pick([
// "TEXT_CLASSIFICATION",
// "NAMED_ENTITY_RECOGNITION",
// "OBJECT_DETECTION",
// "SEMANTIC_SEGMENTATION",
// ]),
// status: Mock.Random.pick(["PENDING", "IN_PROGRESS", "COMPLETED", "PAUSED"]),
// datasetId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
// progress: Mock.Random.float(0, 100, 2, 2),
// createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
// updatedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
// createdBy: Mock.Random.cname(),
// assignedTo: Mock.Random.cname(),
// totalDataCount: Mock.Random.integer(100, 10000),
// annotatedCount: Mock.Random.integer(10, 500),
// configuration: {
// labels: Mock.Random.shuffle([
// "正面",
// "负面",
// "中性",
// "人物",
// "地点",
// "组织",
// "时间",
// ]).slice(0, Mock.Random.integer(3, 5)),
// guidelines: Mock.Random.csentence(10, 50),
// qualityThreshold: Mock.Random.float(0.8, 1.0, 2, 2),
// },
// statistics: {
// accuracy: Mock.Random.float(0.85, 0.99, 2, 2),
// averageTime: Mock.Random.integer(30, 300), // seconds
// reviewCount: Mock.Random.integer(0, 50),
// },
};
}
const annotationTaskList = new Array(25).fill(null).map(annotationTaskItem);
// 标注数据项
function annotationDataItem() {
return {
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
taskId: Mock.Random.pick(annotationTaskList).id,
content: Mock.Random.cparagraph(1, 3),
originalData: {
text: Mock.Random.cparagraph(1, 3),
source: Mock.Random.url(),
metadata: {
author: Mock.Random.cname(),
timestamp: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
},
},
annotations: [
{
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
label: Mock.Random.pick(["正面", "负面", "中性"]),
confidence: Mock.Random.float(0.7, 1.0, 2, 2),
annotator: Mock.Random.cname(),
createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
isPreAnnotation: Mock.Random.boolean(),
},
],
status: Mock.Random.pick(["PENDING", "ANNOTATED", "REVIEWED", "REJECTED"]),
priority: Mock.Random.integer(1, 5),
createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
updatedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
};
}
const annotationDataList = new Array(200).fill(null).map(annotationDataItem);
// 标注模板数据
function annotationTemplateItem() {
return {
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
name: Mock.Random.ctitle(5, 15),
description: Mock.Random.csentence(5, 25),
type: Mock.Random.pick([
"TEXT_CLASSIFICATION",
"NAMED_ENTITY_RECOGNITION",
"OBJECT_DETECTION",
"SEMANTIC_SEGMENTATION",
]),
category: Mock.Random.ctitle(3, 8),
labels: Mock.Random.shuffle([
"正面",
"负面",
"中性",
"人物",
"地点",
"组织",
"时间",
"产品",
"服务",
]).slice(0, Mock.Random.integer(3, 6)),
guidelines: Mock.Random.csentence(10, 50),
usageCount: Mock.Random.integer(0, 100),
createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
createdBy: Mock.Random.cname(),
};
}
const annotationTemplateList = new Array(15)
.fill(null)
.map(annotationTemplateItem);
// 标注者数据
function annotatorItem() {
return {
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
name: Mock.Random.cname(),
email: Mock.Random.email(),
role: Mock.Random.pick(["ANNOTATOR", "REVIEWER", "ADMIN"]),
skillLevel: Mock.Random.pick(["BEGINNER", "INTERMEDIATE", "EXPERT"]),
specialties: Mock.Random.shuffle([
"文本分类",
"命名实体识别",
"目标检测",
"语义分割",
]).slice(0, Mock.Random.integer(1, 3)),
statistics: {
totalAnnotations: Mock.Random.integer(100, 5000),
accuracy: Mock.Random.float(0.85, 0.99, 2, 2),
averageSpeed: Mock.Random.integer(50, 200), // annotations per hour
totalWorkTime: Mock.Random.integer(10, 500), // hours
},
status: Mock.Random.pick(["ACTIVE", "INACTIVE", "SUSPENDED"]),
createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
};
}
const annotatorList = new Array(20).fill(null).map(annotatorItem);
module.exports = function (router) {
// 获取标注任务列表
router.get(API.queryAnnotationTasksUsingGet, (req, res) => {
const { page = 0, size = 20, status, type } = req.query;
let filteredTasks = annotationTaskList;
if (status) {
filteredTasks = filteredTasks.filter((task) => task.status === status);
}
if (type) {
filteredTasks = filteredTasks.filter((task) => task.type === type);
}
const startIndex = page * size;
const endIndex = startIndex + parseInt(size);
const pageData = filteredTasks.slice(startIndex, endIndex);
res.send({
code: "0",
msg: "Success",
data: {
content: pageData,
totalElements: filteredTasks.length,
totalPages: Math.ceil(filteredTasks.length / size),
size: parseInt(size),
number: parseInt(page),
first: page == 0,
last: page >= Math.ceil(filteredTasks.length / size) - 1,
},
});
});
// 创建标注任务
router.post(API.createAnnotationTaskUsingPost, (req, res) => {
const newTask = {
...annotationTaskItem(),
...req.body,
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
status: "PENDING",
progress: 0,
annotatedCount: 0,
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
};
annotationTaskList.push(newTask);
res.status(201).send({
code: "0",
msg: "Annotation task created successfully",
data: newTask,
});
});
// 获取标注任务详情
router.get(API.queryAnnotationTaskByIdUsingGet, (req, res) => {
const { taskId } = req.params;
const task = annotationTaskList.find((t) => t.id === taskId);
if (task) {
res.send({
code: "0",
msg: "Success",
data: task,
});
} else {
res.status(404).send({
code: "1",
msg: "Annotation task not found",
data: null,
});
}
});
// 更新标注任务
router.put(API.syncAnnotationTaskByIdUsingPost, (req, res) => {
const { taskId } = req.params;
const index = annotationTaskList.findIndex((t) => t.id === taskId);
if (index !== -1) {
annotationTaskList[index] = {
...annotationTaskList[index],
...req.body,
updatedAt: new Date().toISOString(),
};
res.send({
code: "0",
msg: "Annotation task updated successfully",
data: annotationTaskList[index],
});
} else {
res.status(404).send({
code: "1",
msg: "Annotation task not found",
data: null,
});
}
});
// 删除标注任务
router.delete(API.deleteAnnotationTaskByIdUsingDelete, (req, res) => {
const { taskId } = req.params;
const index = annotationTaskList.findIndex((t) => t.id === taskId);
if (index !== -1) {
annotationTaskList.splice(index, 1);
res.send({
code: "0",
msg: "Annotation task deleted successfully",
data: null,
});
} else {
res.status(404).send({
code: "1",
msg: "Annotation task not found",
data: null,
});
}
});
// 获取标注数据列表
router.get(API.queryAnnotationDataUsingGet, (req, res) => {
const { taskId } = req.params;
const { page = 0, size = 20, status } = req.query;
let filteredData = annotationDataList.filter(
(data) => data.taskId === taskId
);
if (status) {
filteredData = filteredData.filter((data) => data.status === status);
}
const startIndex = page * size;
const endIndex = startIndex + parseInt(size);
const pageData = filteredData.slice(startIndex, endIndex);
res.send({
code: "0",
msg: "Success",
data: {
content: pageData,
totalElements: filteredData.length,
totalPages: Math.ceil(filteredData.length / size),
size: parseInt(size),
number: parseInt(page),
},
});
});
// 提交标注
router.post(API.submitAnnotationUsingPost, (req, res) => {
const { taskId } = req.params;
const newAnnotation = {
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
taskId,
...req.body,
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
};
res.status(201).send({
code: "0",
msg: "Annotation submitted successfully",
data: newAnnotation,
});
});
// 更新标注
router.put(API.updateAnnotationUsingPut, (req, res) => {
const { taskId, annotationId } = req.params;
res.send({
code: "0",
msg: "Annotation updated successfully",
data: {
id: annotationId,
taskId,
...req.body,
updatedAt: new Date().toISOString(),
},
});
});
// 删除标注
router.delete(API.deleteAnnotationUsingDelete, (req, res) => {
const { taskId, annotationId } = req.params;
res.send({
code: "0",
msg: "Annotation deleted successfully",
data: null,
});
});
// 开始标注任务
router.post(API.startAnnotationTaskUsingPost, (req, res) => {
const { taskId } = req.params;
const task = annotationTaskList.find((t) => t.id === taskId);
if (task) {
task.status = "IN_PROGRESS";
task.updatedAt = new Date().toISOString();
res.send({
code: "0",
msg: "Annotation task started successfully",
data: task,
});
} else {
res.status(404).send({
code: "1",
msg: "Annotation task not found",
data: null,
});
}
});
// 暂停标注任务
router.post(API.pauseAnnotationTaskUsingPost, (req, res) => {
const { taskId } = req.params;
const task = annotationTaskList.find((t) => t.id === taskId);
if (task) {
task.status = "PAUSED";
task.updatedAt = new Date().toISOString();
res.send({
code: "0",
msg: "Annotation task paused successfully",
data: task,
});
} else {
res.status(404).send({
code: "1",
msg: "Annotation task not found",
data: null,
});
}
});
// 恢复标注任务
router.post(API.resumeAnnotationTaskUsingPost, (req, res) => {
const { taskId } = req.params;
const task = annotationTaskList.find((t) => t.id === taskId);
if (task) {
task.status = "IN_PROGRESS";
task.updatedAt = new Date().toISOString();
res.send({
code: "0",
msg: "Annotation task resumed successfully",
data: task,
});
} else {
res.status(404).send({
code: "1",
msg: "Annotation task not found",
data: null,
});
}
});
// 完成标注任务
router.post(API.completeAnnotationTaskUsingPost, (req, res) => {
const { taskId } = req.params;
const task = annotationTaskList.find((t) => t.id === taskId);
if (task) {
task.status = "COMPLETED";
task.progress = 100;
task.updatedAt = new Date().toISOString();
res.send({
code: "0",
msg: "Annotation task completed successfully",
data: task,
});
} else {
res.status(404).send({
code: "1",
msg: "Annotation task not found",
data: null,
});
}
});
// 获取标注任务统计信息
router.get(API.getAnnotationTaskStatisticsUsingGet, (req, res) => {
const { taskId } = req.params;
const task = annotationTaskList.find((t) => t.id === taskId);
if (task) {
const statistics = {
taskId,
totalDataCount: task.totalDataCount,
annotatedCount: task.annotatedCount,
progress: task.progress,
accuracy: task.statistics.accuracy,
averageAnnotationTime: task.statistics.averageTime,
reviewCount: task.statistics.reviewCount,
qualityScore: Mock.Random.float(0.8, 0.99, 2, 2),
annotatorDistribution: {
[Mock.Random.cname()]: Mock.Random.integer(10, 100),
[Mock.Random.cname()]: Mock.Random.integer(10, 100),
[Mock.Random.cname()]: Mock.Random.integer(10, 100),
},
};
res.send({
code: "0",
msg: "Success",
data: statistics,
});
} else {
res.status(404).send({
code: "1",
msg: "Annotation task not found",
data: null,
});
}
});
// 获取整体标注统计信息
router.get(API.getAnnotationStatisticsUsingGet, (req, res) => {
const statistics = {
totalTasks: annotationTaskList.length,
completedTasks: annotationTaskList.filter((t) => t.status === "COMPLETED")
.length,
inProgressTasks: annotationTaskList.filter(
(t) => t.status === "IN_PROGRESS"
).length,
pendingTasks: annotationTaskList.filter((t) => t.status === "PENDING")
.length,
totalAnnotations: annotationDataList.length,
totalAnnotators: annotatorList.length,
averageAccuracy: Mock.Random.float(0.85, 0.95, 2, 2),
taskTypeDistribution: {
TEXT_CLASSIFICATION: Mock.Random.integer(5, 15),
NAMED_ENTITY_RECOGNITION: Mock.Random.integer(3, 10),
OBJECT_DETECTION: Mock.Random.integer(2, 8),
SEMANTIC_SEGMENTATION: Mock.Random.integer(1, 5),
},
};
res.send({
code: "0",
msg: "Success",
data: statistics,
});
});
// 获取标注模板列表
router.get(API.queryAnnotationTemplatesUsingGet, (req, res) => {
const { page = 0, size = 20, type } = req.query;
let filteredTemplates = annotationTemplateList;
if (type) {
filteredTemplates = filteredTemplates.filter(
(template) => template.type === type
);
}
const startIndex = page * size;
const endIndex = startIndex + parseInt(size);
const pageData = filteredTemplates.slice(startIndex, endIndex);
res.send({
code: "0",
msg: "Success",
data: {
content: pageData,
totalElements: filteredTemplates.length,
totalPages: Math.ceil(filteredTemplates.length / size),
size: parseInt(size),
number: parseInt(page),
},
});
});
// 创建标注模板
router.post(API.createAnnotationTemplateUsingPost, (req, res) => {
const newTemplate = {
...annotationTemplateItem(),
...req.body,
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
usageCount: 0,
createdAt: new Date().toISOString(),
};
annotationTemplateList.push(newTemplate);
res.status(201).send({
code: "0",
msg: "Annotation template created successfully",
data: newTemplate,
});
});
// 获取标注模板详情
router.get(API.queryAnnotationTemplateByIdUsingGet, (req, res) => {
const { templateId } = req.params;
const template = annotationTemplateList.find((t) => t.id === templateId);
if (template) {
res.send({
code: "0",
msg: "Success",
data: template,
});
} else {
res.status(404).send({
code: "1",
msg: "Annotation template not found",
data: null,
});
}
});
// 获取标注者列表
router.get(API.queryAnnotatorsUsingGet, (req, res) => {
const { page = 0, size = 20, status, skillLevel } = req.query;
let filteredAnnotators = annotatorList;
if (status) {
filteredAnnotators = filteredAnnotators.filter(
(annotator) => annotator.status === status
);
}
if (skillLevel) {
filteredAnnotators = filteredAnnotators.filter(
(annotator) => annotator.skillLevel === skillLevel
);
}
const startIndex = page * size;
const endIndex = startIndex + parseInt(size);
const pageData = filteredAnnotators.slice(startIndex, endIndex);
res.send({
code: "0",
msg: "Success",
data: {
content: pageData,
totalElements: filteredAnnotators.length,
totalPages: Math.ceil(filteredAnnotators.length / size),
size: parseInt(size),
number: parseInt(page),
},
});
});
// 分配标注者
router.post(API.assignAnnotatorUsingPost, (req, res) => {
const { taskId } = req.params;
const { annotatorIds } = req.body;
res.send({
code: "0",
msg: "Annotators assigned successfully",
data: {
taskId,
assignedAnnotators: annotatorIds,
assignedAt: new Date().toISOString(),
},
});
});
};

View File

@@ -0,0 +1,544 @@
const Mock = require("mockjs");
const API = require("../mock-apis.cjs");
function operatorItem() {
return {
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
name: Mock.Random.ctitle(3, 10),
description: Mock.Random.csentence(5, 20),
version: "1.0.0",
inputs: Mock.Random.integer(1, 5),
outputs: Mock.Random.integer(1, 5),
settings: JSON.stringify({
fileLength: {
name: "文档字数",
description:
"过滤字数不在指定范围内的文档,如[10,10000000]。若输入为空,则不对字数上/下限做限制。",
type: "range",
defaultVal: [10, 10000000],
min: 0,
max: 10000000000000000,
step: 1,
},
host: { type: "input", name: "主机地址", defaultVal: "localhost" },
limit: {
type: "range",
name: "读取行数",
defaultVal: [1000, 2000],
min: 100,
max: 10000,
step: 100,
},
filepath: { type: "input", name: "文件路径", defaultVal: "/path" },
encoding: {
type: "select",
name: "编码",
defaultVal: "utf-8",
options: ["utf-8", "gbk", "ascii"],
},
radio: {
type: "radio",
name: "radio",
defaultVal: "utf-8",
options: ["utf-8", "gbk", "ascii"],
},
features: {
type: "checkbox",
name: "特征列",
defaultVal: ["feature1", "feature3"],
options: ["feature1", "feature2", "feature3"],
},
repeatPhraseRatio: {
name: "文档词重复率",
description: "某个词的统计数/文档总词数 > 设定值,该文档被去除。",
type: "slider",
defaultVal: 0.5,
min: 0,
max: 1,
step: 0.1,
},
hitStopwords: {
name: "去除停用词",
description: "统计重复词时,选择是否要去除停用词。",
type: "switch",
defaultVal: false,
required: true,
checkedLabel: "去除",
unCheckedLabel: "不去除",
},
}),
categories: [Mock.Random.pick([3, 4, 5, 6, 7, 8, 9])],
isStar: Mock.Random.boolean(),
createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
updatedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
};
}
const operatorList = new Array(50).fill(null).map(operatorItem);
// 清洗任务数据
function cleaningTaskItem() {
return {
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
name: Mock.Random.ctitle(5, 20),
description: Mock.Random.csentence(5, 30),
status: Mock.Random.pick([
"PENDING",
"RUNNING",
"COMPLETED",
"FAILED",
"STOPPED",
]),
srcDatasetId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
srcDatasetName: Mock.Random.ctitle(5, 15),
destDatasetId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
destDatasetName: Mock.Random.ctitle(5, 15),
progress: Mock.Random.float(0, 100, 2, 2),
startedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
endedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
updatedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
instance: operatorList,
};
}
const cleaningTaskList = new Array(20).fill(null).map(cleaningTaskItem);
// 清洗模板数据
function cleaningTemplateItem() {
return {
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
name: Mock.Random.ctitle(5, 15),
description: Mock.Random.csentence(5, 25),
instance: operatorList.slice(
Mock.Random.integer(0, 5),
Mock.Random.integer(6, 50)
),
category: Mock.Random.ctitle(3, 8),
createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
updatedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
};
}
const cleaningTemplateList = new Array(15).fill(null).map(cleaningTemplateItem);
const categoryTree = [
{
id: 1,
name: "modal",
count: 7,
categories: [
{ id: 3, name: "text", count: 3, type: null, parentId: null },
{ id: 4, name: "image", count: 0, type: null, parentId: null },
{ id: 5, name: "audio", count: 0, type: null, parentId: null },
{ id: 6, name: "video", count: 0, type: null, parentId: null },
{
id: 7,
name: "multimodal",
count: 0,
type: null,
parentId: null,
},
],
},
{
id: 2,
name: "language",
count: 3,
categories: [
{ id: 8, name: "python", count: 2, type: null, parentId: null },
{ id: 9, name: "java", count: 1, type: null, parentId: null },
],
},
];
module.exports = function (router) {
// 获取清洗任务列表
router.get(API.queryCleaningTasksUsingGet, (req, res) => {
const { page = 0, size = 10, status } = req.query;
let filteredTasks = cleaningTaskList;
if (status) {
filteredTasks = cleaningTaskList.filter((task) => task.status === status);
}
const startIndex = page * size;
const endIndex = startIndex + parseInt(size);
const pageData = filteredTasks.slice(startIndex, endIndex);
res.send({
code: "0",
msg: "Success",
data: {
content: pageData,
totalElements: filteredTasks.length,
totalPages: Math.ceil(filteredTasks.length / size),
size: parseInt(size),
number: parseInt(page),
},
});
});
// 创建清洗任务
router.post(API.createCleaningTaskUsingPost, (req, res) => {
const newTask = {
...cleaningTaskItem(),
...req.body,
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
status: "PENDING",
createdAt: new Date().toISOString(),
};
cleaningTaskList.push(newTask);
res.status(201).send({
code: "0",
msg: "Cleaning task created successfully",
data: newTask,
});
});
// 获取清洗任务详情
router.get(API.queryCleaningTaskByIdUsingGet, (req, res) => {
const { taskId } = req.params;
const task = cleaningTaskList.find((j) => j.id === taskId);
if (task) {
res.send({
code: "0",
msg: "Success",
data: task,
});
} else {
res.status(404).send({
code: "1",
msg: "Cleaning task not found",
data: null,
});
}
});
// 删除清洗任务
router.delete(API.deleteCleaningTaskByIdUsingDelete, (req, res) => {
const { taskId } = req.params;
const index = cleaningTaskList.findIndex((j) => j.id === taskId);
if (index !== -1) {
cleaningTaskList.splice(index, 1);
res.send({
code: "0",
msg: "Cleaning task deleted successfully",
data: null,
});
} else {
res.status(404).send({
code: "1",
msg: "Cleaning task not found",
data: null,
});
}
});
// 执行清洗任务
router.post(API.executeCleaningTaskUsingPost, (req, res) => {
const { taskId } = req.params;
const task = cleaningTaskList.find((j) => j.id === taskId);
if (task) {
task.status = "running";
task.startTime = new Date().toISOString();
res.send({
code: "0",
msg: "Cleaning task execution started",
data: {
executionId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
status: "running",
message: "Task execution started successfully",
},
});
} else {
res.status(404).send({
code: "1",
msg: "Cleaning task not found",
data: null,
});
}
});
// 停止清洗任务
router.post(API.stopCleaningTaskUsingPost, (req, res) => {
const { taskId } = req.params;
const task = cleaningTaskList.find((j) => j.id === taskId);
if (task) {
task.status = "pending";
task.endTime = new Date().toISOString();
res.send({
code: "0",
msg: "Cleaning task stopped successfully",
data: null,
});
} else {
res.status(404).send({
code: "1",
msg: "Cleaning task not found",
data: null,
});
}
});
// 获取清洗模板列表
router.get(API.queryCleaningTemplatesUsingGet, (req, res) => {
const { page = 0, size = 20 } = req.query;
const startIndex = page * size;
const endIndex = startIndex + parseInt(size);
const pageData = cleaningTemplateList.slice(startIndex, endIndex);
res.send({
code: "0",
msg: "Success",
data: { content: pageData, totalElements: cleaningTemplateList.length },
});
});
// 创建清洗模板
router.post(API.createCleaningTemplateUsingPost, (req, res) => {
const newTemplate = {
...cleaningTemplateItem(),
...req.body,
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
createdAt: new Date().toISOString(),
};
cleaningTemplateList.push(newTemplate);
res.status(201).send({
code: "0",
msg: "Cleaning template created successfully",
data: newTemplate,
});
});
// 获取清洗模板详情
router.get(API.queryCleaningTemplateByIdUsingGet, (req, res) => {
const { templateId } = req.params;
const template = cleaningTemplateList.find((t) => t.id === templateId);
if (template) {
res.send({
code: "0",
msg: "Success",
data: template,
});
} else {
res.status(404).send({
code: "1",
msg: "Cleaning template not found",
data: null,
});
}
});
// 删除清洗模板
router.delete(API.deleteCleaningTemplateByIdUsingDelete, (req, res) => {
const { templateId } = req.params;
const index = cleaningTemplateList.findIndex((t) => t.id === templateId);
if (index !== -1) {
cleaningTemplateList.splice(index, 1);
res.send({
code: "0",
msg: "Cleaning template deleted successfully",
data: null,
});
} else {
res.status(404).send({
code: "1",
msg: "Cleaning template not found",
data: null,
});
}
});
// 获取算子列表
router.post(API.queryOperatorsUsingPost, (req, res) => {
const {
page = 0,
size = 20,
categories = [],
operatorName = "",
labelName = "",
isStar,
} = req.body;
let filteredOperators = operatorList;
// 按分类筛选
if (categories && categories.length > 0) {
filteredOperators = filteredOperators.filter((op) =>
categories.includes(op.category.id)
);
}
// 按名称搜索
if (operatorName) {
filteredOperators = filteredOperators.filter((op) =>
op.name.toLowerCase().includes(operatorName.toLowerCase())
);
}
// 按标签筛选
if (labelName) {
filteredOperators = filteredOperators.filter((op) =>
op.labels.some((label) => label.name.includes(labelName))
);
}
// 按收藏状态筛选
if (typeof isStar === "boolean") {
filteredOperators = filteredOperators.filter(
(op) => op.isStar === isStar
);
}
const startIndex = page * size;
const endIndex = startIndex + parseInt(size);
const pageData = filteredOperators.slice(startIndex, endIndex);
res.send({
code: "0",
msg: "Success",
data: {
content: pageData,
totalElements: filteredOperators.length,
totalPages: Math.ceil(filteredOperators.length / size),
size: parseInt(size),
number: parseInt(page),
first: page === 0,
last: page >= Math.ceil(filteredOperators.length / size) - 1,
},
});
});
// 获取算子详情
router.get(API.queryOperatorByIdUsingGet, (req, res) => {
const { id } = req.params;
const operator = operatorList.find((op) => op.id === id);
if (operator) {
// 增加浏览次数模拟
operator.viewCount = (operator.viewCount || 0) + 1;
res.send({
code: "0",
msg: "Success",
data: operator,
});
} else {
res.status(404).send({
error: "OPERATOR_NOT_FOUND",
message: "算子不存在",
timestamp: new Date().toISOString(),
});
}
});
// 更新算子信息
router.put(API.updateOperatorByIdUsingPut, (req, res) => {
const { id } = req.params;
const index = operatorList.findIndex((op) => op.id === id);
if (index !== -1) {
operatorList[index] = {
...operatorList[index],
...req.body,
updatedAt: new Date().toISOString(),
};
res.send({
code: "0",
msg: "Operator updated successfully",
data: operatorList[index],
});
} else {
res.status(404).send({
error: "OPERATOR_NOT_FOUND",
message: "算子不存在",
timestamp: new Date().toISOString(),
});
}
});
// 创建算子
router.post(API.createOperatorUsingPost, (req, res) => {
const { name, description, version, category, documentation } = req.body;
const newOperator = {
...operatorItem(),
...req.body,
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
name,
description,
version,
category:
typeof category === "string"
? { id: category, name: category }
: category,
documentation,
status: "REVIEWING",
downloadCount: 0,
rating: 0,
ratingCount: 0,
isStar: false,
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
};
operatorList.push(newOperator);
res.status(201).send({
code: "0",
msg: "Operator created successfully",
data: newOperator,
});
});
// 上传算子
router.post(API.uploadOperatorUsingPost, (req, res) => {
const { description } = req.body;
const newOperator = {
...operatorItem(),
description: description || "通过文件上传创建的算子",
status: "REVIEWING",
downloadCount: 0,
rating: 0,
ratingCount: 0,
isStar: false,
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
};
operatorList.push(newOperator);
res.status(201).send({
code: "0",
msg: "Operator uploaded successfully",
data: newOperator,
});
});
// 获取算子分类树
router.get(API.queryCategoryTreeUsingGet, (req, res) => {
res.send({
code: "0",
msg: "Success",
data: {
page: 0,
size: categoryTree.length,
totalElements: categoryTree.length,
totalPages: 1,
content: categoryTree,
},
});
});
};

View File

@@ -0,0 +1,231 @@
const Mock = require("mockjs");
const API = require("../mock-apis.cjs");
const { Random } = Mock;
// 生成模拟数据归集统计信息
const collectionStatistics = {
period: Random.pick(["HOUR", "DAY", "WEEK", "MONTH"]),
totalTasks: Random.integer(50, 200),
activeTasks: Random.integer(10, 50),
successfulExecutions: Random.integer(30, 150),
failedExecutions: Random.integer(0, 50),
totalExecutions: Random.integer(20, 100),
avgExecutionTime: Random.integer(1000, 10000), // in milliseconds
avgThroughput: Random.integer(100, 1000), // records per second
topDataSources: new Array(5).fill(null).map(() => ({
dataSourceId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
dataSourceName: Mock.Random.word(5, 15),
type: Mock.Random.pick([
"MySQL",
"PostgreSQL",
"ORACLE",
"SQLSERVER",
"MONGODB",
"REDIS",
"ELASTICSEARCH",
"HIVE",
"HDFS",
"KAFKA",
"HTTP",
"FILE",
]),
taskCount: Mock.Random.integer(1, 20),
executionCount: Mock.Random.integer(1, 50),
recordsProcessed: Mock.Random.integer(70, 100), // percentage
})),
};
// 生成模拟任务数据
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.queryCollectionStatisticsUsingGet, (req, res) => {
res.send({
code: "0",
msg: "Success",
data: collectionStatistics,
});
});
// 获取任务列表
router.post(API.queryTasksUsingPost, (req, res) => {
const { searchTerm, filters, page = 1, size = 10 } = req.body;
let filteredTasks = taskList;
if (searchTerm) {
filteredTasks = filteredTasks.filter((task) =>
task.name.includes(searchTerm)
);
}
if (filters && filters.status && filters.status.length > 0) {
filteredTasks = filteredTasks.filter((task) =>
filters.status.includes(task.status)
);
}
const startIndex = (page - 1) * size;
const endIndex = startIndex + size;
const paginatedTasks = filteredTasks.slice(startIndex, endIndex);
res.send({
code: "0",
msg: "Success",
data: {
totalElements: filteredTasks.length,
page,
size,
results: paginatedTasks,
},
});
});
// 创建任务
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,
});
});
};

View File

@@ -0,0 +1,501 @@
const Mock = require("mockjs");
const API = require("../mock-apis.cjs");
// 质量指标枚举
const QualityMetrics = [
"COMPLETENESS",
"ACCURACY",
"CONSISTENCY",
"VALIDITY",
"UNIQUENESS",
"TIMELINESS"
];
// 适配性标准枚举
const CompatibilityCriteria = [
"FORMAT_COMPATIBILITY",
"SCHEMA_COMPATIBILITY",
"SIZE_ADEQUACY",
"DISTRIBUTION_MATCH",
"FEATURE_COVERAGE"
];
// 价值标准枚举
const ValueCriteria = [
"RARITY",
"DEMAND",
"QUALITY",
"COMPLETENESS",
"TIMELINESS",
"STRATEGIC_IMPORTANCE"
];
// 评估类型枚举
const EvaluationTypes = ["QUALITY", "COMPATIBILITY", "VALUE", "COMPREHENSIVE"];
// 评估状态枚举
const EvaluationStatuses = ["PENDING", "RUNNING", "COMPLETED", "FAILED"];
// 生成质量评估结果
function qualityEvaluationItem() {
return {
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
datasetId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
status: Mock.Random.pick(EvaluationStatuses),
overallScore: Mock.Random.float(0.6, 1.0, 2, 2),
metrics: Mock.Random.shuffle(QualityMetrics).slice(0, Mock.Random.integer(3, 5)).map(metric => ({
metric,
score: Mock.Random.float(0.5, 1.0, 2, 2),
details: {
totalRecords: Mock.Random.integer(1000, 100000),
validRecords: Mock.Random.integer(800, 95000),
issues: Mock.Random.integer(0, 50)
},
issues: new Array(Mock.Random.integer(0, 3)).fill(null).map(() => ({
type: Mock.Random.pick(["MISSING_VALUE", "INVALID_FORMAT", "DUPLICATE", "OUTLIER"]),
severity: Mock.Random.pick(["LOW", "MEDIUM", "HIGH", "CRITICAL"]),
description: Mock.Random.csentence(5, 15),
affectedRecords: Mock.Random.integer(1, 1000),
suggestions: [Mock.Random.csentence(5, 20)]
}))
})),
recommendations: new Array(Mock.Random.integer(2, 5)).fill(null).map(() =>
Mock.Random.csentence(10, 30)
),
createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
detailedResults: {
fieldAnalysis: new Array(Mock.Random.integer(3, 8)).fill(null).map(() => ({
fieldName: Mock.Random.word(5, 10),
dataType: Mock.Random.pick(["STRING", "INTEGER", "FLOAT", "BOOLEAN", "DATE"]),
nullCount: Mock.Random.integer(0, 100),
uniqueCount: Mock.Random.integer(100, 1000),
statistics: {
mean: Mock.Random.float(0, 100, 2, 2),
median: Mock.Random.float(0, 100, 2, 2),
stdDev: Mock.Random.float(0, 50, 2, 2)
}
})),
distributionAnalysis: {
distributions: new Array(3).fill(null).map(() => ({
field: Mock.Random.word(5, 10),
type: Mock.Random.pick(["NORMAL", "UNIFORM", "SKEWED"]),
parameters: {}
})),
outliers: new Array(Mock.Random.integer(0, 5)).fill(null).map(() => ({
field: Mock.Random.word(5, 10),
value: Mock.Random.float(-100, 100, 2, 2),
zScore: Mock.Random.float(-3, 3, 2, 2)
})),
patterns: [
"数据分布较为均匀",
"存在少量异常值",
"部分字段相关性较强"
]
},
correlationAnalysis: {
correlationMatrix: new Array(5).fill(null).map(() =>
new Array(5).fill(null).map(() => Mock.Random.float(-1, 1, 2, 2))
),
significantCorrelations: new Array(Mock.Random.integer(1, 3)).fill(null).map(() => ({
field1: Mock.Random.word(5, 10),
field2: Mock.Random.word(5, 10),
correlation: Mock.Random.float(0.5, 1, 2, 2),
pValue: Mock.Random.float(0, 0.05, 3, 3)
}))
}
},
visualizations: new Array(Mock.Random.integer(2, 4)).fill(null).map(() => ({
type: Mock.Random.pick(["CHART", "GRAPH", "HISTOGRAM", "HEATMAP"]),
title: Mock.Random.ctitle(5, 15),
data: {
labels: new Array(5).fill(null).map(() => Mock.Random.word(3, 8)),
values: new Array(5).fill(null).map(() => Mock.Random.integer(0, 100))
},
config: {
width: 400,
height: 300,
color: Mock.Random.color()
}
}))
};
}
// 生成适配性评估结果
function compatibilityEvaluationItem() {
return {
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
datasetId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
targetType: Mock.Random.pick(["LANGUAGE_MODEL", "CLASSIFICATION_MODEL", "RECOMMENDATION_SYSTEM", "CUSTOM_TASK"]),
compatibilityScore: Mock.Random.float(0.6, 1.0, 2, 2),
results: Mock.Random.shuffle(CompatibilityCriteria).slice(0, Mock.Random.integer(3, 5)).map(criterion => ({
criterion,
score: Mock.Random.float(0.5, 1.0, 2, 2),
status: Mock.Random.pick(["PASS", "WARN", "FAIL"]),
details: Mock.Random.csentence(10, 30)
})),
suggestions: new Array(Mock.Random.integer(2, 4)).fill(null).map(() =>
Mock.Random.csentence(10, 25)
),
createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss")
};
}
// 生成价值评估结果
function valueEvaluationItem() {
return {
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
datasetId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
valueScore: Mock.Random.float(0.6, 1.0, 2, 2),
monetaryValue: Mock.Random.float(10000, 1000000, 2, 2),
strategicValue: Mock.Random.float(0.6, 1.0, 2, 2),
results: Mock.Random.shuffle(ValueCriteria).slice(0, Mock.Random.integer(3, 5)).map(criterion => ({
criterion,
score: Mock.Random.float(0.5, 1.0, 2, 2),
impact: Mock.Random.pick(["LOW", "MEDIUM", "HIGH"]),
explanation: Mock.Random.csentence(10, 30)
})),
insights: new Array(Mock.Random.integer(3, 6)).fill(null).map(() =>
Mock.Random.csentence(15, 40)
),
createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss")
};
}
// 生成评估报告
function evaluationReportItem() {
const type = Mock.Random.pick(EvaluationTypes);
return {
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
datasetId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
datasetName: Mock.Random.ctitle(5, 15),
type,
status: Mock.Random.pick(EvaluationStatuses),
overallScore: Mock.Random.float(0.6, 1.0, 2, 2),
summary: Mock.Random.csentence(20, 50),
createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
completedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
qualityResults: type === "QUALITY" || type === "COMPREHENSIVE" ? qualityEvaluationItem() : null,
compatibilityResults: type === "COMPATIBILITY" || type === "COMPREHENSIVE" ? compatibilityEvaluationItem() : null,
valueResults: type === "VALUE" || type === "COMPREHENSIVE" ? valueEvaluationItem() : null,
attachments: new Array(Mock.Random.integer(1, 3)).fill(null).map(() => ({
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
name: Mock.Random.word(5, 10) + "." + Mock.Random.pick(["pdf", "xlsx", "json"]),
type: Mock.Random.pick(["PDF", "EXCEL", "JSON"]),
size: Mock.Random.integer(1024, 1024 * 1024),
downloadUrl: "/api/v1/evaluation/attachments/" + Mock.Random.guid()
}))
};
}
const qualityEvaluationList = new Array(30).fill(null).map(qualityEvaluationItem);
const compatibilityEvaluationList = new Array(20).fill(null).map(compatibilityEvaluationItem);
const valueEvaluationList = new Array(25).fill(null).map(valueEvaluationItem);
const evaluationReportList = new Array(50).fill(null).map(evaluationReportItem);
module.exports = function (router) {
// 数据质量评估
router.post(API.evaluateDataQualityUsingPost, (req, res) => {
const { datasetId, metrics, sampleSize, parameters } = req.body;
const newEvaluation = {
...qualityEvaluationItem(),
datasetId,
status: "RUNNING",
metrics: metrics.map(metric => ({
metric,
score: Mock.Random.float(0.5, 1.0, 2, 2),
details: {
totalRecords: sampleSize || Mock.Random.integer(1000, 100000),
validRecords: Mock.Random.integer(800, 95000),
issues: Mock.Random.integer(0, 50)
},
issues: []
})),
createdAt: new Date().toISOString()
};
qualityEvaluationList.push(newEvaluation);
// 模拟异步处理,2秒后完成
setTimeout(() => {
newEvaluation.status = "COMPLETED";
}, 2000);
res.send({
code: "0",
msg: "Quality evaluation started successfully",
data: newEvaluation
});
});
// 获取质量评估结果
router.get(API.getQualityEvaluationByIdUsingGet, (req, res) => {
const { evaluationId } = req.params;
const evaluation = qualityEvaluationList.find(e => e.id === evaluationId);
if (evaluation) {
res.send({
code: "0",
msg: "Success",
data: evaluation
});
} else {
res.status(404).send({
code: "1",
msg: "Quality evaluation not found",
data: null
});
}
});
// 适配性评估
router.post(API.evaluateCompatibilityUsingPost, (req, res) => {
const { datasetId, targetType, targetConfig, evaluationCriteria } = req.body;
const newEvaluation = {
...compatibilityEvaluationItem(),
datasetId,
targetType,
results: evaluationCriteria.map(criterion => ({
criterion,
score: Mock.Random.float(0.5, 1.0, 2, 2),
status: Mock.Random.pick(["PASS", "WARN", "FAIL"]),
details: Mock.Random.csentence(10, 30)
})),
createdAt: new Date().toISOString()
};
compatibilityEvaluationList.push(newEvaluation);
res.send({
code: "0",
msg: "Compatibility evaluation completed successfully",
data: newEvaluation
});
});
// 价值评估
router.post(API.evaluateValueUsingPost, (req, res) => {
const { datasetId, valueCriteria, marketContext, businessContext } = req.body;
const newEvaluation = {
...valueEvaluationItem(),
datasetId,
results: valueCriteria.map(criterion => ({
criterion,
score: Mock.Random.float(0.5, 1.0, 2, 2),
impact: Mock.Random.pick(["LOW", "MEDIUM", "HIGH"]),
explanation: Mock.Random.csentence(10, 30)
})),
createdAt: new Date().toISOString()
};
valueEvaluationList.push(newEvaluation);
res.send({
code: "0",
msg: "Value evaluation completed successfully",
data: newEvaluation
});
});
// 获取评估报告列表
router.get(API.queryEvaluationReportsUsingGet, (req, res) => {
const { page = 0, size = 20, type, datasetId } = req.query;
let filteredReports = evaluationReportList;
if (type) {
filteredReports = filteredReports.filter(report => report.type === type);
}
if (datasetId) {
filteredReports = filteredReports.filter(report => report.datasetId === datasetId);
}
const startIndex = page * size;
const endIndex = startIndex + parseInt(size);
const pageData = filteredReports.slice(startIndex, endIndex);
res.send({
code: "0",
msg: "Success",
data: {
content: pageData,
totalElements: filteredReports.length,
totalPages: Math.ceil(filteredReports.length / size),
size: parseInt(size),
number: parseInt(page)
}
});
});
// 获取评估报告详情
router.get(API.getEvaluationReportByIdUsingGet, (req, res) => {
const { reportId } = req.params;
const report = evaluationReportList.find(r => r.id === reportId);
if (report) {
res.send({
code: "0",
msg: "Success",
data: report
});
} else {
res.status(404).send({
code: "1",
msg: "Evaluation report not found",
data: null
});
}
});
// 导出评估报告
router.get(API.exportEvaluationReportUsingGet, (req, res) => {
const { reportId } = req.params;
const { format = "PDF" } = req.query;
const report = evaluationReportList.find(r => r.id === reportId);
if (report) {
const fileName = `evaluation_report_${reportId}.${format.toLowerCase()}`;
res.setHeader('Content-Disposition', `attachment; filename="${fileName}"`);
res.setHeader('Content-Type', 'application/octet-stream');
res.send(`Mock ${format} content for evaluation report ${reportId}`);
} else {
res.status(404).send({
code: "1",
msg: "Evaluation report not found",
data: null
});
}
});
// 批量评估
router.post(API.batchEvaluationUsingPost, (req, res) => {
const { datasetIds, evaluationTypes, parameters } = req.body;
const batchId = Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, "");
const totalTasks = datasetIds.length * evaluationTypes.length;
// 为每个数据集和评估类型组合创建任务
datasetIds.forEach(datasetId => {
evaluationTypes.forEach(type => {
const report = {
...evaluationReportItem(),
datasetId,
type,
status: "PENDING",
batchId
};
evaluationReportList.push(report);
// 模拟异步处理
setTimeout(() => {
report.status = "COMPLETED";
}, Mock.Random.integer(3000, 10000));
});
});
res.status(202).send({
code: "0",
msg: "Batch evaluation submitted successfully",
data: {
batchId,
status: "SUBMITTED",
totalTasks,
submittedAt: new Date().toISOString()
}
});
});
// 获取批量评估状态
router.get("/api/v1/evaluation/batch/:batchId", (req, res) => {
const { batchId } = req.params;
const batchReports = evaluationReportList.filter(r => r.batchId === batchId);
const completedTasks = batchReports.filter(r => r.status === "COMPLETED").length;
const runningTasks = batchReports.filter(r => r.status === "RUNNING").length;
const pendingTasks = batchReports.filter(r => r.status === "PENDING").length;
const failedTasks = batchReports.filter(r => r.status === "FAILED").length;
let overallStatus = "COMPLETED";
if (runningTasks > 0 || pendingTasks > 0) {
overallStatus = "RUNNING";
} else if (failedTasks > 0) {
overallStatus = "PARTIAL_FAILED";
}
res.send({
code: "0",
msg: "Success",
data: {
batchId,
status: overallStatus,
totalTasks: batchReports.length,
completedTasks,
runningTasks,
pendingTasks,
failedTasks,
progress: batchReports.length > 0 ? Math.round((completedTasks / batchReports.length) * 100) : 0,
reports: batchReports
}
});
});
// 获取评估统计信息
router.get("/api/v1/evaluation/statistics", (req, res) => {
const { timeRange = "LAST_30_DAYS" } = req.query;
const statistics = {
totalEvaluations: evaluationReportList.length,
completedEvaluations: evaluationReportList.filter(r => r.status === "COMPLETED").length,
runningEvaluations: evaluationReportList.filter(r => r.status === "RUNNING").length,
failedEvaluations: evaluationReportList.filter(r => r.status === "FAILED").length,
averageScore: Mock.Random.float(0.75, 0.95, 2, 2),
evaluationTypeDistribution: {
QUALITY: evaluationReportList.filter(r => r.type === "QUALITY").length,
COMPATIBILITY: evaluationReportList.filter(r => r.type === "COMPATIBILITY").length,
VALUE: evaluationReportList.filter(r => r.type === "VALUE").length,
COMPREHENSIVE: evaluationReportList.filter(r => r.type === "COMPREHENSIVE").length
},
scoreDistribution: {
excellent: evaluationReportList.filter(r => r.overallScore >= 0.9).length,
good: evaluationReportList.filter(r => r.overallScore >= 0.8 && r.overallScore < 0.9).length,
fair: evaluationReportList.filter(r => r.overallScore >= 0.6 && r.overallScore < 0.8).length,
poor: evaluationReportList.filter(r => r.overallScore < 0.6).length
},
trends: new Array(30).fill(null).map((_, index) => ({
date: Mock.Random.date("yyyy-MM-dd"),
evaluations: Mock.Random.integer(5, 50),
averageScore: Mock.Random.float(0.7, 0.95, 2, 2)
}))
};
res.send({
code: "0",
msg: "Success",
data: statistics
});
});
// 删除评估报告
router.delete("/api/v1/evaluation/reports/:reportId", (req, res) => {
const { reportId } = req.params;
const index = evaluationReportList.findIndex(r => r.id === reportId);
if (index !== -1) {
evaluationReportList.splice(index, 1);
res.send({
code: "0",
msg: "Evaluation report deleted successfully",
data: null
});
} else {
res.status(404).send({
code: "1",
msg: "Evaluation report not found",
data: null
});
}
});
};

View File

@@ -0,0 +1,437 @@
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),
type: Mock.Random.pick(["TEXT", "IMAGE", "AUDIO", "VIDEO"]),
status: Mock.Random.pick(["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) {
console.log("filter type:", type);
filteredDatasets = filteredDatasets.filter(
(dataset) => dataset.type === 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" });
});
};

View File

@@ -0,0 +1,522 @@
const Mock = require("mockjs");
const API = require("../mock-apis.cjs");
// 合成类型枚举
const SynthesisTypes = [
"INSTRUCTION_TUNING",
"COT_DISTILLATION",
"DIALOGUE_GENERATION",
"TEXT_AUGMENTATION",
"MULTIMODAL_SYNTHESIS",
"CUSTOM"
];
// 任务状态枚举
const JobStatuses = ["PENDING", "RUNNING", "COMPLETED", "FAILED", "CANCELLED"];
// 模型配置
function modelConfigItem() {
return {
modelName: Mock.Random.pick([
"gpt-3.5-turbo",
"gpt-4",
"claude-3",
"llama-2-70b",
"qwen-max"
]),
temperature: Mock.Random.float(0.1, 1.0, 2, 2),
maxTokens: Mock.Random.pick([512, 1024, 2048, 4096]),
topP: Mock.Random.float(0.1, 1.0, 2, 2),
frequencyPenalty: Mock.Random.float(0, 2.0, 2, 2)
};
}
// 合成模板数据
function synthesisTemplateItem() {
const type = Mock.Random.pick(SynthesisTypes);
return {
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
name: Mock.Random.ctitle(5, 20),
description: Mock.Random.csentence(5, 30),
type,
category: Mock.Random.pick([
"教育培训", "对话系统", "内容生成", "代码生成", "多模态", "自定义"
]),
modelConfig: modelConfigItem(),
enabled: Mock.Random.boolean(),
promptTemplate: type === "INSTRUCTION_TUNING"
? "请根据以下主题生成一个指令:{topic}\n指令应该包含:\n1. 明确的任务描述\n2. 具体的输入要求\n3. 期望的输出格式"
: type === "COT_DISTILLATION"
? "问题:{question}\n请提供详细的推理步骤,然后给出最终答案。\n推理过程:\n1. 分析问题的关键信息\n2. 应用相关知识和规则\n3. 逐步推导出结论"
: "请根据以下模板生成内容:{template}",
parameters: {
maxLength: Mock.Random.integer(100, 2000),
diversity: Mock.Random.float(0.1, 1.0, 2, 2),
quality: Mock.Random.float(0.7, 1.0, 2, 2)
},
examples: new Array(Mock.Random.integer(2, 5)).fill(null).map(() => ({
input: Mock.Random.csentence(10, 30),
output: Mock.Random.csentence(20, 50),
explanation: Mock.Random.csentence(5, 20)
})),
createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
updatedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss")
};
}
const synthesisTemplateList = new Array(25).fill(null).map(synthesisTemplateItem);
// 合成任务数据
function synthesisJobItem() {
const template = Mock.Random.pick(synthesisTemplateList);
const targetCount = Mock.Random.integer(100, 10000);
const generatedCount = Mock.Random.integer(0, targetCount);
const progress = targetCount > 0 ? (generatedCount / targetCount) * 100 : 0;
return {
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
name: Mock.Random.ctitle(5, 20),
description: Mock.Random.csentence(5, 30),
templateId: template.id,
template: {
id: template.id,
name: template.name,
type: template.type
},
status: Mock.Random.pick(JobStatuses),
progress: Math.round(progress * 100) / 100,
targetCount,
generatedCount,
startTime: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
endTime: progress >= 100 ? Mock.Random.datetime("yyyy-MM-dd HH:mm:ss") : null,
createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
updatedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
statistics: {
totalGenerated: generatedCount,
successfulGenerated: Math.floor(generatedCount * Mock.Random.float(0.85, 0.98, 2, 2)),
failedGenerated: Math.floor(generatedCount * Mock.Random.float(0.02, 0.15, 2, 2)),
averageLength: Mock.Random.integer(50, 500),
uniqueCount: Math.floor(generatedCount * Mock.Random.float(0.8, 0.95, 2, 2))
},
samples: new Array(Math.min(10, generatedCount)).fill(null).map(() => ({
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
content: Mock.Random.cparagraph(1, 3),
score: Mock.Random.float(0.6, 1.0, 2, 2),
metadata: {
length: Mock.Random.integer(50, 500),
model: template.modelConfig.modelName,
timestamp: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss")
},
createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss")
}))
};
}
const synthesisJobList = new Array(30).fill(null).map(synthesisJobItem);
// 生成指令数据
function generatedInstructionItem() {
return {
instruction: Mock.Random.csentence(10, 30),
input: Mock.Random.csentence(5, 20),
output: Mock.Random.csentence(10, 40),
quality: Mock.Random.float(0.7, 1.0, 2, 2)
};
}
// COT 示例数据
function cotExampleItem() {
return {
question: Mock.Random.csentence(10, 25) + "?",
reasoning: Mock.Random.cparagraph(2, 4),
answer: Mock.Random.csentence(5, 15)
};
}
// 蒸馏COT数据
function distilledCOTDataItem() {
return {
question: Mock.Random.csentence(10, 25) + "?",
reasoning: Mock.Random.cparagraph(2, 4),
answer: Mock.Random.csentence(5, 15),
confidence: Mock.Random.float(0.7, 1.0, 2, 2)
};
}
module.exports = function (router) {
// 获取合成模板列表
router.get(API.querySynthesisTemplatesUsingGet, (req, res) => {
const { page = 0, size = 20, type } = req.query;
let filteredTemplates = synthesisTemplateList;
if (type) {
filteredTemplates = synthesisTemplateList.filter(
(template) => template.type === type
);
}
const startIndex = page * size;
const endIndex = startIndex + parseInt(size);
const pageData = filteredTemplates.slice(startIndex, endIndex);
res.send({
code: "0",
msg: "Success",
data: {
content: pageData,
totalElements: filteredTemplates.length,
totalPages: Math.ceil(filteredTemplates.length / size),
size: parseInt(size),
number: parseInt(page)
}
});
});
// 创建合成模板
router.post(API.createSynthesisTemplateUsingPost, (req, res) => {
const newTemplate = {
...synthesisTemplateItem(),
...req.body,
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
enabled: true,
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString()
};
synthesisTemplateList.push(newTemplate);
res.status(201).send({
code: "0",
msg: "Synthesis template created successfully",
data: newTemplate
});
});
// 获取合成模板详情
router.get(API.querySynthesisTemplateByIdUsingGet, (req, res) => {
const { templateId } = req.params;
const template = synthesisTemplateList.find((t) => t.id === templateId);
if (template) {
res.send({
code: "0",
msg: "Success",
data: template
});
} else {
res.status(404).send({
code: "1",
msg: "Synthesis template not found",
data: null
});
}
});
// 更新合成模板
router.put(API.updateSynthesisTemplateByIdUsingPut, (req, res) => {
const { templateId } = req.params;
const index = synthesisTemplateList.findIndex((t) => t.id === templateId);
if (index !== -1) {
synthesisTemplateList[index] = {
...synthesisTemplateList[index],
...req.body,
updatedAt: new Date().toISOString()
};
res.send({
code: "0",
msg: "Synthesis template updated successfully",
data: synthesisTemplateList[index]
});
} else {
res.status(404).send({
code: "1",
msg: "Synthesis template not found",
data: null
});
}
});
// 删除合成模板
router.delete(API.deleteSynthesisTemplateByIdUsingDelete, (req, res) => {
const { templateId } = req.params;
const index = synthesisTemplateList.findIndex((t) => t.id === templateId);
if (index !== -1) {
synthesisTemplateList.splice(index, 1);
res.send({
code: "0",
msg: "Synthesis template deleted successfully",
data: null
});
} else {
res.status(404).send({
code: "1",
msg: "Synthesis template not found",
data: null
});
}
});
// 获取合成任务列表
router.get(API.querySynthesisJobsUsingGet, (req, res) => {
const { page = 0, size = 20, status } = req.query;
let filteredJobs = synthesisJobList;
if (status) {
filteredJobs = synthesisJobList.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.createSynthesisJobUsingPost, (req, res) => {
const { templateId } = req.body;
const template = synthesisTemplateList.find(t => t.id === templateId);
const newJob = {
...synthesisJobItem(),
...req.body,
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
templateId,
template: template ? {
id: template.id,
name: template.name,
type: template.type
} : null,
status: "PENDING",
progress: 0,
generatedCount: 0,
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString()
};
synthesisJobList.push(newJob);
res.status(201).send({
code: "0",
msg: "Synthesis job created successfully",
data: newJob
});
});
// 获取合成任务详情
router.get(API.querySynthesisJobByIdUsingGet, (req, res) => {
const { jobId } = req.params;
const job = synthesisJobList.find((j) => j.id === jobId);
if (job) {
const template = synthesisTemplateList.find(t => t.id === job.templateId);
const jobDetail = {
...job,
template: template || null
};
res.send({
code: "0",
msg: "Success",
data: jobDetail
});
} else {
res.status(404).send({
code: "1",
msg: "Synthesis job not found",
data: null
});
}
});
// 删除合成任务
router.delete(API.deleteSynthesisJobByIdUsingDelete, (req, res) => {
const { jobId } = req.params;
const index = synthesisJobList.findIndex((j) => j.id === jobId);
if (index !== -1) {
synthesisJobList.splice(index, 1);
res.send({
code: "0",
msg: "Synthesis job deleted successfully",
data: null
});
} else {
res.status(404).send({
code: "1",
msg: "Synthesis job not found",
data: null
});
}
});
// 执行合成任务
router.post(API.executeSynthesisJobUsingPost, (req, res) => {
const { jobId } = req.params;
const job = synthesisJobList.find((j) => j.id === jobId);
if (job) {
job.status = "RUNNING";
job.startTime = new Date().toISOString();
job.updatedAt = new Date().toISOString();
// 模拟异步执行
setTimeout(() => {
job.status = Mock.Random.pick(["COMPLETED", "FAILED"]);
job.progress = job.status === "COMPLETED" ? 100 : Mock.Random.float(10, 90, 2, 2);
job.generatedCount = Math.floor((job.progress / 100) * job.targetCount);
job.endTime = new Date().toISOString();
}, Mock.Random.integer(2000, 5000));
res.send({
code: "0",
msg: "Synthesis 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: "Synthesis job not found",
data: null
});
}
});
// 指令调优数据合成
router.post(API.instructionTuningUsingPost, (req, res) => {
const { baseInstructions, targetDomain, count, modelConfig, parameters } = req.body;
const jobId = Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, "");
const generatedInstructions = new Array(count).fill(null).map(() => generatedInstructionItem());
const statistics = {
totalGenerated: count,
averageQuality: Mock.Random.float(0.8, 0.95, 2, 2),
diversityScore: Mock.Random.float(0.7, 0.9, 2, 2)
};
res.send({
code: "0",
msg: "Instruction tuning completed successfully",
data: {
jobId,
generatedInstructions,
statistics
}
});
});
// COT蒸馏数据合成
router.post(API.cotDistillationUsingPost, (req, res) => {
const { sourceModel, targetFormat, examples, parameters } = req.body;
const jobId = Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, "");
const processedCount = examples.length;
const successfulCount = Math.floor(processedCount * Mock.Random.float(0.85, 0.98, 2, 2));
const distilledData = new Array(successfulCount).fill(null).map(() => distilledCOTDataItem());
const statistics = {
totalProcessed: processedCount,
successfulDistilled: successfulCount,
averageConfidence: Mock.Random.float(0.8, 0.95, 2, 2)
};
res.send({
code: "0",
msg: "COT distillation completed successfully",
data: {
jobId,
distilledData,
statistics
}
});
});
// 获取合成任务统计信息
router.get("/api/v1/synthesis/statistics", (req, res) => {
const statistics = {
totalJobs: synthesisJobList.length,
completedJobs: synthesisJobList.filter(j => j.status === "COMPLETED").length,
runningJobs: synthesisJobList.filter(j => j.status === "RUNNING").length,
failedJobs: synthesisJobList.filter(j => j.status === "FAILED").length,
totalGenerated: synthesisJobList.reduce((sum, job) => sum + job.generatedCount, 0),
averageQuality: Mock.Random.float(0.8, 0.95, 2, 2),
templateTypeDistribution: {
"INSTRUCTION_TUNING": synthesisTemplateList.filter(t => t.type === "INSTRUCTION_TUNING").length,
"COT_DISTILLATION": synthesisTemplateList.filter(t => t.type === "COT_DISTILLATION").length,
"DIALOGUE_GENERATION": synthesisTemplateList.filter(t => t.type === "DIALOGUE_GENERATION").length,
"TEXT_AUGMENTATION": synthesisTemplateList.filter(t => t.type === "TEXT_AUGMENTATION").length,
"MULTIMODAL_SYNTHESIS": synthesisTemplateList.filter(t => t.type === "MULTIMODAL_SYNTHESIS").length,
"CUSTOM": synthesisTemplateList.filter(t => t.type === "CUSTOM").length
},
dailyGeneration: new Array(7).fill(null).map((_, index) => ({
date: Mock.Random.date("yyyy-MM-dd"),
count: Mock.Random.integer(100, 5000)
}))
};
res.send({
code: "0",
msg: "Success",
data: statistics
});
});
// 批量操作
router.post("/api/v1/synthesis/jobs/batch", (req, res) => {
const { action, jobIds } = req.body;
let successCount = 0;
let failedCount = 0;
jobIds.forEach(jobId => {
const job = synthesisJobList.find(j => j.id === jobId);
if (job) {
switch(action) {
case "DELETE":
const index = synthesisJobList.findIndex(j => j.id === jobId);
synthesisJobList.splice(index, 1);
successCount++;
break;
case "START":
job.status = "RUNNING";
job.startTime = new Date().toISOString();
successCount++;
break;
case "STOP":
job.status = "CANCELLED";
job.endTime = new Date().toISOString();
successCount++;
break;
}
} else {
failedCount++;
}
});
res.send({
code: "0",
msg: `Batch ${action.toLowerCase()} completed`,
data: {
total: jobIds.length,
success: successCount,
failed: failedCount
}
});
});
};

View File

@@ -0,0 +1,124 @@
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.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,
});
});
};

View File

@@ -0,0 +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);
}
}

View File

@@ -0,0 +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"
}

View File

@@ -0,0 +1,196 @@
export const mockOperators: Operator[] = [
{
id: 1,
name: "图像预处理算子",
version: "1.2.0",
description:
"支持图像缩放、裁剪、旋转、颜色空间转换等常用预处理操作,优化了内存使用和处理速度",
author: "张三",
category: "图像处理",
modality: ["image"],
type: "preprocessing",
tags: ["图像处理", "预处理", "缩放", "裁剪", "旋转"],
createdAt: "2024-01-15",
lastModified: "2024-01-23",
status: "active",
isFavorited: true,
downloads: 1247,
usage: 856,
framework: "PyTorch",
language: "Python",
size: "2.3MB",
dependencies: ["opencv-python", "pillow", "numpy"],
inputFormat: ["jpg", "png", "bmp", "tiff"],
outputFormat: ["jpg", "png", "tensor"],
performance: {
accuracy: 99.5,
speed: "50ms/image",
memory: "128MB",
},
},
{
id: 2,
name: "文本分词算子",
version: "2.1.3",
description:
"基于深度学习的中文分词算子,支持自定义词典,在医学文本上表现优异",
author: "李四",
category: "自然语言处理",
modality: ["text"],
type: "preprocessing",
tags: ["文本处理", "分词", "中文", "NLP", "医学"],
createdAt: "2024-01-10",
lastModified: "2024-01-20",
status: "active",
isFavorited: false,
downloads: 892,
usage: 634,
framework: "TensorFlow",
language: "Python",
size: "15.6MB",
dependencies: ["tensorflow", "jieba", "transformers"],
inputFormat: ["txt", "json", "csv"],
outputFormat: ["json", "txt"],
performance: {
accuracy: 96.8,
speed: "10ms/sentence",
memory: "256MB",
},
},
{
id: 3,
name: "音频特征提取",
version: "1.0.5",
description: "提取音频的MFCC、梅尔频谱、色度等特征,支持多种音频格式",
author: "王五",
category: "音频处理",
modality: ["audio"],
type: "preprocessing",
tags: ["音频处理", "特征提取", "MFCC", "频谱分析"],
createdAt: "2024-01-08",
lastModified: "2024-01-18",
status: "active",
isFavorited: true,
downloads: 456,
usage: 312,
framework: "PyTorch",
language: "Python",
size: "8.9MB",
dependencies: ["librosa", "scipy", "numpy"],
inputFormat: ["wav", "mp3", "flac", "m4a"],
outputFormat: ["npy", "json", "csv"],
performance: {
speed: "2x实时",
memory: "64MB",
},
},
{
id: 4,
name: "视频帧提取算子",
version: "1.3.2",
description: "高效的视频帧提取算子,支持关键帧检测和均匀采样",
author: "赵六",
category: "视频处理",
modality: ["video"],
type: "preprocessing",
tags: ["视频处理", "帧提取", "关键帧", "采样"],
createdAt: "2024-01-05",
lastModified: "2024-01-22",
status: "active",
isFavorited: false,
downloads: 723,
usage: 445,
framework: "OpenCV",
language: "Python",
size: "12.4MB",
dependencies: ["opencv-python", "ffmpeg-python"],
inputFormat: ["mp4", "avi", "mov", "mkv"],
outputFormat: ["jpg", "png", "npy"],
performance: {
speed: "30fps处理",
memory: "512MB",
},
},
{
id: 5,
name: "多模态融合算子",
version: "2.0.1",
description: "支持文本、图像、音频多模态数据融合的深度学习算子",
author: "孙七",
category: "多模态处理",
modality: ["text", "image", "audio"],
type: "training",
tags: ["多模态", "融合", "深度学习", "注意力机制"],
createdAt: "2024-01-12",
lastModified: "2024-01-21",
status: "beta",
isFavorited: false,
downloads: 234,
usage: 156,
framework: "PyTorch",
language: "Python",
size: "45.2MB",
dependencies: ["torch", "transformers", "torchvision", "torchaudio"],
inputFormat: ["json", "jpg", "wav"],
outputFormat: ["tensor", "json"],
performance: {
accuracy: 94.2,
speed: "100ms/sample",
memory: "2GB",
},
},
{
id: 6,
name: "模型推理加速",
version: "1.1.0",
description: "基于TensorRT的模型推理加速算子,支持多种深度学习框架",
author: "周八",
category: "模型优化",
modality: ["image", "text"],
type: "inference",
tags: ["推理加速", "TensorRT", "优化", "GPU"],
createdAt: "2024-01-03",
lastModified: "2024-01-19",
status: "active",
isFavorited: true,
downloads: 567,
usage: 389,
framework: "TensorRT",
language: "Python",
size: "23.7MB",
dependencies: ["tensorrt", "pycuda", "numpy"],
inputFormat: ["onnx", "pb", "pth"],
outputFormat: ["tensor", "json"],
performance: {
speed: "5x加速",
memory: "减少40%",
},
},
{
id: 7,
name: "数据增强算子",
version: "1.4.1",
description: "丰富的数据增强策略,包括几何变换、颜色变换、噪声添加等",
author: "吴九",
category: "数据增强",
modality: ["image"],
type: "preprocessing",
tags: ["数据增强", "几何变换", "颜色变换", "噪声"],
createdAt: "2024-01-01",
lastModified: "2024-01-17",
status: "active",
isFavorited: false,
downloads: 934,
usage: 678,
framework: "Albumentations",
language: "Python",
size: "6.8MB",
dependencies: ["albumentations", "opencv-python", "numpy"],
inputFormat: ["jpg", "png", "bmp"],
outputFormat: ["jpg", "png", "npy"],
performance: {
speed: "20ms/image",
memory: "32MB",
},
},
];

193
frontend/src/mock/ratio.tsx Normal file
View File

@@ -0,0 +1,193 @@
import type { RatioTask } from "@/pages/RatioTask/ratio";
export const mockRatioTasks: RatioTask[] = [
{
id: 1,
name: "多领域数据配比任务",
status: "completed",
progress: 100,
sourceDatasets: [
"orig_20250724_64082",
"financial_qa_dataset",
"medical_corpus",
],
targetCount: 10000,
generatedCount: 10000,
createdAt: "2025-01-24",
ratioType: "dataset",
estimatedTime: "已完成",
quality: 94,
ratioConfigs: [
{
id: "1",
name: "通用文本",
type: "dataset",
quantity: 4000,
percentage: 40,
source: "orig_20250724_64082",
},
{
id: "2",
name: "金融问答",
type: "dataset",
quantity: 3000,
percentage: 30,
source: "financial_qa_dataset",
},
{
id: "3",
name: "医疗语料",
type: "dataset",
quantity: 3000,
percentage: 30,
source: "medical_corpus",
},
],
},
{
id: 2,
name: "标签配比训练集",
status: "running",
progress: 68,
sourceDatasets: ["teacher_model_outputs", "image_text_pairs"],
targetCount: 8000,
generatedCount: 5440,
createdAt: "2025-01-25",
ratioType: "label",
estimatedTime: "剩余 12 分钟",
quality: 89,
ratioConfigs: [
{
id: "1",
name: "问答",
type: "label",
quantity: 2500,
percentage: 31.25,
source: "teacher_model_outputs_问答",
},
{
id: "2",
name: "推理",
type: "label",
quantity: 2000,
percentage: 25,
source: "teacher_model_outputs_推理",
},
{
id: "3",
name: "图像",
type: "label",
quantity: 1800,
percentage: 22.5,
source: "image_text_pairs_图像",
},
{
id: "4",
name: "描述",
type: "label",
quantity: 1700,
percentage: 21.25,
source: "image_text_pairs_描述",
},
],
},
{
id: 3,
name: "平衡数据集配比",
status: "failed",
progress: 25,
sourceDatasets: ["orig_20250724_64082", "financial_qa_dataset"],
targetCount: 5000,
generatedCount: 1250,
createdAt: "2025-01-25",
ratioType: "dataset",
errorMessage: "数据源连接失败,请检查数据集状态",
ratioConfigs: [
{
id: "1",
name: "通用文本",
type: "dataset",
quantity: 2500,
percentage: 50,
source: "orig_20250724_64082",
},
{
id: "2",
name: "金融问答",
type: "dataset",
quantity: 2500,
percentage: 50,
source: "financial_qa_dataset",
},
],
},
{
id: 4,
name: "文本分类配比任务",
status: "pending",
progress: 0,
sourceDatasets: ["text_classification_data", "sentiment_analysis_data"],
targetCount: 6000,
generatedCount: 0,
createdAt: "2025-01-26",
ratioType: "label",
estimatedTime: "预计 15 分钟",
ratioConfigs: [
{
id: "1",
name: "正面",
type: "label",
quantity: 2000,
percentage: 33.33,
source: "sentiment_analysis_data_正面",
},
{
id: "2",
name: "负面",
type: "label",
quantity: 2000,
percentage: 33.33,
source: "sentiment_analysis_data_负面",
},
{
id: "3",
name: "中性",
type: "label",
quantity: 2000,
percentage: 33.33,
source: "sentiment_analysis_data_中性",
},
],
},
{
id: 5,
name: "多模态数据配比",
status: "paused",
progress: 45,
sourceDatasets: ["image_caption_data", "video_description_data"],
targetCount: 12000,
generatedCount: 5400,
createdAt: "2025-01-23",
ratioType: "dataset",
estimatedTime: "已暂停",
quality: 91,
ratioConfigs: [
{
id: "1",
name: "图像描述",
type: "dataset",
quantity: 7000,
percentage: 58.33,
source: "image_caption_data",
},
{
id: "2",
name: "视频描述",
type: "dataset",
quantity: 5000,
percentage: 41.67,
source: "video_description_data",
},
],
},
];

View File

@@ -0,0 +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,
},
];