【Codex】用座位划分模块优化班级空间与课堂管理

座位划分面向班主任的真实排座场景,结合班级、考试成绩、性格测评和座位规则生成可用座位表。

本文基于 SeatAllocationViewSet 和座位工作台页面,把班级选择、考试联动、规则计算和导出任务转换为 Codex 项目代码生成任务。

文章目录

设计与需求

座位划分不能只按普通 CRUD 理解。它连接学生、教师、班级、考试或画像数据,页面操作会影响后续教学管理、班级治理和数据分析。Codex 接收这类任务时,需要拿到真实源码路径、字段约束、接口规则和验收边界,才能生成可落地的项目代码。
#mermaid-svg-kNBdjajGfmz0F4PZ{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-kNBdjajGfmz0F4PZ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-kNBdjajGfmz0F4PZ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-kNBdjajGfmz0F4PZ .error-icon{fill:#552222;}#mermaid-svg-kNBdjajGfmz0F4PZ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-kNBdjajGfmz0F4PZ .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-kNBdjajGfmz0F4PZ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-kNBdjajGfmz0F4PZ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-kNBdjajGfmz0F4PZ .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-kNBdjajGfmz0F4PZ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-kNBdjajGfmz0F4PZ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-kNBdjajGfmz0F4PZ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-kNBdjajGfmz0F4PZ .marker.cross{stroke:#333333;}#mermaid-svg-kNBdjajGfmz0F4PZ svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-kNBdjajGfmz0F4PZ p{margin:0;}#mermaid-svg-kNBdjajGfmz0F4PZ .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-kNBdjajGfmz0F4PZ .cluster-label text{fill:#333;}#mermaid-svg-kNBdjajGfmz0F4PZ .cluster-label span{color:#333;}#mermaid-svg-kNBdjajGfmz0F4PZ .cluster-label span p{background-color:transparent;}#mermaid-svg-kNBdjajGfmz0F4PZ .label text,#mermaid-svg-kNBdjajGfmz0F4PZ span{fill:#333;color:#333;}#mermaid-svg-kNBdjajGfmz0F4PZ .node rect,#mermaid-svg-kNBdjajGfmz0F4PZ .node circle,#mermaid-svg-kNBdjajGfmz0F4PZ .node ellipse,#mermaid-svg-kNBdjajGfmz0F4PZ .node polygon,#mermaid-svg-kNBdjajGfmz0F4PZ .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-kNBdjajGfmz0F4PZ .rough-node .label text,#mermaid-svg-kNBdjajGfmz0F4PZ .node .label text,#mermaid-svg-kNBdjajGfmz0F4PZ .image-shape .label,#mermaid-svg-kNBdjajGfmz0F4PZ .icon-shape .label{text-anchor:middle;}#mermaid-svg-kNBdjajGfmz0F4PZ .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-kNBdjajGfmz0F4PZ .rough-node .label,#mermaid-svg-kNBdjajGfmz0F4PZ .node .label,#mermaid-svg-kNBdjajGfmz0F4PZ .image-shape .label,#mermaid-svg-kNBdjajGfmz0F4PZ .icon-shape .label{text-align:center;}#mermaid-svg-kNBdjajGfmz0F4PZ .node.clickable{cursor:pointer;}#mermaid-svg-kNBdjajGfmz0F4PZ .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-kNBdjajGfmz0F4PZ .arrowheadPath{fill:#333333;}#mermaid-svg-kNBdjajGfmz0F4PZ .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-kNBdjajGfmz0F4PZ .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-kNBdjajGfmz0F4PZ .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-kNBdjajGfmz0F4PZ .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-kNBdjajGfmz0F4PZ .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-kNBdjajGfmz0F4PZ .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-kNBdjajGfmz0F4PZ .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-kNBdjajGfmz0F4PZ .cluster text{fill:#333;}#mermaid-svg-kNBdjajGfmz0F4PZ .cluster span{color:#333;}#mermaid-svg-kNBdjajGfmz0F4PZ div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-kNBdjajGfmz0F4PZ .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-kNBdjajGfmz0F4PZ rect.text{fill:none;stroke-width:0;}#mermaid-svg-kNBdjajGfmz0F4PZ .icon-shape,#mermaid-svg-kNBdjajGfmz0F4PZ .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-kNBdjajGfmz0F4PZ .icon-shape p,#mermaid-svg-kNBdjajGfmz0F4PZ .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-kNBdjajGfmz0F4PZ .icon-shape .label rect,#mermaid-svg-kNBdjajGfmz0F4PZ .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-kNBdjajGfmz0F4PZ .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-kNBdjajGfmz0F4PZ .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-kNBdjajGfmz0F4PZ :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-kNBdjajGfmz0F4PZ .input>*{fill:#EEF4FF!important;stroke:#5B8FF9!important;color:#1D39C4!important;stroke-width:1.2px!important;}#mermaid-svg-kNBdjajGfmz0F4PZ .input span{fill:#EEF4FF!important;stroke:#5B8FF9!important;color:#1D39C4!important;stroke-width:1.2px!important;}#mermaid-svg-kNBdjajGfmz0F4PZ .input tspan{fill:#1D39C4!important;}#mermaid-svg-kNBdjajGfmz0F4PZ .design>*{fill:#F6FFED!important;stroke:#52C41A!important;color:#237804!important;stroke-width:1.2px!important;}#mermaid-svg-kNBdjajGfmz0F4PZ .design span{fill:#F6FFED!important;stroke:#52C41A!important;color:#237804!important;stroke-width:1.2px!important;}#mermaid-svg-kNBdjajGfmz0F4PZ .design tspan{fill:#237804!important;}#mermaid-svg-kNBdjajGfmz0F4PZ .process>*{fill:#FFF7E6!important;stroke:#FA8C16!important;color:#AD4E00!important;stroke-width:1.2px!important;}#mermaid-svg-kNBdjajGfmz0F4PZ .process span{fill:#FFF7E6!important;stroke:#FA8C16!important;color:#AD4E00!important;stroke-width:1.2px!important;}#mermaid-svg-kNBdjajGfmz0F4PZ .process tspan{fill:#AD4E00!important;}#mermaid-svg-kNBdjajGfmz0F4PZ .check>*{fill:#F9F0FF!important;stroke:#722ED1!important;color:#531DAB!important;stroke-width:1.2px!important;}#mermaid-svg-kNBdjajGfmz0F4PZ .check span{fill:#F9F0FF!important;stroke:#722ED1!important;color:#531DAB!important;stroke-width:1.2px!important;}#mermaid-svg-kNBdjajGfmz0F4PZ .check tspan{fill:#531DAB!important;}#mermaid-svg-kNBdjajGfmz0F4PZ .output>*{fill:#E6FFFB!important;stroke:#13C2C2!important;color:#006D75!important;stroke-width:1.2px!important;}#mermaid-svg-kNBdjajGfmz0F4PZ .output span{fill:#E6FFFB!important;stroke:#13C2C2!important;color:#006D75!important;stroke-width:1.2px!important;}#mermaid-svg-kNBdjajGfmz0F4PZ .output tspan{fill:#006D75!important;} 教育管理需求
座位划分设计
页面结构
数据模型
接口规则
权限验收
Codex生成代码

