# PaperManagementPanel 题目配置组件重设计 > 日期: 2026-05-29 > 状态: 待审核 > 范围: PaperManagementPanel.vue 全面模块化拆分与视觉优化 ## 1. 背景与目标 ### 1.1 现状问题 `src/components/exam/PaperManagementPanel.vue` 是一个 **2235 行的巨型单文件组件**,包含 6 个独立功能区全部耦合在一起: | 维度 | 当前数值 | |------|----------| | Template | 567 行 | | Script | ~1065 行 | | Style | ~600 行 | | 功能区数 | 6+ 个 | | 硬编码颜色值 | ~30 处(未使用 design-tokens) | | console.log | ~40 处(调试残留) | ### 1.2 设计目标 1. **组件拆分**: 将单文件拆分为 7 个子组件 + 2 个 composable,每个 < 350 行 2. **代码精简**: 移除冗余逻辑、调试日志、硬编码颜色 3. **视觉优化**: 延续现有扁平设计风格,统一使用 design-tokens 4. **交互改进**: 优化组卷配置区控件、预览区展示、弹窗体验 5. **响应式**: 保持移动端/平板/桌面断点适配 ## 2. 组件架构 ### 2.1 文件结构 ``` src/components/exam/ ├── PaperManagementPanel.vue # 主容器 (~80行) ├── ComposePanel.vue # 智能组卷面板 - 左右分栏容器 (~50行) │ ├── ComposeConfigSidebar.vue # 左侧配置栏 (~200行) │ └── ComposePreviewPane.vue # 右侧预览区 (~180行) ├── PaperListTab.vue # 草稿/已发布列表 - 复用型 (~150行) ├── PaperDetailModal.vue # 试卷详情弹窗 (~250行) ├── PublishDialog.vue # 发布弹窗 (~300行) ├── EntityPickerModal.vue # 通用实体选择器弹窗 (~180行) ├── composables/ │ ├── usePaperManagement.js # 共享状态管理 (~400行) │ └── useQuestionParser.js # 题目数据解析工具 (~150行) └── common/ # 已有公共组件 (不变更) ├── PageHeader.vue ├── StatsRow.vue └── ContentCard.vue ``` ### 2.2 组件树与数据流 ``` PaperManagementPanel (主容器) │ ├─ usePaperManagement (composable: 全局状态中心) │ ├─► Tab Navigation (内置: 智能组卷 / 我的草稿 / 已发布试卷) │ ├─► [activeTab='compose'] ComposePanel │ ├─► ComposeConfigSidebar │ │ props: form, selectedFiles, allFiles, loadingFiles │ │ emit: generate, update:form │ └─► ComposePreviewPane │ props: result, composing, totalScore │ emit: save │ ├─► [activeTab='drafts'] PaperListTab(mode='drafts') │ props: papers, loading │ emit: view, publish, delete │ ├─► [activeTab='published'] PaperListTab(mode='published') │ props: papers, loading │ emit: view, revoke │ ├─► PaperDetailModal (Teleport to body) │ v-model: visible │ props: rawData │ ├─► PublishDialog (Teleport to body) │ v-model: visible │ props: paperId │ emit: confirm │ └─► EntityPickerModal (Teleport to body) │ v-model: visible │ props: type, mode, sourceList, selectedIds │ emit: confirm └─► EntityPickerModal (独立使用场景预留) ``` ### 2.3 通信原则 - **单向数据流**: 父 → 子通过 props,子 → 父通过 emits - **状态提升**: 所有业务状态集中在 `usePaperManagement` composable - **v-model 模式**: 弹窗类组件支持 `v-model:visible` 双向绑定 - **接口最小化**: 每个子组件只暴露必要的 props/emits ## 3. 各组件详细设计 ### 3.1 PaperManagementPanel.vue — 主容器 **职责**: Tab 导航 + 子组件编排 + 状态初始化 **Template 结构**: ```html
``` **Script**: 仅做 composable 解构和事件转发,< 80 行 --- ### 3.2 ComposeConfigSidebar.vue — 组卷配置栏 **职责**: 数据源选择、难度设置、题型数量配置、生成触发 #### Props ```typescript { modelValue: { // composeForm 对象 difficulty: Number, // 1-5 include_personal: Boolean, single_choice_count: Number, multiple_choice_count: Number, true_false_count: Number, fill_blank_count: Number, subjective_count: Number }, selectedFiles: Array, // 已选文件列表 allFiles: Array, // 全量文件列表 loadingFiles: Boolean, totalCount: Number // 计算属性:各题型数量之和 } ``` #### Emits ```typescript { 'update:modelValue': [form], // 表单变更 'toggle-file': [file], // 文件选择切换 'remove-file': [id], // 移除已选文件 'open-picker': [], // 打开文件选择器 'close-picker': [], // 收起文件选择器 'generate': [] // 触发生成试卷 } ``` #### 视觉改进点 | 改进项 | 当前实现 | 新设计 | |--------|----------|--------| | Step 标识 | 圆形数字 badge (1/2/3) | 分隔线 + 小标题,减少视觉噪音 | | 题型数量控件 | `[-] 数字 [+]` 按钮 | Native `