# 上传数据页面 UI 设计文档 ## 1. 页面概述 ### 1.1 功能描述 上传数据页面是纪检初核系统中项目管理模块的核心页面,支持在一个项目中上传多个主体/账户数据进行汇总/独立分析。提供流水导入、征信导入、员工家庭关系导入、名单库选择等功能。 ### 1.2 页面路径 - 菜单位置:项目管理 > 项目详情 > 上传数据 - 路由路径:`/project/:id/upload-data` ### 1.3 页面状态 - 项目状态:已完成 - 最后更新时间:2024-01-20 15:30 --- ## 2. 页面布局 ### 2.1 整体结构 ``` ┌─────────────────────────────────────────────────────────────┐ │ 面包屑导航:项目管理 / 项目详情 / 上传数据 │ ├─────────────────────────────────────────────────────────────┤ │ 页面标题区 │ │ ┌───────────────────────────────────────────────────────┐ │ │ │ 上传数据 │ │ │ │ 项目状态:已完成 最后更新:2024-01-20 15:30 │ │ │ │ 支持在一个项目中上传多个主体/账户数据,进行汇总/独立分析 │ │ │ └───────────────────────────────────────────────────────┘ │ ├─────────────────────────────────────────────────────────────┤ │ 主要内容区(网格布局) │ │ ┌─────────────────┐ ┌─────────────────┐ │ │ │ 流水导入 │ │ 已上传流水查询 │ │ │ │ [上传组件] │ │ [上传组件] │ │ │ └─────────────────┘ └─────────────────┘ │ │ ┌─────────────────┐ ┌─────────────────┐ │ │ │ 征信导入 │ │ 员工家庭关系导入 │ │ │ │ [上传组件] │ │ [上传组件] │ │ │ └─────────────────┘ └─────────────────┘ │ │ ┌─────────────────────────────────────────────┐ │ │ │ 名单库选择 │ │ │ │ ☑ 高风险人员名单(68人) ☑ 历史可疑人员名单 │ │ │ │ ☑ 监管关注名单(32人) │ │ │ └─────────────────────────────────────────────┘ │ ├─────────────────────────────────────────────────────────────┤ │ 数据质量检查区 │ │ ┌────────────────────────────────────────────────────────┐ │ │ │ 数据完整性 格式一致性 余额连续性 │ │ │ │ 98.5% 95.2% 92.8% │ │ │ │ 检查结果: [查看详情] │ │ │ │ • 发现 23 条数据格式不一致 │ │ │ │ • 发现 5 条余额连续性异常 │ │ │ │ • 发现 12 条缺失关键字段 │ │ │ └────────────────────────────────────────────────────────┘ │ ├─────────────────────────────────────────────────────────────┤ │ 操作按钮区 │ │ [拉取本行信息] [生成报告] │ └─────────────────────────────────────────────────────────────┘ ``` ### 2.2 响应式布局 - 桌面端(≥1200px):4列网格布局 - 平板端(768px-1199px):2列网格布局 - 移动端(<768px):单列布局 --- ## 3. 组件设计 ### 3.1 FileUploadCard 上传卡片组件 **Props:** ```typescript interface FileUploadCardProps { title: string; // 卡片标题 description: string; // 描述文字 acceptTypes: string[]; // 接受的文件类型,如 ['xlsx', 'xls', 'pdf'] maxSize?: number; // 最大文件大小(MB),默认 10 multiple?: boolean; // 是否支持多文件上传 uploadUrl: string; // 上传接口地址 onUploadSuccess?: (files: UploadedFile[]) => void; onUploadError?: (error: Error) => void; showFileList?: boolean; // 是否显示已上传文件列表 } ``` **UI 结构:** ```vue ``` ### 3.2 CheckboxGroupSelector 名单库选择组件 **Props:** ```typescript interface CheckboxGroupSelectorProps { options: NameListOption[]; modelValue: string[]; onChange: (value: string[]) => void; } interface NameListOption { label: string; // 显示文本 value: string; // 选中值 count: number; // 人数统计 disabled?: boolean; } ``` **UI 结构:** ```vue ``` ### 3.3 DataQualityPanel 数据质量检查面板 **Props:** ```typescript interface DataQualityPanelProps { metrics: QualityMetric[]; issues: QualityIssue[]; onCheckQuality?: () => void; onViewDetails?: (issue: QualityIssue) => void; } interface QualityMetric { name: string; // 指标名称 value: number; // 百分比值 status: 'good' | 'warning' | 'error'; } interface QualityIssue { type: string; // 问题类型 count: number; // 数量 description: string; details?: any[]; } ``` **UI 结构:** ```vue ``` --- ## 4. 交互说明 ### 4.1 文件上传流程 1. **拖拽上传** - 用户拖拽文件到上传区域 - 显示上传进度条 - 上传成功后显示成功提示 - 自动添加到已上传文件列表 2. **点击上传** - 点击上传区域触发文件选择对话框 - 选择文件后开始上传 - 显示上传进度 3. **文件验证** - 文件格式验证:只接受指定格式 - 文件大小验证:超过限制显示错误提示 - 重复文件验证:同名文件提示是否覆盖 4. **上传状态** - 上传中:显示进度条 - 上传成功:绿色勾选标记 - 上传失败:红色错误标记,显示错误信息 ### 4.2 名单库选择 1. 默认选中全部名单库 2. 点击复选框切换选中状态 3. 实时更新选中人数统计 4. 取消选中时显示确认提示 ### 4.3 数据质量检查 1. **自动触发** - 文件上传完成后自动触发 - 显示检查进度 2. **手动触发** - 点击"重新检查"按钮 - 覆盖之前的检查结果 3. **结果展示** - 三个核心指标以环形进度图展示 - 颜色指示:绿色(≥95%)、黄色(85-94%)、红色(<85%) - 问题列表按严重程度排序 ### 4.4 按钮操作 1. **拉取本行信息** - 点击后显示加载状态 - 从本行系统拉取相关数据 - 完成后显示成功提示并刷新页面 2. **生成报告** - 验证必须上传至少一个文件 - 显示报告生成进度 - 生成成功后跳转到报告页面 --- ## 5. 数据结构 ### 5.1 后端接口 #### 5.1.1 获取项目上传数据状态 ```typescript GET /api/project/{projectId}/upload-status Response: { "code": 200, "data": { "projectStatus": "已完成", "lastUpdateTime": "2024-01-20 15:30:00", "uploadedFiles": { "transactionFiles": [], // 流水文件列表 "inquiryFiles": [], // 征信文件列表 "familyRelationFiles": [] // 家庭关系文件列表 }, "selectedNameLists": [], // 已选名单库 "qualityMetrics": { // 质量指标 "completeness": 98.5, "consistency": 95.2, "continuity": 92.8 }, "qualityIssues": [] // 质量问题列表 } } ``` #### 5.1.2 上传文件接口 ```typescript POST /api/project/{projectId}/upload Content-Type: multipart/form-data Body: { "fileType": "transaction" | "inquiry" | "family_relation", "files": File[] } Response: { "code": 200, "data": { "successCount": 2, "failedCount": 0, "uploadedFiles": [ { "fileId": "123456", "fileName": "流水数据.xlsx", "fileSize": 2048576, "uploadTime": "2024-01-20 15:30:00", "status": "success" } ] } } ``` #### 5.1.3 删除文件接口 ```typescript DELETE /api/project/{projectId}/file/{fileId} Response: { "code": 200, "msg": "删除成功" } ``` #### 5.1.4 获取名单库列表 ```typescript GET /api/name-list/options Response: { "code": 200, "data": [ { "value": "high_risk", "label": "高风险人员名单", "count": 68 }, { "value": "history_suspicious", "label": "历史可疑人员名单", "count": 45 }, { "value": "regulatory_focus", "label": "监管关注名单", "count": 32 } ] } ``` #### 5.1.5 更新名单库选择 ```typescript PUT /api/project/{projectId}/name-lists Body: { "selectedLists": ["high_risk", "history_suspicious", "regulatory_focus"] } Response: { "code": 200, "msg": "更新成功" } ``` #### 5.1.6 执行数据质量检查 ```typescript POST /api/project/{projectId}/quality-check Response: { "code": 200, "data": { "checkId": "qc_123456", "status": "completed", "metrics": { "completeness": 98.5, "consistency": 95.2, "continuity": 92.8 }, "issues": [ { "type": "format_inconsistency", "count": 23, "description": "条数据格式不一致" }, { "type": "balance_anomaly", "count": 5, "description": "条余额连续性异常" }, { "type": "missing_field", "count": 12, "description": "条缺失关键字段" } ] } } ``` #### 5.1.7 拉取本行信息 ```typescript POST /api/project/{projectId}/pull-bank-info Response: { "code": 200, "msg": "拉取成功", "data": { "pulledRecords": 156, "pullTime": "2024-01-20 15:35:00" } } ``` #### 5.1.8 生成报告 ```typescript POST /api/project/{projectId}/generate-report Response: { "code": 200, "data": { "reportId": "rpt_789012", "reportUrl": "/project/123/report/rpt_789012", "generateTime": "2024-01-20 15:40:00" } } ``` ### 5.2 前端数据模型 ```typescript // 上传文件类型 type UploadFileType = 'transaction' | 'inquiry' | 'family_relation'; // 上传文件状态 type UploadStatus = 'uploading' | 'success' | 'error'; // 上传的文件 interface UploadedFile { fileId: string; fileName: string; fileSize: number; uploadTime: string; status: UploadStatus; errorMessage?: string; } // 名单库选项 interface NameListOption { value: string; label: string; count: number; disabled?: boolean; } // 质量指标 interface QualityMetric { name: string; value: number; status: 'good' | 'warning' | 'error'; } // 质量问题 interface QualityIssue { type: string; count: number; description: string; details?: any[]; } // 项目上传数据状态 interface ProjectUploadStatus { projectStatus: string; lastUpdateTime: string; uploadedFiles: { transactionFiles: UploadedFile[]; inquiryFiles: UploadedFile[]; familyRelationFiles: UploadedFile[]; }; selectedNameLists: string[]; qualityMetrics: { completeness: number; consistency: number; continuity: number; }; qualityIssues: QualityIssue[]; } ``` --- ## 6. 样式规范 ### 6.1 颜色规范 ```scss // 主色 $primary-color: #409EFF; $success-color: #67C23A; $warning-color: #E6A23C; $danger-color: #F56C6C; $info-color: #909399; // 中性色 $text-primary: #303133; $text-regular: #606266; $text-secondary: #909399; $text-placeholder: #C0C4CC; // 边框色 $border-base: #DCDFE6; $border-light: #E4E7ED; $border-lighter: #EBEEF5; $border-extra-light: #F2F6FC; // 背景色 $bg-color: #F5F7FA; $card-bg: #FFFFFF; ``` ### 6.2 间距规范 ```scss $spacing-xs: 4px; $spacing-sm: 8px; $spacing-md: 16px; $spacing-lg: 24px; $spacing-xl: 32px; ``` ### 6.3 圆角规范 ```scss $border-radius-sm: 2px; $border-radius-base: 4px; $border-radius-lg: 8px; $border-radius-circle: 50%; ``` ### 6.4 阴影规范 ```scss $box-shadow-base: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04); $box-shadow-dark: 0 2px 8px rgba(0, 0, 0, 0.15), 0 0 6px rgba(0, 0, 0, 0.1); $box-shadow-light: 0 2px 12px 0 rgba(0, 0, 0, 0.1); ``` --- ## 7. 组件样式代码 ### 7.1 上传卡片样式 ```scss .upload-card { height: 100%; .card-header { display: flex; align-items: center; justify-content: space-between; h3 { margin: 0; font-size: 16px; font-weight: 500; color: $text-primary; } .el-icon-info { color: $info-color; cursor: help; } } .upload-area { margin-bottom: $spacing-md; .el-upload-dragger { width: 100%; height: 180px; border: 2px dashed $border-base; border-radius: $border-radius-lg; background: $bg-color; transition: all 0.3s; &:hover { border-color: $primary-color; background: #F0F7FF; } } .upload-content { display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100%; .el-icon-upload { font-size: 48px; color: $primary-color; margin-bottom: $spacing-sm; } p { margin: $spacing-xs 0; font-size: 14px; color: $text-regular; } .upload-tip { font-size: 12px; color: $text-secondary; } } } .file-list { border-top: 1px solid $border-light; padding-top: $spacing-md; h4 { margin: 0 0 $spacing-sm 0; font-size: 14px; color: $text-primary; } } } ``` ### 7.2 数据质量面板样式 ```scss .quality-panel { .panel-header { display: flex; align-items: center; justify-content: space-between; h3 { margin: 0; font-size: 16px; font-weight: 500; } } .metrics-container { display: flex; justify-content: space-around; margin-bottom: $spacing-lg; .metric-item { display: flex; flex-direction: column; align-items: center; .el-progress { margin-bottom: $spacing-sm; } .metric-name { font-size: 14px; color: $text-regular; } } } .issues-section { border-top: 1px solid $border-light; padding-top: $spacing-md; h4 { margin: 0 0 $spacing-md 0; font-size: 14px; color: $text-primary; } .issue-item { margin-bottom: $spacing-sm; &:last-child { margin-bottom: 0; } } } } ``` ### 7.3 页面整体布局样式 ```scss .upload-data-page { padding: $spacing-lg; background: $bg-color; min-height: calc(100vh - 84px); .page-header { background: $card-bg; padding: $spacing-lg; border-radius: $border-radius-lg; margin-bottom: $spacing-lg; box-shadow: $box-shadow-base; h1 { margin: 0 0 $spacing-sm 0; font-size: 24px; font-weight: 500; } .page-info { display: flex; gap: $spacing-lg; font-size: 14px; color: $text-secondary; margin-top: $spacing-sm; .info-item { display: flex; align-items: center; .label { margin-right: $spacing-xs; } .status { color: $success-color; } } } .page-description { margin-top: $spacing-md; padding: $spacing-md; background: #F0F9FF; border-left: 3px solid $primary-color; border-radius: $border-radius-base; font-size: 14px; color: $text-regular; } } .upload-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: $spacing-lg; margin-bottom: $spacing-lg; @media (min-width: 1200px) { grid-template-columns: repeat(4, 1fr); } @media (max-width: 767px) { grid-template-columns: 1fr; } } .full-width { grid-column: 1 / -1; } .action-bar { display: flex; justify-content: center; gap: $spacing-lg; margin-top: $spacing-xl; } } ``` --- ## 8. 技术实现要点 ### 8.1 文件上传 - 使用 Element UI 的 `el-upload` 组件 - 支持拖拽上传和点击上传 - 实现文件类型和大小校验 - 显示上传进度 - 支持断点续传(可选) ### 8.2 数据质量检查 - 异步执行检查任务 - 使用 WebSocket 或轮询获取检查进度 - 实时更新进度和结果 ### 8.3 状态管理 - 使用 Vuex 管理上传状态 - 缓存已上传文件列表 - 同步名单库选择状态 ### 8.4 性能优化 - 文件分片上传大文件 - 使用 Web Worker 处理文件预检查 - 虚拟滚动展示大量文件列表 --- ## 9. 测试要点 ### 9.1 功能测试 - 文件上传各种格式 - 文件大小限制验证 - 删除文件功能 - 名单库选择功能 - 数据质量检查准确性 - 报告生成功能 ### 9.2 兼容性测试 - 主流浏览器兼容 - 不同屏幕尺寸适配 - 文件格式兼容性 ### 9.3 性能测试 - 大文件上传性能 - 多文件同时上传 - 页面加载性能 ### 9.4 异常处理测试 - 网络中断处理 - 文件上传失败处理 - 服务器错误处理 - 文件格式错误处理 --- ## 10. 附录 ### 10.1 相关页面 - 项目详情页:`/project/:id/detail` - 参数配置页:`/project/:id/config` - 初核结果页:`/project/:id/result` - 报告页面:`/project/:id/report/:reportId` ### 10.2 权限要求 - 需要项目成员权限 - 上传操作需要编辑权限 - 删除操作需要删除权限 - 生成报告需要报告权限 ### 10.3 相关文档 - [Element UI Upload 组件文档](https://element.eleme.cn/#/zh-CN/component/upload) - [若依框架前端开发规范](../前端开发规范.md) - [项目接口文档](../API文档/项目管理模块.md) --- **文档版本**: v1.0 **创建时间**: 2024-01-30 **最后更新**: 2024-01-30 **文档状态**: 待评审