Просмотр исходного кода

feat(mode_workflow): 新增批量获取工序解构的API和数据库工具

- 重构通用查询列表参数解析逻辑,保留原有接口兼容旧代码
- 新增fetch_all_process数据库方法支持批量获取案例工序数据
- 添加/api/all_process API端点并更新文档注释
刘文武 1 день назад
Родитель
Сommit
703962e6e3
2 измененных файлов с 49 добавлено и 7 удалено
  1. 31 0
      examples/mode_workflow/db.py
  2. 18 7
      examples/mode_workflow/server.py

+ 31 - 0
examples/mode_workflow/db.py

@@ -794,6 +794,37 @@ def fetch_process(case_id, version=None):
     return _proc_payload(case_id, version, rows)
 
 
+def fetch_all_process(case_ids=None):
+    """批量取多帖工序解构(每帖取最新真实版,link_ 排后),一次查询拍平。
+      - case_ids:选填 case_id 列表;None=全表所有有解构的帖,[]=空(直接返回空)。
+    返回 {case_id: _proc_payload(...)};无解构记录的 case_id 不出现在结果里。"""
+    if case_ids is not None and not case_ids:
+        return {}
+    where, params = "", []
+    if case_ids is not None:
+        where = " WHERE case_id IN (" + ",".join(["%s"] * len(case_ids)) + ")"
+        params = list(case_ids)
+    conn = _conn()
+    try:
+        with conn.cursor() as cur:
+            cur.execute(f"SELECT * FROM mode_process{where} ORDER BY case_id, id", params)
+            rows = cur.fetchall()
+    finally:
+        conn.close()
+    by_case = {}
+    for r in rows:
+        by_case.setdefault(r["case_id"], []).append(r)
+    out = {}
+    for cid, crows in by_case.items():
+        # 选版本:非 link_ 优先(is_real=True 排前),再按 id 最大——口径同 fetch_process
+        best = max(crows, key=lambda r: (not str(r["version"]).startswith("link_"), r["id"]))
+        ver = best["version"]
+        vrows = sorted((r for r in crows if r["version"] == ver),
+                       key=lambda r: (r["seq"] if r["seq"] is not None else 0, r["id"]))
+        out[cid] = _proc_payload(cid, ver, vrows)
+    return out
+
+
 def fetch_process_by_query(query_id, case_id, version=None):
     """同 fetch_process,但用 (query_id, case_id) 精确定位某 query 下该帖的工序
     (category-match 用:post_id=query_id / knowledge_id=case_id)。

+ 18 - 7
examples/mode_workflow/server.py

@@ -6,6 +6,7 @@
   - GET  /search.html         知识检索页(聚类库 tab 内嵌;API 域名由 .env 注入)
   - GET  /api/dashboard       Dashboard 全部聚合指标(含内容树覆盖)
   - GET  /api/queries|posts|process|tools(+_versions)   Dataset 数据
+  - GET  /api/all_posts|all_process   某方向全部帖子 / 批量工序解构(工序库平铺表)
   - GET  /api/extract         点帖子合一:版本列表+解构详情(单连接,带 ETag/304)
   - POST /api/run_search|extract_process|extract_tools  起子进程跑 pipeline
   - GET  /api/task_status     轮询任务状态(读日志尾部)
@@ -275,13 +276,13 @@ def _queries_cached(mode):
     return data
 
 
-def _parse_query_list(raw_query):
-    """从 query string 解析 query_list(选填);三种写法统一成 list[str](去重保序):
-      重复参数  ?query_list=q1&query_list=q2
-      逗号分隔  ?query_list=q1,q2
-      JSON 数组 ?query_list=["q1","q2"]
-    未提供返回 None(=查全部);提供了(哪怕显式空数组)返回 list(可能为空,=过滤后空结果)。"""
-    vals = parse_qs(raw_query).get("query_list")
+def _parse_list_param(raw_query, key):
+    """从 query string 解析某个「列表参数」(选填);三种写法统一成 list[str](去重保序):
+      重复参数  ?key=a&key=b
+      逗号分隔  ?key=a,b
+      JSON 数组 ?key=["a","b"]
+    未提供返回 None(=不过滤);提供了(哪怕显式空数组)返回 list(可能为空,=过滤后空结果)。"""
+    vals = parse_qs(raw_query).get(key)
     if not vals:
         return None
     out = []
@@ -302,6 +303,11 @@ def _parse_query_list(raw_query):
     return res
 
 
+def _parse_query_list(raw_query):
+    """向后兼容封装:解析 query_list 列表参数(见 _parse_list_param)。"""
+    return _parse_list_param(raw_query, "query_list")
+
+
 def _dashboard():
     posts, procs, tools = db.fetch_dashboard_rows()
 
@@ -690,6 +696,11 @@ class Handler(BaseHTTPRequestHandler):
             elif u.path == "/api/process":
                 r = db.fetch_process(qs.get("case_id", ""), qs.get("version"))
                 self._json(r) if r else self._err("无解构记录", 404)
+            elif u.path == "/api/all_process":
+                # 批量解构:一次取多帖(或全表)的最新版工序+steps,供工序库平铺表一次加载。
+                # case_ids 选填(逗号/重复/JSON 三种写法,同 query_list),不传=全表。
+                m = db.fetch_all_process(_parse_list_param(u.query, "case_ids"))
+                self._json({"count": len(m), "procedures_by_case": m})
             elif u.path == "/api/tools_versions":
                 self._json(db.fetch_tools_versions(qs.get("case_id", "")))
             elif u.path == "/api/tools":