Files
STP/docs/architecture/详细设计/评标专家信息维护模块详细设计.md
T

22 KiB
Raw Blame History

评标专家信息维护模块详细设计

1. 概述

1.1 设计目标

评标专家信息维护模块是专家登录后管理个人档案的核心枢纽,设计目标包括:

  • 信息统一管理:集中维护个人基本信息、专业资质、执业资格、联系方式等。
  • 财务信息独立维护:管理银行账户信息,确保评审劳务报酬准确发放。
  • 安全自主可控:支持密码修改、手机/邮箱更换、登录设备管理等安全操作。

1.2 适用角色

  • 已注册并通过审核的外部评标专家。
  • 不同专家根据其专业领域和职称等级,展示差异化内容(如高级职称可参评更高级别项目)。

1.3 核心功能模块

模块 功能简述
个人资料 查看与修改基本信息(工作单位、从事专业、职称等),敏感字段变更需审核
专业资质 上传/更新职称证书、执业资格证书,AI辅助识别与真伪校验
银行账户 维护开户银行及账号(加密存储),用于劳务报酬发放
安全设置 修改密码、更换手机号/邮箱、踢出设备、查看登录日志

2. 页面布局总览

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 820" font-family="'Microsoft YaHei', sans-serif">
  <defs>
    <filter id="shadow" x="-2%" y="-2%" width="104%" height="104%">
      <feDropShadow dx="0" dy="4" stdDeviation="8" flood-color="#000" flood-opacity="0.06"/>
    </filter>
    <filter id="shadowDeep" x="-2%" y="-2%" width="104%" height="104%">
      <feDropShadow dx="0" dy="6" stdDeviation="12" flood-color="#000" flood-opacity="0.10"/>
    </filter>
    <linearGradient id="headerBg" x1="0" y1="0" x2="1" y2="0">
      <stop offset="0%" stop-color="#1a237e"/><stop offset="100%" stop-color="#283593"/>
    </linearGradient>
    <linearGradient id="brandGrad" x1="0%" y1="0%" x2="100%" y2="100%">
      <stop offset="0%" stop-color="#1a237e"/><stop offset="100%" stop-color="#283593"/>
    </linearGradient>
  </defs>
  
  <!-- 背景 -->
  <rect width="1200" height="820" fill="#f5f7fa"/>
  
  <!-- ===== 顶部导航栏 ===== -->
  <rect width="1200" height="64" fill="url(#headerBg)"/>
  <text x="40" y="42" font-size="22" font-weight="bold" fill="#fff">智慧招标平台</text>
  <text x="190" y="42" font-size="13" fill="rgba(255,255,255,0.8)">Smart Tendering Platform</text>
  
  <!-- 导航菜单 -->
  <text x="440" y="42" font-size="15" fill="rgba(255,255,255,0.8)">首页</text>
  <text x="520" y="42" font-size="15" fill="rgba(255,255,255,0.8)">招标公告</text>
  <text x="620" y="42" font-size="15" fill="rgba(255,255,255,0.8)">定标公告</text>
  <text x="720" y="42" font-size="15" fill="rgba(255,255,255,0.8)">企业新闻</text>
  
  <!-- 已登录用户 -->
  <circle cx="1030" cy="32" r="16" fill="rgba(255,255,255,0.3)"/>
  <text x="1030" y="37" text-anchor="middle" font-size="12" fill="#fff"></text>
  <text x="1060" y="37" font-size="14" fill="#fff">王建国</text>
  <text x="1110" y="37" font-size="12" fill="rgba(255,255,255,0.7)"></text>

  <!-- ===== 内容区:左侧菜单 + 右侧内容 ===== -->
  
  <!-- 左侧菜单栏(精简为4项) -->
  <rect x="40" y="90" width="220" height="690" rx="12" fill="#fff" filter="url(#shadow)"/>
  
  <!-- 专家头像 & 基本信息 -->
  <circle cx="150" cy="145" r="50" fill="#e8eaf6" stroke="#c5cae9" stroke-width="2"/>
  <text x="150" y="150" text-anchor="middle" font-size="28" fill="#1a237e" font-weight="bold"></text>
  <text x="150" y="210" text-anchor="middle" font-size="16" font-weight="bold" fill="#1a2332">王建国</text>
  <text x="150" y="235" text-anchor="middle" font-size="13" fill="#4a5568">高级工程师 · 化工专业</text>
  <rect x="80" y="250" width="140" height="24" rx="12" fill="#4caf50"/>
  <text x="150" y="267" text-anchor="middle" font-size="12" fill="#fff">✅ 专家库已入库</text>
  
  <line x1="60" y1="290" x2="240" y2="290" stroke="#f0f2f7" stroke-width="1"/>
  
  <!-- 菜单项(仅保留4项) -->
  <rect x="60" y="310" width="180" height="40" rx="8" fill="#e8eaf6"/>
  <text x="150" y="336" text-anchor="middle" font-size="14" font-weight="bold" fill="#1a237e">👤 个人资料</text>
  
  <rect x="60" y="365" width="180" height="40" rx="8" fill="#f5f5f5"/>
  <text x="150" y="391" text-anchor="middle" font-size="14" fill="#4a5568">🎓 专业资质</text>
  
  <rect x="60" y="420" width="180" height="40" rx="8" fill="#f5f5f5"/>
  <text x="150" y="446" text-anchor="middle" font-size="14" fill="#4a5568">🏦 银行账户</text>
  
  <rect x="60" y="475" width="180" height="40" rx="8" fill="#f5f5f5"/>
  <text x="150" y="501" text-anchor="middle" font-size="14" fill="#4a5568">🔐 安全设置</text>

  <!-- ===== 右侧内容区 ===== -->
  <rect x="280" y="90" width="880" height="690" rx="12" fill="#fff" filter="url(#shadow)"/>
  
  <!-- 页面标题 -->
  <text x="310" y="130" font-size="20" font-weight="bold" fill="#1a2332">👤 个人资料</text>
  <text x="310" y="158" font-size="14" fill="#8895aa">维护您的个人信息,确保资料准确无误</text>
  
  <line x1="310" y1="175" x2="1120" y2="175" stroke="#f0f2f7" stroke-width="2"/>

  <!-- 表单区(两列布局) -->
  <!-- 第一列 -->
  <text x="310" y="215" font-size="14" fill="#4a5568">真实姓名 <tspan fill="#e91e63">*</tspan></text>
  <rect x="310" y="225" width="240" height="38" rx="6" fill="#f5f6fa" stroke="#e0e4ec"/>
  <text x="325" y="250" font-size="14" fill="#1a2332">王建国</text>

  <text x="610" y="215" font-size="14" fill="#4a5568">性别 <tspan fill="#e91e63">*</tspan></text>
  <rect x="610" y="225" width="240" height="38" rx="6" fill="#f5f6fa" stroke="#e0e4ec"/>
  <text x="625" y="250" font-size="14" fill="#1a2332"></text>

  <!-- 第二行 -->
  <text x="310" y="295" font-size="14" fill="#4a5568">身份证号码 <tspan fill="#e91e63">*</tspan></text>
  <rect x="310" y="305" width="240" height="38" rx="6" fill="#f5f6fa" stroke="#e0e4ec"/>
  <text x="325" y="330" font-size="14" fill="#1a2332">110101********4477</text>
  <text x="560" y="330" font-size="12" fill="#4caf50">✅ 已实名认证</text>

  <text x="610" y="295" font-size="14" fill="#4a5568">出生日期</text>
  <rect x="610" y="305" width="240" height="38" rx="6" fill="#f5f6fa" stroke="#e0e4ec"/>
  <text x="625" y="330" font-size="14" fill="#1a2332">1975-03-07</text>

  <!-- 第三行 -->
  <text x="310" y="375" font-size="14" fill="#4a5568">工作单位 <tspan fill="#e91e63">*</tspan></text>
  <rect x="310" y="385" width="240" height="38" rx="6" fill="#ffffff" stroke="#e0e4ec"/>
  <text x="325" y="410" font-size="14" fill="#b0bbcc">请输入工作单位</text>

  <text x="610" y="375" font-size="14" fill="#4a5568">现从事专业 <tspan fill="#e91e63">*</tspan></text>
  <rect x="610" y="385" width="240" height="38" rx="6" fill="#ffffff" stroke="#e0e4ec"/>
  <text x="625" y="410" font-size="14" fill="#b0bbcc">请输入专业名称</text>

  <!-- 第四行 -->
  <text x="310" y="455" font-size="14" fill="#4a5568">技术职称 <tspan fill="#e91e63">*</tspan></text>
  <rect x="310" y="465" width="240" height="38" rx="6" fill="#ffffff" stroke="#e0e4ec"/>
  <text x="325" y="490" font-size="14" fill="#b0bbcc">请选择职称等级</text>

  <text x="610" y="455" font-size="14" fill="#4a5568">职称专业 <tspan fill="#e91e63">*</tspan></text>
  <rect x="610" y="465" width="240" height="38" rx="6" fill="#ffffff" stroke="#e0e4ec"/>
  <text x="625" y="490" font-size="14" fill="#b0bbcc">请输入职称专业</text>

  <!-- 第五行 -->
  <text x="310" y="535" font-size="14" fill="#4a5568">手机号码 <tspan fill="#e91e63">*</tspan></text>
  <rect x="310" y="545" width="240" height="38" rx="6" fill="#f5f6fa" stroke="#e0e4ec"/>
  <text x="325" y="570" font-size="14" fill="#1a2332">138****8000</text>
  <text x="560" y="570" font-size="12" fill="#4caf50">✅ 已验证</text>

  <text x="610" y="535" font-size="14" fill="#4a5568">电子邮箱 <tspan fill="#e91e63">*</tspan></text>
  <rect x="610" y="545" width="240" height="38" rx="6" fill="#f5f6fa" stroke="#e0e4ec"/>
  <text x="625" y="570" font-size="14" fill="#1a2332">wangjg@example.com</text>
  <text x="860" y="570" font-size="12" fill="#4caf50">✅ 已验证</text>

  <!-- 底部按钮 -->
  <line x1="310" y1="620" x2="1120" y2="620" stroke="#f0f2f7" stroke-width="2"/>
  
  <rect x="900" y="640" width="120" height="40" rx="8" fill="#e0e4ec"/>
  <text x="960" y="666" text-anchor="middle" font-size="15" fill="#666">取消</text>
  
  <rect x="1040" y="640" width="120" height="40" rx="8" fill="url(#brandGrad)"/>
  <text x="1100" y="666" text-anchor="middle" font-size="15" font-weight="bold" fill="#fff">保存修改</text>

  <!-- 右侧小滨 AI 助手 -->
  <rect x="840" y="660" width="220" height="105" rx="10" fill="#ffffff" stroke="#e0e4ec" filter="url(#shadow)"/>
  <circle cx="860" cy="685" r="14" fill="#1a237e"/>
  <text x="860" y="690" text-anchor="middle" font-size="10" fill="#fff" font-weight="bold">小滨</text>
  <text x="885" y="690" font-size="13" font-weight="bold" fill="#1a2332">AI 助手</text>
  <rect x="845" y="705" width="200" height="45" rx="6" fill="#e8eaf6" stroke="#c5cae9"/>
  <text x="860" y="725" font-size="11" fill="#1a237e">💡 温馨提示</text>
  <text x="860" y="742" font-size="10" fill="#4a5568">· 修改手机号/邮箱需双因子验证</text>
  <text x="860" y="752" font-size="10" fill="#4a5568">· 银行账号变更需验证登录密码</text>
