【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 分阶段实现联动、批量排座和下载任务。

相关推荐
Mr数据杨41 分钟前
【Codex】用系统配置工作台集中维护平台运行参数
django·codex·项目开发
Mr数据杨3 小时前
【Codex】用学生生活日常模块记录校园生活过程
django·生活·codex·项目开发
Mr数据杨4 小时前
【Codex】用角色管理模块控制不同岗位的数据与操作权限
django·codex·项目开发
Mr数据杨4 小时前
【Codex】用用户管理模块维护后台账号与登录权限
django·codex·项目开发
Mr数据杨7 小时前
【Codex】用学生支持周报模块跟踪个性化支持进展
android·java·javascript·django·codex·项目开发
零号栈帧7 小时前
Codex 手机控制台——AgentDeck
windows·cloudflare·codex·pwa·ai agent
Mr数据杨7 小时前
【Codex】用登录日志模块审计用户登录与访问行为
django·codex·项目开发
青 春 记 忆10 小时前
零基础入门python35:Django用户登录与权限边界
python·django·后端开发