# Design Document: Mobile Adaptation and Import Feature
## Overview
本设计文档描述工作统计系统的手机适配和数据导入功能的技术实现方案。手机适配将通过CSS媒体查询和Ant Design的响应式组件实现;导入功能将在后端使用openpyxl解析XLSX文件,前端使用Ant Design的Upload组件。
## Architecture
### 系统架构图
```mermaid
graph TB
subgraph Frontend
A[index.html] --> B[Viewport Meta]
C[Layout.jsx] --> D[Responsive Sider]
E[Components] --> F[Mobile CSS]
G[Import.jsx] --> H[Upload Component]
end
subgraph Backend
I[import_routes.py] --> J[ImportService]
J --> K[Template Generator]
J --> L[XLSX Parser]
L --> M[Data Validator]
M --> N[WorkRecord Creator]
end
H -->|POST /api/import/upload| I
H -->|GET /api/import/template| I
```
### 技术栈
- **前端**: React + Ant Design (响应式组件)
- **后端**: Flask + openpyxl (XLSX处理)
- **样式**: CSS Media Queries + Ant Design Grid
## Components and Interfaces
### 1. Viewport Configuration (index.html)
修改viewport meta标签以禁止用户缩放:
```html
```
### 2. Responsive Layout Component (Layout.jsx)
增强现有Layout组件以支持移动端:
```jsx
// 移动端检测
const [isMobile, setIsMobile] = useState(window.innerWidth < 768)
// 移动端使用Drawer替代Sider
{isMobile ? (
) : (
)}
```
### 3. Import Service (Backend)
新增 `backend/app/services/import_service.py`:
```python
class ImportService:
REQUIRED_COLUMNS = ['人员姓名', '物品名称', '工作日期', '数量']
MAX_FILE_SIZE = 5 * 1024 * 1024 # 5MB
@staticmethod
def generate_template() -> BytesIO:
"""生成导入模板XLSX文件"""
pass
@staticmethod
def parse_and_validate(file_content: bytes) -> Tuple[List[dict], List[str]]:
"""解析并验证XLSX文件内容
Returns: (valid_records, errors)
"""
pass
@staticmethod
def import_records(records: List[dict]) -> int:
"""批量创建工作记录
Returns: 成功导入的记录数
"""
pass
```
### 4. Import Routes (Backend)
新增 `backend/app/routes/import_routes.py`:
```python
@import_bp.route('/template', methods=['GET'])
def download_template():
"""下载导入模板"""
pass
@import_bp.route('/upload', methods=['POST'])
def upload_import():
"""上传并导入XLSX文件"""
pass
```
### 5. Import Component (Frontend)
新增 `frontend/src/components/Import.jsx`:
```jsx
function Import() {
// 模板下载
const handleDownloadTemplate = async () => { ... }
// 文件上传
const handleUpload = async (file) => { ... }
return (
{errors && }
{success && }
)
}
```
### 6. API Extensions
扩展 `frontend/src/services/api.js`:
```javascript
export const importApi = {
downloadTemplate: () => axios.get('/api/import/template', { responseType: 'blob' }),
upload: (file) => {
const formData = new FormData()
formData.append('file', file)
return api.post('/api/import/upload', formData, {
headers: { 'Content-Type': 'multipart/form-data' }
})
}
}
```
## Data Models
### Import Template Structure
| 列名 | 字段 | 类型 | 说明 |
|------|------|------|------|
| 人员姓名 | person_name | string | 必须匹配系统中已存在的人员 |
| 物品名称 | item_name | string | 必须匹配系统中已存在的物品 |
| 工作日期 | work_date | date | 格式: YYYY-MM-DD |
| 数量 | quantity | number | 正整数 |
### Import Response
```typescript
// 成功响应
interface ImportSuccessResponse {
success: true
count: number // 导入记录数
}
// 失败响应
interface ImportErrorResponse {
success: false
errors: string[] // 错误信息列表
}
```
## Correctness Properties
*A property is a characteristic or behavior that should hold true across all valid executions of a system—essentially, a formal statement about what the system should do. Properties serve as the bridge between human-readable specifications and machine-verifiable correctness guarantees.*
### Property 1: Template Column Completeness
*For any* generated import template, it SHALL contain all required columns (人员姓名, 物品名称, 工作日期, 数量) in the header row.
**Validates: Requirements 3.2**
### Property 2: XLSX Format Validation
*For any* uploaded file that is not a valid XLSX format, the Import_Service SHALL reject it with a format error.
**Validates: Requirements 4.2**
### Property 3: Required Column Validation
*For any* uploaded XLSX file missing one or more required columns, the Import_Service SHALL reject it with a column missing error.
**Validates: Requirements 4.3**
### Property 4: Row Validation Error Format
*For any* row with invalid data (non-existent person, non-existent item, invalid date format, non-positive quantity, or empty required field), the Import_Service SHALL return an error message containing the row number and specific error reason.
**Validates: Requirements 4.4, 4.5, 5.1, 5.2, 5.3, 5.4, 5.5**
### Property 5: Successful Import Record Count
*For any* valid import file with N rows of data, the Import_Service SHALL create exactly N work records and return count=N.
**Validates: Requirements 4.6, 4.7**
### Property 6: Atomic Import Operation
*For any* import file containing at least one invalid row, the Import_Service SHALL NOT create any work records (all-or-nothing).
**Validates: Requirements 4.8**
### Property 7: File Size Validation
*For any* uploaded file exceeding 5MB, the System SHALL reject the upload with a file size error.
**Validates: Requirements 4.11**
## Error Handling
### Backend Error Handling
| 错误类型 | HTTP状态码 | 错误消息格式 |
|---------|-----------|-------------|
| 文件格式错误 | 400 | "文件格式错误,请上传XLSX文件" |
| 文件过大 | 400 | "文件大小超过限制(最大5MB)" |
| 缺少必需列 | 400 | "缺少必需列: xxx" |
| 人员不存在 | 400 | "第X行: 人员 'xxx' 不存在" |
| 物品不存在 | 400 | "第X行: 物品 'xxx' 不存在" |
| 日期格式错误 | 400 | "第X行: 日期格式错误,应为 YYYY-MM-DD" |
| 数量无效 | 400 | "第X行: 数量必须为正数" |
| 字段为空 | 400 | "第X行: 'xxx' 不能为空" |
### Frontend Error Display
- 所有验证错误显示在可滚动列表中
- 第一个错误高亮显示
- 提供"重新上传"按钮
## Testing Strategy
### Unit Tests
1. **Template Generation Tests**
- 验证模板包含所有必需列
- 验证模板包含示例数据
- 验证日期格式正确
2. **Validation Tests**
- 测试各种无效输入的错误消息
- 测试边界条件(空文件、单行、多行)
3. **Import Tests**
- 测试成功导入场景
- 测试部分失败场景(原子性)
### Property-Based Tests
使用 `hypothesis` 库进行属性测试:
1. **Property 1**: 生成模板列完整性
2. **Property 4**: 验证错误消息格式
3. **Property 5**: 成功导入记录计数
4. **Property 6**: 原子性操作验证
### Test Configuration
- Property tests: 最少100次迭代
- 使用 pytest + hypothesis
- 测试标签格式: `**Feature: mobile-and-import, Property N: {property_text}**`
## Mobile Responsive Breakpoints
```css
/* 移动端 */
@media (max-width: 767px) {
/* 单列布局 */
/* 抽屉式导航 */
/* 卡片式表格 */
}
/* 平板 */
@media (min-width: 768px) and (max-width: 991px) {
/* 两列布局 */
}
/* 桌面 */
@media (min-width: 992px) {
/* 多列布局 */
}
```