</svg>

3. 各功能模块详细说明

3.1 左侧菜单栏

菜单项 图标 说明 高亮规则
个人资料 👤 基本信息维护(姓名、身份证、单位、职称、联系方式等) 默认高亮
专业资质 🎓 职称证书、执业资格证书的上传与更新,AI辅助识别 点击切换
银行账户 🏦 维护开户行、户名、银行账号,用于评审劳务报酬发放 点击切换
安全设置 🔐 修改密码、更换手机号/邮箱、登录设备管理、查看登录日志 点击切换

3.2 个人资料(默认激活页)

页面功能

  • 展示并允许修改专家的基本档案信息。
  • 所有字段均来自注册时提交的数据,除联系方式外,其他字段(姓名、身份证、职称等)变更需经过“AI审核”或“人工复核”(与供应商营业执照变更逻辑一致,确保资质真实性)。

字段列表

字段名 组件类型 是否必填 备注
真实姓名 只读文本 变更需提交证明材料人工审核
性别 只读文本 从身份证自动识别
身份证号码 只读(脱敏) 变更需人工审核(关键标识)
出生日期 只读文本 从身份证自动计算
工作单位 文本输入框 可修改(需人工复核)
现从事专业 文本输入框 可修改
技术职称 下拉选择 高级/副高级/中级/初级
职称专业 文本输入框 如:化学工程与工艺
手机号码 文本输入框 修改需双因子验证(旧+新)
电子邮箱 文本输入框 修改需双因子验证(旧+新)

