Files
smart 67837df8d0 docs: 更新TRA编程培训课程材料、课件与AI技能交付包
- 新增全套考试卷、评估卷、参考答案与考试培训包模板
- 修正slidev培训课件:调整模块标题、链路图缩放,替换工单示例为通用业务对象
- 修正课堂红线表述为证据红线,将小组作业调整为个人作业要求
- 新增权限、状态流转、审计日志、看板指标四类可复用业务规则块
- 整理AI工程技能交付包,迁移旧资产至客户专属交付包并统一术语
- 新增考试输出模板与TRAE使用记录文档
2026-08-08 11:00:36 +08:00

198 lines
12 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from copy import deepcopy
from pathlib import Path
from docx import Document
from docx.enum.text import WD_BREAK
ROOT = Path('/Users/smart/Documents/TRAE培训/TRAE课件/exams')
SOURCE = ROOT / 'TRAE编程培训考试评估卷-实操与项目实战.docx'
TARGET = ROOT / 'TRAE编程培训考试评估卷-实操与项目实战(修订版).docx'
def replace_paragraph(paragraph, text, bold=None, size=None):
first_run = paragraph.runs[0] if paragraph.runs else None
old_bold = first_run.bold if first_run else None
old_size = first_run.font.size if first_run else None
paragraph.clear()
run = paragraph.add_run(text)
run.bold = old_bold if bold is None else bold
if size is not None:
run.font.size = size
elif old_size is not None:
run.font.size = old_size
return paragraph
def replace_cell(cell, text, bold=None):
for paragraph in cell.paragraphs[1:]:
paragraph._element.getparent().remove(paragraph._element)
paragraph = cell.paragraphs[0]
first_run = paragraph.runs[0] if paragraph.runs else None
old_bold = first_run.bold if first_run else None
old_size = first_run.font.size if first_run else None
paragraph.clear()
run = paragraph.add_run(text)
run.bold = old_bold if bold is None else bold
if old_size is not None:
run.font.size = old_size
def find_paragraph(document, text):
for paragraph in document.paragraphs:
if text in paragraph.text:
return paragraph
raise ValueError(f'Paragraph not found: {text}')
def set_table_rows(table, rows):
while len(table.rows) < len(rows):
table.add_row()
if len(table.rows) != len(rows):
raise ValueError('Unexpected table row count')
for row, values in zip(table.rows, rows):
if len(row.cells) != len(values):
raise ValueError('Unexpected table column count')
for cell, value in zip(row.cells, values):
replace_cell(cell, value)
def clone_paragraph(document, source_paragraph, text):
paragraph = document.add_paragraph()
placeholder = paragraph._p
element = deepcopy(source_paragraph._element)
placeholder.getparent().replace(placeholder, element)
paragraph._p = paragraph._element = element
replace_paragraph(paragraph, text)
return paragraph
def clone_table(document, source_table):
table = document.add_table(rows=1, cols=1)
placeholder = table._tbl
element = deepcopy(source_table._element)
placeholder.getparent().replace(placeholder, element)
table._tbl = table._element = element
return table
def insert_after(anchor, element):
anchor._element.addnext(element._element)
doc = Document(SOURCE)
replace_paragraph(find_paragraph(doc, '实操 + 公务用车项目实战综合卷'), '实操 + 系统用户状态管理综合卷')
# 1. Fixed time: 20 minutes for A, 60 for B, 10 for submission check.
set_table_rows(doc.tables[0], [
['项目', '说明'],
['适用对象', '参加 TRAE 编程培训并完成 JeecgBoot 实战的技术学员。'],
['考试形式', '允许使用 TRAE,上机完成;提交 Markdown 产物包与 AI 使用记录。'],
['建议时长', '90 分钟:A 卷 20 分钟,B 卷 60 分钟,提交检查 10 分钟。'],
['总分', '100 分:小实操 30 分,项目实战 70 分。'],
['评估目标', '考察学员能否把真实研发问题拆成 TRAE 可执行、团队可验收、后续可复用的工程任务。'],
])
set_table_rows(doc.tables[2], [
['部分', '时间', '分值', '形式', '核心能力'],
['A. 小实操', '20 分钟', '30 分', '个人完成', 'Prompt 改写、证据判断'],
['B. 项目实战', '60 分钟', '70 分', '个人完成', '项目理解、变更边界、测试安全网、Review 与交付'],
['提交检查', '10 分钟', '-', '个人完成', '核对目录、文件名与执行状态'],
['合计', '90 分钟', '100 分', '上机 + 文档交付', '个人基本功 + 项目落地能力'],
])
# 2. Deliverable templates and missing-file treatment.
replace_paragraph(find_paragraph(doc, '建议要求学员提交一个 Markdown 目录包'), '使用 exam-kit/exam-output/ 中的模板提交,目录和文件名不得改动:')
set_table_rows(doc.tables[3], [
['文件', '主要内容'],
['01-project-understanding.md', '结论摘要、证据表、影响与保护边界、待确认项'],
['02-change-and-test.md', '验收标准、校验位置、不改动项、测试矩阵、执行状态'],
['03-pr-and-assets.md', 'Review、PR 说明、可复用 Prompt、Rule/Checklist/Skill 设计卡'],
['trae-usage-record.md', 'Prompt、采纳/否决、人工判断点、证据或验证状态;缺失则任务 3 的如实记录项计 0 分'],
])
# Insert the fixed source / tools contract after the deliverable table.
input_heading = clone_paragraph(doc, find_paragraph(doc, '二、最终提交物'), '考试输入与作答约束')
input_intro = clone_paragraph(doc, find_paragraph(doc, '使用 exam-kit/exam-output/'), 'B 卷仅以 exam-kit/ 中的固定版本、指定 diff 和模板为准。')
input_table = clone_table(doc, doc.tables[3])
set_table_rows(input_table, [
['项目', '统一要求'],
['固定源码', 'GitHub jeecgboot/JeecgBoot;标签 v3.9.2:7df07a823fd558be857d0208ccae96342539fbc1。'],
['指定模块', 'jeecg-module-system;以 SysUserController.frozenBatch 和 SysUserServiceImpl.updateStatus 为事实入口。'],
['指定 diff', 'exam-kit/review-diff.patch;仅以该两文件变更为 Review 输入。'],
['允许材料', 'TRAE、GitHub 固定版本与 exam-kit;版本不一致时记录环境问题并联系监考人员。'],
])
anchor = doc.tables[3]
insert_after(anchor, input_heading)
insert_after(input_heading, input_intro)
insert_after(input_intro, input_table)
replace_paragraph(find_paragraph(doc, '本部分由学员个人完成,重点考察 TRAE 基础使用'), '本部分由学员个人完成,重点考察 TRAE 基础使用与 AI 协作基本功。限时 20 分钟。')
replace_cell(doc.tables[5].cell(0, 0), '原始 Prompt\n帮我看一下系统用户批量冻结/解冻功能有没有问题。')
replace_cell(doc.tables[7].cell(0, 0), 'AI 输出片段\n页面已限制状态值,因此 Service 不需要校验;直接调用接口也不会有问题。')
replace_paragraph(find_paragraph(doc, 'B 卷:公务用车项目实战'), 'B 卷:系统用户状态管理项目实战(70 分)')
replace_paragraph(find_paragraph(doc, '本部分使用 JeecgBoot 现有公务用车模块'), '本部分使用 exam-kit 指定版本的 JeecgBoot 系统用户模块,由学员个人完成。限时 60 分钟。')
replace_cell(doc.tables[9].cell(0, 0), '实战任务背景\n案例使用 GitHub 公开的 JeecgBoot v3.9.2 中系统用户模块。训练改造要求:批量冻结/解冻用户时,后端必须拒绝空白或 1、2 之外的状态值;页面限制不能替代 Service 入口的业务保护。本次考试不要求完整开发所有代码,重点考察如何使用 TRAE 完成项目理解、变更边界分析、测试设计、Review 和资产沉淀。')
# 3. Observable requirements for B tasks.
replace_paragraph(find_paragraph(doc, '使用 TRAE 输出公务用车模块结构说明'), '使用 TRAE 完成 01-project-understanding.md:说明系统用户模块结构、批量冻结/解冻接口、Service 入口、权限、管理员保护、缓存和测试入口。证据表至少含 5 条有效依据,每条必须写文件路径、符号或方法,以及它证明的结论;另说明非法状态值与接口、用户状态写入、缓存失效的影响关系,并区分事实、推断和待确认项。')
replace_paragraph(find_paragraph(doc, '输出最小改造方案和测试安全网'), '完成 02-change-and-test.md:说明应在哪个方法、哪次用户状态写入之前校验非法状态值;列出不改动的接口权限、管理员保护和缓存失效逻辑及依据;为空白或非法状态、正常冻结、正常解冻、无权限调用、管理员保护与缓存/用户状态回归逐项写明预期结果、验证入口、执行状态。已执行项必须给出命令和结果,未执行项必须说明原因和计划验证方式。')
replace_paragraph(find_paragraph(doc, '基于 `main...training/require-cancel-reason`'), '基于 exam-kit/review-diff.patch 的实际两文件 diff,完成 03-pr-and-assets.md:生成 Review 和 PR 说明,再输出一条可复用 Prompt 及一条 Rule、Checklist 或 Skill 设计卡。Review 可以得出“未发现阻断问题”的结论,但必须说明检查范围、证据和残余风险;所有已执行与未执行的验证必须如实标注。')
# 4. Replace vague scoring with observable, non-overlapping criteria.
set_table_rows(doc.tables[6], [
['评分项', '分值'],
['背景与目标清楚', '3'],
['范围可控,限定目录、文件、接口或页面', '2'],
['约束清楚,含项目规则、安全、权限、测试要求及信息不足时先提问', '4'],
['输出格式明确,如表格、清单、报告或 PR 说明', '3'],
['验收标准和证据要求明确', '3'],
])
set_table_rows(doc.tables[10], [
['评分项', '分值'],
['系统用户模块与批量冻结/解冻入口明确', '4'],
['frozenBatch 接口、Controller 与 Service 调用链明确', '5'],
['权限、管理员保护、缓存和测试入口明确', '4'],
['至少 5 条有效证据,每条含路径、符号和证明内容', '7'],
['影响与保护边界完整,并区分事实、推断和待确认项', '5'],
])
set_table_rows(doc.tables[11], [
['评分项', '分值'],
['状态校验改造目标和验收标准清楚', '4'],
['校验方法、位置和副作用前后顺序正确', '5'],
['不改动项及其依据清楚', '4'],
['非法状态、冻结、解冻、权限、管理员保护/缓存五类场景完整', '8'],
['验证命令、执行结果或未执行原因明确', '4'],
])
set_table_rows(doc.tables[12], [
['评分项', '分值'],
['Review 结论、证据、风险和验收方式完整', '5'],
['PR 说明包含背景、实现、测试和风险', '5'],
['可复用 Prompt 的输入、约束、输出和验收清楚', '5'],
['Rule、Checklist 或 Skill 设计卡的边界和验收清楚', '3'],
['AI 使用记录完整;不编造测试结果,能说明人工取舍', '2'],
])
replace_paragraph(find_paragraph(doc, '三、综合评分维度'), '三、阅卷通用原则(不重复计分)')
set_table_rows(doc.tables[13], [
['阅卷原则', '优秀表现', '使用方式'],
['证据意识', '结论能引用文件、函数、接口、日志或数据来源', '仅用于判断对应任务中的证据项,不单独追加扣分'],
['上下文选择', '知道先全局找路,再文件聚焦,再代码细查', '仅用于判断对应任务中的任务表达与证据项'],
['任务表达', '背景、目标、范围、约束、输出、验收完整', '仅用于判断 A 卷 Prompt 改写项'],
['风险意识', '能识别权限、状态、审计、异常态、测试缺口', '仅用于判断 B 卷影响、测试和 Review 项'],
['人机协作', '知道哪些让 AI 做,哪些必须人工确认', '仅用于判断 AI 使用记录与待确认项'],
['资产意识', '能沉淀可复用 Prompt、Rule、Checklist、Skill', '仅用于判断任务 3 的资产项'],
])
set_table_rows(doc.tables[15], [
['环节', '要求'],
['发卷前检查', '发放 exam-kit;核对 GitHub 仓库、v3.9.2 完整提交和 review-diff.patch 均可读取。'],
['考试输入', '考试前完成 GitHub 固定版本下载;版本不一致时由监考人员处理,不得由学员自行替换版本。'],
['过程记录', '必须提交 trae-usage-record.md;缺失时任务 3 的 AI 使用记录项计 0 分。'],
['阅卷方式', '先核对四个交付文件,再按对应评分表打分;通用原则不重复扣分。'],
['独立作答', '抽查关键路径、证据来源和人工取舍,确认交付物与作答者理解一致。'],
])
doc.core_properties.title = 'TRAE 编程培训考试评估卷(修订版)'
doc.core_properties.subject = '实操与系统用户状态管理综合卷'
doc.save(TARGET)
print(TARGET)