From 289ccb1656d6d849a0b693b9819a18f51ddf4c46 Mon Sep 17 00:00:00 2001 From: yumoqing Date: Mon, 3 Aug 2026 10:46:32 +0800 Subject: [PATCH] feat: add cockpit index page + DDL reference for SDLC module --- mysql.ddl.sql | 255 +++++++++++++++++++++++++++++++++++++++ wwwroot/index_cockpit.ui | 203 +++++++++++++++++++++++++++++++ 2 files changed, 458 insertions(+) create mode 100644 mysql.ddl.sql create mode 100644 wwwroot/index_cockpit.ui diff --git a/mysql.ddl.sql b/mysql.ddl.sql new file mode 100644 index 0000000..2cffd23 --- /dev/null +++ b/mysql.ddl.sql @@ -0,0 +1,255 @@ + +-- models/sd_deploy_envs.json + + + + + +-- 建库时请用以下语句,支持emoji字符 +-- CREATE DATABASE mydb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +drop table if exists sd_deploy_envs; +CREATE TABLE sd_deploy_envs +( + + `id` VARCHAR(32) NOT NULL comment '主键ID', + `project_id` VARCHAR(32) NOT NULL comment '项目ID', + `env_type` VARCHAR(20) NOT NULL comment '环境类型', + `host` VARCHAR(200) NOT NULL comment 'SSH主机地址', + `port` int NOT NULL DEFAULT '22' comment 'SSH端口', + `user` VARCHAR(100) NOT NULL comment 'SSH用户', + `ssh_key_path` VARCHAR(500) comment 'SSH密钥路径', + `sudo_enabled` VARCHAR(1) NOT NULL DEFAULT ''N'' comment '免密Sudo', + `deploy_path` VARCHAR(500) NOT NULL comment '部署目录', + `python_path` VARCHAR(500) comment 'Python路径', + `db_host` VARCHAR(200) comment '数据库地址', + `db_port` int DEFAULT '3306' comment '数据库端口', + `db_name` VARCHAR(100) comment '数据库名', + `db_user` VARCHAR(100) comment '数据库用户', + `db_password` VARCHAR(500) comment '数据库密码(加密)', + `status` VARCHAR(20) NOT NULL DEFAULT ''configured'' comment '环境状态', + `verified_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP comment '最近验证时间', + `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL comment '创建时间', + `updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP comment '更新时间' + + +,primary key(id) + + +) +CHARACTER SET utf8mb4 +COLLATE utf8mb4_unicode_ci +engine=innodb +comment '部署环境表' +; + +CREATE INDEX sd_deploy_envs_idx_sd_deploy_envs_project ON sd_deploy_envs(project_id); +CREATE INDEX sd_deploy_envs_idx_sd_deploy_envs_type ON sd_deploy_envs(env_type); +CREATE UNIQUE INDEX sd_deploy_envs_idx_sd_deploy_envs_unique ON sd_deploy_envs(project_id,env_type); + +-- models/sd_test_plans.json + + + + + +-- 建库时请用以下语句,支持emoji字符 +-- CREATE DATABASE mydb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +drop table if exists sd_test_plans; +CREATE TABLE sd_test_plans +( + + `id` VARCHAR(32) NOT NULL comment '主键ID', + `iteration_id` VARCHAR(32) NOT NULL comment '迭代ID', + `plan_name` VARCHAR(200) NOT NULL comment '方案名称', + `plan_type` VARCHAR(20) NOT NULL comment '方案类型', + `scope` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci comment '测试范围', + `environment` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci comment '测试环境要求(JSON)', + `entry_criteria` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci comment '准入条件', + `exit_criteria` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci comment '准出条件', + `status` VARCHAR(20) NOT NULL DEFAULT ''draft'' comment '方案状态', + `created_by` VARCHAR(32) comment '创建人', + `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL comment '创建时间', + `updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP comment '更新时间' + + +,primary key(id) + + +) +CHARACTER SET utf8mb4 +COLLATE utf8mb4_unicode_ci +engine=innodb +comment '测试方案表' +; + +CREATE INDEX sd_test_plans_idx_sd_test_plans_iteration ON sd_test_plans(iteration_id); +CREATE INDEX sd_test_plans_idx_sd_test_plans_status ON sd_test_plans(status); + +-- models/sd_test_cases.json + + + + + +-- 建库时请用以下语句,支持emoji字符 +-- CREATE DATABASE mydb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +drop table if exists sd_test_cases; +CREATE TABLE sd_test_cases +( + + `id` VARCHAR(32) NOT NULL comment '主键ID', + `plan_id` VARCHAR(32) NOT NULL comment '方案ID', + `case_name` VARCHAR(200) NOT NULL comment '用例名称', + `case_type` VARCHAR(20) NOT NULL comment '用例类型', + `priority` VARCHAR(10) NOT NULL DEFAULT ''P2'' comment '优先级', + `precondition` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci comment '前置条件', + `steps` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci comment '测试步骤(JSON数组)', + `expected_result` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci comment '预期结果', + `actual_result` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci comment '实际结果', + `status` VARCHAR(20) NOT NULL DEFAULT ''pending'' comment '用例状态', + `executed_by` VARCHAR(32) comment '执行人', + `executed_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP comment '执行时间', + `duration_ms` int comment '执行耗时(毫秒)', + `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL comment '创建时间' + + +,primary key(id) + + +) +CHARACTER SET utf8mb4 +COLLATE utf8mb4_unicode_ci +engine=innodb +comment '测试用例表' +; + +CREATE INDEX sd_test_cases_idx_sd_test_cases_plan ON sd_test_cases(plan_id); +CREATE INDEX sd_test_cases_idx_sd_test_cases_status ON sd_test_cases(status); +CREATE INDEX sd_test_cases_idx_sd_test_cases_type ON sd_test_cases(case_type); + +-- models/sd_iterations.json + + + + + +-- 建库时请用以下语句,支持emoji字符 +-- CREATE DATABASE mydb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +drop table if exists sd_iterations; +CREATE TABLE sd_iterations +( + + `id` VARCHAR(32) NOT NULL comment '主键ID', + `project_id` VARCHAR(32) NOT NULL comment '项目ID', + `iteration_name` VARCHAR(200) NOT NULL comment '迭代名称', + `iteration_type` VARCHAR(20) NOT NULL DEFAULT ''new_feature'' comment '迭代类型', + `scope` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci comment '迭代范围(JSON)', + `task_id` VARCHAR(32) comment '关联Pipeline任务ID', + `status` VARCHAR(20) NOT NULL DEFAULT ''planning'' comment '迭代状态', + `priority` int NOT NULL DEFAULT '5' comment '优先级', + `started_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP comment '开始时间', + `completed_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP comment '完成时间', + `created_by` VARCHAR(32) comment '创建人', + `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL comment '创建时间', + `updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP comment '更新时间' + + +,primary key(id) + + +) +CHARACTER SET utf8mb4 +COLLATE utf8mb4_unicode_ci +engine=innodb +comment 'SDLC迭代表' +; + +CREATE INDEX sd_iterations_idx_sd_iterations_project ON sd_iterations(project_id); +CREATE INDEX sd_iterations_idx_sd_iterations_status ON sd_iterations(status); + +-- models/sd_bugs.json + + + + + +-- 建库时请用以下语句,支持emoji字符 +-- CREATE DATABASE mydb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +drop table if exists sd_bugs; +CREATE TABLE sd_bugs +( + + `id` VARCHAR(32) NOT NULL comment '主键ID', + `iteration_id` VARCHAR(32) NOT NULL comment '迭代ID', + `case_id` VARCHAR(32) comment '关联用例ID', + `step_name` VARCHAR(100) comment '发现步骤名', + `title` VARCHAR(300) NOT NULL comment 'Bug标题', + `description` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci comment '详细描述', + `severity` VARCHAR(10) NOT NULL DEFAULT ''major'' comment '严重程度', + `priority` VARCHAR(10) NOT NULL DEFAULT ''P1'' comment '优先级', + `status` VARCHAR(20) NOT NULL DEFAULT ''open'' comment 'Bug状态', + `reporter_type` VARCHAR(10) NOT NULL comment '提交人类型', + `reporter_id` VARCHAR(32) NOT NULL comment '提交人ID', + `assignee_id` VARCHAR(32) comment '处理人ID', + `fix_description` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci comment '修复说明', + `fix_commit` VARCHAR(100) comment '修复Commit', + `verified_by` VARCHAR(32) comment '验证人', + `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL comment '创建时间', + `updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP comment '更新时间', + `closed_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP comment '关闭时间' + + +,primary key(id) + + +) +CHARACTER SET utf8mb4 +COLLATE utf8mb4_unicode_ci +engine=innodb +comment 'Bug管理表' +; + +CREATE INDEX sd_bugs_idx_sd_bugs_iteration ON sd_bugs(iteration_id); +CREATE INDEX sd_bugs_idx_sd_bugs_status ON sd_bugs(status); +CREATE INDEX sd_bugs_idx_sd_bugs_severity ON sd_bugs(severity); +CREATE INDEX sd_bugs_idx_sd_bugs_assignee ON sd_bugs(assignee_id); + +-- models/sd_projects.json + + + + + +-- 建库时请用以下语句,支持emoji字符 +-- CREATE DATABASE mydb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +drop table if exists sd_projects; +CREATE TABLE sd_projects +( + + `id` VARCHAR(32) NOT NULL comment '主键ID', + `name` VARCHAR(200) NOT NULL comment '项目名称', + `description` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci comment '项目描述', + `project_type` VARCHAR(50) NOT NULL DEFAULT ''web_app'' comment '项目类型', + `tech_stack` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci comment '技术栈配置(JSON)', + `repo_url` VARCHAR(500) comment '代码仓库地址', + `pipeline_id` VARCHAR(32) comment '关联Pipeline定义ID', + `status` VARCHAR(20) NOT NULL DEFAULT ''draft'' comment '项目状态', + `org_id` VARCHAR(32) NOT NULL DEFAULT ''0'' comment '组织ID', + `created_by` VARCHAR(32) comment '创建人', + `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL comment '创建时间', + `updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP comment '更新时间' + + +,primary key(id) + + +) +CHARACTER SET utf8mb4 +COLLATE utf8mb4_unicode_ci +engine=innodb +comment 'SDLC项目表' +; + +CREATE INDEX sd_projects_idx_sd_projects_status ON sd_projects(status); +CREATE INDEX sd_projects_idx_sd_projects_org ON sd_projects(org_id); + diff --git a/wwwroot/index_cockpit.ui b/wwwroot/index_cockpit.ui new file mode 100644 index 0000000..5197e9e --- /dev/null +++ b/wwwroot/index_cockpit.ui @@ -0,0 +1,203 @@ +{ + "widgettype": "VBox", + "options": { + "width": "100%", + "height": "100%", + "padding": "0" + }, + "subwidgets": [ + { + "widgettype": "HBox", + "options": { + "width": "100%", + "alignItems": "center", + "padding": "16px 24px 8px 24px", + "cheight": 6, + "gap": "12px" + }, + "subwidgets": [ + { + "widgettype": "Title2", + "options": { + "text": "开发产线驾驶舱" + } + }, + { + "widgettype": "Text", + "options": { + "text": "AI驱动的对话式开发", + "cfontsize": 0.9, + "color": "#94a3b8" + } + }, + { + "widgettype": "Filler" + }, + { + "widgettype": "Form", + "id": "model_selector", + "options": { + "name": "model_selector", + "cols": 1, + "fields": [ + { + "name": "model_id", + "uitype": "code", + "label": "", + "placeholder": "选择模型", + "cwidth": 12, + "dataurl": "/pipeline-sdlc/api/cockpit_model_options.dspy", + "valueField": "model_id", + "textField": "model_id_text", + "params": { + "valueField": "model_id", + "textField": "model_id_text" + } + } + ] + } + }, + { + "widgettype": "Button", + "options": { + "name": "model_config", + "label": "模型配置", + "css": "small" + }, + "binds": [ + { + "wid": "self", + "event": "click", + "actiontype": "script", + "target": "self", + "script": "var pw=new bricks.PopupWindow({title:'模型配置',cwidth:36,cheight:26,auto_open:true});bricks.widgetBuild({widgettype:'urlwidget',options:{url:'/pipeline_core/llm/index.ui',method:'GET'}},pw.content_w).then(function(w){if(w)pw.content_w.add_widget(w);});" + } + ] + } + ] + }, + { + "widgettype": "HBox", + "options": { + "width": "100%", + "padding": "8px 24px 8px 24px", + "cheight": 4, + "gap": "16px" + }, + "subwidgets": [ + { + "widgettype": "urlwidget", + "id": "stats_row", + "options": { + "url": "{{entire_url('/pipeline-sdlc/api/cockpit_stats.dspy')}}", + "method": "GET" + } + } + ] + }, + { + "widgettype": "HBox", + "id": "context_bar", + "options": { + "width": "100%", + "padding": "4px 24px 4px 24px", + "cheight": 2.5, + "gap": "12px", + "alignItems": "center", + "bgcolor": "#e8f0fe" + }, + "subwidgets": [ + { + "widgettype": "Text", + "options": { + "text": "📁 当前项目:--", + "cfontsize": 0.85, + "color": "#1e40af" + } + }, + { + "widgettype": "Text", + "options": { + "text": "🔄 当前迭代:--", + "cfontsize": 0.85, + "color": "#1e40af" + } + } + ] + }, + { + "widgettype": "VBox", + "options": { + "css": "filler", + "width": "100%", + "height": "100%", + "padding": "0 24px 0 24px", + "gap": "0" + }, + "subwidgets": [ + { + "widgettype": "VScrollPanel", + "id": "chat_scroll", + "options": { + "css": "filler", + "width": "100%", + "height": "100%", + "bgcolor": "#f8fafc", + "border": "1px solid #e2e8f0", + "borderBottom": "none", + "borderRadius": "8px 8px 0 0", + "padding": "16px" + }, + "subwidgets": [ + { + "widgettype": "VBox", + "options": { + "alignItems": "center", + "padding": "40px 0", + "gap": "12px" + }, + "subwidgets": [ + { + "widgettype": "Text", + "options": { + "text": "选择一个迭代后,在下方输入你的需求。", + "cfontsize": 1, + "color": "#64748b" + } + }, + { + "widgettype": "Text", + "options": { + "text": "Agent 将自动分析需求、生成设计、驱动产线执行。", + "cfontsize": 0.85, + "color": "#94a3b8" + } + } + ] + } + ] + }, + { + "widgettype": "TextFiles", + "id": "chat_input", + "options": { + "bgcolor": "#fff", + "border": "1px solid #e2e8f0", + "borderTop": "none", + "borderRadius": "0 0 8px 8px", + "padding": "10px 14px 10px 14px" + }, + "binds": [ + { + "wid": "self", + "event": "inputed", + "actiontype": "script", + "target": "self", + "script": "var p=params.prompt;var files=params.add_files||[];var iid='';try{var iter=bricks.getWidgetById('current_iteration_id',bricks.app);if(iter)iid=iter.options.value||'';}catch(e){}var mid='';try{var el=document.querySelector('#model_selector select')||document.querySelector('select');if(el)mid=el.value||'';}catch(e){}var chat=bricks.getWidgetById('chat_scroll',bricks.app);var at=null;if(chat){var ub=new bricks.HBox({width:'100%'});var um=new bricks.VBox({width:'85%',alignSelf:'flex-end',bgcolor:'#dbeafe',borderRadius:'12px',padding:'12px 16px',marginBottom:'10px',gap:'4px'});um.add_widget(new bricks.Text({text:'\\u4f60',cfontsize:0.75,color:'#2563eb',fontWeight:'bold'}));um.add_widget(new bricks.Text({text:p,cfontsize:0.95,color:'#1e293b',whiteSpace:'pre-wrap'}));ub.add_widget(new bricks.VBox({css:'filler'}));ub.add_widget(um);ub.add_widget(new bricks.Svg({rate:2,url:bricks_resource('imgs/chat-user.svg')}));chat.add_widget(ub);var ab=new bricks.HBox({width:'100%'});var am=new bricks.VBox({width:'85%',alignSelf:'flex-start',bgcolor:'#e8f0fe',borderRadius:'12px',padding:'12px 16px',marginBottom:'10px',gap:'4px'});am.add_widget(new bricks.Text({text:'Agent',cfontsize:0.75,color:'#3b82f6',fontWeight:'bold'}));at=new bricks.Text({text:'\\u6b63\\u5728\\u5206\\u6790\\u9700\\u6c42...',cfontsize:0.85,color:'#64748b'});am.add_widget(at);ab.add_widget(new bricks.Svg({rate:2,url:bricks_resource('imgs/llm.svg')}));ab.add_widget(am);ab.add_widget(new bricks.VBox({css:'filler'}));chat.add_widget(ab);}var body='message_text='+encodeURIComponent(p)+'&iteration_id='+encodeURIComponent(iid)+'&model_id='+encodeURIComponent(mid)+'&action=send_message&file_paths='+encodeURIComponent(JSON.stringify(files.map(function(f){return f.name||f})));fetch('/pipeline-sdlc/api/cockpit_chat.dspy',{method:'POST',headers:{'Content-Type':'application/x-www-form-urlencoded'},body:body}).then(function(r){return r.json()}).then(function(r){if(r.success){if(at)at.set_text(r.agent_reply||'\\u5df2\\u5904\\u7406');var s=bricks.getWidgetById('stats_row',bricks.app);if(s)s.render({});}else{if(at)at.set_text('\\u9519\\u8bef: '+(r.error||'\\u672a\\u77e5\\u9519\\u8bef'));}});" + } + ] + } + ] + } + ] +} \ No newline at end of file