feat(ownership): 三张跨产线表归属迁入——sd_projects/sd_project_role_models/pipeline_deliverables models+CRUD json+15个api dspy+手写角色模型页自pipeline-sdlc迁入(第2轮迁归属)
- models: 3张表JSON迁入(sd_projects全产线项目容器/pipeline_deliverables被bidding+service+core写681行实证/sd_project_role_models被pipeline-service三处消费)——分层倒置修复:core的agent_config.py裸查sd_projects/pipeline_deliverables,低层查高层表
- json: sd_project_list.json/pipeline_deliverables_list.json迁入,subtables迭代/仓库页改绝对路径/pipeline-sdlc/**(跨模块相对路径会解析到core不存在的目录)
- api: 15个CRUD页面依赖的dspy迁入(get_project_options等,entire_url('../api/')相对解析跟页面走);get_module_dbname('pipeline_sdlc')→pipeline_core(app层一律返pipeline,行为不变仅语义归位)
- init/data.json: 4组字典随表迁(sd_project_status/sd_project_type/deliverable_type/review_status)——normalize幂等键{parentid}_{k}不变,import_init重跑无副作用
- .gitignore: 补wwwroot/sd_projects/+wwwroot/pipeline_deliverables/(xls2ui生成目录,build.sh第7步清单已含pipeline_core,重生成不脏工作树)
This commit is contained in:
parent
b37c2628f2
commit
4b2fd4cd7a
2
.gitignore
vendored
2
.gitignore
vendored
@ -12,3 +12,5 @@ wwwroot/llm/
|
|||||||
wwwroot/pipeline_steps/
|
wwwroot/pipeline_steps/
|
||||||
wwwroot/pipeline_versions/
|
wwwroot/pipeline_versions/
|
||||||
wwwroot/pipelines/
|
wwwroot/pipelines/
|
||||||
|
wwwroot/sd_projects/
|
||||||
|
wwwroot/pipeline_deliverables/
|
||||||
|
|||||||
146
init/data.json
146
init/data.json
@ -4,21 +4,149 @@
|
|||||||
"parentid": "pipeline_type",
|
"parentid": "pipeline_type",
|
||||||
"parentname": "产线类型",
|
"parentname": "产线类型",
|
||||||
"items": [
|
"items": [
|
||||||
{"k": "text", "v": "文本"},
|
{
|
||||||
{"k": "audio", "v": "音频"},
|
"k": "text",
|
||||||
{"k": "video", "v": "视频"},
|
"v": "文本"
|
||||||
{"k": "image", "v": "图片"},
|
},
|
||||||
{"k": "multimodal", "v": "多模态"}
|
{
|
||||||
|
"k": "audio",
|
||||||
|
"v": "音频"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"k": "video",
|
||||||
|
"v": "视频"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"k": "image",
|
||||||
|
"v": "图片"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"k": "multimodal",
|
||||||
|
"v": "多模态"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"parentid": "pipeline_status",
|
"parentid": "pipeline_status",
|
||||||
"parentname": "产线状态",
|
"parentname": "产线状态",
|
||||||
"items": [
|
"items": [
|
||||||
{"k": "draft", "v": "草稿"},
|
{
|
||||||
{"k": "published", "v": "已发布"},
|
"k": "draft",
|
||||||
{"k": "archived", "v": "已归档"}
|
"v": "草稿"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"k": "published",
|
||||||
|
"v": "已发布"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"k": "archived",
|
||||||
|
"v": "已归档"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parentid": "sd_project_status",
|
||||||
|
"parentname": "项目状态",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"k": "draft",
|
||||||
|
"v": "草稿"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"k": "active",
|
||||||
|
"v": "进行中"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"k": "paused",
|
||||||
|
"v": "已暂停"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"k": "completed",
|
||||||
|
"v": "已完成"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"k": "archived",
|
||||||
|
"v": "已归档"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parentid": "sd_project_type",
|
||||||
|
"parentname": "项目类型",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"k": "general",
|
||||||
|
"v": "通用项目"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"k": "bidding",
|
||||||
|
"v": "投标项目"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"k": "web_app",
|
||||||
|
"v": "Web应用"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"k": "api_service",
|
||||||
|
"v": "API服务"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"k": "module",
|
||||||
|
"v": "Sage模块"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"k": "mobile_app",
|
||||||
|
"v": "移动应用"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"k": "cli_tool",
|
||||||
|
"v": "CLI工具"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"k": "data_pipeline",
|
||||||
|
"v": "数据管道"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parentid": "deliverable_type",
|
||||||
|
"parentname": "交付件类型",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"k": "code",
|
||||||
|
"v": "代码"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"k": "doc",
|
||||||
|
"v": "文档"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"k": "config",
|
||||||
|
"v": "配置"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"k": "test-report",
|
||||||
|
"v": "测试报告"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parentid": "review_status",
|
||||||
|
"parentname": "评审状态",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"k": "pending",
|
||||||
|
"v": "待评审"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"k": "approved",
|
||||||
|
"v": "通过"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"k": "rejected",
|
||||||
|
"v": "驳回"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
67
json/pipeline_deliverables_list.json
Normal file
67
json/pipeline_deliverables_list.json
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
{
|
||||||
|
"tblname": "pipeline_deliverables",
|
||||||
|
"title": "交付件管理",
|
||||||
|
"params": {
|
||||||
|
"sortby": [
|
||||||
|
"created_at desc"
|
||||||
|
],
|
||||||
|
"confidential_fields": [],
|
||||||
|
"browserfields": {
|
||||||
|
"exclouded": [
|
||||||
|
"content",
|
||||||
|
"file_path",
|
||||||
|
"target_path"
|
||||||
|
],
|
||||||
|
"alters": {
|
||||||
|
"project_id": {
|
||||||
|
"uitype": "code",
|
||||||
|
"dataurl": "{{entire_url('../api/get_project_options.dspy')}}",
|
||||||
|
"valueField": "value",
|
||||||
|
"textField": "text"
|
||||||
|
},
|
||||||
|
"deliverable_type": {
|
||||||
|
"uitype": "code",
|
||||||
|
"dataurl": "{{entire_url('../api/get_search_deliverable_type.dspy')}}",
|
||||||
|
"valueField": "value",
|
||||||
|
"textField": "text"
|
||||||
|
},
|
||||||
|
"review_status": {
|
||||||
|
"uitype": "code",
|
||||||
|
"dataurl": "{{entire_url('../api/get_search_review_status.dspy')}}",
|
||||||
|
"valueField": "value",
|
||||||
|
"textField": "text"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"editexclouded": [
|
||||||
|
"id",
|
||||||
|
"created_at",
|
||||||
|
"reviewed_by",
|
||||||
|
"created_by"
|
||||||
|
],
|
||||||
|
"editable": {
|
||||||
|
"new_data_url": "{{entire_url('../api/sd_deliverable_create.dspy')}}",
|
||||||
|
"update_data_url": "{{entire_url('../api/sd_deliverable_update.dspy')}}",
|
||||||
|
"delete_data_url": "{{entire_url('../api/sd_deliverable_delete.dspy')}}"
|
||||||
|
},
|
||||||
|
"data_filter": {
|
||||||
|
"AND": [
|
||||||
|
{
|
||||||
|
"field": "title",
|
||||||
|
"op": "LIKE",
|
||||||
|
"var": "title_input"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"field": "review_status",
|
||||||
|
"op": "=",
|
||||||
|
"var": "status_input"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"field": "deliverable_type",
|
||||||
|
"op": "=",
|
||||||
|
"var": "type_input"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
80
json/sd_project_list.json
Normal file
80
json/sd_project_list.json
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
{
|
||||||
|
"tblname": "sd_projects",
|
||||||
|
"title": "项目管理",
|
||||||
|
"params": {
|
||||||
|
"sortby": [
|
||||||
|
"created_at desc"
|
||||||
|
],
|
||||||
|
"logined_userorgid": "org_id",
|
||||||
|
"confidential_fields": [],
|
||||||
|
"browserfields": {
|
||||||
|
"exclouded": [
|
||||||
|
"tech_stack"
|
||||||
|
],
|
||||||
|
"alters": {
|
||||||
|
"status": {
|
||||||
|
"uitype": "code",
|
||||||
|
"dataurl": "{{entire_url('../api/get_search_status.dspy')}}",
|
||||||
|
"valueField": "value",
|
||||||
|
"textField": "text"
|
||||||
|
},
|
||||||
|
"project_type": {
|
||||||
|
"uitype": "code",
|
||||||
|
"dataurl": "{{entire_url('../api/get_search_project_type.dspy')}}",
|
||||||
|
"valueField": "value",
|
||||||
|
"textField": "text"
|
||||||
|
},
|
||||||
|
"pipeline_id": {
|
||||||
|
"uitype": "code",
|
||||||
|
"dataurl": "{{entire_url('../api/get_pipeline_options.dspy')}}",
|
||||||
|
"valueField": "value",
|
||||||
|
"textField": "text"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"editexclouded": [
|
||||||
|
"id",
|
||||||
|
"created_at",
|
||||||
|
"updated_at",
|
||||||
|
"org_id"
|
||||||
|
],
|
||||||
|
"editable": {
|
||||||
|
"new_data_url": "{{entire_url('../api/sd_project_create.dspy')}}",
|
||||||
|
"update_data_url": "{{entire_url('../api/sd_project_update.dspy')}}",
|
||||||
|
"delete_data_url": "{{entire_url('../api/sd_project_delete.dspy')}}"
|
||||||
|
},
|
||||||
|
"data_filter": {
|
||||||
|
"AND": [
|
||||||
|
{
|
||||||
|
"field": "name",
|
||||||
|
"op": "LIKE",
|
||||||
|
"var": "name_input"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"field": "status",
|
||||||
|
"op": "=",
|
||||||
|
"var": "status_input"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"field": "project_type",
|
||||||
|
"op": "=",
|
||||||
|
"var": "type_input"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"subtables": [
|
||||||
|
{
|
||||||
|
"field": "project_id",
|
||||||
|
"title": "迭代列表",
|
||||||
|
"url": "{{entire_url('/pipeline-sdlc/sd_iterations/index.ui?project_id=${id}')}}",
|
||||||
|
"subtable": "sd_iterations"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"field": "project_id",
|
||||||
|
"title": "代码仓库",
|
||||||
|
"url": "{{entire_url('/pipeline-sdlc/sd_project_repos/index.ui?project_id=${id}')}}",
|
||||||
|
"subtable": "sd_project_repos"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
36
models/pipeline_deliverables.json
Normal file
36
models/pipeline_deliverables.json
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
{
|
||||||
|
"summary": [
|
||||||
|
{
|
||||||
|
"name": "pipeline_deliverables",
|
||||||
|
"title": "任务交付件",
|
||||||
|
"primary": ["id"],
|
||||||
|
"catelog": "entity"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"fields": [
|
||||||
|
{"name": "id", "title": "主键ID", "type": "str", "length": 32, "nullable": "no"},
|
||||||
|
{"name": "project_id", "title": "项目ID", "type": "str", "length": 32, "nullable": "no"},
|
||||||
|
{"name": "task_id", "title": "任务ID", "type": "str", "length": 32},
|
||||||
|
{"name": "title", "title": "交付件标题", "type": "str", "length": 200, "nullable": "no"},
|
||||||
|
{"name": "deliverable_type", "title": "交付件类型", "type": "str", "length": 32, "nullable": "no", "default": "'code'"},
|
||||||
|
{"name": "repo_name", "title": "目标仓库别名", "type": "str", "length": 100},
|
||||||
|
{"name": "target_path", "title": "仓库内相对路径", "type": "str", "length": 500},
|
||||||
|
{"name": "file_path", "title": "本地存储路径", "type": "str", "length": 500},
|
||||||
|
{"name": "content", "title": "交付件内容", "type": "longtext"},
|
||||||
|
{"name": "quality_score", "title": "质量评分(0-100)", "type": "int", "nullable": "no", "default": "80"},
|
||||||
|
{"name": "review_status", "title": "评审状态", "type": "str", "length": 20, "nullable": "no", "default": "'pending'"},
|
||||||
|
{"name": "review_comment", "title": "评审意见", "type": "text"},
|
||||||
|
{"name": "reviewed_by", "title": "评审人", "type": "str", "length": 32},
|
||||||
|
{"name": "created_by", "title": "创建人", "type": "str", "length": 32, "nullable": "no"},
|
||||||
|
{"name": "created_at", "title": "创建时间", "type": "timestamp", "nullable": "no"}
|
||||||
|
],
|
||||||
|
"indexes": [
|
||||||
|
{"name": "idx_pd_project", "idxtype": "index", "idxfields": ["project_id"]},
|
||||||
|
{"name": "idx_pd_task", "idxtype": "index", "idxfields": ["task_id"]},
|
||||||
|
{"name": "idx_pd_review", "idxtype": "index", "idxfields": ["review_status"]}
|
||||||
|
],
|
||||||
|
"codes": [
|
||||||
|
{"field": "deliverable_type", "table": "appcodes_kv", "valuefield": "k", "textfield": "v", "cond": "parentid='deliverable_type'"},
|
||||||
|
{"field": "review_status", "table": "appcodes_kv", "valuefield": "k", "textfield": "v", "cond": "parentid='review_status'"}
|
||||||
|
]
|
||||||
|
}
|
||||||
25
models/sd_project_role_models.json
Normal file
25
models/sd_project_role_models.json
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"summary": [
|
||||||
|
{
|
||||||
|
"name": "sd_project_role_models",
|
||||||
|
"title": "项目角色模型配置",
|
||||||
|
"primary": ["id"],
|
||||||
|
"catelog": "entity"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"fields": [
|
||||||
|
{"name": "id", "title": "主键ID", "type": "str", "length": 32, "nullable": "no"},
|
||||||
|
{"name": "project_id", "title": "项目ID", "type": "str", "length": 32, "nullable": "no"},
|
||||||
|
{"name": "role", "title": "角色名", "type": "str", "length": 64, "nullable": "no"},
|
||||||
|
{"name": "model_name", "title": "模型名(llm.name,空=用项目缺省模型)", "type": "str", "length": 128},
|
||||||
|
{"name": "created_at", "title": "创建时间", "type": "timestamp", "nullable": "no"},
|
||||||
|
{"name": "updated_at", "title": "更新时间", "type": "timestamp"}
|
||||||
|
],
|
||||||
|
"indexes": [
|
||||||
|
{"name": "uk_sd_project_role_models_pr", "idxtype": "unique", "idxfields": ["project_id", "role"]}
|
||||||
|
],
|
||||||
|
"codes": [
|
||||||
|
{"field": "role", "table": "appcodes_kv", "valuefield": "k", "textfield": "v", "cond": "parentid='sd_role'"},
|
||||||
|
{"field": "model_name", "table": "llm", "valuefield": "name", "textfield": "name", "cond": ""}
|
||||||
|
]
|
||||||
|
}
|
||||||
35
models/sd_projects.json
Normal file
35
models/sd_projects.json
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"summary": [
|
||||||
|
{
|
||||||
|
"name": "sd_projects",
|
||||||
|
"title": "SDLC项目表",
|
||||||
|
"primary": ["id"],
|
||||||
|
"catelog": "entity"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"fields": [
|
||||||
|
{"name": "id", "title": "主键ID", "type": "str", "length": 32, "nullable": "no"},
|
||||||
|
{"name": "name", "title": "项目名称", "type": "str", "length": 200, "nullable": "no"},
|
||||||
|
{"name": "description", "title": "项目描述", "type": "text"},
|
||||||
|
{"name": "project_type", "title": "项目类型", "type": "str", "length": 50, "nullable": "no", "default": "'general'"},
|
||||||
|
{"name": "tech_stack", "title": "技术栈配置(JSON)", "type": "text"},
|
||||||
|
{"name": "repo_url", "title": "主仓库地址", "type": "str", "length": 500},
|
||||||
|
{"name": "directory_name", "title": "项目目录名(创建时定死,工作空间解析只读此字段)", "type": "str", "length": 200},
|
||||||
|
{"name": "workspace_dir", "title": "项目工作目录", "type": "str", "length": 500},
|
||||||
|
{"name": "default_model", "title": "项目默认模型(llm_model.name,空=走治理链缺省)", "type": "str", "length": 128},
|
||||||
|
{"name": "pipeline_id", "title": "关联Pipeline定义ID(general=通用项目,不挂产线)", "type": "str", "length": 32, "default": "'general'"},
|
||||||
|
{"name": "status", "title": "项目状态", "type": "str", "length": 20, "nullable": "no", "default": "'draft'"},
|
||||||
|
{"name": "org_id", "title": "组织ID", "type": "str", "length": 32, "nullable": "no", "default": "'0'"},
|
||||||
|
{"name": "created_by", "title": "创建人", "type": "str", "length": 32},
|
||||||
|
{"name": "created_at", "title": "创建时间", "type": "timestamp", "nullable": "no"},
|
||||||
|
{"name": "updated_at", "title": "更新时间", "type": "timestamp"}
|
||||||
|
],
|
||||||
|
"indexes": [
|
||||||
|
{"name": "idx_sd_projects_status", "idxtype": "index", "idxfields": ["status"]},
|
||||||
|
{"name": "idx_sd_projects_org", "idxtype": "index", "idxfields": ["org_id"]}
|
||||||
|
],
|
||||||
|
"codes": [
|
||||||
|
{"field": "status", "table": "appcodes_kv", "valuefield": "k", "textfield": "v", "cond": "parentid='sd_project_status'"},
|
||||||
|
{"field": "project_type", "table": "appcodes_kv", "valuefield": "k", "textfield": "v", "cond": "parentid='sd_project_type'"}
|
||||||
|
]
|
||||||
|
}
|
||||||
16
wwwroot/api/get_model_options.dspy
Normal file
16
wwwroot/api/get_model_options.dspy
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# get_model_options.dspy — 角色模型配置下拉(value=模型注册名)
|
||||||
|
# 2026-09-04 收敛:实现统一在模型治理模块 pipeline_llm.selection.model_options,
|
||||||
|
# 本文件只作 URL 入口。保留历史格式:首项「缺省(用项目默认模型)」+ value/text 两列。
|
||||||
|
# capabilities='chat':角色模型也是会话/任务 agent 用的对话模型,只列 t2t/i2t/m2t
|
||||||
|
# (2026-09-06 用户定夺;防把 embedding 等非对话模型配给角色后推理链报能力不匹配)。
|
||||||
|
|
||||||
|
rows = [{'value': '', 'text': '缺省(用项目默认模型)'}]
|
||||||
|
try:
|
||||||
|
org_id = await get_userorgid()
|
||||||
|
if org_id:
|
||||||
|
opts = await llm_model_options(org_id, value_field='name', capabilities='chat')
|
||||||
|
rows += [{'value': r['value'], 'text': r['text']} for r in opts]
|
||||||
|
return json.dumps(rows, ensure_ascii=False)
|
||||||
|
except Exception as e:
|
||||||
|
debug(f'get_model_options error: {e}')
|
||||||
|
return json.dumps(rows, ensure_ascii=False)
|
||||||
10
wwwroot/api/get_pipeline_options.dspy
Normal file
10
wwwroot/api/get_pipeline_options.dspy
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import json
|
||||||
|
result = json.dumps([{'value': '', 'text': '请选择'}], ensure_ascii=False)
|
||||||
|
try:
|
||||||
|
async with get_sor_context(request._run_ns, 'pipeline') as sor:
|
||||||
|
rows = await sor.sqlExe("select id as value, name as text from pipelines order by name")
|
||||||
|
r = [{'value': '', 'text': '请选择'}] + list(rows)
|
||||||
|
return json.dumps(r, ensure_ascii=False)
|
||||||
|
except Exception as e:
|
||||||
|
debug(f'get_pipeline_options error: {e}')
|
||||||
|
return json.dumps(result, ensure_ascii=False)
|
||||||
9
wwwroot/api/get_project_options.dspy
Normal file
9
wwwroot/api/get_project_options.dspy
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
result = []
|
||||||
|
try:
|
||||||
|
async with get_sor_context(request._run_ns, 'pipeline') as sor:
|
||||||
|
rows = await sor.sqlExe("select id as project_id, name as project_id_text from sd_projects where pipeline_id='sdlc_general' order by name", {})
|
||||||
|
result = list(rows)
|
||||||
|
return json.dumps(result, ensure_ascii=False)
|
||||||
|
except Exception as e:
|
||||||
|
debug(f'dropdown error: {e}')
|
||||||
|
return json.dumps(result, ensure_ascii=False)
|
||||||
9
wwwroot/api/get_project_select_options.dspy
Normal file
9
wwwroot/api/get_project_select_options.dspy
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import json
|
||||||
|
try:
|
||||||
|
async with get_sor_context(request._run_ns, 'pipeline') as sor:
|
||||||
|
rows = await sor.sqlExe("select id as value, name as text from sd_projects order by created_at desc", {})
|
||||||
|
r = [{'value': '', 'text': '请选择'}] + list(rows)
|
||||||
|
return json.dumps(r, ensure_ascii=False)
|
||||||
|
except Exception as e:
|
||||||
|
debug(f'get_project_select_options error: {e}')
|
||||||
|
return json.dumps([{'value': '', 'text': '请选择'}], ensure_ascii=False)
|
||||||
12
wwwroot/api/get_role_options.dspy
Normal file
12
wwwroot/api/get_role_options.dspy
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import json
|
||||||
|
roles = [
|
||||||
|
{'value': 'agent.pm', 'text': 'PM 项目经理'},
|
||||||
|
{'value': 'agent.requirement', 'text': '需求分析师'},
|
||||||
|
{'value': 'agent.design', 'text': '系统设计师'},
|
||||||
|
{'value': 'agent.develop', 'text': '开发工程师'},
|
||||||
|
{'value': 'agent.deploy_test', 'text': '测试部署工程师'},
|
||||||
|
{'value': 'agent.test', 'text': '测试工程师'},
|
||||||
|
{'value': 'agent.deploy_prod', 'text': '生产部署工程师'},
|
||||||
|
{'value': 'agent.qc', 'text': 'QC 质量控制'},
|
||||||
|
]
|
||||||
|
return json.dumps(roles, ensure_ascii=False)
|
||||||
9
wwwroot/api/get_search_deliverable_type.dspy
Normal file
9
wwwroot/api/get_search_deliverable_type.dspy
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
result = [{'value': '', 'text': '全部'}]
|
||||||
|
try:
|
||||||
|
async with get_sor_context(request._run_ns, 'pipeline') as sor:
|
||||||
|
rows = await sor.sqlExe("select k as value, v as text from appcodes_kv where parentid=${parentid}$ order by v", {'parentid': 'deliverable_type'})
|
||||||
|
result = [{'value': '', 'text': '全部'}] + list(rows)
|
||||||
|
return json.dumps(result, ensure_ascii=False)
|
||||||
|
except Exception as e:
|
||||||
|
debug(f'search error: {e}')
|
||||||
|
return json.dumps(result, ensure_ascii=False)
|
||||||
9
wwwroot/api/get_search_project_type.dspy
Normal file
9
wwwroot/api/get_search_project_type.dspy
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
result = [{'value': '', 'text': '全部'}]
|
||||||
|
try:
|
||||||
|
async with get_sor_context(request._run_ns, 'pipeline') as sor:
|
||||||
|
rows = await sor.sqlExe("select k as value, v as text from appcodes_kv where parentid=${parentid}$ order by v", {'parentid': 'sd_project_type'})
|
||||||
|
result = [{'value': '', 'text': '全部'}] + list(rows)
|
||||||
|
return json.dumps(result, ensure_ascii=False)
|
||||||
|
except Exception as e:
|
||||||
|
debug(f'search error: {e}')
|
||||||
|
return json.dumps(result, ensure_ascii=False)
|
||||||
9
wwwroot/api/get_search_review_status.dspy
Normal file
9
wwwroot/api/get_search_review_status.dspy
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
result = [{'value': '', 'text': '全部'}]
|
||||||
|
try:
|
||||||
|
async with get_sor_context(request._run_ns, 'pipeline') as sor:
|
||||||
|
rows = await sor.sqlExe("select k as value, v as text from appcodes_kv where parentid=${parentid}$ order by v", {'parentid': 'review_status'})
|
||||||
|
result = [{'value': '', 'text': '全部'}] + list(rows)
|
||||||
|
return json.dumps(result, ensure_ascii=False)
|
||||||
|
except Exception as e:
|
||||||
|
debug(f'search error: {e}')
|
||||||
|
return json.dumps(result, ensure_ascii=False)
|
||||||
9
wwwroot/api/get_search_status.dspy
Normal file
9
wwwroot/api/get_search_status.dspy
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
result = [{'value': '', 'text': '全部'}]
|
||||||
|
try:
|
||||||
|
async with get_sor_context(request._run_ns, 'pipeline') as sor:
|
||||||
|
rows = await sor.sqlExe("select k as value, v as text from appcodes_kv where parentid=${parentid}$ order by v", {'parentid': 'sd_project_status'})
|
||||||
|
result = [{'value': '', 'text': '全部'}] + list(rows)
|
||||||
|
return json.dumps(result, ensure_ascii=False)
|
||||||
|
except Exception as e:
|
||||||
|
debug(f'search error: {e}')
|
||||||
|
return json.dumps(result, ensure_ascii=False)
|
||||||
26
wwwroot/api/sd_deliverable_create.dspy
Normal file
26
wwwroot/api/sd_deliverable_create.dspy
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
user_id = await get_user()
|
||||||
|
if not user_id:
|
||||||
|
return {"widgettype":"Error","options":{"title":"操作失败","message":'未登录',"cwidth":16,"cheight":9,"timeout":3}}
|
||||||
|
|
||||||
|
data = {
|
||||||
|
'id': getID(),
|
||||||
|
'project_id': params_kw.get('project_id', ''),
|
||||||
|
'task_id': params_kw.get('task_id', ''),
|
||||||
|
'title': params_kw.get('title', ''),
|
||||||
|
'deliverable_type': params_kw.get('deliverable_type', 'code'),
|
||||||
|
'repo_name': params_kw.get('repo_name', ''),
|
||||||
|
'target_path': params_kw.get('target_path', ''),
|
||||||
|
'file_path': params_kw.get('file_path', ''),
|
||||||
|
'content': params_kw.get('content', ''),
|
||||||
|
'quality_score': params_kw.get('quality_score', 80),
|
||||||
|
'review_status': params_kw.get('review_status', 'pending'),
|
||||||
|
'created_by': user_id,
|
||||||
|
'created_at': curDateString(),
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
async with get_sor_context(request._run_ns, 'pipeline') as sor:
|
||||||
|
await sor.C('pipeline_deliverables', data)
|
||||||
|
return {"widgettype":"Message","options":{"title":"创建成功","message":"ok","cwidth":16,"cheight":9,"timeout":3,"user_data": data}}
|
||||||
|
except Exception as e:
|
||||||
|
return {"widgettype":"Error","options":{"title":"操作失败","message":str(e),"cwidth":16,"cheight":9,"timeout":3}}
|
||||||
14
wwwroot/api/sd_deliverable_delete.dspy
Normal file
14
wwwroot/api/sd_deliverable_delete.dspy
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
user_id = await get_user()
|
||||||
|
if not user_id:
|
||||||
|
return {"widgettype":"Error","options":{"title":"操作失败","message":'未登录',"cwidth":16,"cheight":9,"timeout":3}}
|
||||||
|
|
||||||
|
rec_id = params_kw.get('id', '')
|
||||||
|
if not rec_id:
|
||||||
|
return {"widgettype":"Error","options":{"title":"操作失败","message":'缺少id',"cwidth":16,"cheight":9,"timeout":3}}
|
||||||
|
|
||||||
|
try:
|
||||||
|
async with get_sor_context(request._run_ns, 'pipeline') as sor:
|
||||||
|
await sor.D('pipeline_deliverables', {'id': rec_id})
|
||||||
|
return {"widgettype":"Message","options":{"title":"操作成功","message":"ok","cwidth":16,"cheight":9,"timeout":3}}
|
||||||
|
except Exception as e:
|
||||||
|
return {"widgettype":"Error","options":{"title":"操作失败","message":str(e),"cwidth":16,"cheight":9,"timeout":3}}
|
||||||
19
wwwroot/api/sd_deliverable_update.dspy
Normal file
19
wwwroot/api/sd_deliverable_update.dspy
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
user_id = await get_user()
|
||||||
|
if not user_id:
|
||||||
|
return {"widgettype":"Error","options":{"title":"操作失败","message":'未登录',"cwidth":16,"cheight":9,"timeout":3}}
|
||||||
|
|
||||||
|
rec_id = params_kw.get('id', '')
|
||||||
|
if not rec_id:
|
||||||
|
return {"widgettype":"Error","options":{"title":"操作失败","message":'缺少id',"cwidth":16,"cheight":9,"timeout":3}}
|
||||||
|
|
||||||
|
data = {'id': rec_id}
|
||||||
|
for f in ['project_id', 'task_id', 'title', 'deliverable_type', 'repo_name', 'target_path', 'file_path', 'content', 'quality_score', 'review_status', 'review_comment']:
|
||||||
|
if f in params_kw:
|
||||||
|
data[f] = params_kw[f]
|
||||||
|
|
||||||
|
try:
|
||||||
|
async with get_sor_context(request._run_ns, 'pipeline') as sor:
|
||||||
|
await sor.U('pipeline_deliverables', data)
|
||||||
|
return {"widgettype":"Message","options":{"title":"操作成功","message":"ok","cwidth":16,"cheight":9,"timeout":3}}
|
||||||
|
except Exception as e:
|
||||||
|
return {"widgettype":"Error","options":{"title":"操作失败","message":str(e),"cwidth":16,"cheight":9,"timeout":3}}
|
||||||
25
wwwroot/api/sd_project_create.dspy
Normal file
25
wwwroot/api/sd_project_create.dspy
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
user_id = await get_user()
|
||||||
|
if not user_id:
|
||||||
|
return {"widgettype":"Error","options":{"title":"操作失败","message":'未登录',"cwidth":16,"cheight":9,"timeout":3}}
|
||||||
|
|
||||||
|
org_id = (await get_userorgid()) or '0'
|
||||||
|
data = {
|
||||||
|
'id': getID(),
|
||||||
|
'name': params_kw.get('name', ''),
|
||||||
|
'description': params_kw.get('description', ''),
|
||||||
|
'project_type': params_kw.get('project_type', ''),
|
||||||
|
'tech_stack': params_kw.get('tech_stack', ''),
|
||||||
|
'repo_url': params_kw.get('repo_url', ''),
|
||||||
|
'pipeline_id': params_kw.get('pipeline_id', '') or 'sdlc_general',
|
||||||
|
'status': params_kw.get('status', ''),
|
||||||
|
'org_id': org_id,
|
||||||
|
'created_by': user_id,
|
||||||
|
'created_at': curDateString(),
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
async with get_sor_context(request._run_ns, 'pipeline') as sor:
|
||||||
|
await sor.C('sd_projects', data)
|
||||||
|
return {"widgettype":"Message","options":{"title":"创建成功","message":"ok","cwidth":16,"cheight":9,"timeout":3},"user_data": data}
|
||||||
|
except Exception as e:
|
||||||
|
return {"widgettype":"Error","options":{"title":"操作失败","message":str(e),"cwidth":16,"cheight":9,"timeout":3}}
|
||||||
17
wwwroot/api/sd_project_delete.dspy
Normal file
17
wwwroot/api/sd_project_delete.dspy
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
user_id = await get_user()
|
||||||
|
if not user_id:
|
||||||
|
return {"widgettype":"Error","options":{"title":"操作失败","message":'未登录',"cwidth":16,"cheight":9,"timeout":3}}
|
||||||
|
|
||||||
|
rec_id = params_kw.get('id', '')
|
||||||
|
if not rec_id:
|
||||||
|
return {"widgettype":"Error","options":{"title":"操作失败","message":'缺少id',"cwidth":16,"cheight":9,"timeout":3}}
|
||||||
|
|
||||||
|
try:
|
||||||
|
async with get_sor_context(request._run_ns, 'pipeline') as sor:
|
||||||
|
ok, emsg = await check_project_owner(rec_id, user_id, sor)
|
||||||
|
if not ok:
|
||||||
|
return {"widgettype":"Error","options":{"title":"操作失败","message":emsg,"cwidth":16,"cheight":9,"timeout":3}}
|
||||||
|
await sor.D('sd_projects', {'id': rec_id})
|
||||||
|
return {"widgettype":"Message","options":{"title":"操作成功","message":"ok","cwidth":16,"cheight":9,"timeout":3}}
|
||||||
|
except Exception as e:
|
||||||
|
return {"widgettype":"Error","options":{"title":"操作失败","message":str(e),"cwidth":16,"cheight":9,"timeout":3}}
|
||||||
33
wwwroot/api/sd_project_update.dspy
Normal file
33
wwwroot/api/sd_project_update.dspy
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
user_id = await get_user()
|
||||||
|
if not user_id:
|
||||||
|
return {"widgettype":"Error","options":{"title":"操作失败","message":'未登录',"cwidth":16,"cheight":9,"timeout":3}}
|
||||||
|
|
||||||
|
rec_id = params_kw.get('id', '')
|
||||||
|
if not rec_id:
|
||||||
|
return {"widgettype":"Error","options":{"title":"操作失败","message":'缺少id',"cwidth":16,"cheight":9,"timeout":3}}
|
||||||
|
|
||||||
|
data = {'id': rec_id, 'updated_at': curDateString()}
|
||||||
|
if 'name' in params_kw:
|
||||||
|
data['name'] = params_kw['name']
|
||||||
|
if 'description' in params_kw:
|
||||||
|
data['description'] = params_kw['description']
|
||||||
|
if 'project_type' in params_kw:
|
||||||
|
data['project_type'] = params_kw['project_type']
|
||||||
|
if 'tech_stack' in params_kw:
|
||||||
|
data['tech_stack'] = params_kw['tech_stack']
|
||||||
|
if 'repo_url' in params_kw:
|
||||||
|
data['repo_url'] = params_kw['repo_url']
|
||||||
|
if 'pipeline_id' in params_kw:
|
||||||
|
data['pipeline_id'] = params_kw['pipeline_id']
|
||||||
|
if 'status' in params_kw:
|
||||||
|
data['status'] = params_kw['status']
|
||||||
|
|
||||||
|
try:
|
||||||
|
async with get_sor_context(request._run_ns, 'pipeline') as sor:
|
||||||
|
ok, emsg = await check_project_owner(rec_id, user_id, sor)
|
||||||
|
if not ok:
|
||||||
|
return {"widgettype":"Error","options":{"title":"操作失败","message":emsg,"cwidth":16,"cheight":9,"timeout":3}}
|
||||||
|
await sor.U('sd_projects', data)
|
||||||
|
return {"widgettype":"Message","options":{"title":"操作成功","message":"ok","cwidth":16,"cheight":9,"timeout":3}}
|
||||||
|
except Exception as e:
|
||||||
|
return {"widgettype":"Error","options":{"title":"操作失败","message":str(e),"cwidth":16,"cheight":9,"timeout":3}}
|
||||||
@ -0,0 +1,69 @@
|
|||||||
|
|
||||||
|
ns = params_kw.copy()
|
||||||
|
for k,v in ns.items():
|
||||||
|
if v == 'NaN' or v == 'null' or v == '':
|
||||||
|
ns[k] = None
|
||||||
|
id = params_kw.id
|
||||||
|
if not id or len(id) > 32:
|
||||||
|
id = uuid()
|
||||||
|
ns['id'] = id
|
||||||
|
|
||||||
|
# 会话当前项目强制(auto):project_id 用当前项目,忽略前端传值
|
||||||
|
_uid = await get_user()
|
||||||
|
if not _uid:
|
||||||
|
_uid = 'user-01'
|
||||||
|
_dbname = get_module_dbname('pipeline_core')
|
||||||
|
async with DBPools().sqlorContext(_dbname) as _sor:
|
||||||
|
_prec = await _sor.sqlExe("SELECT current_project_id FROM pipeline_agent_settings WHERE user_id=${u}$", {"u": _uid})
|
||||||
|
await _sor.sqlExe("COMMIT", {})
|
||||||
|
_cur_pid = getattr(_prec[0], 'current_project_id', '') if _prec else ''
|
||||||
|
if not _cur_pid:
|
||||||
|
return {"widgettype":"Error","options":{"title":"错误","timeout":3,"cwidth":20,"cheight":9,"message":"请先在会话中切换项目"}}
|
||||||
|
ns['project_id'] = _cur_pid
|
||||||
|
|
||||||
|
if not ns.get('role'):
|
||||||
|
return {"widgettype":"Error","options":{"title":"Error","timeout":3,"cwidth":16,"cheight":9,"message":"需要 role"}}
|
||||||
|
|
||||||
|
userorgid = await get_userorgid()
|
||||||
|
if not userorgid:
|
||||||
|
return {
|
||||||
|
"widgettype":"Error",
|
||||||
|
"options":{
|
||||||
|
"title":"Authorization Error",
|
||||||
|
"timeout":3,
|
||||||
|
"cwidth":16,
|
||||||
|
"cheight":9,
|
||||||
|
"message":"Please login"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
db = DBPools()
|
||||||
|
dbname = get_module_dbname('pipeline_core')
|
||||||
|
async with db.sqlorContext(dbname) as sor:
|
||||||
|
# 已存在则更新(upsert by project_id+role)
|
||||||
|
r = await sor.sqlExe("select id from sd_project_role_models where project_id=${pid}$ and role=${role}$", {"pid": ns['project_id'], "role": ns['role']})
|
||||||
|
if r:
|
||||||
|
await sor.sqlExe("update sd_project_role_models set model_name=${m}$ where id=${id}$", {"m": ns.get('model_name'), "id": r[0].id})
|
||||||
|
else:
|
||||||
|
await sor.C('sd_project_role_models', ns.copy())
|
||||||
|
return {
|
||||||
|
"widgettype":"Message",
|
||||||
|
"options":{
|
||||||
|
"cwidth":16,
|
||||||
|
"cheight":9,
|
||||||
|
"title":"Add Success",
|
||||||
|
"timeout":3,
|
||||||
|
"message":"ok"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
"widgettype":"Error",
|
||||||
|
"options":{
|
||||||
|
"title":"Add Error",
|
||||||
|
"cwidth":16,
|
||||||
|
"cheight":9,
|
||||||
|
"timeout":3,
|
||||||
|
"message":"failed"
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,44 @@
|
|||||||
|
|
||||||
|
ns = params_kw.copy()
|
||||||
|
id = params_kw.id
|
||||||
|
if not id:
|
||||||
|
return {"widgettype":"Error","options":{"title":"Error","timeout":3,"cwidth":16,"cheight":9,"message":"需要 id"}}
|
||||||
|
|
||||||
|
userorgid = await get_userorgid()
|
||||||
|
if not userorgid:
|
||||||
|
return {
|
||||||
|
"widgettype":"Error",
|
||||||
|
"options":{
|
||||||
|
"title":"Authorization Error",
|
||||||
|
"timeout":3,
|
||||||
|
"cwidth":16,
|
||||||
|
"cheight":9,
|
||||||
|
"message":"Please login"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
db = DBPools()
|
||||||
|
dbname = get_module_dbname('pipeline_core')
|
||||||
|
async with db.sqlorContext(dbname) as sor:
|
||||||
|
await sor.D('sd_project_role_models', {'id': id})
|
||||||
|
return {
|
||||||
|
"widgettype":"Message",
|
||||||
|
"options":{
|
||||||
|
"cwidth":16,
|
||||||
|
"cheight":9,
|
||||||
|
"title":"Delete Success",
|
||||||
|
"timeout":3,
|
||||||
|
"message":"ok"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
"widgettype":"Error",
|
||||||
|
"options":{
|
||||||
|
"title":"Delete Error",
|
||||||
|
"cwidth":16,
|
||||||
|
"cheight":9,
|
||||||
|
"timeout":3,
|
||||||
|
"message":"failed"
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,87 @@
|
|||||||
|
|
||||||
|
ns = params_kw.copy()
|
||||||
|
|
||||||
|
# 会话当前项目强制过滤(auto):读 current_project_id,无项目报错
|
||||||
|
_uid = await get_user()
|
||||||
|
if not _uid:
|
||||||
|
_uid = 'user-01'
|
||||||
|
_cur_pid = ''
|
||||||
|
_dbname = get_module_dbname('pipeline_core')
|
||||||
|
async with DBPools().sqlorContext(_dbname) as _sor:
|
||||||
|
_prec = await _sor.sqlExe(
|
||||||
|
"SELECT current_project_id FROM pipeline_agent_settings WHERE user_id=${u}$",
|
||||||
|
{"u": _uid})
|
||||||
|
await _sor.sqlExe("COMMIT", {})
|
||||||
|
_cur_pid = getattr(_prec[0], 'current_project_id', '') if _prec else ''
|
||||||
|
if not _cur_pid:
|
||||||
|
return {"widgettype":"Error","options":{"title":"错误","timeout":3,"cwidth":20,"cheight":9,"message":"请先在会话中切换项目"}}
|
||||||
|
ns['_cur_pid'] = _cur_pid
|
||||||
|
|
||||||
|
userorgid = await get_userorgid()
|
||||||
|
if not userorgid:
|
||||||
|
return {
|
||||||
|
"widgettype":"Error",
|
||||||
|
"options":{
|
||||||
|
"title":"Authorization Error",
|
||||||
|
"timeout":3,
|
||||||
|
"cwidth":16,
|
||||||
|
"cheight":9,
|
||||||
|
"message":"Please login"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
debug(f'get_sd_project_role_models.dspy:{ns=}')
|
||||||
|
if not ns.get('page'):
|
||||||
|
ns['page'] = 1
|
||||||
|
if not ns.get('sort'):
|
||||||
|
ns['sort'] = ["role asc"]
|
||||||
|
|
||||||
|
sql = '''select a.*, b.name as project_name,
|
||||||
|
case a.role
|
||||||
|
when 'agent.pm' then 'PM 项目经理'
|
||||||
|
when 'agent.requirement' then '需求分析师'
|
||||||
|
when 'agent.design' then '系统设计师'
|
||||||
|
when 'agent.develop' then '开发工程师'
|
||||||
|
when 'agent.deploy_test' then '测试部署工程师'
|
||||||
|
when 'agent.test' then '测试工程师'
|
||||||
|
when 'agent.deploy_prod' then '生产部署工程师'
|
||||||
|
when 'agent.qc' then 'QC 质量控制'
|
||||||
|
else a.role end as role_text
|
||||||
|
from (select * from sd_project_role_models where project_id = ${_cur_pid}$ [[filterstr]]) a
|
||||||
|
left join sd_projects b on a.project_id = b.id'''
|
||||||
|
|
||||||
|
filterjson = params_kw.get('data_filter')
|
||||||
|
if filterjson and isinstance(filterjson, str):
|
||||||
|
try:
|
||||||
|
filterjson = json.loads(filterjson)
|
||||||
|
except (json.JSONDecodeError, TypeError):
|
||||||
|
filterjson = None
|
||||||
|
|
||||||
|
if filterjson:
|
||||||
|
filterdic = ns.copy()
|
||||||
|
filterdic['filterstr'] = ''
|
||||||
|
dbf = DBFilter(filterjson)
|
||||||
|
conds = dbf.gen(ns)
|
||||||
|
if conds:
|
||||||
|
ns.update(dbf.consts)
|
||||||
|
conds = f' and {conds}'
|
||||||
|
filterdic['filterstr'] = conds
|
||||||
|
ac = ArgsConvert('[[', ']]')
|
||||||
|
vars = ac.findAllVariables(sql)
|
||||||
|
NameSpace = {v:'${' + v + '}$' for v in vars if v != 'filterstr'}
|
||||||
|
filterdic.update(NameSpace)
|
||||||
|
sql = ac.convert(sql, filterdic)
|
||||||
|
else:
|
||||||
|
ac = ArgsConvert('[[', ']]')
|
||||||
|
sql = ac.convert(sql, {'filterstr': ''})
|
||||||
|
|
||||||
|
debug(f'{sql=}')
|
||||||
|
db = DBPools()
|
||||||
|
dbname = get_module_dbname('pipeline_core')
|
||||||
|
async with db.sqlorContext(dbname) as sor:
|
||||||
|
r = await sor.sqlPaging(sql, ns)
|
||||||
|
return r
|
||||||
|
return {
|
||||||
|
"total":0,
|
||||||
|
"rows":[]
|
||||||
|
}
|
||||||
66
wwwroot/sd_project_role_models/index.ui
Normal file
66
wwwroot/sd_project_role_models/index.ui
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
|
||||||
|
{
|
||||||
|
"widgettype":"VBox",
|
||||||
|
"options":{"cheight":40,"width":"100%"},
|
||||||
|
"subwidgets":[{
|
||||||
|
"id":"sd_project_role_models_tbl",
|
||||||
|
"widgettype":"Tabular",
|
||||||
|
"options":{
|
||||||
|
"width":"100%",
|
||||||
|
"height":"100%",
|
||||||
|
"title":"项目角色模型配置",
|
||||||
|
"css":"card",
|
||||||
|
"editable":{
|
||||||
|
"new_data_url":"{{entire_url('add_sd_project_role_models.dspy')}}",
|
||||||
|
"delete_data_url":"{{entire_url('delete_sd_project_role_models.dspy')}}",
|
||||||
|
"update_data_url":"{{entire_url('update_sd_project_role_models.dspy')}}"
|
||||||
|
},
|
||||||
|
"data_url":"{{entire_url('./get_sd_project_role_models.dspy')}}",
|
||||||
|
"data_method":"GET",
|
||||||
|
"data_params":{{json.dumps(params_kw, indent=4, ensure_ascii=False)}},
|
||||||
|
"row_options":{
|
||||||
|
"browserfields":{
|
||||||
|
"alters":{
|
||||||
|
"project_id":{
|
||||||
|
"uitype":"code",
|
||||||
|
"dataurl":"{{entire_url('../api/get_project_select_options.dspy')}}",
|
||||||
|
"valueField":"value",
|
||||||
|
"textField":"text"
|
||||||
|
},
|
||||||
|
"role":{
|
||||||
|
"uitype":"code",
|
||||||
|
"dataurl":"{{entire_url('../api/get_role_options.dspy')}}",
|
||||||
|
"valueField":"value",
|
||||||
|
"textField":"text"
|
||||||
|
},
|
||||||
|
"model_name":{
|
||||||
|
"uitype":"code",
|
||||||
|
"dataurl":"{{entire_url('../api/get_model_options.dspy')}}",
|
||||||
|
"valueField":"value",
|
||||||
|
"textField":"text"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"editexclouded":["id","created_at","updated_at","project_name","role_text"],
|
||||||
|
"fields":[
|
||||||
|
{"name":"id","title":"主键ID","type":"str","length":32,"cwidth":18,"uitype":"str","datatype":"str","label":"主键ID"},
|
||||||
|
{"name":"project_name","title":"项目","type":"str","length":200,"cwidth":22,"uitype":"str","datatype":"str","label":"项目"},
|
||||||
|
{"name":"project_id","title":"项目ID","type":"str","length":32,"cwidth":0,"uitype":"code","valueField":"value","textField":"text","dataurl":"{{entire_url('../api/get_project_select_options.dspy')}}","label":"项目ID"},
|
||||||
|
{"name":"role_text","title":"角色","type":"str","length":64,"cwidth":20,"uitype":"str","datatype":"str","label":"角色"},
|
||||||
|
{"name":"role","title":"角色名","type":"str","length":64,"cwidth":0,"uitype":"code","valueField":"value","textField":"text","dataurl":"{{entire_url('../api/get_role_options.dspy')}}","label":"角色名"},
|
||||||
|
{"name":"model_name","title":"模型","type":"str","length":128,"cwidth":20,"uitype":"code","valueField":"value","textField":"text","dataurl":"{{entire_url('../api/get_model_options.dspy')}}","label":"模型(空=缺省)"},
|
||||||
|
{"name":"created_at","title":"创建时间","type":"timestamp","uitype":"str","datatype":"timestamp","label":"创建时间"},
|
||||||
|
{"name":"updated_at","title":"更新时间","type":"timestamp","uitype":"str","datatype":"timestamp","label":"更新时间"}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"data_filter":{
|
||||||
|
"AND":[
|
||||||
|
{"field":"role","op":"LIKE","var":"role_input"},
|
||||||
|
{"field":"project_id","op":"=","var":"project_id_input"}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"page_rows":100,
|
||||||
|
"cache_limit":5
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
@ -0,0 +1,60 @@
|
|||||||
|
|
||||||
|
ns = params_kw.copy()
|
||||||
|
for k,v in ns.items():
|
||||||
|
if v == 'NaN' or v == 'null' or v == '':
|
||||||
|
ns[k] = None
|
||||||
|
id = params_kw.id
|
||||||
|
if not id:
|
||||||
|
return {"widgettype":"Error","options":{"title":"Error","timeout":3,"cwidth":16,"cheight":9,"message":"需要 id"}}
|
||||||
|
|
||||||
|
# 会话当前项目强制(auto):project_id 用当前项目,忽略前端传值
|
||||||
|
_uid = await get_user()
|
||||||
|
if not _uid:
|
||||||
|
_uid = 'user-01'
|
||||||
|
_dbname = get_module_dbname('pipeline_core')
|
||||||
|
async with DBPools().sqlorContext(_dbname) as _sor:
|
||||||
|
_prec = await _sor.sqlExe("SELECT current_project_id FROM pipeline_agent_settings WHERE user_id=${u}$", {"u": _uid})
|
||||||
|
await _sor.sqlExe("COMMIT", {})
|
||||||
|
_cur_pid = getattr(_prec[0], 'current_project_id', '') if _prec else ''
|
||||||
|
if not _cur_pid:
|
||||||
|
return {"widgettype":"Error","options":{"title":"错误","timeout":3,"cwidth":20,"cheight":9,"message":"请先在会话中切换项目"}}
|
||||||
|
ns['project_id'] = _cur_pid
|
||||||
|
|
||||||
|
userorgid = await get_userorgid()
|
||||||
|
if not userorgid:
|
||||||
|
return {
|
||||||
|
"widgettype":"Error",
|
||||||
|
"options":{
|
||||||
|
"title":"Authorization Error",
|
||||||
|
"timeout":3,
|
||||||
|
"cwidth":16,
|
||||||
|
"cheight":9,
|
||||||
|
"message":"Please login"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
db = DBPools()
|
||||||
|
dbname = get_module_dbname('pipeline_core')
|
||||||
|
async with db.sqlorContext(dbname) as sor:
|
||||||
|
await sor.U('sd_project_role_models', ns.copy())
|
||||||
|
return {
|
||||||
|
"widgettype":"Message",
|
||||||
|
"options":{
|
||||||
|
"cwidth":16,
|
||||||
|
"cheight":9,
|
||||||
|
"title":"Update Success",
|
||||||
|
"timeout":3,
|
||||||
|
"message":"ok"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
"widgettype":"Error",
|
||||||
|
"options":{
|
||||||
|
"title":"Update Error",
|
||||||
|
"cwidth":16,
|
||||||
|
"cheight":9,
|
||||||
|
"timeout":3,
|
||||||
|
"message":"failed"
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user