关键字段变更规则

字段 变更是否需要审核 审核方式
姓名 需上传身份证正反面扫描件,AI比对+人工复核
身份证号 是(阻断) 系统唯一标识,变更走特殊流程(人工/线下)
职称/专业 需上传新职称证书扫描件,AI识别+人工审核
工作单位 人工审核(原单位离职风险)
手机/邮箱 否(即时生效) 双因子验证通过即可

3.3 专业资质

页面功能

  • 展示当前上传的职称/执业资格证书文件列表(类似供应商的资质文件管理)。
  • 支持上传新证书、重命名、删除旧证书。
  • AI 自动识别证书真伪(防篡改检测)和信息提取(证书编号、发证机关、有效期等)。

文件列表示例

文件名称 上传时间 大小 状态 操作
职称证书_教授.pdf 2026-06-15 2.1MB 已认证 重命名 / 删除
注册化工工程师资格证书.pdf 2026-05-20 3.4MB 审核中 删除

操作

  • 上传新资质文件(支持 PDF/JPG/PNG,≤20MB)。
  • 删除/重命名。
  • 点击文件名预览文件。

3.4 银行账户

页面功能

  • 维护专家的银行账户信息,用于支付评审报酬。
  • 字段:开户银行名称、开户行网点、户名、银行账号。
  • 银行账号加密存储AES-256-GCM,与全局安全策略一致)。
  • 修改需验证当前登录密码(或短信验证码)防止盗用。

