327 lines
17 KiB
Python
327 lines
17 KiB
Python
|
|
#!/usr/bin/env python3
|
|||
|
|
"""
|
|||
|
|
为模板市场添加假数据
|
|||
|
|
"""
|
|||
|
|
import sys
|
|||
|
|
import os
|
|||
|
|
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
|||
|
|
|
|||
|
|
from app.core.database import SessionLocal, engine
|
|||
|
|
from app.models.workflow_template import WorkflowTemplate, TemplateRating, TemplateFavorite
|
|||
|
|
from app.models.user import User
|
|||
|
|
from sqlalchemy import text
|
|||
|
|
import uuid
|
|||
|
|
from datetime import datetime, timedelta
|
|||
|
|
import random
|
|||
|
|
|
|||
|
|
# 模板数据
|
|||
|
|
TEMPLATE_DATA = [
|
|||
|
|
{
|
|||
|
|
"name": "智能客服工作流",
|
|||
|
|
"description": "一个完整的智能客服工作流,支持自动回复、问题分类和转人工功能。",
|
|||
|
|
"category": "llm",
|
|||
|
|
"tags": ["客服", "AI", "自动化"],
|
|||
|
|
"nodes": [
|
|||
|
|
{"id": "start", "type": "start", "position": {"x": 100, "y": 100}, "data": {"label": "开始"}},
|
|||
|
|
{"id": "input", "type": "input", "position": {"x": 300, "y": 100}, "data": {"label": "接收用户消息"}},
|
|||
|
|
{"id": "llm", "type": "llm", "position": {"x": 500, "y": 100}, "data": {"label": "AI回复", "model": "gpt-3.5-turbo", "prompt": "你是一个专业的客服助手"}},
|
|||
|
|
{"id": "condition", "type": "condition", "position": {"x": 700, "y": 100}, "data": {"label": "是否需要转人工", "expression": "sentiment_score < 0.3"}},
|
|||
|
|
{"id": "output1", "type": "output", "position": {"x": 900, "y": 50}, "data": {"label": "AI回复"}},
|
|||
|
|
{"id": "output2", "type": "output", "position": {"x": 900, "y": 150}, "data": {"label": "转人工"}},
|
|||
|
|
{"id": "end", "type": "end", "position": {"x": 1100, "y": 100}, "data": {"label": "结束"}}
|
|||
|
|
],
|
|||
|
|
"edges": [
|
|||
|
|
{"id": "e1", "source": "start", "target": "input"},
|
|||
|
|
{"id": "e2", "source": "input", "target": "llm"},
|
|||
|
|
{"id": "e3", "source": "llm", "target": "condition"},
|
|||
|
|
{"id": "e4", "source": "condition", "target": "output1", "sourceHandle": "true"},
|
|||
|
|
{"id": "e5", "source": "condition", "target": "output2", "sourceHandle": "false"},
|
|||
|
|
{"id": "e6", "source": "output1", "target": "end"},
|
|||
|
|
{"id": "e7", "source": "output2", "target": "end"}
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"name": "数据清洗工作流",
|
|||
|
|
"description": "自动清洗和转换数据,支持多种数据源格式。",
|
|||
|
|
"category": "data_processing",
|
|||
|
|
"tags": ["数据处理", "ETL", "数据清洗"],
|
|||
|
|
"nodes": [
|
|||
|
|
{"id": "start", "type": "start", "position": {"x": 100, "y": 100}, "data": {"label": "开始"}},
|
|||
|
|
{"id": "input", "type": "input", "position": {"x": 300, "y": 100}, "data": {"label": "读取数据"}},
|
|||
|
|
{"id": "transform1", "type": "transform", "position": {"x": 500, "y": 100}, "data": {"label": "数据清洗", "mappings": [{"from": "name", "to": "姓名"}]}},
|
|||
|
|
{"id": "transform2", "type": "transform", "position": {"x": 700, "y": 100}, "data": {"label": "数据验证"}},
|
|||
|
|
{"id": "output", "type": "output", "position": {"x": 900, "y": 100}, "data": {"label": "输出结果"}},
|
|||
|
|
{"id": "end", "type": "end", "position": {"x": 1100, "y": 100}, "data": {"label": "结束"}}
|
|||
|
|
],
|
|||
|
|
"edges": [
|
|||
|
|
{"id": "e1", "source": "start", "target": "input"},
|
|||
|
|
{"id": "e2", "source": "input", "target": "transform1"},
|
|||
|
|
{"id": "e3", "source": "transform1", "target": "transform2"},
|
|||
|
|
{"id": "e4", "source": "transform2", "target": "output"},
|
|||
|
|
{"id": "e5", "source": "output", "target": "end"}
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"name": "定时数据同步",
|
|||
|
|
"description": "定时从数据库同步数据到另一个系统,支持增量同步。",
|
|||
|
|
"category": "automation",
|
|||
|
|
"tags": ["定时任务", "数据同步", "自动化"],
|
|||
|
|
"nodes": [
|
|||
|
|
{"id": "start", "type": "start", "position": {"x": 100, "y": 100}, "data": {"label": "开始"}},
|
|||
|
|
{"id": "schedule", "type": "schedule", "position": {"x": 300, "y": 100}, "data": {"label": "定时触发", "delay_type": "fixed", "delay_value": 3600, "delay_unit": "seconds"}},
|
|||
|
|
{"id": "db1", "type": "database", "position": {"x": 500, "y": 100}, "data": {"label": "读取源数据", "query": "SELECT * FROM source_table"}},
|
|||
|
|
{"id": "transform", "type": "transform", "position": {"x": 700, "y": 100}, "data": {"label": "数据转换"}},
|
|||
|
|
{"id": "db2", "type": "database", "position": {"x": 900, "y": 100}, "data": {"label": "写入目标", "query": "INSERT INTO target_table"}},
|
|||
|
|
{"id": "end", "type": "end", "position": {"x": 1100, "y": 100}, "data": {"label": "结束"}}
|
|||
|
|
],
|
|||
|
|
"edges": [
|
|||
|
|
{"id": "e1", "source": "start", "target": "schedule"},
|
|||
|
|
{"id": "e2", "source": "schedule", "target": "db1"},
|
|||
|
|
{"id": "e3", "source": "db1", "target": "transform"},
|
|||
|
|
{"id": "e4", "source": "transform", "target": "db2"},
|
|||
|
|
{"id": "e5", "source": "db2", "target": "end"}
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"name": "API数据聚合",
|
|||
|
|
"description": "从多个API获取数据并聚合处理,支持错误重试。",
|
|||
|
|
"category": "integration",
|
|||
|
|
"tags": ["API", "数据聚合", "集成"],
|
|||
|
|
"nodes": [
|
|||
|
|
{"id": "start", "type": "start", "position": {"x": 100, "y": 100}, "data": {"label": "开始"}},
|
|||
|
|
{"id": "http1", "type": "http", "position": {"x": 300, "y": 50}, "data": {"label": "API 1", "url": "https://api1.example.com/data", "method": "GET"}},
|
|||
|
|
{"id": "http2", "type": "http", "position": {"x": 300, "y": 150}, "data": {"label": "API 2", "url": "https://api2.example.com/data", "method": "GET"}},
|
|||
|
|
{"id": "transform", "type": "transform", "position": {"x": 500, "y": 100}, "data": {"label": "数据聚合"}},
|
|||
|
|
{"id": "output", "type": "output", "position": {"x": 700, "y": 100}, "data": {"label": "输出结果"}},
|
|||
|
|
{"id": "end", "type": "end", "position": {"x": 900, "y": 100}, "data": {"label": "结束"}}
|
|||
|
|
],
|
|||
|
|
"edges": [
|
|||
|
|
{"id": "e1", "source": "start", "target": "http1"},
|
|||
|
|
{"id": "e2", "source": "start", "target": "http2"},
|
|||
|
|
{"id": "e3", "source": "http1", "target": "transform"},
|
|||
|
|
{"id": "e4", "source": "http2", "target": "transform"},
|
|||
|
|
{"id": "e5", "source": "transform", "target": "output"},
|
|||
|
|
{"id": "e6", "source": "output", "target": "end"}
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"name": "邮件通知工作流",
|
|||
|
|
"description": "根据条件发送邮件通知,支持HTML格式和附件。",
|
|||
|
|
"category": "automation",
|
|||
|
|
"tags": ["邮件", "通知", "自动化"],
|
|||
|
|
"nodes": [
|
|||
|
|
{"id": "start", "type": "start", "position": {"x": 100, "y": 100}, "data": {"label": "开始"}},
|
|||
|
|
{"id": "input", "type": "input", "position": {"x": 300, "y": 100}, "data": {"label": "接收事件"}},
|
|||
|
|
{"id": "condition", "type": "condition", "position": {"x": 500, "y": 100}, "data": {"label": "判断是否需要通知", "expression": "event_type == 'alert'"}},
|
|||
|
|
{"id": "email", "type": "email", "position": {"x": 700, "y": 100}, "data": {"label": "发送邮件", "to_email": "admin@example.com", "subject": "系统通知"}},
|
|||
|
|
{"id": "end", "type": "end", "position": {"x": 900, "y": 100}, "data": {"label": "结束"}}
|
|||
|
|
],
|
|||
|
|
"edges": [
|
|||
|
|
{"id": "e1", "source": "start", "target": "input"},
|
|||
|
|
{"id": "e2", "source": "input", "target": "condition"},
|
|||
|
|
{"id": "e3", "source": "condition", "target": "email", "sourceHandle": "true"},
|
|||
|
|
{"id": "e4", "source": "condition", "target": "end", "sourceHandle": "false"},
|
|||
|
|
{"id": "e5", "source": "email", "target": "end"}
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"name": "内容生成工作流",
|
|||
|
|
"description": "使用AI生成文章、摘要等内容,支持多种格式输出。",
|
|||
|
|
"category": "llm",
|
|||
|
|
"tags": ["AI", "内容生成", "LLM"],
|
|||
|
|
"nodes": [
|
|||
|
|
{"id": "start", "type": "start", "position": {"x": 100, "y": 100}, "data": {"label": "开始"}},
|
|||
|
|
{"id": "input", "type": "input", "position": {"x": 300, "y": 100}, "data": {"label": "输入主题"}},
|
|||
|
|
{"id": "llm1", "type": "llm", "position": {"x": 500, "y": 100}, "data": {"label": "生成大纲", "model": "gpt-4", "prompt": "根据主题生成文章大纲"}},
|
|||
|
|
{"id": "llm2", "type": "llm", "position": {"x": 700, "y": 100}, "data": {"label": "生成内容", "model": "gpt-4", "prompt": "根据大纲生成完整文章"}},
|
|||
|
|
{"id": "transform", "type": "transform", "position": {"x": 900, "y": 100}, "data": {"label": "格式化输出"}},
|
|||
|
|
{"id": "output", "type": "output", "position": {"x": 1100, "y": 100}, "data": {"label": "输出文章"}},
|
|||
|
|
{"id": "end", "type": "end", "position": {"x": 1300, "y": 100}, "data": {"label": "结束"}}
|
|||
|
|
],
|
|||
|
|
"edges": [
|
|||
|
|
{"id": "e1", "source": "start", "target": "input"},
|
|||
|
|
{"id": "e2", "source": "input", "target": "llm1"},
|
|||
|
|
{"id": "e3", "source": "llm1", "target": "llm2"},
|
|||
|
|
{"id": "e4", "source": "llm2", "target": "transform"},
|
|||
|
|
{"id": "e5", "source": "transform", "target": "output"},
|
|||
|
|
{"id": "e6", "source": "output", "target": "end"}
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"name": "文件处理工作流",
|
|||
|
|
"description": "批量处理文件,支持上传、下载、格式转换等功能。",
|
|||
|
|
"category": "data_processing",
|
|||
|
|
"tags": ["文件处理", "批量操作"],
|
|||
|
|
"nodes": [
|
|||
|
|
{"id": "start", "type": "start", "position": {"x": 100, "y": 100}, "data": {"label": "开始"}},
|
|||
|
|
{"id": "loop", "type": "loop", "position": {"x": 300, "y": 100}, "data": {"label": "遍历文件列表"}},
|
|||
|
|
{"id": "file_read", "type": "file_operation", "position": {"x": 500, "y": 100}, "data": {"label": "读取文件", "operation": "read"}},
|
|||
|
|
{"id": "transform", "type": "transform", "position": {"x": 700, "y": 100}, "data": {"label": "处理文件"}},
|
|||
|
|
{"id": "file_write", "type": "file_operation", "position": {"x": 900, "y": 100}, "data": {"label": "保存文件", "operation": "write"}},
|
|||
|
|
{"id": "loop_end", "type": "loop_end", "position": {"x": 1100, "y": 100}, "data": {"label": "循环结束"}},
|
|||
|
|
{"id": "end", "type": "end", "position": {"x": 1300, "y": 100}, "data": {"label": "结束"}}
|
|||
|
|
],
|
|||
|
|
"edges": [
|
|||
|
|
{"id": "e1", "source": "start", "target": "loop"},
|
|||
|
|
{"id": "e2", "source": "loop", "target": "file_read"},
|
|||
|
|
{"id": "e3", "source": "file_read", "target": "transform"},
|
|||
|
|
{"id": "e4", "source": "transform", "target": "file_write"},
|
|||
|
|
{"id": "e5", "source": "file_write", "target": "loop_end"},
|
|||
|
|
{"id": "e6", "source": "loop_end", "target": "loop"},
|
|||
|
|
{"id": "e7", "source": "loop_end", "target": "end"}
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"name": "Webhook触发器",
|
|||
|
|
"description": "接收外部Webhook请求并触发工作流,支持多种认证方式。",
|
|||
|
|
"category": "integration",
|
|||
|
|
"tags": ["Webhook", "触发器", "集成"],
|
|||
|
|
"nodes": [
|
|||
|
|
{"id": "start", "type": "start", "position": {"x": 100, "y": 100}, "data": {"label": "开始"}},
|
|||
|
|
{"id": "webhook", "type": "webhook", "position": {"x": 300, "y": 100}, "data": {"label": "接收Webhook", "url": "/api/v1/webhooks/trigger"}},
|
|||
|
|
{"id": "transform", "type": "transform", "position": {"x": 500, "y": 100}, "data": {"label": "处理数据"}},
|
|||
|
|
{"id": "http", "type": "http", "position": {"x": 700, "y": 100}, "data": {"label": "调用外部API", "url": "https://api.example.com/process", "method": "POST"}},
|
|||
|
|
{"id": "output", "type": "output", "position": {"x": 900, "y": 100}, "data": {"label": "返回结果"}},
|
|||
|
|
{"id": "end", "type": "end", "position": {"x": 1100, "y": 100}, "data": {"label": "结束"}}
|
|||
|
|
],
|
|||
|
|
"edges": [
|
|||
|
|
{"id": "e1", "source": "start", "target": "webhook"},
|
|||
|
|
{"id": "e2", "source": "webhook", "target": "transform"},
|
|||
|
|
{"id": "e3", "source": "transform", "target": "http"},
|
|||
|
|
{"id": "e4", "source": "http", "target": "output"},
|
|||
|
|
{"id": "e5", "source": "output", "target": "end"}
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
|
|||
|
|
def get_random_user(db):
|
|||
|
|
"""获取一个随机用户"""
|
|||
|
|
users = db.query(User).all()
|
|||
|
|
if users:
|
|||
|
|
return random.choice(users)
|
|||
|
|
return None
|
|||
|
|
|
|||
|
|
def add_template_data():
|
|||
|
|
"""添加模板数据"""
|
|||
|
|
db = SessionLocal()
|
|||
|
|
try:
|
|||
|
|
# 获取用户
|
|||
|
|
user = get_random_user(db)
|
|||
|
|
if not user:
|
|||
|
|
print("❌ 没有找到用户,请先创建用户")
|
|||
|
|
return
|
|||
|
|
|
|||
|
|
print(f"✅ 使用用户: {user.username}")
|
|||
|
|
print(f"📝 开始添加模板数据...\n")
|
|||
|
|
|
|||
|
|
added_count = 0
|
|||
|
|
skipped_count = 0
|
|||
|
|
|
|||
|
|
for template_info in TEMPLATE_DATA:
|
|||
|
|
# 检查模板是否已存在
|
|||
|
|
existing = db.query(WorkflowTemplate).filter(
|
|||
|
|
WorkflowTemplate.name == template_info["name"],
|
|||
|
|
WorkflowTemplate.user_id == user.id
|
|||
|
|
).first()
|
|||
|
|
|
|||
|
|
if existing:
|
|||
|
|
print(f"ℹ️ 模板已存在: {template_info['name']}")
|
|||
|
|
skipped_count += 1
|
|||
|
|
continue
|
|||
|
|
|
|||
|
|
# 创建模板
|
|||
|
|
template = WorkflowTemplate(
|
|||
|
|
id=str(uuid.uuid4()),
|
|||
|
|
name=template_info["name"],
|
|||
|
|
description=template_info["description"],
|
|||
|
|
category=template_info["category"],
|
|||
|
|
tags=template_info["tags"],
|
|||
|
|
nodes=template_info["nodes"],
|
|||
|
|
edges=template_info["edges"],
|
|||
|
|
is_public=True,
|
|||
|
|
is_featured=random.choice([True, False]), # 随机设置为精选
|
|||
|
|
view_count=random.randint(0, 1000),
|
|||
|
|
use_count=random.randint(0, 100),
|
|||
|
|
rating_count=random.randint(0, 50),
|
|||
|
|
rating_avg=round(random.uniform(3.5, 5.0), 1),
|
|||
|
|
user_id=user.id,
|
|||
|
|
created_at=datetime.now() - timedelta(days=random.randint(0, 30)),
|
|||
|
|
updated_at=datetime.now() - timedelta(days=random.randint(0, 7))
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
db.add(template)
|
|||
|
|
added_count += 1
|
|||
|
|
print(f"✅ 添加模板: {template_info['name']}")
|
|||
|
|
|
|||
|
|
db.commit()
|
|||
|
|
|
|||
|
|
print(f"\n{'='*60}")
|
|||
|
|
print(f"✅ 数据添加完成!")
|
|||
|
|
print(f" 新增: {added_count} 个模板")
|
|||
|
|
print(f" 跳过: {skipped_count} 个模板(已存在)")
|
|||
|
|
print(f"{'='*60}")
|
|||
|
|
|
|||
|
|
# 添加一些评分和收藏数据
|
|||
|
|
print(f"\n📝 添加评分和收藏数据...")
|
|||
|
|
|
|||
|
|
templates = db.query(WorkflowTemplate).filter(
|
|||
|
|
WorkflowTemplate.is_public == True
|
|||
|
|
).all()
|
|||
|
|
|
|||
|
|
if templates and user:
|
|||
|
|
# 为部分模板添加评分
|
|||
|
|
for template in random.sample(templates, min(5, len(templates))):
|
|||
|
|
existing_rating = db.query(TemplateRating).filter(
|
|||
|
|
TemplateRating.template_id == template.id,
|
|||
|
|
TemplateRating.user_id == user.id
|
|||
|
|
).first()
|
|||
|
|
|
|||
|
|
if not existing_rating:
|
|||
|
|
rating = TemplateRating(
|
|||
|
|
id=str(uuid.uuid4()),
|
|||
|
|
template_id=template.id,
|
|||
|
|
user_id=user.id,
|
|||
|
|
rating=random.randint(4, 5),
|
|||
|
|
comment=random.choice([
|
|||
|
|
"非常好用的模板!",
|
|||
|
|
"简单易用,推荐!",
|
|||
|
|
"功能完整,值得收藏。",
|
|||
|
|
"帮我节省了很多时间。",
|
|||
|
|
"模板设计得很专业。"
|
|||
|
|
])
|
|||
|
|
)
|
|||
|
|
db.add(rating)
|
|||
|
|
|
|||
|
|
# 为部分模板添加收藏
|
|||
|
|
for template in random.sample(templates, min(3, len(templates))):
|
|||
|
|
existing_favorite = db.query(TemplateFavorite).filter(
|
|||
|
|
TemplateFavorite.template_id == template.id,
|
|||
|
|
TemplateFavorite.user_id == user.id
|
|||
|
|
).first()
|
|||
|
|
|
|||
|
|
if not existing_favorite:
|
|||
|
|
favorite = TemplateFavorite(
|
|||
|
|
id=str(uuid.uuid4()),
|
|||
|
|
template_id=template.id,
|
|||
|
|
user_id=user.id
|
|||
|
|
)
|
|||
|
|
db.add(favorite)
|
|||
|
|
|
|||
|
|
db.commit()
|
|||
|
|
print(f"✅ 已添加评分和收藏数据")
|
|||
|
|
|
|||
|
|
except Exception as e:
|
|||
|
|
db.rollback()
|
|||
|
|
print(f"❌ 添加数据失败: {e}")
|
|||
|
|
import traceback
|
|||
|
|
traceback.print_exc()
|
|||
|
|
finally:
|
|||
|
|
db.close()
|
|||
|
|
|
|||
|
|
if __name__ == "__main__":
|
|||
|
|
print("="*60)
|
|||
|
|
print("模板市场假数据生成工具")
|
|||
|
|
print("="*60)
|
|||
|
|
print()
|
|||
|
|
add_template_data()
|