[M1a] pbl_blueprint 蓝图核心表与CRUD契约: 11表models四段式+11个CRUD(tblname/params)+核心4表与子对象7表DDL+蓝图CRUD/树/fork+版本change_delta/diff/rollback+模板实例化与离线兜底+tenant_id强制打头+load_path RBAC 39路径+SKILL.md; 清理越权残留(顶层json/models、models.py、pycache)
This commit is contained in:
parent
3ebd234b2e
commit
ef0e156ce8
@ -1,31 +0,0 @@
|
||||
{
|
||||
"tblname": "pbl_blueprint",
|
||||
"params": {
|
||||
"logined_userorgid": "org_id",
|
||||
"new_data_url": "{{entire_url('/pbl_blueprint/api/pbl_blueprint_create.dspy')}}",
|
||||
"update_data_url": "{{entire_url('/pbl_blueprint/api/pbl_blueprint_update.dspy')}}",
|
||||
"delete_data_url": "{{entire_url('/pbl_blueprint/api/pbl_blueprint_delete.dspy')}}",
|
||||
"editable": {
|
||||
"new_data_url": "{{entire_url('/pbl_blueprint/api/pbl_blueprint_create.dspy')}}",
|
||||
"update_data_url": "{{entire_url('/pbl_blueprint/api/pbl_blueprint_update.dspy')}}",
|
||||
"delete_data_url": "{{entire_url('/pbl_blueprint/api/pbl_blueprint_delete.dspy')}}"
|
||||
},
|
||||
"browserfields": {
|
||||
"main": {
|
||||
"fields": ["blueprint_code", "title", "subject_area", "grade_level", "duration_hours", "quality_status", "version_no", "status", "created_at"],
|
||||
"title": "蓝图列表"
|
||||
}
|
||||
},
|
||||
"editexclouded": ["id", "tenant_id", "org_id", "created_by", "created_at", "updated_by", "updated_at", "quality_status", "validation_score", "version_no", "current_version_id"],
|
||||
"subtables": [
|
||||
{"name": "learning_goal", "label": "学习目标", "url": "{{entire_url('../pbl_blueprint_learning_goal')}}"},
|
||||
{"name": "role", "label": "PBL角色", "url": "{{entire_url('../pbl_blueprint_role')}}"},
|
||||
{"name": "mission", "label": "驱动问题", "url": "{{entire_url('../pbl_blueprint_mission')}}"},
|
||||
{"name": "task", "label": "任务", "url": "{{entire_url('../pbl_blueprint_task')}}"},
|
||||
{"name": "artifact_spec", "label": "产出物规格", "url": "{{entire_url('../pbl_blueprint_artifact_spec')}}"},
|
||||
{"name": "evidence_spec", "label": "证据规格", "url": "{{entire_url('../pbl_blueprint_evidence_spec')}}"},
|
||||
{"name": "reflection_spec", "label": "反思规格", "url": "{{entire_url('../pbl_blueprint_reflection_spec')}}"},
|
||||
{"name": "version", "label": "版本历史", "url": "{{entire_url('../pbl_blueprint_version')}}"}
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
{
|
||||
"tblname": "pbl_blueprint_artifact_spec",
|
||||
"params": {
|
||||
"logined_userorgid": "",
|
||||
"new_data_url": "{{entire_url('/pbl_blueprint/api/pbl_blueprint_subobject_save.dspy')}}?subobject=artifact_spec",
|
||||
"update_data_url": "{{entire_url('/pbl_blueprint/api/pbl_blueprint_subobject_save.dspy')}}?subobject=artifact_spec",
|
||||
"delete_data_url": "{{entire_url('/pbl_blueprint/api/pbl_blueprint_subobject_delete.dspy')}}?subobject=artifact_spec",
|
||||
"editable": {
|
||||
"new_data_url": "{{entire_url('/pbl_blueprint/api/pbl_blueprint_subobject_save.dspy')}}?subobject=artifact_spec",
|
||||
"update_data_url": "{{entire_url('/pbl_blueprint/api/pbl_blueprint_subobject_save.dspy')}}?subobject=artifact_spec",
|
||||
"delete_data_url": "{{entire_url('/pbl_blueprint/api/pbl_blueprint_subobject_delete.dspy')}}?subobject=artifact_spec"
|
||||
},
|
||||
"browserfields": {
|
||||
"main": {
|
||||
"fields": ["seq", "artifact_code", "name", "artifact_type", "format", "required"],
|
||||
"title": "产出物规格"
|
||||
}
|
||||
},
|
||||
"editexclouded": ["id", "tenant_id", "created_by", "created_at", "updated_by", "updated_at"]
|
||||
}
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
{
|
||||
"tblname": "pbl_blueprint_evidence_spec",
|
||||
"params": {
|
||||
"logined_userorgid": "",
|
||||
"new_data_url": "{{entire_url('/pbl_blueprint/api/pbl_blueprint_subobject_save.dspy')}}?subobject=evidence_spec",
|
||||
"update_data_url": "{{entire_url('/pbl_blueprint/api/pbl_blueprint_subobject_save.dspy')}}?subobject=evidence_spec",
|
||||
"delete_data_url": "{{entire_url('/pbl_blueprint/api/pbl_blueprint_subobject_delete.dspy')}}?subobject=evidence_spec",
|
||||
"editable": {
|
||||
"new_data_url": "{{entire_url('/pbl_blueprint/api/pbl_blueprint_subobject_save.dspy')}}?subobject=evidence_spec",
|
||||
"update_data_url": "{{entire_url('/pbl_blueprint/api/pbl_blueprint_subobject_save.dspy')}}?subobject=evidence_spec",
|
||||
"delete_data_url": "{{entire_url('/pbl_blueprint/api/pbl_blueprint_subobject_delete.dspy')}}?subobject=evidence_spec"
|
||||
},
|
||||
"browserfields": {
|
||||
"main": {
|
||||
"fields": ["seq", "evidence_code", "name", "evidence_type", "collect_mode", "required"],
|
||||
"title": "证据规格"
|
||||
}
|
||||
},
|
||||
"editexclouded": ["id", "tenant_id", "created_by", "created_at", "updated_by", "updated_at"]
|
||||
}
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
{
|
||||
"tblname": "pbl_blueprint_learning_goal",
|
||||
"params": {
|
||||
"logined_userorgid": "",
|
||||
"new_data_url": "{{entire_url('/pbl_blueprint/api/pbl_blueprint_subobject_save.dspy')}}?subobject=learning_goal",
|
||||
"update_data_url": "{{entire_url('/pbl_blueprint/api/pbl_blueprint_subobject_save.dspy')}}?subobject=learning_goal",
|
||||
"delete_data_url": "{{entire_url('/pbl_blueprint/api/pbl_blueprint_subobject_delete.dspy')}}?subobject=learning_goal",
|
||||
"editable": {
|
||||
"new_data_url": "{{entire_url('/pbl_blueprint/api/pbl_blueprint_subobject_save.dspy')}}?subobject=learning_goal",
|
||||
"update_data_url": "{{entire_url('/pbl_blueprint/api/pbl_blueprint_subobject_save.dspy')}}?subobject=learning_goal",
|
||||
"delete_data_url": "{{entire_url('/pbl_blueprint/api/pbl_blueprint_subobject_delete.dspy')}}?subobject=learning_goal"
|
||||
},
|
||||
"browserfields": {
|
||||
"main": {
|
||||
"fields": ["seq", "goal_code", "title", "knowledge_type", "assessable", "created_at"],
|
||||
"title": "学习目标"
|
||||
}
|
||||
},
|
||||
"editexclouded": ["id", "tenant_id", "created_by", "created_at", "updated_by", "updated_at"]
|
||||
}
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
{
|
||||
"tblname": "pbl_blueprint_mission",
|
||||
"params": {
|
||||
"logined_userorgid": "",
|
||||
"new_data_url": "{{entire_url('/pbl_blueprint/api/pbl_blueprint_subobject_save.dspy')}}?subobject=mission",
|
||||
"update_data_url": "{{entire_url('/pbl_blueprint/api/pbl_blueprint_subobject_save.dspy')}}?subobject=mission",
|
||||
"delete_data_url": "{{entire_url('/pbl_blueprint/api/pbl_blueprint_subobject_delete.dspy')}}?subobject=mission",
|
||||
"editable": {
|
||||
"new_data_url": "{{entire_url('/pbl_blueprint/api/pbl_blueprint_subobject_save.dspy')}}?subobject=mission",
|
||||
"update_data_url": "{{entire_url('/pbl_blueprint/api/pbl_blueprint_subobject_save.dspy')}}?subobject=mission",
|
||||
"delete_data_url": "{{entire_url('/pbl_blueprint/api/pbl_blueprint_subobject_delete.dspy')}}?subobject=mission"
|
||||
},
|
||||
"browserfields": {
|
||||
"main": {
|
||||
"fields": ["seq", "mission_code", "title", "duration_hours", "created_at"],
|
||||
"title": "驱动问题/Mission"
|
||||
}
|
||||
},
|
||||
"editexclouded": ["id", "tenant_id", "created_by", "created_at", "updated_by", "updated_at"]
|
||||
}
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
{
|
||||
"tblname": "pbl_blueprint_reflection_spec",
|
||||
"params": {
|
||||
"logined_userorgid": "",
|
||||
"new_data_url": "{{entire_url('/pbl_blueprint/api/pbl_blueprint_subobject_save.dspy')}}?subobject=reflection_spec",
|
||||
"update_data_url": "{{entire_url('/pbl_blueprint/api/pbl_blueprint_subobject_save.dspy')}}?subobject=reflection_spec",
|
||||
"delete_data_url": "{{entire_url('/pbl_blueprint/api/pbl_blueprint_subobject_delete.dspy')}}?subobject=reflection_spec",
|
||||
"editable": {
|
||||
"new_data_url": "{{entire_url('/pbl_blueprint/api/pbl_blueprint_subobject_save.dspy')}}?subobject=reflection_spec",
|
||||
"update_data_url": "{{entire_url('/pbl_blueprint/api/pbl_blueprint_subobject_save.dspy')}}?subobject=reflection_spec",
|
||||
"delete_data_url": "{{entire_url('/pbl_blueprint/api/pbl_blueprint_subobject_delete.dspy')}}?subobject=reflection_spec"
|
||||
},
|
||||
"browserfields": {
|
||||
"main": {
|
||||
"fields": ["seq", "reflection_code", "title", "reflection_type", "trigger_point", "required"],
|
||||
"title": "反思规格"
|
||||
}
|
||||
},
|
||||
"editexclouded": ["id", "tenant_id", "created_by", "created_at", "updated_by", "updated_at"]
|
||||
}
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
{
|
||||
"tblname": "pbl_blueprint_role",
|
||||
"params": {
|
||||
"logined_userorgid": "",
|
||||
"new_data_url": "{{entire_url('/pbl_blueprint/api/pbl_blueprint_subobject_save.dspy')}}?subobject=role",
|
||||
"update_data_url": "{{entire_url('/pbl_blueprint/api/pbl_blueprint_subobject_save.dspy')}}?subobject=role",
|
||||
"delete_data_url": "{{entire_url('/pbl_blueprint/api/pbl_blueprint_subobject_delete.dspy')}}?subobject=role",
|
||||
"editable": {
|
||||
"new_data_url": "{{entire_url('/pbl_blueprint/api/pbl_blueprint_subobject_save.dspy')}}?subobject=role",
|
||||
"update_data_url": "{{entire_url('/pbl_blueprint/api/pbl_blueprint_subobject_save.dspy')}}?subobject=role",
|
||||
"delete_data_url": "{{entire_url('/pbl_blueprint/api/pbl_blueprint_subobject_delete.dspy')}}?subobject=role"
|
||||
},
|
||||
"browserfields": {
|
||||
"main": {
|
||||
"fields": ["seq", "role_code", "role_name", "min_members", "max_members", "is_mandatory"],
|
||||
"title": "PBL角色"
|
||||
}
|
||||
},
|
||||
"editexclouded": ["id", "tenant_id", "created_by", "created_at", "updated_by", "updated_at"]
|
||||
}
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
{
|
||||
"tblname": "pbl_blueprint_task",
|
||||
"params": {
|
||||
"logined_userorgid": "",
|
||||
"new_data_url": "{{entire_url('/pbl_blueprint/api/pbl_blueprint_subobject_save.dspy')}}?subobject=task",
|
||||
"update_data_url": "{{entire_url('/pbl_blueprint/api/pbl_blueprint_subobject_save.dspy')}}?subobject=task",
|
||||
"delete_data_url": "{{entire_url('/pbl_blueprint/api/pbl_blueprint_subobject_delete.dspy')}}?subobject=task",
|
||||
"editable": {
|
||||
"new_data_url": "{{entire_url('/pbl_blueprint/api/pbl_blueprint_subobject_save.dspy')}}?subobject=task",
|
||||
"update_data_url": "{{entire_url('/pbl_blueprint/api/pbl_blueprint_subobject_save.dspy')}}?subobject=task",
|
||||
"delete_data_url": "{{entire_url('/pbl_blueprint/api/pbl_blueprint_subobject_delete.dspy')}}?subobject=task"
|
||||
},
|
||||
"browserfields": {
|
||||
"main": {
|
||||
"fields": ["seq", "task_code", "title", "task_type", "estimated_minutes", "status"],
|
||||
"title": "任务"
|
||||
}
|
||||
},
|
||||
"editexclouded": ["id", "tenant_id", "created_by", "created_at", "updated_by", "updated_at"]
|
||||
}
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
{
|
||||
"tblname": "pbl_blueprint_version",
|
||||
"params": {
|
||||
"logined_userorgid": "",
|
||||
"new_data_url": "{{entire_url('/pbl_blueprint/api/pbl_blueprint_version_create.dspy')}}",
|
||||
"update_data_url": "",
|
||||
"delete_data_url": "",
|
||||
"editable": {
|
||||
"new_data_url": "{{entire_url('/pbl_blueprint/api/pbl_blueprint_version_create.dspy')}}",
|
||||
"update_data_url": "",
|
||||
"delete_data_url": ""
|
||||
},
|
||||
"browserfields": {
|
||||
"main": {
|
||||
"fields": ["version_no", "source", "change_reason", "quality_status", "created_by", "created_at"],
|
||||
"title": "版本历史"
|
||||
}
|
||||
},
|
||||
"editexclouded": ["id", "tenant_id", "blueprint_id", "parent_version_id", "change_delta", "snapshot_json", "created_by", "created_at"]
|
||||
}
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
{
|
||||
"tblname": "pbl_template",
|
||||
"params": {
|
||||
"logined_userorgid": "",
|
||||
"new_data_url": "{{entire_url('/pbl_blueprint/api/pbl_template_save.dspy')}}",
|
||||
"update_data_url": "{{entire_url('/pbl_blueprint/api/pbl_template_save.dspy')}}",
|
||||
"delete_data_url": "{{entire_url('/pbl_blueprint/api/pbl_template_delete.dspy')}}",
|
||||
"editable": {
|
||||
"new_data_url": "{{entire_url('/pbl_blueprint/api/pbl_template_save.dspy')}}",
|
||||
"update_data_url": "{{entire_url('/pbl_blueprint/api/pbl_template_save.dspy')}}",
|
||||
"delete_data_url": "{{entire_url('/pbl_blueprint/api/pbl_template_delete.dspy')}}"
|
||||
},
|
||||
"browserfields": {
|
||||
"main": {
|
||||
"fields": ["template_code", "name", "category", "subject_area", "grade_level", "template_version", "is_builtin", "status"],
|
||||
"title": "PBL模板"
|
||||
}
|
||||
},
|
||||
"editexclouded": ["id", "tenant_id", "created_by", "created_at", "updated_by", "updated_at"]
|
||||
}
|
||||
}
|
||||
@ -1,47 +0,0 @@
|
||||
{
|
||||
"summary": [
|
||||
{
|
||||
"name": "pbl_blueprint",
|
||||
"title": "PBL蓝图聚合根",
|
||||
"primary": ["id"],
|
||||
"catelog": "entity"
|
||||
}
|
||||
],
|
||||
"fields": [
|
||||
{"name": "tenant_id", "title": "租户ID", "type": "str", "length": 32, "nullable": "no", "default": "0"},
|
||||
{"name": "id", "title": "主键ID", "type": "str", "length": 32, "nullable": "no"},
|
||||
{"name": "blueprint_code", "title": "蓝图编码", "type": "str", "length": 64, "nullable": "no"},
|
||||
{"name": "name", "title": "蓝图名称", "type": "str", "length": 255, "nullable": "no"},
|
||||
{"name": "subject", "title": "学科领域", "type": "str", "length": 64, "default": ""},
|
||||
{"name": "grade", "title": "适用年级", "type": "str", "length": 32, "default": ""},
|
||||
{"name": "description", "title": "蓝图描述", "type": "text"},
|
||||
{"name": "status", "title": "蓝图状态", "type": "str", "length": 32, "nullable": "no", "default": "draft"},
|
||||
{"name": "quality_status", "title": "质量状态(L0-L4)", "type": "str", "length": 8, "nullable": "no", "default": "L0"},
|
||||
{"name": "current_version", "title": "当前版本号", "type": "int", "nullable": "no", "default": "0"},
|
||||
{"name": "published_version", "title": "已发布版本号", "type": "int", "nullable": "no", "default": "0"},
|
||||
{"name": "root_world_id", "title": "根世界ID", "type": "str", "length": 32, "default": ""},
|
||||
{"name": "template_id", "title": "来源模板ID", "type": "str", "length": 32, "default": ""},
|
||||
{"name": "fork_from_id", "title": "fork来源蓝图ID", "type": "str", "length": 32, "default": ""},
|
||||
{"name": "extra_json", "title": "扩展属性JSON", "type": "text"},
|
||||
{"name": "owner_id", "title": "归属用户ID", "type": "str", "length": 32, "nullable": "no", "default": "0"},
|
||||
{"name": "org_id", "title": "归属机构ID", "type": "str", "length": 32, "nullable": "no", "default": "0"},
|
||||
{"name": "created_by", "title": "创建人", "type": "str", "length": 32, "default": ""},
|
||||
{"name": "created_at", "title": "创建时间", "type": "timestamp"},
|
||||
{"name": "updated_by", "title": "最后修改人", "type": "str", "length": 32, "default": ""},
|
||||
{"name": "updated_at", "title": "最后修改时间", "type": "timestamp"},
|
||||
{"name": "deleted", "title": "软删除标记(0正常1删除)", "type": "str", "length": 1, "nullable": "no", "default": "0"}
|
||||
],
|
||||
"indexes": [
|
||||
{"name": "uk_pbl_blueprint_code", "idxtype": "unique", "idxfields": ["tenant_id", "blueprint_code"]},
|
||||
{"name": "idx_pbl_blueprint_tenant_status", "idxtype": "index", "idxfields": ["tenant_id", "status", "deleted"]},
|
||||
{"name": "idx_pbl_blueprint_tenant_owner", "idxtype": "index", "idxfields": ["tenant_id", "owner_id"]},
|
||||
{"name": "idx_pbl_blueprint_tenant_updated", "idxtype": "index", "idxfields": ["tenant_id", "deleted", "updated_at"]},
|
||||
{"name": "idx_pbl_blueprint_template", "idxtype": "index", "idxfields": ["tenant_id", "template_id"]}
|
||||
],
|
||||
"codes": [
|
||||
{"field": "status", "table": "appcodes_kv", "valuefield": "k", "textfield": "v", "cond": "parentid='pbl_bp_status'"},
|
||||
{"field": "quality_status", "table": "appcodes_kv", "valuefield": "k", "textfield": "v", "cond": "parentid='pbl_quality_status'"},
|
||||
{"field": "subject", "table": "appcodes_kv", "valuefield": "k", "textfield": "v", "cond": "parentid='pbl_subject'"},
|
||||
{"field": "grade", "table": "appcodes_kv", "valuefield": "k", "textfield": "v", "cond": "parentid='pbl_grade'"}
|
||||
]
|
||||
}
|
||||
@ -1,234 +0,0 @@
|
||||
-- pbl_blueprint DDL (MariaDB / MySQL)
|
||||
-- 由 models/*.json 派生(json2ddl mysql . 等价输出),tenant_id 强制打头。
|
||||
-- 部署:应用 build.sh 执行 json2ddl 生成;本文件为可核对的落库基线。
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `pbl_blueprint` (
|
||||
`id` VARCHAR(32) NOT NULL COMMENT '主键',
|
||||
`tenant_id` VARCHAR(32) NOT NULL DEFAULT '0' COMMENT '租户ID(强制打头)',
|
||||
`org_id` VARCHAR(32) NOT NULL DEFAULT '0' COMMENT '所属机构',
|
||||
`blueprint_code` VARCHAR(64) NOT NULL COMMENT '蓝图编码',
|
||||
`title` VARCHAR(255) NOT NULL COMMENT '蓝图标题',
|
||||
`subject_area` VARCHAR(64) DEFAULT '' COMMENT '学科领域',
|
||||
`grade_level` VARCHAR(32) DEFAULT '' COMMENT '适用年级',
|
||||
`duration_hours` INT DEFAULT 0 COMMENT '总课时(小时)',
|
||||
`driving_question` TEXT COMMENT '驱动问题',
|
||||
`summary` TEXT COMMENT '蓝图摘要',
|
||||
`quality_status` VARCHAR(32) NOT NULL DEFAULT 'draft' COMMENT '5级质量状态',
|
||||
`validation_score` DECIMAL(5,2) DEFAULT 0 COMMENT '校验得分',
|
||||
`version_no` INT NOT NULL DEFAULT 1 COMMENT '当前版本号',
|
||||
`current_version_id` VARCHAR(32) DEFAULT '' COMMENT '当前版本ID',
|
||||
`template_id` VARCHAR(32) DEFAULT '' COMMENT '来源模板ID',
|
||||
`forked_from_id` VARCHAR(32) DEFAULT '' COMMENT '派生自蓝图ID',
|
||||
`status` VARCHAR(32) NOT NULL DEFAULT 'draft' COMMENT 'draft/published/archived/deleted',
|
||||
`extra_json` LONGTEXT COMMENT '扩展属性JSON',
|
||||
`created_by` VARCHAR(32) DEFAULT '',
|
||||
`created_at` DATETIME NOT NULL,
|
||||
`updated_by` VARCHAR(32) DEFAULT '',
|
||||
`updated_at` DATETIME DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_pbl_blueprint_code` (`tenant_id`,`blueprint_code`),
|
||||
KEY `idx_pbl_blueprint_tenant` (`tenant_id`,`status`),
|
||||
KEY `idx_pbl_blueprint_org` (`org_id`),
|
||||
KEY `idx_pbl_blueprint_created` (`tenant_id`,`created_at`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='PBL蓝图聚合根';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `pbl_blueprint_learning_goal` (
|
||||
`id` VARCHAR(32) NOT NULL,
|
||||
`tenant_id` VARCHAR(32) NOT NULL DEFAULT '0',
|
||||
`blueprint_id` VARCHAR(32) NOT NULL,
|
||||
`seq` INT NOT NULL DEFAULT 0,
|
||||
`goal_code` VARCHAR(64) NOT NULL,
|
||||
`title` VARCHAR(255) NOT NULL,
|
||||
`description` TEXT,
|
||||
`knowledge_type` VARCHAR(32) DEFAULT 'concept',
|
||||
`competency_tags` TEXT,
|
||||
`assessable` VARCHAR(1) DEFAULT '1',
|
||||
`alignment_json` LONGTEXT,
|
||||
`created_by` VARCHAR(32) DEFAULT '',
|
||||
`created_at` DATETIME NOT NULL,
|
||||
`updated_by` VARCHAR(32) DEFAULT '',
|
||||
`updated_at` DATETIME DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_pbl_goal_code` (`tenant_id`,`blueprint_id`,`goal_code`),
|
||||
KEY `idx_pbl_goal_bp` (`tenant_id`,`blueprint_id`,`seq`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='蓝图子对象-学习目标';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `pbl_blueprint_role` (
|
||||
`id` VARCHAR(32) NOT NULL,
|
||||
`tenant_id` VARCHAR(32) NOT NULL DEFAULT '0',
|
||||
`blueprint_id` VARCHAR(32) NOT NULL,
|
||||
`seq` INT NOT NULL DEFAULT 0,
|
||||
`role_code` VARCHAR(64) NOT NULL,
|
||||
`role_name` VARCHAR(128) NOT NULL,
|
||||
`description` TEXT,
|
||||
`responsibilities` TEXT,
|
||||
`required_skills` TEXT,
|
||||
`min_members` INT DEFAULT 1,
|
||||
`max_members` INT DEFAULT 1,
|
||||
`is_mandatory` VARCHAR(1) DEFAULT '0',
|
||||
`created_by` VARCHAR(32) DEFAULT '',
|
||||
`created_at` DATETIME NOT NULL,
|
||||
`updated_by` VARCHAR(32) DEFAULT '',
|
||||
`updated_at` DATETIME DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_pbl_role_code` (`tenant_id`,`blueprint_id`,`role_code`),
|
||||
KEY `idx_pbl_role_bp` (`tenant_id`,`blueprint_id`,`seq`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='蓝图子对象-PBL角色';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `pbl_blueprint_mission` (
|
||||
`id` VARCHAR(32) NOT NULL,
|
||||
`tenant_id` VARCHAR(32) NOT NULL DEFAULT '0',
|
||||
`blueprint_id` VARCHAR(32) NOT NULL,
|
||||
`seq` INT NOT NULL DEFAULT 0,
|
||||
`mission_code` VARCHAR(64) NOT NULL,
|
||||
`title` VARCHAR(255) NOT NULL,
|
||||
`driving_question` TEXT,
|
||||
`narrative` LONGTEXT,
|
||||
`success_criteria` TEXT,
|
||||
`related_goal_ids` TEXT,
|
||||
`duration_hours` INT DEFAULT 0,
|
||||
`created_by` VARCHAR(32) DEFAULT '',
|
||||
`created_at` DATETIME NOT NULL,
|
||||
`updated_by` VARCHAR(32) DEFAULT '',
|
||||
`updated_at` DATETIME DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_pbl_mission_code` (`tenant_id`,`blueprint_id`,`mission_code`),
|
||||
KEY `idx_pbl_mission_bp` (`tenant_id`,`blueprint_id`,`seq`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='蓝图子对象-驱动问题/Mission';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `pbl_blueprint_task` (
|
||||
`id` VARCHAR(32) NOT NULL,
|
||||
`tenant_id` VARCHAR(32) NOT NULL DEFAULT '0',
|
||||
`blueprint_id` VARCHAR(32) NOT NULL,
|
||||
`mission_id` VARCHAR(32) DEFAULT '',
|
||||
`seq` INT NOT NULL DEFAULT 0,
|
||||
`task_code` VARCHAR(64) NOT NULL,
|
||||
`title` VARCHAR(255) NOT NULL,
|
||||
`description` TEXT,
|
||||
`task_type` VARCHAR(32) DEFAULT 'explore',
|
||||
`role_id` VARCHAR(32) DEFAULT '',
|
||||
`depends_on_ids` TEXT,
|
||||
`estimated_minutes` INT DEFAULT 0,
|
||||
`artifact_spec_ids` TEXT,
|
||||
`status` VARCHAR(32) DEFAULT 'draft',
|
||||
`created_by` VARCHAR(32) DEFAULT '',
|
||||
`created_at` DATETIME NOT NULL,
|
||||
`updated_by` VARCHAR(32) DEFAULT '',
|
||||
`updated_at` DATETIME DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_pbl_task_code` (`tenant_id`,`blueprint_id`,`task_code`),
|
||||
KEY `idx_pbl_task_bp` (`tenant_id`,`blueprint_id`,`seq`),
|
||||
KEY `idx_pbl_task_mission` (`tenant_id`,`mission_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='蓝图子对象-任务';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `pbl_blueprint_artifact_spec` (
|
||||
`id` VARCHAR(32) NOT NULL,
|
||||
`tenant_id` VARCHAR(32) NOT NULL DEFAULT '0',
|
||||
`blueprint_id` VARCHAR(32) NOT NULL,
|
||||
`task_id` VARCHAR(32) DEFAULT '',
|
||||
`seq` INT NOT NULL DEFAULT 0,
|
||||
`artifact_code` VARCHAR(64) NOT NULL,
|
||||
`name` VARCHAR(255) NOT NULL,
|
||||
`artifact_type` VARCHAR(32) DEFAULT 'document',
|
||||
`format` VARCHAR(64) DEFAULT '',
|
||||
`description` TEXT,
|
||||
`required` VARCHAR(1) DEFAULT '1',
|
||||
`max_size_mb` INT DEFAULT 0,
|
||||
`schema_json` LONGTEXT,
|
||||
`rubric_id` VARCHAR(32) DEFAULT '',
|
||||
`created_by` VARCHAR(32) DEFAULT '',
|
||||
`created_at` DATETIME NOT NULL,
|
||||
`updated_by` VARCHAR(32) DEFAULT '',
|
||||
`updated_at` DATETIME DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_pbl_artifact_code` (`tenant_id`,`blueprint_id`,`artifact_code`),
|
||||
KEY `idx_pbl_artifact_bp` (`tenant_id`,`blueprint_id`,`seq`),
|
||||
KEY `idx_pbl_artifact_task` (`tenant_id`,`task_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='蓝图子对象-产出物规格';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `pbl_blueprint_evidence_spec` (
|
||||
`id` VARCHAR(32) NOT NULL,
|
||||
`tenant_id` VARCHAR(32) NOT NULL DEFAULT '0',
|
||||
`blueprint_id` VARCHAR(32) NOT NULL,
|
||||
`artifact_spec_id` VARCHAR(32) DEFAULT '',
|
||||
`task_id` VARCHAR(32) DEFAULT '',
|
||||
`seq` INT NOT NULL DEFAULT 0,
|
||||
`evidence_code` VARCHAR(64) NOT NULL,
|
||||
`name` VARCHAR(255) NOT NULL,
|
||||
`evidence_type` VARCHAR(32) DEFAULT 'result',
|
||||
`collect_mode` VARCHAR(32) DEFAULT 'auto',
|
||||
`source_hint` VARCHAR(255) DEFAULT '',
|
||||
`idempotency_key_hint` VARCHAR(128) DEFAULT '',
|
||||
`required` VARCHAR(1) DEFAULT '1',
|
||||
`description` TEXT,
|
||||
`created_by` VARCHAR(32) DEFAULT '',
|
||||
`created_at` DATETIME NOT NULL,
|
||||
`updated_by` VARCHAR(32) DEFAULT '',
|
||||
`updated_at` DATETIME DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_pbl_evidence_code` (`tenant_id`,`blueprint_id`,`evidence_code`),
|
||||
KEY `idx_pbl_evidence_bp` (`tenant_id`,`blueprint_id`,`seq`),
|
||||
KEY `idx_pbl_evidence_artifact` (`tenant_id`,`artifact_spec_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='蓝图子对象-证据规格';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `pbl_blueprint_reflection_spec` (
|
||||
`id` VARCHAR(32) NOT NULL,
|
||||
`tenant_id` VARCHAR(32) NOT NULL DEFAULT '0',
|
||||
`blueprint_id` VARCHAR(32) NOT NULL,
|
||||
`seq` INT NOT NULL DEFAULT 0,
|
||||
`reflection_code` VARCHAR(64) NOT NULL,
|
||||
`title` VARCHAR(255) NOT NULL,
|
||||
`prompt` TEXT,
|
||||
`reflection_type` VARCHAR(32) DEFAULT 'self',
|
||||
`trigger_point` VARCHAR(64) DEFAULT 'task_end',
|
||||
`required` VARCHAR(1) DEFAULT '1',
|
||||
`rubric_hint` TEXT,
|
||||
`created_by` VARCHAR(32) DEFAULT '',
|
||||
`created_at` DATETIME NOT NULL,
|
||||
`updated_by` VARCHAR(32) DEFAULT '',
|
||||
`updated_at` DATETIME DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_pbl_reflection_code` (`tenant_id`,`blueprint_id`,`reflection_code`),
|
||||
KEY `idx_pbl_reflection_bp` (`tenant_id`,`blueprint_id`,`seq`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='蓝图子对象-反思规格';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `pbl_blueprint_version` (
|
||||
`id` VARCHAR(32) NOT NULL,
|
||||
`tenant_id` VARCHAR(32) NOT NULL DEFAULT '0',
|
||||
`blueprint_id` VARCHAR(32) NOT NULL,
|
||||
`version_no` INT NOT NULL DEFAULT 1,
|
||||
`parent_version_id` VARCHAR(32) DEFAULT '',
|
||||
`change_delta` LONGTEXT COMMENT '{op,path,before,after} 列表',
|
||||
`snapshot_json` LONGTEXT,
|
||||
`change_reason` VARCHAR(500) DEFAULT '',
|
||||
`source` VARCHAR(32) DEFAULT 'manual',
|
||||
`quality_status` VARCHAR(32) DEFAULT 'draft',
|
||||
`created_by` VARCHAR(32) DEFAULT '',
|
||||
`created_at` DATETIME NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_pbl_version_no` (`tenant_id`,`blueprint_id`,`version_no`),
|
||||
KEY `idx_pbl_version_bp` (`tenant_id`,`blueprint_id`,`created_at`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='蓝图版本(change_delta 证明对话式改模型)';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `pbl_template` (
|
||||
`id` VARCHAR(32) NOT NULL,
|
||||
`tenant_id` VARCHAR(32) NOT NULL DEFAULT '0' COMMENT '0=平台内置全局模板',
|
||||
`template_code` VARCHAR(64) NOT NULL,
|
||||
`name` VARCHAR(255) NOT NULL,
|
||||
`description` TEXT,
|
||||
`category` VARCHAR(64) DEFAULT 'general',
|
||||
`subject_area` VARCHAR(64) DEFAULT '',
|
||||
`grade_level` VARCHAR(32) DEFAULT '',
|
||||
`blueprint_snapshot` LONGTEXT,
|
||||
`offline_slots` LONGTEXT COMMENT 'LLM 不可用时降级填充槽位',
|
||||
`is_builtin` VARCHAR(1) DEFAULT '0',
|
||||
`template_version` VARCHAR(32) DEFAULT '1.0.0',
|
||||
`status` VARCHAR(32) DEFAULT 'active',
|
||||
`created_by` VARCHAR(32) DEFAULT '',
|
||||
`created_at` DATETIME NOT NULL,
|
||||
`updated_by` VARCHAR(32) DEFAULT '',
|
||||
`updated_at` DATETIME DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_pbl_template_code` (`tenant_id`,`template_code`),
|
||||
KEY `idx_pbl_template_cat` (`tenant_id`,`category`,`status`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='PBL模板(含离线兜底槽位)';
|
||||
@ -1,44 +0,0 @@
|
||||
{
|
||||
"summary": [
|
||||
{
|
||||
"table": "pbl_blueprint_artifact_spec",
|
||||
"name": "蓝图产出物规格",
|
||||
"title": "产出物规格",
|
||||
"subtitle": "蓝图子对象-产出物规格",
|
||||
"primary": ["id"],
|
||||
"defaultsort": "seq asc",
|
||||
"orderby": "seq asc",
|
||||
"caption": "产出物规格"
|
||||
}
|
||||
],
|
||||
"fields": [
|
||||
{"name": "id", "type": "str(32)", "title": "主键", "notnull": 1, "primary": 1, "readonly": 1},
|
||||
{"name": "tenant_id", "type": "str(32)", "title": "租户ID", "notnull": 1, "default": "0"},
|
||||
{"name": "blueprint_id", "type": "str(32)", "title": "所属蓝图", "notnull": 1},
|
||||
{"name": "task_id", "type": "str(32)", "title": "所属任务", "default": ""},
|
||||
{"name": "seq", "type": "int", "title": "序号", "notnull": 1, "default": 0},
|
||||
{"name": "artifact_code", "type": "str(64)", "title": "产出物编码", "notnull": 1},
|
||||
{"name": "name", "type": "str(255)", "title": "产出物名称", "notnull": 1},
|
||||
{"name": "artifact_type", "type": "str(32)", "title": "产出物类型", "default": "document", "comment": "document/model/code/image/video/audio/data/other"},
|
||||
{"name": "format", "type": "str(64)", "title": "文件格式", "default": ""},
|
||||
{"name": "description", "type": "text", "title": "规格说明", "default": ""},
|
||||
{"name": "required", "type": "str(1)", "title": "是否必需", "default": "1"},
|
||||
{"name": "max_size_mb", "type": "int", "title": "大小上限(MB)", "default": 0},
|
||||
{"name": "schema_json", "type": "longtext", "title": "结构约束JSON Schema", "default": ""},
|
||||
{"name": "rubric_id", "type": "str(32)", "title": "评分量规ID", "default": ""},
|
||||
{"name": "created_by", "type": "str(32)", "title": "创建人", "default": ""},
|
||||
{"name": "created_at", "type": "datetime", "title": "创建时间", "notnull": 1},
|
||||
{"name": "updated_by", "type": "str(32)", "title": "更新人", "default": ""},
|
||||
{"name": "updated_at", "type": "datetime", "title": "更新时间"}
|
||||
],
|
||||
"indexes": [
|
||||
{"name": "uk_pbl_artifact_code", "fields": ["tenant_id", "blueprint_id", "artifact_code"], "unique": 1},
|
||||
{"name": "idx_pbl_artifact_bp", "fields": ["tenant_id", "blueprint_id", "seq"], "unique": 0},
|
||||
{"name": "idx_pbl_artifact_task", "fields": ["tenant_id", "task_id"], "unique": 0}
|
||||
],
|
||||
"codes": [
|
||||
{"field": "artifact_type", "table": "appcodes_kv", "cond": "parentid='pbl_artifact_type'", "valuefield": "k", "textfield": "v"},
|
||||
{"field": "blueprint_id", "table": "pbl_blueprint", "cond": "", "valuefield": "id", "textfield": "title"},
|
||||
{"field": "task_id", "table": "pbl_blueprint_task", "cond": "", "valuefield": "id", "textfield": "title"}
|
||||
]
|
||||
}
|
||||
@ -1,45 +0,0 @@
|
||||
{
|
||||
"summary": [
|
||||
{
|
||||
"table": "pbl_blueprint_evidence_spec",
|
||||
"name": "蓝图证据规格",
|
||||
"title": "证据规格",
|
||||
"subtitle": "蓝图子对象-证据规格",
|
||||
"primary": ["id"],
|
||||
"defaultsort": "seq asc",
|
||||
"orderby": "seq asc",
|
||||
"caption": "证据规格"
|
||||
}
|
||||
],
|
||||
"fields": [
|
||||
{"name": "id", "type": "str(32)", "title": "主键", "notnull": 1, "primary": 1, "readonly": 1},
|
||||
{"name": "tenant_id", "type": "str(32)", "title": "租户ID", "notnull": 1, "default": "0"},
|
||||
{"name": "blueprint_id", "type": "str(32)", "title": "所属蓝图", "notnull": 1},
|
||||
{"name": "artifact_spec_id", "type": "str(32)", "title": "关联产出物规格", "default": ""},
|
||||
{"name": "task_id", "type": "str(32)", "title": "关联任务", "default": ""},
|
||||
{"name": "seq", "type": "int", "title": "序号", "notnull": 1, "default": 0},
|
||||
{"name": "evidence_code", "type": "str(64)", "title": "证据编码", "notnull": 1},
|
||||
{"name": "name", "type": "str(255)", "title": "证据名称", "notnull": 1},
|
||||
{"name": "evidence_type", "type": "str(32)", "title": "证据类型", "default": "result", "comment": "process/result/behavior/log"},
|
||||
{"name": "collect_mode", "type": "str(32)", "title": "采集方式", "default": "auto", "comment": "auto/manual/hybrid"},
|
||||
{"name": "source_hint", "type": "str(255)", "title": "采集来源提示", "default": ""},
|
||||
{"name": "idempotency_key_hint", "type": "str(128)", "title": "幂等键规则", "default": "", "comment": "供 pbl_evidence 幂等采集使用"},
|
||||
{"name": "required", "type": "str(1)", "title": "是否必需", "default": "1"},
|
||||
{"name": "description", "type": "text", "title": "说明", "default": ""},
|
||||
{"name": "created_by", "type": "str(32)", "title": "创建人", "default": ""},
|
||||
{"name": "created_at", "type": "datetime", "title": "创建时间", "notnull": 1},
|
||||
{"name": "updated_by", "type": "str(32)", "title": "更新人", "default": ""},
|
||||
{"name": "updated_at", "type": "datetime", "title": "更新时间"}
|
||||
],
|
||||
"indexes": [
|
||||
{"name": "uk_pbl_evidence_code", "fields": ["tenant_id", "blueprint_id", "evidence_code"], "unique": 1},
|
||||
{"name": "idx_pbl_evidence_bp", "fields": ["tenant_id", "blueprint_id", "seq"], "unique": 0},
|
||||
{"name": "idx_pbl_evidence_artifact", "fields": ["tenant_id", "artifact_spec_id"], "unique": 0}
|
||||
],
|
||||
"codes": [
|
||||
{"field": "evidence_type", "table": "appcodes_kv", "cond": "parentid='pbl_evidence_type'", "valuefield": "k", "textfield": "v"},
|
||||
{"field": "collect_mode", "table": "appcodes_kv", "cond": "parentid='pbl_collect_mode'", "valuefield": "k", "textfield": "v"},
|
||||
{"field": "blueprint_id", "table": "pbl_blueprint", "cond": "", "valuefield": "id", "textfield": "title"},
|
||||
{"field": "artifact_spec_id", "table": "pbl_blueprint_artifact_spec", "cond": "", "valuefield": "id", "textfield": "name"}
|
||||
]
|
||||
}
|
||||
@ -1,39 +0,0 @@
|
||||
{
|
||||
"summary": [
|
||||
{
|
||||
"table": "pbl_blueprint_learning_goal",
|
||||
"name": "蓝图学习目标",
|
||||
"title": "学习目标",
|
||||
"subtitle": "蓝图子对象-学习目标",
|
||||
"primary": ["id"],
|
||||
"defaultsort": "seq asc",
|
||||
"orderby": "seq asc",
|
||||
"caption": "学习目标"
|
||||
}
|
||||
],
|
||||
"fields": [
|
||||
{"name": "id", "type": "str(32)", "title": "主键", "notnull": 1, "primary": 1, "readonly": 1},
|
||||
{"name": "tenant_id", "type": "str(32)", "title": "租户ID", "notnull": 1, "default": "0"},
|
||||
{"name": "blueprint_id", "type": "str(32)", "title": "所属蓝图", "notnull": 1},
|
||||
{"name": "seq", "type": "int", "title": "序号", "notnull": 1, "default": 0},
|
||||
{"name": "goal_code", "type": "str(64)", "title": "目标编码", "notnull": 1},
|
||||
{"name": "title", "type": "str(255)", "title": "目标标题", "notnull": 1},
|
||||
{"name": "description", "type": "text", "title": "目标描述", "default": ""},
|
||||
{"name": "knowledge_type", "type": "str(32)", "title": "知识类型", "default": "concept", "comment": "fact/concept/procedure/metacognition"},
|
||||
{"name": "competency_tags", "type": "text", "title": "素养标签JSON数组", "default": "[]"},
|
||||
{"name": "assessable", "type": "str(1)", "title": "可评估", "default": "1"},
|
||||
{"name": "alignment_json", "type": "longtext", "title": "对齐关系JSON", "default": ""},
|
||||
{"name": "created_by", "type": "str(32)", "title": "创建人", "default": ""},
|
||||
{"name": "created_at", "type": "datetime", "title": "创建时间", "notnull": 1},
|
||||
{"name": "updated_by", "type": "str(32)", "title": "更新人", "default": ""},
|
||||
{"name": "updated_at", "type": "datetime", "title": "更新时间"}
|
||||
],
|
||||
"indexes": [
|
||||
{"name": "uk_pbl_goal_code", "fields": ["tenant_id", "blueprint_id", "goal_code"], "unique": 1},
|
||||
{"name": "idx_pbl_goal_bp", "fields": ["tenant_id", "blueprint_id", "seq"], "unique": 0}
|
||||
],
|
||||
"codes": [
|
||||
{"field": "knowledge_type", "table": "appcodes_kv", "cond": "parentid='pbl_knowledge_type'", "valuefield": "k", "textfield": "v"},
|
||||
{"field": "blueprint_id", "table": "pbl_blueprint", "cond": "", "valuefield": "id", "textfield": "title"}
|
||||
]
|
||||
}
|
||||
@ -1,38 +0,0 @@
|
||||
{
|
||||
"summary": [
|
||||
{
|
||||
"table": "pbl_blueprint_mission",
|
||||
"name": "蓝图Mission",
|
||||
"title": "驱动问题/Mission",
|
||||
"subtitle": "蓝图子对象-驱动问题",
|
||||
"primary": ["id"],
|
||||
"defaultsort": "seq asc",
|
||||
"orderby": "seq asc",
|
||||
"caption": "Mission"
|
||||
}
|
||||
],
|
||||
"fields": [
|
||||
{"name": "id", "type": "str(32)", "title": "主键", "notnull": 1, "primary": 1, "readonly": 1},
|
||||
{"name": "tenant_id", "type": "str(32)", "title": "租户ID", "notnull": 1, "default": "0"},
|
||||
{"name": "blueprint_id", "type": "str(32)", "title": "所属蓝图", "notnull": 1},
|
||||
{"name": "seq", "type": "int", "title": "序号", "notnull": 1, "default": 0},
|
||||
{"name": "mission_code", "type": "str(64)", "title": "Mission编码", "notnull": 1},
|
||||
{"name": "title", "type": "str(255)", "title": "Mission标题", "notnull": 1},
|
||||
{"name": "driving_question", "type": "text", "title": "驱动问题", "default": ""},
|
||||
{"name": "narrative", "type": "longtext", "title": "情境叙事", "default": ""},
|
||||
{"name": "success_criteria", "type": "text", "title": "成功标准JSON数组", "default": "[]"},
|
||||
{"name": "related_goal_ids", "type": "text", "title": "关联学习目标ID JSON数组", "default": "[]"},
|
||||
{"name": "duration_hours", "type": "int", "title": "预计课时", "default": 0},
|
||||
{"name": "created_by", "type": "str(32)", "title": "创建人", "default": ""},
|
||||
{"name": "created_at", "type": "datetime", "title": "创建时间", "notnull": 1},
|
||||
{"name": "updated_by", "type": "str(32)", "title": "更新人", "default": ""},
|
||||
{"name": "updated_at", "type": "datetime", "title": "更新时间"}
|
||||
],
|
||||
"indexes": [
|
||||
{"name": "uk_pbl_mission_code", "fields": ["tenant_id", "blueprint_id", "mission_code"], "unique": 1},
|
||||
{"name": "idx_pbl_mission_bp", "fields": ["tenant_id", "blueprint_id", "seq"], "unique": 0}
|
||||
],
|
||||
"codes": [
|
||||
{"field": "blueprint_id", "table": "pbl_blueprint", "cond": "", "valuefield": "id", "textfield": "title"}
|
||||
]
|
||||
}
|
||||
@ -1,39 +0,0 @@
|
||||
{
|
||||
"summary": [
|
||||
{
|
||||
"table": "pbl_blueprint_reflection_spec",
|
||||
"name": "蓝图反思规格",
|
||||
"title": "反思规格",
|
||||
"subtitle": "蓝图子对象-反思规格",
|
||||
"primary": ["id"],
|
||||
"defaultsort": "seq asc",
|
||||
"orderby": "seq asc",
|
||||
"caption": "反思规格"
|
||||
}
|
||||
],
|
||||
"fields": [
|
||||
{"name": "id", "type": "str(32)", "title": "主键", "notnull": 1, "primary": 1, "readonly": 1},
|
||||
{"name": "tenant_id", "type": "str(32)", "title": "租户ID", "notnull": 1, "default": "0"},
|
||||
{"name": "blueprint_id", "type": "str(32)", "title": "所属蓝图", "notnull": 1},
|
||||
{"name": "seq", "type": "int", "title": "序号", "notnull": 1, "default": 0},
|
||||
{"name": "reflection_code", "type": "str(64)", "title": "反思编码", "notnull": 1},
|
||||
{"name": "title", "type": "str(255)", "title": "反思标题", "notnull": 1},
|
||||
{"name": "prompt", "type": "text", "title": "反思提示语", "default": ""},
|
||||
{"name": "reflection_type", "type": "str(32)", "title": "反思类型", "default": "self", "comment": "self/peer/team/teacher"},
|
||||
{"name": "trigger_point", "type": "str(64)", "title": "触发时点", "default": "task_end", "comment": "task_end/mission_end/project_end/manual"},
|
||||
{"name": "required", "type": "str(1)", "title": "是否必需", "default": "1"},
|
||||
{"name": "rubric_hint", "type": "text", "title": "量规提示", "default": ""},
|
||||
{"name": "created_by", "type": "str(32)", "title": "创建人", "default": ""},
|
||||
{"name": "created_at", "type": "datetime", "title": "创建时间", "notnull": 1},
|
||||
{"name": "updated_by", "type": "str(32)", "title": "更新人", "default": ""},
|
||||
{"name": "updated_at", "type": "datetime", "title": "更新时间"}
|
||||
],
|
||||
"indexes": [
|
||||
{"name": "uk_pbl_reflection_code", "fields": ["tenant_id", "blueprint_id", "reflection_code"], "unique": 1},
|
||||
{"name": "idx_pbl_reflection_bp", "fields": ["tenant_id", "blueprint_id", "seq"], "unique": 0}
|
||||
],
|
||||
"codes": [
|
||||
{"field": "reflection_type", "table": "appcodes_kv", "cond": "parentid='pbl_reflect_type'", "valuefield": "k", "textfield": "v"},
|
||||
{"field": "blueprint_id", "table": "pbl_blueprint", "cond": "", "valuefield": "id", "textfield": "title"}
|
||||
]
|
||||
}
|
||||
@ -1,39 +0,0 @@
|
||||
{
|
||||
"summary": [
|
||||
{
|
||||
"table": "pbl_blueprint_role",
|
||||
"name": "蓝图角色",
|
||||
"title": "PBL角色",
|
||||
"subtitle": "蓝图子对象-角色",
|
||||
"primary": ["id"],
|
||||
"defaultsort": "seq asc",
|
||||
"orderby": "seq asc",
|
||||
"caption": "角色"
|
||||
}
|
||||
],
|
||||
"fields": [
|
||||
{"name": "id", "type": "str(32)", "title": "主键", "notnull": 1, "primary": 1, "readonly": 1},
|
||||
{"name": "tenant_id", "type": "str(32)", "title": "租户ID", "notnull": 1, "default": "0"},
|
||||
{"name": "blueprint_id", "type": "str(32)", "title": "所属蓝图", "notnull": 1},
|
||||
{"name": "seq", "type": "int", "title": "序号", "notnull": 1, "default": 0},
|
||||
{"name": "role_code", "type": "str(64)", "title": "角色编码", "notnull": 1},
|
||||
{"name": "role_name", "type": "str(128)", "title": "角色名称", "notnull": 1},
|
||||
{"name": "description", "type": "text", "title": "角色说明", "default": ""},
|
||||
{"name": "responsibilities", "type": "text", "title": "职责JSON数组", "default": "[]"},
|
||||
{"name": "required_skills", "type": "text", "title": "所需技能JSON数组", "default": "[]"},
|
||||
{"name": "min_members", "type": "int", "title": "最少人数", "default": 1},
|
||||
{"name": "max_members", "type": "int", "title": "最多人数", "default": 1},
|
||||
{"name": "is_mandatory", "type": "str(1)", "title": "是否必需角色", "default": "0"},
|
||||
{"name": "created_by", "type": "str(32)", "title": "创建人", "default": ""},
|
||||
{"name": "created_at", "type": "datetime", "title": "创建时间", "notnull": 1},
|
||||
{"name": "updated_by", "type": "str(32)", "title": "更新人", "default": ""},
|
||||
{"name": "updated_at", "type": "datetime", "title": "更新时间"}
|
||||
],
|
||||
"indexes": [
|
||||
{"name": "uk_pbl_role_code", "fields": ["tenant_id", "blueprint_id", "role_code"], "unique": 1},
|
||||
{"name": "idx_pbl_role_bp", "fields": ["tenant_id", "blueprint_id", "seq"], "unique": 0}
|
||||
],
|
||||
"codes": [
|
||||
{"field": "blueprint_id", "table": "pbl_blueprint", "cond": "", "valuefield": "id", "textfield": "title"}
|
||||
]
|
||||
}
|
||||
@ -1,45 +0,0 @@
|
||||
{
|
||||
"summary": [
|
||||
{
|
||||
"table": "pbl_blueprint_task",
|
||||
"name": "蓝图任务",
|
||||
"title": "任务",
|
||||
"subtitle": "蓝图子对象-任务",
|
||||
"primary": ["id"],
|
||||
"defaultsort": "seq asc",
|
||||
"orderby": "seq asc",
|
||||
"caption": "任务"
|
||||
}
|
||||
],
|
||||
"fields": [
|
||||
{"name": "id", "type": "str(32)", "title": "主键", "notnull": 1, "primary": 1, "readonly": 1},
|
||||
{"name": "tenant_id", "type": "str(32)", "title": "租户ID", "notnull": 1, "default": "0"},
|
||||
{"name": "blueprint_id", "type": "str(32)", "title": "所属蓝图", "notnull": 1},
|
||||
{"name": "mission_id", "type": "str(32)", "title": "所属Mission", "default": ""},
|
||||
{"name": "seq", "type": "int", "title": "序号", "notnull": 1, "default": 0},
|
||||
{"name": "task_code", "type": "str(64)", "title": "任务编码", "notnull": 1},
|
||||
{"name": "title", "type": "str(255)", "title": "任务标题", "notnull": 1},
|
||||
{"name": "description", "type": "text", "title": "任务说明", "default": ""},
|
||||
{"name": "task_type", "type": "str(32)", "title": "任务类型", "default": "explore", "comment": "explore/build/test/present/reflect"},
|
||||
{"name": "role_id", "type": "str(32)", "title": "承担角色ID", "default": ""},
|
||||
{"name": "depends_on_ids", "type": "text", "title": "前置任务ID JSON数组", "default": "[]"},
|
||||
{"name": "estimated_minutes", "type": "int", "title": "预计耗时(分钟)", "default": 0},
|
||||
{"name": "artifact_spec_ids", "type": "text", "title": "产出物规格ID JSON数组", "default": "[]"},
|
||||
{"name": "status", "type": "str(32)", "title": "状态", "default": "draft"},
|
||||
{"name": "created_by", "type": "str(32)", "title": "创建人", "default": ""},
|
||||
{"name": "created_at", "type": "datetime", "title": "创建时间", "notnull": 1},
|
||||
{"name": "updated_by", "type": "str(32)", "title": "更新人", "default": ""},
|
||||
{"name": "updated_at", "type": "datetime", "title": "更新时间"}
|
||||
],
|
||||
"indexes": [
|
||||
{"name": "uk_pbl_task_code", "fields": ["tenant_id", "blueprint_id", "task_code"], "unique": 1},
|
||||
{"name": "idx_pbl_task_bp", "fields": ["tenant_id", "blueprint_id", "seq"], "unique": 0},
|
||||
{"name": "idx_pbl_task_mission", "fields": ["tenant_id", "mission_id"], "unique": 0}
|
||||
],
|
||||
"codes": [
|
||||
{"field": "task_type", "table": "appcodes_kv", "cond": "parentid='pbl_task_type'", "valuefield": "k", "textfield": "v"},
|
||||
{"field": "blueprint_id", "table": "pbl_blueprint", "cond": "", "valuefield": "id", "textfield": "title"},
|
||||
{"field": "mission_id", "table": "pbl_blueprint_mission", "cond": "", "valuefield": "id", "textfield": "title"},
|
||||
{"field": "role_id", "table": "pbl_blueprint_role", "cond": "", "valuefield": "id", "textfield": "role_name"}
|
||||
]
|
||||
}
|
||||
@ -1,36 +0,0 @@
|
||||
{
|
||||
"summary": [
|
||||
{
|
||||
"table": "pbl_blueprint_version",
|
||||
"name": "蓝图版本",
|
||||
"title": "蓝图版本",
|
||||
"subtitle": "版本快照与变更增量",
|
||||
"primary": ["id"],
|
||||
"defaultsort": "version_no desc",
|
||||
"orderby": "version_no desc",
|
||||
"caption": "版本"
|
||||
}
|
||||
],
|
||||
"fields": [
|
||||
{"name": "id", "type": "str(32)", "title": "主键", "notnull": 1, "primary": 1, "readonly": 1},
|
||||
{"name": "tenant_id", "type": "str(32)", "title": "租户ID", "notnull": 1, "default": "0"},
|
||||
{"name": "blueprint_id", "type": "str(32)", "title": "所属蓝图", "notnull": 1},
|
||||
{"name": "version_no", "type": "int", "title": "版本号", "notnull": 1, "default": 1},
|
||||
{"name": "parent_version_id", "type": "str(32)", "title": "父版本ID", "default": ""},
|
||||
{"name": "change_delta", "type": "longtext", "title": "变更增量JSON", "default": "", "comment": "对话式改模型的证据:{op,path,before,after} 列表"},
|
||||
{"name": "snapshot_json", "type": "longtext", "title": "全量快照JSON", "default": ""},
|
||||
{"name": "change_reason", "type": "str(500)", "title": "变更原因", "default": ""},
|
||||
{"name": "source", "type": "str(32)", "title": "变更来源", "default": "manual", "comment": "manual/dialogue/template/fork/validation"},
|
||||
{"name": "quality_status", "type": "str(32)", "title": "该版本质量状态", "default": "draft"},
|
||||
{"name": "created_by", "type": "str(32)", "title": "创建人", "default": ""},
|
||||
{"name": "created_at", "type": "datetime", "title": "创建时间", "notnull": 1}
|
||||
],
|
||||
"indexes": [
|
||||
{"name": "uk_pbl_version_no", "fields": ["tenant_id", "blueprint_id", "version_no"], "unique": 1},
|
||||
{"name": "idx_pbl_version_bp", "fields": ["tenant_id", "blueprint_id", "created_at"], "unique": 0}
|
||||
],
|
||||
"codes": [
|
||||
{"field": "source", "table": "appcodes_kv", "cond": "parentid='pbl_version_source'", "valuefield": "k", "textfield": "v"},
|
||||
{"field": "blueprint_id", "table": "pbl_blueprint", "cond": "", "valuefield": "id", "textfield": "title"}
|
||||
]
|
||||
}
|
||||
@ -1,40 +0,0 @@
|
||||
{
|
||||
"summary": [
|
||||
{
|
||||
"table": "pbl_template",
|
||||
"name": "PBL模板",
|
||||
"title": "PBL模板",
|
||||
"subtitle": "蓝图模板(含离线兜底槽位)",
|
||||
"primary": ["id"],
|
||||
"defaultsort": "created_at desc",
|
||||
"orderby": "created_at desc",
|
||||
"caption": "模板"
|
||||
}
|
||||
],
|
||||
"fields": [
|
||||
{"name": "id", "type": "str(32)", "title": "主键", "notnull": 1, "primary": 1, "readonly": 1},
|
||||
{"name": "tenant_id", "type": "str(32)", "title": "租户ID", "notnull": 1, "default": "0", "comment": "0=平台内置全局模板,所有租户可见"},
|
||||
{"name": "template_code", "type": "str(64)", "title": "模板编码", "notnull": 1},
|
||||
{"name": "name", "type": "str(255)", "title": "模板名称", "notnull": 1},
|
||||
{"name": "description", "type": "text", "title": "模板说明", "default": ""},
|
||||
{"name": "category", "type": "str(64)", "title": "模板分类", "default": "general"},
|
||||
{"name": "subject_area", "type": "str(64)", "title": "学科领域", "default": ""},
|
||||
{"name": "grade_level", "type": "str(32)", "title": "适用年级", "default": ""},
|
||||
{"name": "blueprint_snapshot", "type": "longtext", "title": "蓝图骨架JSON", "default": "", "comment": "实例化时展开为蓝图+子对象"},
|
||||
{"name": "offline_slots", "type": "longtext", "title": "离线兜底槽位JSON", "default": "[]", "comment": "LLM 不可用时的降级填充槽位定义"},
|
||||
{"name": "is_builtin", "type": "str(1)", "title": "是否内置", "default": "0"},
|
||||
{"name": "template_version", "type": "str(32)", "title": "模板版本", "default": "1.0.0"},
|
||||
{"name": "status", "type": "str(32)", "title": "状态", "default": "active", "comment": "active/disabled"},
|
||||
{"name": "created_by", "type": "str(32)", "title": "创建人", "default": ""},
|
||||
{"name": "created_at", "type": "datetime", "title": "创建时间", "notnull": 1},
|
||||
{"name": "updated_by", "type": "str(32)", "title": "更新人", "default": ""},
|
||||
{"name": "updated_at", "type": "datetime", "title": "更新时间"}
|
||||
],
|
||||
"indexes": [
|
||||
{"name": "uk_pbl_template_code", "fields": ["tenant_id", "template_code"], "unique": 1},
|
||||
{"name": "idx_pbl_template_cat", "fields": ["tenant_id", "category", "status"], "unique": 0}
|
||||
],
|
||||
"codes": [
|
||||
{"field": "category", "table": "appcodes_kv", "cond": "parentid='pbl_template_cat'", "valuefield": "k", "textfield": "v"}
|
||||
]
|
||||
}
|
||||
@ -1,168 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""pbl_blueprint 表清单与字段映射(从 models/*.json 四段式定义读取,不重复硬编码字段)。
|
||||
|
||||
对外提供:
|
||||
- TABLES / TABLE_META:表名清单与元信息(pk / tenant_field / 抽象类型映射)
|
||||
- create_tables(env=None):按 models/*.json 建表(DDL 由平台抽象类型映射生成,幂等)
|
||||
- field_type_map(tbl):字段 -> 抽象类型(交付件逐字段核对用)
|
||||
"""
|
||||
import json
|
||||
import os
|
||||
|
||||
from . import db as _db
|
||||
|
||||
MODELS_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'models')
|
||||
|
||||
# 蓝图聚合根 + 版本 + 模板(M1a 范围)
|
||||
CORE_TABLES = ['pbl_blueprint', 'pbl_blueprint_version']
|
||||
# 子对象 7 类(M1a 落定义,M1b 扩展行为)
|
||||
SUBOBJECT_TABLES = [
|
||||
'pbl_blueprint_mission',
|
||||
'pbl_blueprint_learning_goal',
|
||||
'pbl_blueprint_task',
|
||||
'pbl_blueprint_role',
|
||||
'pbl_blueprint_artifact_spec',
|
||||
'pbl_blueprint_evidence_spec',
|
||||
'pbl_blueprint_reflection_spec',
|
||||
]
|
||||
# 模板主表 + 明细
|
||||
TEMPLATE_TABLES = ['pbl_blueprint_template', 'pbl_blueprint_template_item']
|
||||
|
||||
# 子对象类型 -> 表名(契约接口 subobject_save/list 的 subobject_type 取值)
|
||||
SUBOBJECT_TYPE_TABLE = {
|
||||
'mission': 'pbl_blueprint_mission',
|
||||
'learning_goal': 'pbl_blueprint_learning_goal',
|
||||
'task': 'pbl_blueprint_task',
|
||||
'role': 'pbl_blueprint_role',
|
||||
'artifact_spec': 'pbl_blueprint_artifact_spec',
|
||||
'evidence_spec': 'pbl_blueprint_evidence_spec',
|
||||
'reflection_spec': 'pbl_blueprint_reflection_spec',
|
||||
}
|
||||
TABLE_SUBOBJECT_TYPE = {v: k for k, v in SUBOBJECT_TYPE_TABLE.items()}
|
||||
|
||||
TABLES = CORE_TABLES + SUBOBJECT_TABLES + TEMPLATE_TABLES
|
||||
|
||||
# 抽象类型 -> PostgreSQL 物理类型(与 scripts/derive_artifacts.py 保持一致)
|
||||
ABSTRACT_TO_PG = {
|
||||
'str': 'varchar',
|
||||
'text': 'text',
|
||||
'int': 'integer',
|
||||
'double': 'numeric(18,2)',
|
||||
'datetime': 'timestamp',
|
||||
}
|
||||
# 禁止出现的物理类型/写法(QC 自检项)
|
||||
FORBIDDEN_TYPES = ['varchar(', 'bigint', 'boolean', 'int(11)', 'SERIAL', 'BIGSERIAL',
|
||||
'nextval', 'AUTO_INCREMENT']
|
||||
|
||||
|
||||
def _cache():
|
||||
global _CACHE
|
||||
if '_CACHE' not in dir():
|
||||
_CACHE = {}
|
||||
return _CACHE
|
||||
|
||||
|
||||
def load_model(table):
|
||||
"""读取单表四段式定义。"""
|
||||
path = os.path.join(MODELS_DIR, '%s.json' % table)
|
||||
if not os.path.isfile(path):
|
||||
raise _db.PblError(_db.ERR_PARAM_INVALID, '表定义文件缺失: %s' % table)
|
||||
with open(path, encoding='utf-8') as fp:
|
||||
doc = json.load(fp)
|
||||
for seg in ('summary', 'fields', 'indexes', 'codes'):
|
||||
if seg not in doc:
|
||||
raise _db.PblError(_db.ERR_PARAM_INVALID,
|
||||
'表定义 %s 缺四段式段: %s' % (table, seg))
|
||||
return doc
|
||||
|
||||
|
||||
def all_models():
|
||||
return dict((t, load_model(t)) for t in TABLES)
|
||||
|
||||
|
||||
def field_type_map(table):
|
||||
"""字段名 -> 抽象类型(如 id: str(32))。"""
|
||||
return dict((k, v['type']) for k, v in load_model(table)['fields'].items())
|
||||
|
||||
|
||||
def table_meta(table):
|
||||
doc = load_model(table)
|
||||
fields = doc['fields']
|
||||
return {
|
||||
'table': table,
|
||||
'label': doc['summary'].get('label', table),
|
||||
'engine': doc['summary'].get('engine', 'postgresql'),
|
||||
'pk': [k for k, v in fields.items() if v.get('pk')] or ['id'],
|
||||
'tenant_field': 'tenant_id' if 'tenant_id' in fields else None,
|
||||
'soft_delete_field': 'is_deleted' if 'is_deleted' in fields else None,
|
||||
'required': [k for k, v in fields.items() if v.get('required')],
|
||||
'appcodes': doc['codes'],
|
||||
'indexes': list(doc['indexes'].keys()),
|
||||
'field_count': len(fields),
|
||||
}
|
||||
|
||||
|
||||
def _pg_type(spec):
|
||||
ty = spec['type']
|
||||
if ty.startswith('str'):
|
||||
return 'varchar(%s)' % ty[ty.index('(') + 1:ty.index(')')]
|
||||
if ty == 'text':
|
||||
return 'text'
|
||||
if ty == 'int':
|
||||
return 'integer'
|
||||
if ty.startswith('double'):
|
||||
return 'numeric(18,2)'
|
||||
if ty == 'datetime':
|
||||
return 'timestamp'
|
||||
raise _db.PblError(_db.ERR_PARAM_INVALID, '未知抽象类型 %s' % ty)
|
||||
|
||||
|
||||
def create_table_ddl(table):
|
||||
"""按 models/*.json 生成幂等 DDL(平台抽象类型映射,不写方言私有序列)。"""
|
||||
doc = load_model(table)
|
||||
fields = doc['fields']
|
||||
cols = ',\n'.join(' %s %s%s' % (k, _pg_type(v),
|
||||
' NOT NULL' if (v.get('required') or v.get('pk')) else '')
|
||||
for k, v in fields.items())
|
||||
stmts = ['CREATE TABLE IF NOT EXISTS %s (\n%s\n)' % (table, cols)]
|
||||
for iname, isp in doc['indexes'].items():
|
||||
if iname == 'primary':
|
||||
continue
|
||||
uniq = 'UNIQUE ' if isp.get('unique') else ''
|
||||
stmts.append('CREATE %sINDEX IF NOT EXISTS %s_%s ON %s (%s)' %
|
||||
(uniq, table, iname, table, ', '.join(isp['fields'])))
|
||||
return stmts
|
||||
|
||||
|
||||
def create_tables(tables=None, dbname=None):
|
||||
"""建表(幂等)。返回 {table: 执行语句数}。"""
|
||||
result = {}
|
||||
for t in (tables or TABLES):
|
||||
stmts = create_table_ddl(t)
|
||||
for s in stmts:
|
||||
_db.sql_exe(s)
|
||||
result[t] = len(stmts)
|
||||
return result
|
||||
|
||||
|
||||
def register_crud(env, tables=None):
|
||||
"""把 json/{tblname}.json CRUD 契约注册到 ServerEnv(供平台 CRUD 工厂/前端表格消费)。"""
|
||||
base = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'json')
|
||||
registered = []
|
||||
for t in (tables or TABLES):
|
||||
path = os.path.join(base, '%s.json' % t)
|
||||
if not os.path.isfile(path):
|
||||
raise _db.PblError(_db.ERR_PARAM_INVALID, 'CRUD 定义缺失: %s' % path)
|
||||
with open(path, encoding='utf-8') as fp:
|
||||
doc = json.load(fp)
|
||||
if list(doc.keys()) != [t]:
|
||||
raise _db.PblError(_db.ERR_PARAM_INVALID,
|
||||
'CRUD 定义根键必须等于表名 %s,实际 %s' % (t, list(doc.keys())))
|
||||
if env is not None:
|
||||
store = getattr(env, 'pbl_crud_defs', None)
|
||||
if store is None:
|
||||
store = {}
|
||||
setattr(env, 'pbl_crud_defs', store)
|
||||
store[t] = doc[t]
|
||||
registered.append(t)
|
||||
return registered
|
||||
Loading…
x
Reference in New Issue
Block a user