Files
ccdi/doc/frontend/上传数据页面UI设计文档.md
2026-01-30 15:50:30 +08:00

23 KiB
Raw Blame History

上传数据页面 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 响应式布局

  • 桌面端≥1200px4列网格布局
  • 平板端768px-1199px2列网格布局
  • 移动端(<768px单列布局

3. 组件设计

3.1 FileUploadCard 上传卡片组件

Props:

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 结构:

<template>
  <el-card class="upload-card">
    <template #header>
      <div class="card-header">
        <h3>{{ title }}</h3>
        <el-tooltip :content="description" placement="top">
          <i class="el-icon-info"></i>
        </el-tooltip>
      </div>
    </template>

    <el-upload
      class="upload-area"
      :action="uploadUrl"
      :accept="acceptTypes.join(',')"
      :multiple="multiple"
      :limit="10"
      :file-list="fileList"
      :on-success="handleSuccess"
      :on-error="handleError"
      :before-upload="beforeUpload"
      drag
    >
      <div class="upload-content">
        <i class="el-icon-upload"></i>
        <p>拖拽文件到此处或点击上传</p>
        <p class="upload-tip">支持格式: {{ acceptTypes.join(', ') }}</p>
      </div>
    </el-upload>

    <div v-if="showFileList && uploadedFiles.length" class="file-list">
      <h4>已上传文件</h4>
      <el-table :data="uploadedFiles" size="small">
        <el-table-column prop="fileName" label="文件名" />
        <el-table-column prop="fileSize" label="大小" width="100" />
        <el-table-column prop="uploadTime" label="上传时间" width="160" />
        <el-table-column prop="status" label="状态" width="80">
          <template #default="{ row }">
            <el-tag :type="row.status === 'success' ? 'success' : 'danger'">
              {{ row.status === 'success' ? '成功' : '失败' }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column label="操作" width="100" fixed="right">
          <template #default="{ row }">
            <el-button type="text" size="small" @click="handleDelete(row)">
              删除
            </el-button>
          </template>
        </el-table-column>
      </el-table>
    </div>
  </el-card>
</template>

3.2 CheckboxGroupSelector 名单库选择组件

Props:

interface CheckboxGroupSelectorProps {
  options: NameListOption[];
  modelValue: string[];
  onChange: (value: string[]) => void;
}

interface NameListOption {
  label: string;      // 显示文本
  value: string;      // 选中值
  count: number;      // 人数统计
  disabled?: boolean;
}

UI 结构:

<template>
  <el-card class="name-list-selector">
    <template #header>
      <h3>名单库选择</h3>
    </template>
    <p class="selector-description">选择中介库管理内的名单</p>
    <el-checkbox-group v-model="selectedLists" @change="handleChange">
      <el-checkbox
        v-for="option in options"
        :key="option.value"
        :label="option.value"
        :disabled="option.disabled"
      >
        {{ option.label }}({{ option.count }})
      </el-checkbox>
    </el-checkbox-group>
  </el-card>
</template>

3.3 DataQualityPanel 数据质量检查面板

Props:

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 结构:

<template>
  <el-card class="quality-panel">
    <template #header>
      <div class="panel-header">
        <h3>数据质量检查</h3>
        <el-button type="primary" size="small" @click="handleCheck">
          重新检查
        </el-button>
      </div>
    </template>

    <!-- 质量指标 -->
    <div class="metrics-container">
      <div
        v-for="metric in metrics"
        :key="metric.name"
        class="metric-item"
        :class="`metric-${metric.status}`"
      >
        <el-progress
          type="circle"
          :percentage="metric.value"
          :status="metric.status"
        />
        <span class="metric-name">{{ metric.name }}</span>
      </div>
    </div>

    <!-- 问题列表 -->
    <div class="issues-section">
      <h4>检查结果</h4>
      <el-alert
        v-for="(issue, index) in issues"
        :key="index"
        :type="getIssueType(issue)"
        :closable="false"
        class="issue-item"
      >
        <template #title>
          发现 <strong>{{ issue.count }}</strong> {{ issue.description }}
        </template>
      </el-alert>
      <el-button type="text" @click="handleViewDetails">查看详情 →</el-button>
    </div>
  </el-card>
</template>

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 获取项目上传数据状态

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 上传文件接口

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 删除文件接口

DELETE /api/project/{projectId}/file/{fileId}

Response:
{
  "code": 200,
  "msg": "删除成功"
}

5.1.4 获取名单库列表

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 更新名单库选择

PUT /api/project/{projectId}/name-lists

Body:
{
  "selectedLists": ["high_risk", "history_suspicious", "regulatory_focus"]
}

Response:
{
  "code": 200,
  "msg": "更新成功"
}

5.1.6 执行数据质量检查

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 拉取本行信息

POST /api/project/{projectId}/pull-bank-info

Response:
{
  "code": 200,
  "msg": "拉取成功",
  "data": {
    "pulledRecords": 156,
    "pullTime": "2024-01-20 15:35:00"
  }
}

5.1.8 生成报告

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 前端数据模型

// 上传文件类型
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 颜色规范

// 主色
$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 间距规范

$spacing-xs: 4px;
$spacing-sm: 8px;
$spacing-md: 16px;
$spacing-lg: 24px;
$spacing-xl: 32px;

6.3 圆角规范

$border-radius-sm: 2px;
$border-radius-base: 4px;
$border-radius-lg: 8px;
$border-radius-circle: 50%;

6.4 阴影规范

$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 上传卡片样式

.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 数据质量面板样式

.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 页面整体布局样式

.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 相关文档


文档版本: v1.0 创建时间: 2024-01-30 最后更新: 2024-01-30 文档状态: 待评审