需求层描述 设计层转换 Codex 代码生成方向
班级选择 select_classes_dict 提供树形班级 生成班级树、叶子节点校验和权限校验
考试联动 get_class_exams 返回班级可选考试 生成考试下拉、默认考试和切换刷新
排座计算 generate_seat_plan 返回 seat_plan、seat_matrix、students 生成规则面板、座位网格和溢出提示
导出任务 export_seat_plan_download_task 创建下载中心任务 生成导出按钮和任务创建提示

可以直接使用下面的Prompt进行模块功能的设计

text 复制代码
请基于教育管理系统源码设计 座位划分 模块,不要编造代码中不存在的能力。

业务范围:按班级加载学生和考试成绩,设置行列、关闭座位、性别互补、性格互补、学业互补和特殊学生关注规则,生成座位表并创建下载中心导出任务。
后端路径:server_backend/modules/User/views_app/SeatAllocation.py、server_backend/modules/User/utils.py
前端路径:server_vue3/src/views/modules/User/SeatAllocation/index.vue、UserWorkbenchesApplication/index.vue
接口入口:/api/User/SeatAllocation/get_class_exams/、get_class_students/、generate_seat_plan/、export_seat_plan_download_task/
核心字段:该视图使用 DummyModel 作为 ViewSet 占位,核心数据来自 StudentManage、StudentAdmissionAssessment、TestingCenter.ExaminationStudentScore 和下载中心任务
扩展能力:数据联动、批量处理、导入导出

请输出模块设计方案,包含页面结构、数据模型、接口规则、权限验收、异常边界和 Codex 分阶段生成项目代码的任务拆分。扩展能力只允许使用源码中已经存在的能力。

后端设计

后端设计重点不是堆接口,而是把座位划分沉淀成可复用的数据底座。当前模块基于 CustomModelViewSetCustomModelRefSerializerCustomModelInFilterDefaultRouter 注册接口,结合模型字段、只读字段、范围筛选和动作接口形成稳定契约。

后端设计项 设计重点 Codex 生成方向
班级权限 check_class_permission 校验用户班级范围 防止越权查看其他班级学生
学生特征 build_student_features 聚合成绩和性格 输出学生表、考试序列、最近考试和排座依据
排座算法 build_layoutbuild_seat_plan_payload 生成座位 支持关闭座位、容量截断和规则权重
导出任务 build_seat_plan_export_excel_bytes + create_download_center_task 返回 download_center_id 供下载中心处理

可以直接使用下面的Prompt进行后端代码的设计

text 复制代码
请按 座位划分 的真实业务补齐或重构后端代码。

需要读取并遵守:
- server_backend/modules/User/views_app/SeatAllocation.py、server_backend/modules/User/utils.py
- server_backend/modules/User/models.py
- server_backend/modules/User/urls.py

生成要求:
- 按 SeatAllocation 模型字段设计序列化规则,不要新增无来源字段。
- 使用 CustomModelViewSet、CustomModelRefSerializer 和 CustomModelInFilter 保持项目风格。
- 补齐列表查询、详情、新增、编辑、删除或只读接口边界。
- 保留 read_only_fields、search_fields、range_fields 和权限校验逻辑。
- 扩展能力只实现:数据联动、批量处理、导入导出。
- 输出需要包含模型字段说明、接口清单、路由注册、筛选规则、权限规则和异常处理。

前端设计

前端设计重点不是把字段堆到页面上,而是让管理人员能高效完成座位划分的业务操作。当前模块使用 fs-pagefs-crudcreateCrudOptions、接口封装和 Element Plus 组件组织列表、搜索、表单、抽屉或业务操作。

前端设计项 设计重点 Codex 生成方向
控制面板 班级树、考试下拉、成绩表、规则滑块和行列输入 生成响应式状态和加载提示
座位网格 seatRowsseatColsdisabledSeatLabels 控制布局 生成座位开关、空座、关闭座和学生卡片
自动排座 规则、行列或关闭座位变化后触发重新生成 生成防抖、loading 和异常提示
导出按钮 调用 export_seat_plan_download_task 生成任务创建提示,不直接处理文件流