字段列表

字段名 组件类型 是否必填 备注
开户银行名称 下拉选择/文本输入 如:中国银行、工商银行
开户行网点 文本输入框 如:中国银行北京分行营业部
户名 只读文本 与专家真实姓名一致(自动关联)
银行账号 文本输入框(掩码) 显示后4位,修改时需输入完整账号
确认银行账号 文本输入框(掩码) 修改时需二次输入确认

安全要求

  • 银行账号仅显示后 4 位(如 **** **** **** 8888)。
  • 修改时需进行身份二次验证(短信验证码或当前登录密码)。

3.5 安全设置

功能与供应商安全设置一致,包括:

功能项 验证强度 说明
修改登录密码 高(验证旧密码) 强制密码复杂度;修改后清除所有会话,重新登录
更换绑定手机号 最高(旧+新双因子) 新号全局唯一,30天内限3次
更换绑定邮箱 最高(旧+新双因子) 新邮箱全局唯一,30天内限3次
登录设备管理 中(登录态+二次确认) 查看在线设备列表,支持“踢出所有设备”
登录日志查看 低(仅登录态) 最近90天登录记录,异常登录自动标记(红底)

4. 关键业务流程

4.1 联系人信息变更(手机号/邮箱)流程

flowchart TD
    A[专家点击修改手机号] --> B[输入新手机号]
    B --> C[系统校验新号是否已被占用]
    C -->|已被占用| D[提示“该手机号已被其他专家绑定”]
    C -->|未被占用| E[发送验证码至旧手机]
    E --> F[专家输入旧手机验证码]
    F --> G{验证通过?}
    G -->|否| H[提示错误,可重试(5次锁定)]
    G -->|是| I[发送验证码至新手机]
    I --> J[输入新手机验证码]
    J --> K{验证通过?}
    K -->|否| L[提示错误]
    K -->|是| M[提交变更请求]
    M --> N[数据库更新手机号]
    N --> O[更新登录名(若为登录凭证)]
    O --> P[清除所有验证码缓存]
    P --> Q[记录审计日志]
    Q --> R[发送通知至新旧手机号]

