feat: output_format 支持多选,报告可同时发送多种格式

- ConfigManager: get_output_format 改为返回 list,向后兼容旧 string 值
- set_output_format 接受逗号分隔的格式列表
- Dispatcher: dispatch() 循环所有选中格式逐一分发
- manual (/群分析): 使用列表中的第一种格式
- 命令 /设置格式: 支持 image,html 等逗号分隔多选
- 配置面板 output_format 改为 list 类型 (可多选)
This commit is contained in:
SXP-Simon
2026-07-21 15:50:31 +08:00
parent 3a03c1f272
commit c19332a887
3 changed files with 40 additions and 29 deletions
+18 -7
View File
@@ -621,7 +621,7 @@ class GroupDailyAnalysis(Star):
platform_id = result["platform_id"]
analysis_result = result["analysis_result"]
adapter = result["adapter"]
output_format = self.config_manager.get_output_format()
output_format = self.config_manager.get_output_format()[0]
is_qq_official = adapter.get_platform_name() == "qq_official"
# 定义获取回调
@@ -764,7 +764,7 @@ class GroupDailyAnalysis(Star):
async def set_output_format(self, event: AstrMessageEvent, format_input: str = ""):
"""
设置分析报告输出格式(跨平台支持)
用法: /设置格式 [格式名称或序号]
用法: /设置格式 [格式名称或序号] 或 image,html 等逗号分隔的组合
"""
# 命令由插件处理,禁用默认 LLM 回退。
event.should_call_llm(True)
@@ -777,19 +777,19 @@ class GroupDailyAnalysis(Star):
}
if not format_input:
current_format = self.config_manager.get_output_format()
current = ", ".join(self.config_manager.get_output_format())
format_list_str = "\n".join(
[
f"{i}{f} - {format_display_names[f]}"
for i, f in enumerate(available_formats, start=1)
]
)
yield event.plain_result(f"""📊 当前输出格式: {current_format}
yield event.plain_result(f"""📊 当前输出格式: {current}
可用格式:
{format_list_str}
用法: /设置格式 [名称或序号]""")
用法: /设置格式 [名称或序号] 如 /设置格式 image,html""")
return
target_format = None
@@ -805,6 +805,17 @@ class GroupDailyAnalysis(Star):
if input_lower in available_formats:
target_format = input_lower
# 支持逗号分隔的多个格式
if not target_format:
parts = [f.strip() for f in format_input.replace("", ",").split(",")]
if all(p in available_formats for p in parts) and len(parts) > 1:
try:
self.config_manager.set_output_format(parts)
yield event.plain_result(f"✅ 输出格式已设置为: {', '.join(parts)}")
except Exception as e:
yield event.plain_result(f"❌ 设置失败: {e}")
return
if not target_format:
yield event.plain_result(
f"❌ 无效的格式类型 '{format_input}'。可用: {', '.join(available_formats)} 或序号 1-{len(available_formats)}"
@@ -812,7 +823,7 @@ class GroupDailyAnalysis(Star):
return
try:
self.config_manager.set_output_format(target_format)
self.config_manager.set_output_format(target_format) # type: ignore[arg-type]
yield event.plain_result(f"✅ 输出格式已设置为: {target_format}")
except Exception as e:
yield event.plain_result(f"❌ 设置失败: {e}")
@@ -992,7 +1003,7 @@ class GroupDailyAnalysis(Star):
)
auto_time = self.config_manager.get_auto_analysis_time()
output_format = self.config_manager.get_output_format()
output_format = self.config_manager.get_output_format()[0]
min_threshold = self.config_manager.get_min_messages_threshold()
# 增量分析状态
+10 -9
View File
@@ -146,9 +146,10 @@ class ConfigManager:
"""
return self.is_auto_analysis_enabled()
def get_output_format(self) -> str:
def get_output_format(self) -> list[str]:
"""获取输出格式"""
return self._get_group("basic").get("output_format", "image")
val = self._get_group("basic").get("output_format", ["image"])
return val if isinstance(val, list) else [val]
def get_qq_official_t2i_summary_dashboard_enabled(self) -> bool:
"""是否启用 QQ 官方 T2I 概览图。"""
@@ -494,15 +495,15 @@ class ConfigManager:
prompts["golden_quote_analysis_prompts"]["golden_quote_v2_prompt"] = prompt
self.config.save_config()
def set_output_format(self, format_type: str):
def set_output_format(self, format_types: str | list[str]):
"""设置输出格式"""
valid_formats = ["image", "text", "html"]
if format_type.lower() not in valid_formats:
raise ValueError(
f"无效的输出格式: {format_type}。有效选项: {valid_formats}"
)
if isinstance(format_types, str):
format_types = [f.strip() for f in format_types.replace("", ",").split(",")]
for f in format_types:
if f not in ("image", "text", "html"):
raise ValueError(f"无效格式: {f}。有效: image, text, html")
self._ensure_group("basic")["output_format"] = format_type.lower()
self._ensure_group("basic")["output_format"] = format_types
self.config.save_config()
def set_group_list_mode(self, mode: str):
+12 -13
View File
@@ -45,24 +45,23 @@ class ReportDispatcher:
分发分析报告
"""
trace_id = TraceContext.get()
output_format = self.config_manager.get_output_format()
output_formats = self.config_manager.get_output_format()
logger.info(
f"[{trace_id}] 正在分发群 {group_id} 的报告 (格式: {output_format})"
f"[{trace_id}] 正在分发群 {group_id} 的报告 (格式: {', '.join(output_formats)})"
)
success = False
if output_format == "image":
success = await self._dispatch_image(group_id, analysis_result, platform_id)
elif output_format == "html":
success = await self._dispatch_html(group_id, analysis_result, platform_id)
else:
success = await self._dispatch_text(group_id, analysis_result, platform_id)
dispatch_map = {
"image": self._dispatch_image,
"html": self._dispatch_html,
"text": self._dispatch_text,
}
for fmt in output_formats:
handler = dispatch_map.get(fmt)
if handler:
await handler(group_id, analysis_result, platform_id)
if success:
logger.info(f"[{trace_id}] 群 {group_id} 的报告分发成功")
else:
logger.warning(f"[{trace_id}] 群 {group_id} 的报告分发失败")
logger.info(f"[{trace_id}] 群 {group_id} 的报告分发完成")
async def _dispatch_image(
self, group_id: str, analysis_result: dict[str, Any], platform_id: str | None