pipeline-sdlc/wwwroot/api/task_io.dspy

162 lines
6.5 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# task_io.dspy - 任务的输入输出ResourceBrowser 右侧面板5 秒自动刷新)
import json
uid = await get_user()
if not uid:
uid = 'user-01'
task_id = (params_kw or {}).get('id', '').strip()
dbname = get_module_dbname('pipeline-sdlc')
_state_colors = {
'completed': '#16a34a',
'approved': '#16a34a',
'running': '#2563eb',
'failed': '#dc2626',
'waiting': '#f0a040',
'submitted': '#64748b',
'review': '#2196f3',
'rejected': '#dc2626',
'paused': '#f0a040',
'cancelled': '#64748b',
}
if not task_id:
return json.dumps({
"widgettype": "Text",
"options": {"text": "请选择左侧任务查看输入输出", "cfontsize": 0.9, "color": "#94a3b8", "padding": "16px"},
}, ensure_ascii=False)
async with DBPools().sqlorContext(dbname) as sor:
recs = await sor.sqlExe(
"SELECT id, title, role, state, params, last_error, created_at, updated_at "
"FROM pipeline_tasks WHERE id=${t}$", {"t": task_id})
if not recs:
return json.dumps({
"widgettype": "Text",
"options": {"text": "任务不存在", "cfontsize": 0.9, "color": "#94a3b8", "padding": "16px"},
}, ensure_ascii=False)
task = recs[0]
title = getattr(task, 'title', '') or ''
role = getattr(task, 'role', '') or ''
state = getattr(task, 'state', '') or ''
last_error = getattr(task, 'last_error', '') or ''
created_at = str(getattr(task, 'created_at', '') or '')[:16]
updated_at = str(getattr(task, 'updated_at', '') or '')[:16]
# 输入params 里的 description / input_text
params_str = getattr(task, 'params', '') or ''
description = ''
try:
p = json.loads(params_str) if params_str else {}
description = p.get('description', '') or p.get('input_text', '') or p.get('prompt', '') or ''
except Exception:
description = params_str
# 输出:交付件
dels = await sor.sqlExe(
"SELECT deliverable_type, title, content, review_status, quality_score, review_comment "
"FROM pipeline_deliverables WHERE task_id=${t}$ ORDER BY created_at DESC", {"t": task_id})
sc = _state_colors.get(state, '#64748b')
subwidgets = []
# 标题行:任务名 + 状态
subwidgets.append({
"widgettype": "Text",
"options": {"text": title, "halign": "left", "cfontsize": 1.15, "style": {"fontWeight": "bold", "color": "#1e293b"}},
})
subwidgets.append({
"widgettype": "HBox",
"options": {"gap": "12px", "width": "100%"},
"subwidgets": [
{"widgettype": "Text", "options": {"text": "状态: " + state, "cfontsize": 0.8, "color": sc, "halign": "left"}},
{"widgettype": "Text", "options": {"text": "角色: " + role, "cfontsize": 0.8, "color": "#64748b", "halign": "left"}},
{"widgettype": "Text", "options": {"text": "更新: " + updated_at, "cfontsize": 0.75, "color": "#94a3b8", "halign": "left"}},
{"widgettype": "Filler"},
],
})
if last_error:
subwidgets.append({
"widgettype": "Text",
"options": {"text": "错误: " + last_error[:300], "halign": "left", "cfontsize": 0.8, "css": "resp-error", "wrap": True},
})
# 输入
subwidgets.append({
"widgettype": "Text",
"options": {"text": "—— 输入 ——", "halign": "left", "cfontsize": 0.85, "style": {"fontWeight": "bold", "color": "#3b82f6", "marginTop": "8px"}},
})
subwidgets.append({
"widgettype": "Text",
"options": {"text": (description or "(无)")[:4000], "halign": "left", "cfontsize": 0.85, "color": "#334155", "wrap": True, "css": "card"},
})
# 输出
subwidgets.append({
"widgettype": "Text",
"options": {"text": "—— 输出(交付件)——", "halign": "left", "cfontsize": 0.85, "style": {"fontWeight": "bold", "color": "#16a34a", "marginTop": "8px"}},
})
if not dels:
subwidgets.append({
"widgettype": "Text",
"options": {"text": "(暂无交付件)", "halign": "left", "cfontsize": 0.8, "color": "#94a3b8"},
})
else:
for d in dels:
d_type = getattr(d, 'deliverable_type', '') or ''
d_title = getattr(d, 'title', '') or ''
d_content = getattr(d, 'content', '') or ''
d_status = getattr(d, 'review_status', '') or ''
d_score = getattr(d, 'quality_score', '') or ''
d_comment = getattr(d, 'review_comment', '') or ''
card = {
"widgettype": "VBox",
"options": {"css": "card", "gap": "4px", "width": "100%", "padding": "8px"},
"subwidgets": [
{"widgettype": "HBox", "options": {"gap": "8px", "width": "100%"},
"subwidgets": [
{"widgettype": "Text", "options": {"text": d_type, "cfontsize": 0.8, "color": "#3b82f6", "halign": "left"}},
{"widgettype": "Text", "options": {"text": d_title, "cfontsize": 0.8, "color": "#1e293b", "halign": "left"}},
{"widgettype": "Filler"},
{"widgettype": "Text", "options": {"text": d_status, "cfontsize": 0.75, "color": "#94a3b8", "halign": "left"}},
]},
{"widgettype": "Text", "options": {"text": (d_content or "")[:3000], "cfontsize": 0.78, "color": "#475569", "wrap": True, "halign": "left"}},
],
}
if d_comment:
card["subwidgets"].append({
"widgettype": "Text",
"options": {"text": "审核意见: " + d_comment[:300], "cfontsize": 0.75, "color": "#f0a040", "wrap": True, "halign": "left"},
})
subwidgets.append(card)
# 5 秒刷新on_parent 事件add_widget 时触发)里 setInterval重新 render_browser 刷新当前任务内容
refresh_script = (
"if(!window._task_io_timer){"
"window._task_io_timer=setInterval(function(){"
"var rb=bricks.getWidgetById('task_rb',bricks.app);"
"if(rb&&rb.current_id){var cid=rb.current_id;rb.current_id=undefined;rb.render_browser(cid);}"
"},5000);}"
)
resp = {
"widgettype": "VBox",
"options": {"width": "100%", "height": "100%", "padding": "12px", "gap": "6px", "overflowY": "auto"},
"subwidgets": subwidgets,
"binds": [{
"wid": "self",
"event": "on_parent",
"actiontype": "script",
"target": "self",
"script": refresh_script,
}],
}
return json.dumps(resp, ensure_ascii=False)