feat(monitor_web): 导出筛选模态框 — 不再一点就跑全量 (closes #112)
## 痛点 之前 Web UI 工具箱里 "③ 导出聊天" / "⑦ 企业微信导出" 一点就跑全量。 用户 3142 个个人微信会话 + 14 个企微会话, 全量导出几个 GB JSON 几小时, 还没法只导某几个群。 ## 设计 点击导出按钮 → 弹模态框选会话 + 格式 → 确认后才跑。 ``` ┌────────────────────────────────────────┐ │ 导出个人微信聊天 [×] │ ├────────────────────────────────────────┤ │ 🔍 按名字 / wxid 搜索... │ │ ┌──────────────────────────────────┐ │ │ │ ☐ [群] 交易所消息 2026-05-14│ │ │ │ ☐ [单聊] 张三 2026-05-13│ │ │ │ ☐ [公众号] xxx日报 2026-05-10│ │ │ │ ... │ │ │ └──────────────────────────────────┘ │ │ [全选] [清空] [选最近30天活跃] 已选 N│ │ │ │ 格式 (仅企微) ☑CSV ☐HTML ☐JSON │ │ │ │ [取消] [确认导出 →] │ └────────────────────────────────────────┘ ``` ## 实现拆解 ### Backend 1. **GET /api/sessions?source=wechat|wxwork** — 列会话 - wechat: 从 decrypted/session/session.db SessionTable 读, 拼合 contact.db 的 nick_name/remark, type 分群/单聊/公众号 - wxwork: 从 wxwork_decrypted/session.db conversation_table 读, id 前缀分 R/S/E/Y → 群/单聊/外部/其他 - 按 last_ts 降序 2. **TOOL_TASKS schema 加 build_steps + needs_modal** - 旧固定任务: `steps: [cmd, ...]` - 新动态任务: `build_steps: fn(users, formats) → [cmd, ...]` - export_all / wxwork_export 用 build_steps + needs_modal 标记 3. **_run_tool_task 接收 args**, 优先调 build_steps 生成 cmd 4. **POST /api/tool body 接收 args**: `{task, args: {users:[...], formats:[...]}}` ### CLI 脚本 - `export_all_chats.py` 加 `--users wxid1,wxid2` (alt: env WECHAT_EXPORT_USERS), 在加载完 sessions 后做白名单过滤, 空集报错退出 - `export_wxwork_messages.py` 原本就支持 `--conversation` (multi-arg) + `--formats csv,html,json`, 不动它, monitor_web 拼 argv 即可 ### Frontend - HTML 加 `#exportModal` 模态框骨架 (overlay + dialog + search + list + format checkboxes + footer buttons) - CSS .modal-* 一套 (用 design tokens, 跟整体暗色风格统一) - JS: - NEEDS_MODAL = {export_all: 'export_wechat', wxwork_export: 'export_wxwork'} - runTool 拦截这两个 task → openExportModal - openExportModal fetch /api/sessions → renderSessions (复选框列表) - filterSessions 实时搜索过滤 - selectAllSessions / selectRecentSessions(30) 批量选择 - confirmExport 收集 selected usernames + formats → runToolWithArgs - runTool 拆成 runTool (entry, 拦截/取消) + runToolWithArgs (实际跑) ## 实测验证 ``` $ curl -s "http://localhost:5678/api/sessions?source=wxwork" [{"username": "R:358645240322", "name": "交易所消息", "type": "群", "last_ts": 1778658597, ...}, {"username": "E:10223", "name": "E:10223", "type": "外部", ...}, ...] $ curl -s "http://localhost:5678/api/sessions?source=wechat" [{"username": "46222992238@chatroom", "name": "月下健人", "type": "群", "last_ts": 1779014016, ...}, ...] ``` API 返回正确, 个人微信 3142 个 / 企微 14 个会话, 按 last_ts 降序。 测试 185/185 通过。 ## 副带改进 - runToolWithArgs 拆出来后, fix 之前一个小 bug: error 路径里的 `b.textContent = b.dataset.origText` 改成 innerHTML 路径 (一致性) ## 仍未跟进 (follow-up) - export_all_chats 加 `--format csv,html` 多格式输出 (个人微信脚本 目前只支持 JSON, 模态框格式选项对它隐藏了, 看 #109 推进) - 个人微信导出 sessions 列表性能: 3142 个一次 fetch ~5MB JSON, 搜索 + render 在低端机可能卡, 可加分页 / 虚拟列表
This commit is contained in:
@@ -299,6 +299,12 @@ def main():
|
||||
action="store_true",
|
||||
help="预览模式:显示将导出的会话数和新消息数,不实际写入",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--users",
|
||||
default=None,
|
||||
help="只导出指定 username 的会话, 逗号分隔 (如 wxid_xxx,12345@chatroom). "
|
||||
"为空时导出全部 (旧行为). 也可用 env WECHAT_EXPORT_USERS",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
@@ -338,6 +344,18 @@ def main():
|
||||
print(f"会话数据库查询失败: {e}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
# username 白名单过滤 (--users 参数 / WECHAT_EXPORT_USERS 环境变量)
|
||||
users_filter_raw = args.users or os.environ.get("WECHAT_EXPORT_USERS", "")
|
||||
if users_filter_raw.strip():
|
||||
wanted = {u.strip() for u in users_filter_raw.split(",") if u.strip()}
|
||||
before = len(sessions)
|
||||
sessions = [u for u in sessions if u in wanted]
|
||||
print(f"按 --users 过滤: {before} → {len(sessions)} 会话")
|
||||
if not sessions:
|
||||
print(f"[!] 指定的 username 列表跟会话表没交集 (wanted={list(wanted)[:5]}...)",
|
||||
file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
names = mcp_server.get_contact_names()
|
||||
|
||||
# 显示模式信息
|
||||
|
||||
Reference in New Issue
Block a user