# 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 `