refactor(todo_badge): 待办列表/详情改由 dspy 返回 bricks widget 渲染,JS 只负责角标与打开弹窗

This commit is contained in:
yumoqing 2026-08-25 14:59:09 +08:00
parent 5f18745ace
commit 71566bea56

View File

@ -1,5 +1,8 @@
// 待办角标1 分钟定时刷新 + 点击打开待办列表
// 由 HTML shell 自动加载configuredServer.get_js_files 收集 wwwroot 下 .js在 bricks.js 之后引入)
// 列表与详情的界面全部由后端 dspy 返回 bricks widget 描述渲染:
// /pipeline-sdlc/api/my_todos_popup.dspy → 待办列表弹窗
// /pipeline-sdlc/api/todo_detail.dspy → 待办详情(正文 MdWidget + VScrollPanel 滚动 + 操作按钮)
(function(){
if (typeof bricks === 'undefined') return;
@ -16,93 +19,23 @@
};
window.openMyTodos = function(){
var pw = new bricks.PopupWindow({title:'我的待办', width:'72%', height:'80%', auto_open:true});
var vs = new bricks.VScrollPanel({css:'filler', padding:'12px', gap:'8px'});
pw.content_w.add_widget(vs);
fetch('/pipeline-sdlc/api/my_todos.dspy')
// 已打开则先关掉,避免叠加多个列表弹窗
var old = bricks.getWidgetById && bricks.getWidgetById('my_todos_pw', bricks.app);
if (old && old.destroy) { old.destroy(); }
return fetch('/pipeline-sdlc/api/my_todos_popup.dspy')
.then(function(r){ return r.json(); })
.then(function(d){
var todos = (d && d.todos) || [];
if (todos.length === 0) {
vs.add_widget(new bricks.Text({text:'暂无待办', cfontsize:0.9, color:'#94a3b8'}));
.then(function(desc){
if (!desc) { return; }
if (desc.error || desc.success === false) {
var m = new bricks.Message({title:'打开失败', message: desc.error || '无法加载待办'});
m.open();
return;
}
todos.forEach(function(t){
var src = t.source || '';
var title = src === 'question' ? (t.question || '') : (t.title || '');
var label = src === 'question' ? '问题' : (t.task_type === 'bug_acceptance' ? 'Bug验收' : (t.task_type === 'requirement_confirmation' ? '需求确认' : (t.task_type === 'design_confirmation' ? '设计确认' : '人类任务')));
var card = new bricks.VBox({bgcolor:'#fff', border:'1px solid #e2e8f0', borderRadius:'8px', padding:'10px 14px', gap:'6px', marginBottom:'4px'});
var hdr = new bricks.HBox({alignItems:'center', gap:'8px'});
hdr.add_widget(new bricks.Text({text:label, cfontsize:0.7, color:'#ffffff', padding:'1px 8px', style:{background: src==='question' ? '#8b5cf6' : (t.task_type==='bug_acceptance' ? '#f0a040' : '#2563eb'), borderRadius:'10px', fontWeight:'bold'}}));
hdr.add_widget(new bricks.Text({text:title, cfontsize:0.9, color:'#1e293b', fontWeight:'bold'}));
card.add_widget(hdr);
if (t.project_name) {
card.add_widget(new bricks.Text({text:'项目:' + t.project_name, cfontsize:0.7, color:'#94a3b8'}));
}
if (src === 'human_task' && t.task_type === 'bug_acceptance') {
var hb = new bricks.HBox({gap:'6px'});
var okb = new bricks.Button({label:'通过', css:'small'});
okb.bind('click', function(){
fetch('/pipeline-sdlc/api/bug_accept.dspy', {method:'POST', headers:{'Content-Type':'application/x-www-form-urlencoded'}, body:'bug_id='+encodeURIComponent(t.bug_id)+'&accept=1'})
.then(function(r){ return r.json(); })
.then(function(d){
alert(d.success ? '验收通过Bug已关闭' : (d.error || '失败'));
if (d.success) { pw.destroy(); refreshTodo(); }
});
});
var nob = new bricks.Button({label:'不通过', css:'small'});
nob.bind('click', function(){
fetch('/pipeline-sdlc/api/bug_accept.dspy', {method:'POST', headers:{'Content-Type':'application/x-www-form-urlencoded'}, body:'bug_id='+encodeURIComponent(t.bug_id)+'&accept=0'})
.then(function(r){ return r.json(); })
.then(function(d){
alert(d.success ? '验收不通过Bug已重新打开' : (d.error || '失败'));
if (d.success) { pw.destroy(); refreshTodo(); }
});
});
hb.add_widget(okb);
hb.add_widget(nob);
card.add_widget(hb);
} else if (src === 'human_task' && (t.task_type === 'requirement_confirmation' || t.task_type === 'design_confirmation')) {
var cb = new bricks.HBox({gap:'6px'});
var okb2 = new bricks.Button({label:'确认通过', css:'small'});
okb2.bind('click', function(){
fetch('/pipeline-sdlc/api/stage_confirm.dspy', {method:'POST', headers:{'Content-Type':'application/x-www-form-urlencoded'}, body:'human_task_id='+encodeURIComponent(t.id)+'&confirmed=1'})
.then(function(r){ return r.json(); })
.then(function(d){
alert(d.success ? (d.message || '已确认,继续后续任务') : (d.error || '失败'));
if (d.success) { pw.destroy(); refreshTodo(); }
});
});
var rb2 = new bricks.Button({label:'不确定,退回重做', css:'small'});
rb2.bind('click', function(){
var v = prompt('请填写修改意见(将退回重做):', '');
if (v === null) return;
fetch('/pipeline-sdlc/api/stage_confirm.dspy', {method:'POST', headers:{'Content-Type':'application/x-www-form-urlencoded'}, body:'human_task_id='+encodeURIComponent(t.id)+'&confirmed=0&comment='+encodeURIComponent(v)})
.then(function(r){ return r.json(); })
.then(function(d){
alert(d.success ? (d.message || '已退回重做') : (d.error || '失败'));
if (d.success) { pw.destroy(); refreshTodo(); }
});
});
cb.add_widget(okb2);
cb.add_widget(rb2);
card.add_widget(cb);
} else if (src === 'human_task') {
var db = new bricks.Button({label:'处理', css:'small'});
db.bind('click', function(){
var v = prompt('请输入处理结果:', '');
if (v === null) return;
fetch('/pipeline-sdlc/api/human_task_complete.dspy', {method:'POST', headers:{'Content-Type':'application/x-www-form-urlencoded'}, body:'human_task_id='+encodeURIComponent(t.id)+'&result_data='+encodeURIComponent(JSON.stringify({content:v}))})
.then(function(r){ return r.json(); })
.then(function(d){
alert(d.success ? '已提交等待QC检查' : (d.error || '失败'));
if (d.success) { pw.destroy(); refreshTodo(); }
});
});
card.add_widget(db);
}
vs.add_widget(card);
});
return bricks.widgetBuild(desc, bricks.app);
})
.catch(function(e){
var m2 = new bricks.Message({title:'打开失败', message:'网络错误:' + e});
m2.open();
});
};