4.2 资质证书更新(AI审核)流程

flowchart TD
    A[专家上传新职称证书] --> B[文件上传至OSS]
    B --> C[调用OCR服务提取文字字段]
    C --> D[AI真实性审查(ELA/翻拍检测)]
    D -->|不通过| E[驳回:证书疑似伪造或翻拍]
    D -->|通过| F[AI提取信息:证书编号/发证机关/有效期等]
    F --> G[与数据库现有字段比对]
    G --> H{关键信息是否变更?}
    H -->|否| I[仅更新文件URL]
    H -->|是| J[记录变更差异,触发人工复核]
    J --> K[推送待办至管理员]
    K --> L[管理员审核]
    L -->|通过| M[更新主表+记录审计]
    L -->|不通过| N[驳回并通知专家]

4.3 银行账户修改流程

flowchart TD
    A[专家点击“修改银行账户”] --> B[弹窗显示当前账户信息(脱敏)]
    B --> C[输入新开户行、新账号、确认账号]
    C --> D[点击“下一步”]
    D --> E[发送短信验证码至绑定手机]
    E --> F[输入短信验证码]
    F --> G{验证通过?}
    G -->|否| H[提示错误,可重试]
    G -->|是| I[提交变更请求]
    I --> J[数据库更新银行账号(加密存储)]
    J --> K[记录审计日志(含新旧账号)]
    K --> L[发送通知至手机/邮箱]

4.4 安全设置 —— 修改密码流程

sequenceDiagram
    participant U as 专家
    participant FE as 前端
    participant Svc as 账户服务
    participant DB as 数据库
    participant Cache as Redis

    U->>FE: 填写旧密码+新密码
    FE->>FE: 前端校验(非空/强度/新旧不同)
    FE->>Svc: PUT /api/v1/expert/password
    Svc->>DB: 查询当前密码哈希
    DB-->>Svc: password_hash
    Svc->>Svc: 比对旧密码
    alt 旧密码错误
        Svc->>Cache: INCR fail_count
        alt fail_count >= 5
            Svc-->>FE: 403 账号已锁定30分钟
        else <5
            Svc-->>FE: 401 当前密码错误
        end
    else 旧密码正确
        Svc->>Cache: DEL fail_count
        Svc->>Svc: 新密码哈希
        Svc->>DB: UPDATE password_hash
        Svc->>Cache: DEL 所有会话
        Svc-->>FE: 200 成功,请重新登录
        FE->>FE: 清除本地Token,跳转登录页
    end

5. 数据模型

5.1 专家信息表 t_expert_profile(核心字段)