可以直接使用下面的Prompt进行前端代码的设计

text 复制代码
请按 座位划分 的真实业务生成或补齐前端代码。

需要读取并遵守:
- server_vue3/src/views/modules/User/SeatAllocation/index.vue、UserWorkbenchesApplication/index.vue
- 页面内通过 request 调用 /api/User/SeatAllocation/*

生成要求:
- 使用项目现有 fs-crud、Element Plus、request 封装和 api.ts 风格。
- 生成列表查询、筛选区域、新增编辑表单、详情或抽屉交互、权限按钮和保存回显。
- 处理字段转换:班级树叶子节点触发考试加载,考试选择触发学生成绩加载,行列和关闭座位转换为 disabled_seat_labels,规则对象转换为后端 rules
- 扩展交互只实现:数据联动、批量处理、导入导出。
- 不要添加源码中未实现的扩展入口。

扩展功能

座位划分的扩展能力覆盖数据联动、整班批量排座和导出下载。它不是维护一条记录,而是把班级数据转换成可使用的排座方案。

扩展功能 主要用途 落地重点
数据联动 班级、考试、学生成绩、性格和座位布局联动 保持 class_name、exam_code、rules、disabled_seat_labels 一致
批量处理 整班学生按规则一次性生成座位表 处理容量、关闭座位、溢出和特殊学生
导入导出 生成 Excel 并创建下载中心任务 返回 download_center_id,由下载中心下载

数据联动

座位划分的数据联动体现在 selectedClass、selectedExam、studentScoreTable、rules、seatRows、seatCols、disabledSeatLabels、seat_plan。前端选择、搜索或抽屉打开后,会生成接口参数 class_name、exam_code、rows、cols、rules、disabled_seat_labels,后端按学生、班级、日期或类型筛选,再把结果回填到列表、表单或业务面板中。
#mermaid-svg-pYDteUUwhbi3b5dB{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-pYDteUUwhbi3b5dB .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-pYDteUUwhbi3b5dB .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-pYDteUUwhbi3b5dB .error-icon{fill:#552222;}#mermaid-svg-pYDteUUwhbi3b5dB .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-pYDteUUwhbi3b5dB .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-pYDteUUwhbi3b5dB .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-pYDteUUwhbi3b5dB .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-pYDteUUwhbi3b5dB .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-pYDteUUwhbi3b5dB .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-pYDteUUwhbi3b5dB .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-pYDteUUwhbi3b5dB .marker{fill:#333333;stroke:#333333;}#mermaid-svg-pYDteUUwhbi3b5dB .marker.cross{stroke:#333333;}#mermaid-svg-pYDteUUwhbi3b5dB svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-pYDteUUwhbi3b5dB p{margin:0;}#mermaid-svg-pYDteUUwhbi3b5dB .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-pYDteUUwhbi3b5dB .cluster-label text{fill:#333;}#mermaid-svg-pYDteUUwhbi3b5dB .cluster-label span{color:#333;}#mermaid-svg-pYDteUUwhbi3b5dB .cluster-label span p{background-color:transparent;}#mermaid-svg-pYDteUUwhbi3b5dB .label text,#mermaid-svg-pYDteUUwhbi3b5dB span{fill:#333;color:#333;}#mermaid-svg-pYDteUUwhbi3b5dB .node rect,#mermaid-svg-pYDteUUwhbi3b5dB .node circle,#mermaid-svg-pYDteUUwhbi3b5dB .node ellipse,#mermaid-svg-pYDteUUwhbi3b5dB .node polygon,#mermaid-svg-pYDteUUwhbi3b5dB .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-pYDteUUwhbi3b5dB .rough-node .label text,#mermaid-svg-pYDteUUwhbi3b5dB .node .label text,#mermaid-svg-pYDteUUwhbi3b5dB .image-shape .label,#mermaid-svg-pYDteUUwhbi3b5dB .icon-shape .label{text-anchor:middle;}#mermaid-svg-pYDteUUwhbi3b5dB .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-pYDteUUwhbi3b5dB .rough-node .label,#mermaid-svg-pYDteUUwhbi3b5dB .node .label,#mermaid-svg-pYDteUUwhbi3b5dB .image-shape .label,#mermaid-svg-pYDteUUwhbi3b5dB .icon-shape .label{text-align:center;}#mermaid-svg-pYDteUUwhbi3b5dB .node.clickable{cursor:pointer;}#mermaid-svg-pYDteUUwhbi3b5dB .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-pYDteUUwhbi3b5dB .arrowheadPath{fill:#333333;}#mermaid-svg-pYDteUUwhbi3b5dB .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-pYDteUUwhbi3b5dB .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-pYDteUUwhbi3b5dB .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-pYDteUUwhbi3b5dB .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-pYDteUUwhbi3b5dB .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-pYDteUUwhbi3b5dB .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-pYDteUUwhbi3b5dB .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-pYDteUUwhbi3b5dB .cluster text{fill:#333;}#mermaid-svg-pYDteUUwhbi3b5dB .cluster span{color:#333;}#mermaid-svg-pYDteUUwhbi3b5dB div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-pYDteUUwhbi3b5dB .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-pYDteUUwhbi3b5dB rect.text{fill:none;stroke-width:0;}#mermaid-svg-pYDteUUwhbi3b5dB .icon-shape,#mermaid-svg-pYDteUUwhbi3b5dB .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-pYDteUUwhbi3b5dB .icon-shape p,#mermaid-svg-pYDteUUwhbi3b5dB .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-pYDteUUwhbi3b5dB .icon-shape .label rect,#mermaid-svg-pYDteUUwhbi3b5dB .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-pYDteUUwhbi3b5dB .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-pYDteUUwhbi3b5dB .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-pYDteUUwhbi3b5dB :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-pYDteUUwhbi3b5dB .input>*{fill:#EEF4FF!important;stroke:#5B8FF9!important;color:#1D39C4!important;stroke-width:1.2px!important;}#mermaid-svg-pYDteUUwhbi3b5dB .input span{fill:#EEF4FF!important;stroke:#5B8FF9!important;color:#1D39C4!important;stroke-width:1.2px!important;}#mermaid-svg-pYDteUUwhbi3b5dB .input tspan{fill:#1D39C4!important;}#mermaid-svg-pYDteUUwhbi3b5dB .process>*{fill:#FFF7E6!important;stroke:#FA8C16!important;color:#AD4E00!important;stroke-width:1.2px!important;}#mermaid-svg-pYDteUUwhbi3b5dB .process span{fill:#FFF7E6!important;stroke:#FA8C16!important;color:#AD4E00!important;stroke-width:1.2px!important;}#mermaid-svg-pYDteUUwhbi3b5dB .process tspan{fill:#AD4E00!important;}#mermaid-svg-pYDteUUwhbi3b5dB .output>*{fill:#E6FFFB!important;stroke:#13C2C2!important;color:#006D75!important;stroke-width:1.2px!important;}#mermaid-svg-pYDteUUwhbi3b5dB .output span{fill:#E6FFFB!important;stroke:#13C2C2!important;color:#006D75!important;stroke-width:1.2px!important;}#mermaid-svg-pYDteUUwhbi3b5dB .output tspan{fill:#006D75!important;} 结果阶段
处理阶段
输入阶段
筛选条件
表单选择
抽屉打开
生成参数
请求接口
字段转换
刷新列表
表单回显
状态更新

交给 Codex 生成时,要明确联动边界:只处理源码中存在的字段和接口,不把其他学生画像、考试分析或 AI 评估能力塞进本模块。保存动作必须保证 刷新考试列表、成绩表、座位网格、容量统计和导出任务。

可以直接使用下面的Prompt进行数据联动设计

text 复制代码
请为 座位划分 设计数据联动实现。

联动字段:selectedClass、selectedExam、studentScoreTable、rules、seatRows、seatCols、disabledSeatLabels、seat_plan
接口参数:class_name、exam_code、rows、cols、rules、disabled_seat_labels
结果回填:刷新考试列表、成绩表、座位网格、容量统计和导出任务
源码边界:只使用当前模块已经存在的模型字段、api.ts 请求和页面组件,不新增未实现的业务能力。

请输出联动流程、字段映射表、异常处理、保存回显规则和需要修改的文件路径。

批量处理

座位划分的批量处理不是简单多选删除,而是把一组学生或班级数据按业务规则一次性生成结果。源码中的 generate_seat_plan 按整班学生生成 seat_plan、seat_matrix、arranged_count、overflow_count 需要统计成功、跳过、失败和更新数量,便于页面提示和后续验收。
#mermaid-svg-UXdy9F4apSHsn4te{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-UXdy9F4apSHsn4te .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-UXdy9F4apSHsn4te .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-UXdy9F4apSHsn4te .error-icon{fill:#552222;}#mermaid-svg-UXdy9F4apSHsn4te .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-UXdy9F4apSHsn4te .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-UXdy9F4apSHsn4te .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-UXdy9F4apSHsn4te .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-UXdy9F4apSHsn4te .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-UXdy9F4apSHsn4te .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-UXdy9F4apSHsn4te .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-UXdy9F4apSHsn4te .marker{fill:#333333;stroke:#333333;}#mermaid-svg-UXdy9F4apSHsn4te .marker.cross{stroke:#333333;}#mermaid-svg-UXdy9F4apSHsn4te svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-UXdy9F4apSHsn4te p{margin:0;}#mermaid-svg-UXdy9F4apSHsn4te .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-UXdy9F4apSHsn4te .cluster-label text{fill:#333;}#mermaid-svg-UXdy9F4apSHsn4te .cluster-label span{color:#333;}#mermaid-svg-UXdy9F4apSHsn4te .cluster-label span p{background-color:transparent;}#mermaid-svg-UXdy9F4apSHsn4te .label text,#mermaid-svg-UXdy9F4apSHsn4te span{fill:#333;color:#333;}#mermaid-svg-UXdy9F4apSHsn4te .node rect,#mermaid-svg-UXdy9F4apSHsn4te .node circle,#mermaid-svg-UXdy9F4apSHsn4te .node ellipse,#mermaid-svg-UXdy9F4apSHsn4te .node polygon,#mermaid-svg-UXdy9F4apSHsn4te .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-UXdy9F4apSHsn4te .rough-node .label text,#mermaid-svg-UXdy9F4apSHsn4te .node .label text,#mermaid-svg-UXdy9F4apSHsn4te .image-shape .label,#mermaid-svg-UXdy9F4apSHsn4te .icon-shape .label{text-anchor:middle;}#mermaid-svg-UXdy9F4apSHsn4te .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-UXdy9F4apSHsn4te .rough-node .label,#mermaid-svg-UXdy9F4apSHsn4te .node .label,#mermaid-svg-UXdy9F4apSHsn4te .image-shape .label,#mermaid-svg-UXdy9F4apSHsn4te .icon-shape .label{text-align:center;}#mermaid-svg-UXdy9F4apSHsn4te .node.clickable{cursor:pointer;}#mermaid-svg-UXdy9F4apSHsn4te .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-UXdy9F4apSHsn4te .arrowheadPath{fill:#333333;}#mermaid-svg-UXdy9F4apSHsn4te .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-UXdy9F4apSHsn4te .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-UXdy9F4apSHsn4te .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-UXdy9F4apSHsn4te .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-UXdy9F4apSHsn4te .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-UXdy9F4apSHsn4te .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-UXdy9F4apSHsn4te .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-UXdy9F4apSHsn4te .cluster text{fill:#333;}#mermaid-svg-UXdy9F4apSHsn4te .cluster span{color:#333;}#mermaid-svg-UXdy9F4apSHsn4te div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-UXdy9F4apSHsn4te .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-UXdy9F4apSHsn4te rect.text{fill:none;stroke-width:0;}#mermaid-svg-UXdy9F4apSHsn4te .icon-shape,#mermaid-svg-UXdy9F4apSHsn4te .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-UXdy9F4apSHsn4te .icon-shape p,#mermaid-svg-UXdy9F4apSHsn4te .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-UXdy9F4apSHsn4te .icon-shape .label rect,#mermaid-svg-UXdy9F4apSHsn4te .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-UXdy9F4apSHsn4te .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-UXdy9F4apSHsn4te .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-UXdy9F4apSHsn4te :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-UXdy9F4apSHsn4te .input>*{fill:#EEF4FF!important;stroke:#5B8FF9!important;color:#1D39C4!important;stroke-width:1.2px!important;}#mermaid-svg-UXdy9F4apSHsn4te .input span{fill:#EEF4FF!important;stroke:#5B8FF9!important;color:#1D39C4!important;stroke-width:1.2px!important;}#mermaid-svg-UXdy9F4apSHsn4te .input tspan{fill:#1D39C4!important;}#mermaid-svg-UXdy9F4apSHsn4te .process>*{fill:#FFF7E6!important;stroke:#FA8C16!important;color:#AD4E00!important;stroke-width:1.2px!important;}#mermaid-svg-UXdy9F4apSHsn4te .process span{fill:#FFF7E6!important;stroke:#FA8C16!important;color:#AD4E00!important;stroke-width:1.2px!important;}#mermaid-svg-UXdy9F4apSHsn4te .process tspan{fill:#AD4E00!important;}#mermaid-svg-UXdy9F4apSHsn4te .check>*{fill:#F9F0FF!important;stroke:#722ED1!important;color:#531DAB!important;stroke-width:1.2px!important;}#mermaid-svg-UXdy9F4apSHsn4te .check span{fill:#F9F0FF!important;stroke:#722ED1!important;color:#531DAB!important;stroke-width:1.2px!important;}#mermaid-svg-UXdy9F4apSHsn4te .check tspan{fill:#531DAB!important;}#mermaid-svg-UXdy9F4apSHsn4te .output>*{fill:#E6FFFB!important;stroke:#13C2C2!important;color:#006D75!important;stroke-width:1.2px!important;}#mermaid-svg-UXdy9F4apSHsn4te .output span{fill:#E6FFFB!important;stroke:#13C2C2!important;color:#006D75!important;stroke-width:1.2px!important;}#mermaid-svg-UXdy9F4apSHsn4te .output tspan{fill:#006D75!important;} 批量输入
规则校验
事务处理
统计结果
页面反馈

交给 Codex 生成时,要要求接口返回结构化汇总,不要只返回一句成功。重复账号、未分班学生、无座位容量、空数据等情况都需要明确处理。

可以直接使用下面的Prompt进行批量处理功能设计

text 复制代码
请为 座位划分 设计批量处理能力。

真实批量操作:generate_seat_plan 按整班学生生成 seat_plan、seat_matrix、arranged_count、overflow_count
要求:校验输入、统计成功数量、统计跳过数量、统计失败数量、返回结构化 data,并在前端显示明确提示。
不要新增源码中未实现的批量流程。

导入导出

座位划分的导出能力围绕 export_seat_plan_download_task 生成座位表 Excel 并写入下载中心 展开。后端生成 Excel 字节流并创建下载中心任务,前端只接收 download_center_id 和提示信息,避免在业务页面直接处理文件流。
#mermaid-svg-jZON9C4vnqunckIC{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-jZON9C4vnqunckIC .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-jZON9C4vnqunckIC .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-jZON9C4vnqunckIC .error-icon{fill:#552222;}#mermaid-svg-jZON9C4vnqunckIC .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-jZON9C4vnqunckIC .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-jZON9C4vnqunckIC .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-jZON9C4vnqunckIC .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-jZON9C4vnqunckIC .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-jZON9C4vnqunckIC .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-jZON9C4vnqunckIC .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-jZON9C4vnqunckIC .marker{fill:#333333;stroke:#333333;}#mermaid-svg-jZON9C4vnqunckIC .marker.cross{stroke:#333333;}#mermaid-svg-jZON9C4vnqunckIC svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-jZON9C4vnqunckIC p{margin:0;}#mermaid-svg-jZON9C4vnqunckIC .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-jZON9C4vnqunckIC .cluster-label text{fill:#333;}#mermaid-svg-jZON9C4vnqunckIC .cluster-label span{color:#333;}#mermaid-svg-jZON9C4vnqunckIC .cluster-label span p{background-color:transparent;}#mermaid-svg-jZON9C4vnqunckIC .label text,#mermaid-svg-jZON9C4vnqunckIC span{fill:#333;color:#333;}#mermaid-svg-jZON9C4vnqunckIC .node rect,#mermaid-svg-jZON9C4vnqunckIC .node circle,#mermaid-svg-jZON9C4vnqunckIC .node ellipse,#mermaid-svg-jZON9C4vnqunckIC .node polygon,#mermaid-svg-jZON9C4vnqunckIC .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-jZON9C4vnqunckIC .rough-node .label text,#mermaid-svg-jZON9C4vnqunckIC .node .label text,#mermaid-svg-jZON9C4vnqunckIC .image-shape .label,#mermaid-svg-jZON9C4vnqunckIC .icon-shape .label{text-anchor:middle;}#mermaid-svg-jZON9C4vnqunckIC .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-jZON9C4vnqunckIC .rough-node .label,#mermaid-svg-jZON9C4vnqunckIC .node .label,#mermaid-svg-jZON9C4vnqunckIC .image-shape .label,#mermaid-svg-jZON9C4vnqunckIC .icon-shape .label{text-align:center;}#mermaid-svg-jZON9C4vnqunckIC .node.clickable{cursor:pointer;}#mermaid-svg-jZON9C4vnqunckIC .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-jZON9C4vnqunckIC .arrowheadPath{fill:#333333;}#mermaid-svg-jZON9C4vnqunckIC .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-jZON9C4vnqunckIC .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-jZON9C4vnqunckIC .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-jZON9C4vnqunckIC .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-jZON9C4vnqunckIC .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-jZON9C4vnqunckIC .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-jZON9C4vnqunckIC .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-jZON9C4vnqunckIC .cluster text{fill:#333;}#mermaid-svg-jZON9C4vnqunckIC .cluster span{color:#333;}#mermaid-svg-jZON9C4vnqunckIC div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-jZON9C4vnqunckIC .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-jZON9C4vnqunckIC rect.text{fill:none;stroke-width:0;}#mermaid-svg-jZON9C4vnqunckIC .icon-shape,#mermaid-svg-jZON9C4vnqunckIC .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-jZON9C4vnqunckIC .icon-shape p,#mermaid-svg-jZON9C4vnqunckIC .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-jZON9C4vnqunckIC .icon-shape .label rect,#mermaid-svg-jZON9C4vnqunckIC .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-jZON9C4vnqunckIC .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-jZON9C4vnqunckIC .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-jZON9C4vnqunckIC :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-jZON9C4vnqunckIC .input>*{fill:#EEF4FF!important;stroke:#5B8FF9!important;color:#1D39C4!important;stroke-width:1.2px!important;}#mermaid-svg-jZON9C4vnqunckIC .input span{fill:#EEF4FF!important;stroke:#5B8FF9!important;color:#1D39C4!important;stroke-width:1.2px!important;}#mermaid-svg-jZON9C4vnqunckIC .input tspan{fill:#1D39C4!important;}#mermaid-svg-jZON9C4vnqunckIC .process>*{fill:#FFF7E6!important;stroke:#FA8C16!important;color:#AD4E00!important;stroke-width:1.2px!important;}#mermaid-svg-jZON9C4vnqunckIC .process span{fill:#FFF7E6!important;stroke:#FA8C16!important;color:#AD4E00!important;stroke-width:1.2px!important;}#mermaid-svg-jZON9C4vnqunckIC .process tspan{fill:#AD4E00!important;}#mermaid-svg-jZON9C4vnqunckIC .output>*{fill:#E6FFFB!important;stroke:#13C2C2!important;color:#006D75!important;stroke-width:1.2px!important;}#mermaid-svg-jZON9C4vnqunckIC .output span{fill:#E6FFFB!important;stroke:#13C2C2!important;color:#006D75!important;stroke-width:1.2px!important;}#mermaid-svg-jZON9C4vnqunckIC .output tspan{fill:#006D75!important;} 导出参数
生成表格
创建任务
下载中心

Codex 生成时要保留下载中心任务模式,不能把导出结果硬塞到列表接口。文件名、任务名、描述信息需要带上班级、考试或模块标识,便于用户在下载中心识别。

可以直接使用下面的Prompt进行导入导出功能设计

text 复制代码
请为 座位划分 设计导出能力。

真实导出逻辑:export_seat_plan_download_task 生成座位表 Excel 并写入下载中心
后端要求:生成 Excel 内容,调用 create_download_center_task,返回 download_center_id。
前端要求:按钮触发导出接口,展示任务创建提示,不直接处理二进制文件。
不要添加源码中未实现的导入流程。

Codex开发标准

使用 Codex 开发座位划分时,不能直接让模型自由写代码。PDD 定义业务边界和验收口径,SOP 约束目录、文件职责和开发顺序,接口权限规则保证生成代码能进入现有系统。
#mermaid-svg-d5mmoRH3K352p3lv{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-d5mmoRH3K352p3lv .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-d5mmoRH3K352p3lv .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-d5mmoRH3K352p3lv .error-icon{fill:#552222;}#mermaid-svg-d5mmoRH3K352p3lv .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-d5mmoRH3K352p3lv .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-d5mmoRH3K352p3lv .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-d5mmoRH3K352p3lv .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-d5mmoRH3K352p3lv .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-d5mmoRH3K352p3lv .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-d5mmoRH3K352p3lv .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-d5mmoRH3K352p3lv .marker{fill:#333333;stroke:#333333;}#mermaid-svg-d5mmoRH3K352p3lv .marker.cross{stroke:#333333;}#mermaid-svg-d5mmoRH3K352p3lv svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-d5mmoRH3K352p3lv p{margin:0;}#mermaid-svg-d5mmoRH3K352p3lv .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-d5mmoRH3K352p3lv .cluster-label text{fill:#333;}#mermaid-svg-d5mmoRH3K352p3lv .cluster-label span{color:#333;}#mermaid-svg-d5mmoRH3K352p3lv .cluster-label span p{background-color:transparent;}#mermaid-svg-d5mmoRH3K352p3lv .label text,#mermaid-svg-d5mmoRH3K352p3lv span{fill:#333;color:#333;}#mermaid-svg-d5mmoRH3K352p3lv .node rect,#mermaid-svg-d5mmoRH3K352p3lv .node circle,#mermaid-svg-d5mmoRH3K352p3lv .node ellipse,#mermaid-svg-d5mmoRH3K352p3lv .node polygon,#mermaid-svg-d5mmoRH3K352p3lv .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-d5mmoRH3K352p3lv .rough-node .label text,#mermaid-svg-d5mmoRH3K352p3lv .node .label text,#mermaid-svg-d5mmoRH3K352p3lv .image-shape .label,#mermaid-svg-d5mmoRH3K352p3lv .icon-shape .label{text-anchor:middle;}#mermaid-svg-d5mmoRH3K352p3lv .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-d5mmoRH3K352p3lv .rough-node .label,#mermaid-svg-d5mmoRH3K352p3lv .node .label,#mermaid-svg-d5mmoRH3K352p3lv .image-shape .label,#mermaid-svg-d5mmoRH3K352p3lv .icon-shape .label{text-align:center;}#mermaid-svg-d5mmoRH3K352p3lv .node.clickable{cursor:pointer;}#mermaid-svg-d5mmoRH3K352p3lv .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-d5mmoRH3K352p3lv .arrowheadPath{fill:#333333;}#mermaid-svg-d5mmoRH3K352p3lv .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-d5mmoRH3K352p3lv .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-d5mmoRH3K352p3lv .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-d5mmoRH3K352p3lv .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-d5mmoRH3K352p3lv .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-d5mmoRH3K352p3lv .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-d5mmoRH3K352p3lv .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-d5mmoRH3K352p3lv .cluster text{fill:#333;}#mermaid-svg-d5mmoRH3K352p3lv .cluster span{color:#333;}#mermaid-svg-d5mmoRH3K352p3lv div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-d5mmoRH3K352p3lv .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-d5mmoRH3K352p3lv rect.text{fill:none;stroke-width:0;}#mermaid-svg-d5mmoRH3K352p3lv .icon-shape,#mermaid-svg-d5mmoRH3K352p3lv .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-d5mmoRH3K352p3lv .icon-shape p,#mermaid-svg-d5mmoRH3K352p3lv .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-d5mmoRH3K352p3lv .icon-shape .label rect,#mermaid-svg-d5mmoRH3K352p3lv .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-d5mmoRH3K352p3lv .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-d5mmoRH3K352p3lv .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-d5mmoRH3K352p3lv :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-d5mmoRH3K352p3lv .input>*{fill:#EEF4FF!important;stroke:#5B8FF9!important;color:#1D39C4!important;stroke-width:1.2px!important;}#mermaid-svg-d5mmoRH3K352p3lv .input span{fill:#EEF4FF!important;stroke:#5B8FF9!important;color:#1D39C4!important;stroke-width:1.2px!important;}#mermaid-svg-d5mmoRH3K352p3lv .input tspan{fill:#1D39C4!important;}#mermaid-svg-d5mmoRH3K352p3lv .design>*{fill:#F6FFED!important;stroke:#52C41A!important;color:#237804!important;stroke-width:1.2px!important;}#mermaid-svg-d5mmoRH3K352p3lv .design span{fill:#F6FFED!important;stroke:#52C41A!important;color:#237804!important;stroke-width:1.2px!important;}#mermaid-svg-d5mmoRH3K352p3lv .design tspan{fill:#237804!important;}#mermaid-svg-d5mmoRH3K352p3lv .dev>*{fill:#FFF7E6!important;stroke:#FA8C16!important;color:#AD4E00!important;stroke-width:1.2px!important;}#mermaid-svg-d5mmoRH3K352p3lv .dev span{fill:#FFF7E6!important;stroke:#FA8C16!important;color:#AD4E00!important;stroke-width:1.2px!important;}#mermaid-svg-d5mmoRH3K352p3lv .dev tspan{fill:#AD4E00!important;}#mermaid-svg-d5mmoRH3K352p3lv .check>*{fill:#F9F0FF!important;stroke:#722ED1!important;color:#531DAB!important;stroke-width:1.2px!important;}#mermaid-svg-d5mmoRH3K352p3lv .check span{fill:#F9F0FF!important;stroke:#722ED1!important;color:#531DAB!important;stroke-width:1.2px!important;}#mermaid-svg-d5mmoRH3K352p3lv .check tspan{fill:#531DAB!important;} 验收交付
Codex开发
模块设计
输入约束
需求边界
PDD设计
SOP目录
接口权限
后端设计
前端设计
扩展功能
读取上下文
生成后端
生成前端
补齐扩展
功能自检
PDD验收
问题修复
模块交付

SOP 标准

SOP 用来约束代码目录、文件职责和开发顺序。座位划分的目录结构需要贴合现有 User 模块,不应为单篇文章另起一套风格。

text 复制代码
server_backend/modules/User/
  views_app/SeatAllocation.py
  utils.py
  urls.py
server_vue3/src/views/modules/User/SeatAllocation/
  index.vue
server_vue3/src/views/modules/User/UserWorkbenchesApplication/
  index.vue
docs/modules/座位划分/
  pdd.md
  api.md
  test-cases.md
  codex-sop.md
开发阶段 Codex 执行目标 输出结果
模块设计 读取模型、视图、路由和前端页面 pdd.md 明确业务边界
目录规划 对齐后端 views_app、前端模块目录和接口封装 codex-sop.md 明确文件职责
后端实现 生成模型序列化、视图接口、筛选和权限校验 后端接口可被前端稳定调用
前端实现 生成列表、表单、抽屉、按钮和接口调用 页面操作闭环可运行
功能补齐 按真实扩展能力补齐联动、批量、文件或生成逻辑 扩展能力与源码一致
验收修复 根据 PDD 和测试用例修复偏差 test-cases.md 与代码一致

可以直接使用下面的Prompt进行SOP撰写

text 复制代码
请为 座位划分 编写 Codex 开发 SOP。

要求:
- 先输出目录结构,不要直接写代码。
- 先生成 docs/modules/座位划分/pdd.md、api.md、test-cases.md 和 codex-sop.md。
- 目录必须贴合现有路径:server_backend/modules/User/views_app/SeatAllocation.py、server_backend/modules/User/utils.py、server_vue3/src/views/modules/User/SeatAllocation/index.vue、UserWorkbenchesApplication/index.vue。
- SOP 需要约束模型字段、接口视图、路由注册、前端 crud 配置、接口封装、权限按钮、保存回显和扩展能力。
- 扩展能力只包含:数据联动、批量处理、导入导出。
- 文档完成后,再按 SOP 分阶段生成项目代码。

PDD 标准

PDD 是座位划分的设计与验收文档,用于判断 Codex 输出是否符合真实业务。验收不能只看页面能否打开,还要检查字段、接口、权限、筛选、联动和扩展能力是否匹配源码。

验收维度 验收重点 通过标准
业务目标 按班级加载学生和考试成绩,设置行列、关闭座位、性别互补、性格互补、学业互补和特殊学生关注规则,生成座位表并创建下载中心导出任务。 页面和接口能支撑模块业务闭环
页面结构 server_vue3/src/views/modules/User/SeatAllocation/index.vue、UserWorkbenchesApplication/index.vue 列表、表单、抽屉或操作按钮与源码一致
数据模型 该视图使用 DummyModel 作为 ViewSet 占位,核心数据来自 StudentManage、StudentAdmissionAssessment、TestingCenter.ExaminationStudentScore 和下载中心任务 字段类型、只读字段、唯一约束不偏离模型
接口规则 /api/User/SeatAllocation/get_class_exams/、get_class_students/、generate_seat_plan/、export_seat_plan_download_task/ 列表、保存、删除、动作接口请求参数正确
权限控制 登录用户、班级范围或系统权限 非授权数据不可越权访问
测试用例 正常、异常、空数据、回显和删除 test-cases.md 覆盖主要路径
数据联动 班级、考试、规则和座位布局联动 切换班级或考试后成绩与座位同步刷新
批量处理 整班排座 容量不足、关闭座位和空班级处理正确
导入导出 座位表导出任务 下载中心任务创建成功并返回 ID

可以直接使用下面的Prompt进行PDD 验收

text 复制代码
请根据 docs/modules/座位划分/pdd.md 对 座位划分 进行验收。

验收范围:业务目标、页面结构、数据模型、接口规则、权限控制、测试用例、数据联动、批量处理、导入导出。

请输出验收结果表,字段包含:验收项、通过状态、发现问题、涉及文件、修复建议。不要只给结论;必须指出未通过项的具体文件位置和建议改法。

总结

座位划分把班级学生、考试成绩、性格测评和座位规则汇总为可执行的班级排座方案,是班主任日常治理中高频且有明确业务闭环的模块。

Codex 开发该模块时,应由 PDD 定义排座规则、接口参数和导出边界,由 SOP 约束后端算法与前端工作台结构,再用 Prompt 分阶段实现联动、批量排座和下载任务。

相关推荐
IT毕设实战小研8 小时前
基于大数据的商场商铺数据分析与可视化的设计与实现
android·java·大数据·django·课程设计
华科大胡子9 小时前
Codex 下载与本地部署实战:从安装到跑通全流程
codex
troy1281 天前
Python 基础语法(九):Django/Flask/FastAPI 三大 Web 框架详细对比解析
python·jupyter·django·flask·github·fastapi
高洁011 天前
大模型的幻觉怎么治
人工智能·深度学习·django·transformer·tornado
新时代牛马1 天前
容器里拿到root 就等于宿主机沦陷?Capability、seccomp、AppArmor与user ns 讲透
django
烂蜻蜓1 天前
Django入门教程(十六):Cookie与Session详解——用户状态管理的底层原理与实战
django
仙逆GPT1 天前
ChatGPT、Codex趋势:Agent越来越会自己分派子任务以后,为什么“任务路由”会比Agent数量更重要?
codex·ai agent·chatgptplus·多agent·chatgptpro
j7~1 天前
【C++微服务项目开发脚手架】(环境篇)虚拟机 + Docker + MySQL/Redis/RabbitMQ/ES/etcd/FastDFS 全套配齐
linux·c++·ubuntu·docker·vmware·项目开发·微服务脚手架
言乐61 天前
Python:用AES-GCM算法加密链接内容,并生成可分享的加密链接和解密工具
python·django·virtualenv·pygame·tornado