配置全面迁移数据库:PromptConfig、TaskConfig动态调度、敏感词/清洗规则/趋势映射/平台标签/痛点模板全部可编辑
- 新增 PromptConfig 模型 + API,支持提示词在线编辑(16条默认) - 调度器动态读取 TaskConfig.schedule,admin 可调执行时间 - 新增 KeywordDomainMap、SensitiveWord、ContentCleanRule、TrendFieldMapping 表 - DOMAINS、TREND_DOMAIN_MAP、PLATFORM_TAGS、china_pains、RSS关键词、priority_weights 全部迁移到 DB - tasks.html 重构:卡片网格+配置/产出/历史/提示词四个Tab,折叠显示 - 清理冗余代码:DEFAULT_PROMPTS死代码、collector.py unreachable代码、compliance_checker bug - strip_thinking_html 改用 DB 规则优先
This commit is contained in:
@@ -471,24 +471,59 @@ class TaskLog(Base):
|
||||
__tablename__ = "task_logs"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True, autoincrement=True)
|
||||
module_id = Column(String, nullable=False, index=True) # scheduled_collect / scheduled_generate 等
|
||||
task_name = Column(String, nullable=False)
|
||||
topic_id = Column(String, nullable=True)
|
||||
status = Column(String, nullable=False)
|
||||
topic_id = Column(String, nullable=True, index=True)
|
||||
status = Column(String, nullable=False) # pending / running / success / failed / cancelled
|
||||
message = Column(Text, nullable=True)
|
||||
error_trace = Column(Text, nullable=True)
|
||||
triggered_by = Column(String, default="scheduler") # scheduler / manual / api
|
||||
result_data = Column(JSON, default=dict) # 产出摘要:{topics_found, articles_created, issues_fixed, ...}
|
||||
started_at = Column(DateTime(timezone=True), server_default=func.now())
|
||||
finished_at = Column(DateTime(timezone=True), nullable=True)
|
||||
duration = Column(Integer, nullable=True)
|
||||
duration = Column(Integer, nullable=True) # seconds
|
||||
next_run_time = Column(DateTime(timezone=True), nullable=True)
|
||||
|
||||
def to_dict(self):
|
||||
return {
|
||||
"id": self.id,
|
||||
"module_id": self.module_id,
|
||||
"task_name": self.task_name,
|
||||
"topic_id": self.topic_id,
|
||||
"status": self.status,
|
||||
"message": self.message,
|
||||
"error_trace": self.error_trace,
|
||||
"triggered_by": self.triggered_by,
|
||||
"result_data": self.result_data or {},
|
||||
"started_at": self.started_at.isoformat() if self.started_at else None,
|
||||
"finished_at": self.finished_at.isoformat() if self.finished_at else None,
|
||||
"duration": self.duration,
|
||||
"next_run_time": self.next_run_time.isoformat() if self.next_run_time else None,
|
||||
}
|
||||
|
||||
|
||||
class TaskConfig(Base):
|
||||
__tablename__ = "task_configs"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True, autoincrement=True)
|
||||
module_id = Column(String, unique=True, nullable=False)
|
||||
enabled = Column(Boolean, default=True)
|
||||
params = Column(JSON, default=dict) # 各任务自定义参数,JSON 格式
|
||||
schedule = Column(String, nullable=True) # cron 表达式,覆盖默认
|
||||
last_modified_by = Column(String, nullable=True)
|
||||
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
||||
updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now())
|
||||
|
||||
def to_dict(self):
|
||||
return {
|
||||
"id": self.id,
|
||||
"module_id": self.module_id,
|
||||
"enabled": self.enabled,
|
||||
"params": self.params or {},
|
||||
"schedule": self.schedule,
|
||||
"last_modified_by": self.last_modified_by,
|
||||
"created_at": self.created_at.isoformat() if self.created_at else None,
|
||||
"updated_at": self.updated_at.isoformat() if self.updated_at else None,
|
||||
}
|
||||
|
||||
|
||||
@@ -527,6 +562,101 @@ class LLMConfig(Base):
|
||||
}
|
||||
|
||||
|
||||
class PromptConfig(Base):
|
||||
__tablename__ = "prompt_configs"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True, autoincrement=True)
|
||||
key = Column(String, unique=True, nullable=False, index=True)
|
||||
module_id = Column(String, nullable=True, index=True)
|
||||
category = Column(String, default="prompt") # prompt / rule / template
|
||||
version = Column(String, default="v1")
|
||||
content = Column(Text, nullable=False)
|
||||
variables = Column(JSON, default=[]) # [{name, description, default_value}]
|
||||
description = Column(String, nullable=True)
|
||||
enabled = Column(Boolean, default=True)
|
||||
temperature = Column(Float, nullable=True)
|
||||
max_tokens = Column(Integer, nullable=True)
|
||||
created_by = Column(String, nullable=True)
|
||||
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
||||
updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now())
|
||||
|
||||
def to_dict(self):
|
||||
return {
|
||||
"id": self.id,
|
||||
"key": self.key,
|
||||
"module_id": self.module_id,
|
||||
"category": self.category,
|
||||
"version": self.version,
|
||||
"content": self.content,
|
||||
"variables": self.variables or [],
|
||||
"description": self.description,
|
||||
"enabled": self.enabled,
|
||||
"temperature": self.temperature,
|
||||
"max_tokens": self.max_tokens,
|
||||
"created_by": self.created_by,
|
||||
"created_at": self.created_at.isoformat() if self.created_at else None,
|
||||
"updated_at": self.updated_at.isoformat() if self.updated_at else None,
|
||||
}
|
||||
|
||||
|
||||
class KeywordDomainMap(Base):
|
||||
__tablename__ = "keyword_domain_map"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True, autoincrement=True)
|
||||
pattern = Column(String, nullable=False)
|
||||
domain = Column(String, nullable=False)
|
||||
sort_order = Column(Integer, default=0)
|
||||
is_active = Column(Boolean, default=True)
|
||||
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
||||
updated_at = Column(DateTime(timezone=True), onupdate=func.now())
|
||||
|
||||
def to_dict(self):
|
||||
return {
|
||||
"id": self.id, "pattern": self.pattern, "domain": self.domain,
|
||||
"sort_order": self.sort_order, "is_active": self.is_active,
|
||||
"created_at": self.created_at.isoformat() if self.created_at else None,
|
||||
"updated_at": self.updated_at.isoformat() if self.updated_at else None,
|
||||
}
|
||||
|
||||
|
||||
class SensitiveWord(Base):
|
||||
__tablename__ = "sensitive_words"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True, autoincrement=True)
|
||||
word = Column(String, nullable=False)
|
||||
category = Column(String, default="general")
|
||||
is_active = Column(Boolean, default=True)
|
||||
added_by = Column(String, nullable=True)
|
||||
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
||||
|
||||
def to_dict(self):
|
||||
return {
|
||||
"id": self.id, "word": self.word, "category": self.category,
|
||||
"is_active": self.is_active, "added_by": self.added_by,
|
||||
"created_at": self.created_at.isoformat() if self.created_at else None,
|
||||
}
|
||||
|
||||
|
||||
class ContentCleanRule(Base):
|
||||
__tablename__ = "content_clean_rules"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True, autoincrement=True)
|
||||
rule_type = Column(String, nullable=False) # thinking / preface / verbosity / html_thinking
|
||||
pattern = Column(Text, nullable=False)
|
||||
description = Column(String, nullable=True)
|
||||
is_active = Column(Boolean, default=True)
|
||||
sort_order = Column(Integer, default=0)
|
||||
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
||||
|
||||
def to_dict(self):
|
||||
return {
|
||||
"id": self.id, "rule_type": self.rule_type, "pattern": self.pattern,
|
||||
"description": self.description, "is_active": self.is_active,
|
||||
"sort_order": self.sort_order,
|
||||
"created_at": self.created_at.isoformat() if self.created_at else None,
|
||||
}
|
||||
|
||||
|
||||
class SystemConfig(Base):
|
||||
__tablename__ = "system_configs"
|
||||
|
||||
@@ -557,6 +687,7 @@ class CollectorCategory(Base):
|
||||
name = Column(String, unique=True, nullable=False)
|
||||
description = Column(Text, nullable=True)
|
||||
search_query = Column(String, nullable=True)
|
||||
pain_template = Column(Text, nullable=True)
|
||||
sort_order = Column(Integer, default=0)
|
||||
is_active = Column(Boolean, default=True)
|
||||
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
||||
@@ -570,6 +701,7 @@ class CollectorCategory(Base):
|
||||
"name": self.name,
|
||||
"description": self.description,
|
||||
"search_query": self.search_query,
|
||||
"pain_template": self.pain_template,
|
||||
"sort_order": self.sort_order,
|
||||
"is_active": self.is_active,
|
||||
"created_at": self.created_at.isoformat() if self.created_at else None,
|
||||
@@ -577,6 +709,24 @@ class CollectorCategory(Base):
|
||||
}
|
||||
|
||||
|
||||
class TrendFieldMapping(Base):
|
||||
__tablename__ = "trend_field_mappings"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True, autoincrement=True)
|
||||
trend_keyword = Column(String, nullable=False)
|
||||
field_name = Column(String, nullable=False)
|
||||
sort_order = Column(Integer, default=0)
|
||||
is_active = Column(Boolean, default=True)
|
||||
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
||||
|
||||
def to_dict(self):
|
||||
return {
|
||||
"id": self.id, "trend_keyword": self.trend_keyword, "field_name": self.field_name,
|
||||
"sort_order": self.sort_order, "is_active": self.is_active,
|
||||
"created_at": self.created_at.isoformat() if self.created_at else None,
|
||||
}
|
||||
|
||||
|
||||
class CollectorSource(Base):
|
||||
"""采集信息源(可在运营管理中动态编辑)"""
|
||||
__tablename__ = "collector_sources"
|
||||
|
||||
Reference in New Issue
Block a user