字段名 类型 约束 说明
expert_id VARCHAR(32) PK 专家档案编号
user_id VARCHAR(32) FK 关联STP用户账号表
real_name VARCHAR(64) NOT NULL 真实姓名
id_card_no VARCHAR(128) NOT NULL, UNIQUE 身份证号(AES-256加密)
id_card_md5 CHAR(32) UNIQUE MD5盲索引
gender TINYINT 1-男,2-女
birth_date DATE 出生日期
company VARCHAR(128) 工作单位
profession VARCHAR(64) NOT NULL 从事专业
title VARCHAR(32) NOT NULL 职称等级
title_major VARCHAR(64) 职称专业
phone VARCHAR(128) NOT NULL, UNIQUE 手机号(加密)
phone_md5 CHAR(32) UNIQUE MD5
email VARCHAR(128) NOT NULL 邮箱
bank_name VARCHAR(64) 开户银行
bank_branch VARCHAR(128) 开户行网点
bank_account VARCHAR(128) 银行账号(加密)
bank_account_md5 CHAR(32) MD5
status VARCHAR(20) NOT NULL ACTIVE/LOCKED/REJECTED
activated_at DATETIME 激活时间
updated_at DATETIME 更新时间

5.2 资质证书表 t_expert_qualification

字段名 类型 说明
id BIGINT PK
expert_id VARCHAR(32) FK
file_name VARCHAR(256) 文件显示名称
file_url VARCHAR(512) OSS存储URL
file_size BIGINT 文件大小(字节)
ocr_result JSON OCR识别结果(含证书编号、发证机关、有效期)
audit_status VARCHAR(20) PASS / PENDING / FAIL
audit_comment TEXT 审核备注
upload_time DATETIME 上传时间
status VARCHAR(20) ACTIVE / DELETED

6. API 接口设计

6.1 获取专家信息

项目 内容
路径 GET /api/v1/expert/profile
响应 返回完整的专家信息(敏感字段脱敏)

6.2 更新专家信息(普通字段)

项目 内容
路径 PUT /api/v1/expert/profile
请求体 { "company": "新单位", "profession": "新专业" }
限制 姓名、身份证号、职称不允许通过此接口修改(或触发审核)

6.3 更新手机号/邮箱

项目 内容
路径 PUT /api/v1/expert/contact
请求体 { "field":"phone", "newValue":"...", "oldOtpToken":"...", "newOtpToken":"..." }

6.4 上传资质证书

项目 内容
路径 POST /api/v1/expert/qualification
方法 multipart/form-data
响应 { "fileId":"...", "auditStatus":"PENDING" }

6.5 删除资质证书

项目 内容
路径 DELETE /api/v1/expert/qualification/{fileId}

6.6 更新银行账户

项目 内容
路径 PUT /api/v1/expert/bank-account
请求体 { "bankName":"...", "bankBranch":"...", "bankAccount":"...", "confirmAccount":"...", "smsCode":"..." }

6.7 修改密码

项目 内容
路径 PUT /api/v1/expert/password
请求体 { "oldPassword":"...", "newPassword":"..." }

7. 业务规则汇总

ID 规则 适用场景
R01 身份证号全局唯一,不可重复注册(包括审核中状态) 注册/信息变更
R02 修改手机号/邮箱必须双因子验证(旧+新),即时生效 联系人变更
R03 修改姓名、职称、身份证号必须经 AI 审核或人工复核 个人资料变更
R04 银行账号加密存储,修改需短信验证码二次确认 银行账户
R05 上传资质证书自动触发 AI 真实性审查(ELA/翻拍检测) 专业资质
R06 所有信息变更均需记录审计日志(哈希链防篡改) 全场景
R07 专家账户锁定后,不可参与评标抽取(需管理员解封) 违规处理
R08 修改银行账号后,同步通知管理员(用于财务系统更新) 银行账户

8. 安全与合规

安全维度 措施
敏感信息加密 身份证号、手机号、银行账号使用 AES-256-GCM 字段级加密
脱敏展示 身份证号 110101********4477,手机号 138****8000,银行账号 **** **** **** 8888
审计追溯 所有变更操作(含IP、时间、新旧值)写入哈希链,保留≥7年
密码安全 同平台全局策略(Argon2id哈希,强度要求≥8位含大小写数字特殊字符)