Files
STP/docs/architecture/详细设计/供应商注册模块.md
T

56 KiB
Raw Blame History

智慧招标平台(STP)供应商注册模块详细设计说明书

文档名称 供应商注册模块详细设计说明书
文档版本 V1.0
编制日期 2026-06-30
关联文档 《需求分析说明书 V1.4》《供应商报名详细设计》《SRM接口方案》

目录

  1. 模块概述
  2. 用户角色与权限
  3. 页面UI详细设计
  4. 字段级校验规则
  5. AI自动审核详细设计
  6. 完整业务流程(含状态机)
  7. 时序图(含外部系统交互)
  8. 数据模型完整定义
  9. API接口详细规范
  10. 业务规则与约束
  11. 异常处理矩阵
  12. 通知策略
  13. SRM双向同步机制
  14. 供应商联系人变更(注册后维护)
  15. 安全与合规
  16. 附录

1. 模块概述

1.1 建设目标

建立面向潜在投标供应商的轻量化、全自动、即时生效的注册机制。注册阶段仅做主体身份认证(营业执照有效性核验),不进行人工资格审核。通过即开通平台登录权限和投标报名资格,深度资质审核后移至投标报名环节按项目要求执行

1.2 核心设计理念:注册与审核分离

阶段 审核内容 审核方式 通过标准
注册阶段 营业执照有效性、企业存续状态、基础信息一致性、严重违法筛查 全自动AI(无人工) 所有一票否决项通过
投标报名阶段 项目特定资质、业绩、财务能力、技术能力 AI初审 + 人工复核 满足具体项目资格要求

1.3 设计原则

  • 极简快速:提交即审核,5秒内出结果,无等待队列。
  • AI全自动:OCR + 工商API + 风险图谱全链路自动化。
  • 一次注册,双平台通用:自动同步至SRM,建立统一供应商身份(srm_id双向绑定)。
  • 审核后置:深度资质审核下沉至报名环节,降低准入门槛。
  • 安全合规:敏感字段(信用代码、手机号)AES-256-GCM加密存储,全量审计。

1.4 适用范围

  • 适用对象:所有拟参与滨化集团招标项目的潜在供应商(含工程、货物、服务类)。
  • 与SRM关系:新供应商自动在SRM创建档案(状态:待认证);已存续SRM供应商通过“无感登录”直接绑定,无需重复注册。

2. 用户角色与权限

角色 权限范围
供应商申请人(未注册) 访问注册页面、提交申请、查看审核结果。
已注册供应商(ACTIVE 登录平台、浏览公告、投标报名、维护企业信息(含联系人变更)。
供应商管理专员 查看注册统计、处理注册异常申诉、执行黑名单管理(冻结/解封)。
系统管理员 配置AI审核阈值、管理工商API密钥、查看系统日志。
合规/审计 查阅注册审计日志(只读)。

3. 页面UI详细设计

3.1 注册步骤导航条

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 100" font-family="'Microsoft YaHei', sans-serif">
  <rect width="1000" height="100" fill="#f8f9fc"/>
  <rect x="50" y="30" width="900" height="40" rx="20" fill="#fff" stroke="#e0e4ec"/>
  
  <circle cx="160" cy="50" r="18" fill="#c2185b"/>
  <text x="160" y="56" text-anchor="middle" font-size="14" fill="#fff" font-weight="bold">1</text>
  <text x="160" y="85" text-anchor="middle" font-size="12" fill="#c2185b" font-weight="bold">企业信息</text>
  <line x1="178" y1="50" x2="252" y2="50" stroke="#c2185b" stroke-width="3"/>
  
  <circle cx="270" cy="50" r="18" fill="#e0e4ec"/>
  <text x="270" y="56" text-anchor="middle" font-size="14" fill="#8895aa">2</text>
  <text x="270" y="85" text-anchor="middle" font-size="12" fill="#8895aa">联系人</text>
  <line x1="288" y1="50" x2="362" y2="50" stroke="#e0e4ec" stroke-width="3"/>
  
  <circle cx="380" cy="50" r="18" fill="#e0e4ec"/>
  <text x="380" y="56" text-anchor="middle" font-size="14" fill="#8895aa">3</text>
  <text x="380" y="85" text-anchor="middle" font-size="12" fill="#8895aa">提交/自动审核</text>

  <rect x="730" y="32" width="190" height="28" rx="14" fill="#e8f5e9" stroke="#4caf50"/>
  <text x="825" y="51" text-anchor="middle" font-size="12" fill="#2e7d32">⚡ AI即时审核 · 秒级通过</text>
</svg>

3.2 步骤一:企业信息

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1100 920" font-family="'Microsoft YaHei', 'PingFang SC', sans-serif">
  <defs>
    <filter id="shadowLight" x="-2%" y="-2%" width="104%" height="104%">
      <feDropShadow dx="0" dy="4" stdDeviation="8" flood-color="#000" flood-opacity="0.04"/>
    </filter>
    <linearGradient id="brandGrad" x1="0%" y1="0%" x2="100%" y2="100%">
      <stop offset="0%" stop-color="#c2185b"/>
      <stop offset="100%" stop-color="#e91e63"/>
    </linearGradient>
  </defs>

  <rect width="1100" height="920" fill="#f5f7fa"/>
  
  <!-- 主卡片 -->
  <rect x="80" y="30" width="940" height="860" rx="16" fill="#fff" filter="url(#shadowLight)"/>
  
  <text x="120" y="80" font-size="22" font-weight="bold" fill="#1a2332">供应商注册</text>
  <text x="120" y="108" font-size="14" fill="#8895aa">请填写企业真实信息,上传营业执照,系统将自动识别并回填</text>
  <line x1="120" y1="125" x2="980" y2="125" stroke="#f0f2f7" stroke-width="2"/>

  <!-- 营业执照上传区(突出显示) -->
  <rect x="120" y="145" width="820" height="80" rx="8" stroke-dasharray="8,4" fill="#fafbfc" stroke="#c2185b" stroke-width="2"/>
  <text x="530" y="180" text-anchor="middle" font-size="16" fill="#c2185b">📄 上传营业执照(JPG/PNG/PDF,≤10MB</text>
  <text x="530" y="208" text-anchor="middle" font-size="13" fill="#8895aa">支持拖拽或点击上传,AI 将自动识别企业信息并填充表单</text>

  <!-- 识别状态条 -->
  <rect x="120" y="240" width="820" height="30" rx="4" fill="#e8f5e9" stroke="#a5d6a7"/>
  <text x="140" y="260" font-size="13" fill="#2e7d32">✅ 已识别:营业执照信息提取成功(统一信用代码:91370100XXXXXXXXXX</text>

  <!-- ===== 表单字段 ===== -->
  <!-- 第一行:企业全称 + 统一社会信用代码 -->
  <text x="120" y="300" font-size="14" fill="#4a5568">企业全称 <tspan fill="#e91e63">*</tspan></text>
  <rect x="120" y="310" width="380" height="40" rx="6" fill="#fafbfc" stroke="#e0e4ec"/>
  <text x="135" y="336" font-size="14" fill="#b0bbcc">系统自动识别或手动输入</text>

  <text x="540" y="300" font-size="14" fill="#4a5568">统一社会信用代码 <tspan fill="#e91e63">*</tspan></text>
  <rect x="540" y="310" width="380" height="40" rx="6" fill="#fafbfc" stroke="#e0e4ec"/>
  <text x="555" y="336" font-size="14" fill="#b0bbcc">18位代码</text>

  <!-- 第二行:注册资本 + 法定代表人 -->
  <text x="120" y="380" font-size="14" fill="#4a5568">注册资本(万元) <tspan fill="#e91e63">*</tspan></text>
  <rect x="120" y="390" width="180" height="40" rx="6" fill="#fafbfc" stroke="#e0e4ec"/>
  <text x="135" y="416" font-size="14" fill="#b0bbcc">数字</text>

  <text x="340" y="380" font-size="14" fill="#4a5568">法定代表人 <tspan fill="#e91e63">*</tspan></text>
  <rect x="340" y="390" width="180" height="40" rx="6" fill="#fafbfc" stroke="#e0e4ec"/>
  <text x="355" y="416" font-size="14" fill="#b0bbcc">姓名</text>

  <text x="560" y="380" font-size="14" fill="#4a5568">行业分类 <tspan fill="#e91e63">*</tspan></text>
  <rect x="560" y="390" width="260" height="40" rx="6" fill="#fafbfc" stroke="#e0e4ec"/>
  <text x="575" y="416" font-size="14" fill="#b0bbcc">请选择/输入行业</text>

  <!-- 第三行:地址 -->
  <text x="120" y="460" font-size="14" fill="#4a5568">注册地址 <tspan fill="#e91e63">*</tspan></text>
  <rect x="120" y="470" width="560" height="40" rx="6" fill="#fafbfc" stroke="#e0e4ec"/>
  <text x="135" y="496" font-size="14" fill="#b0bbcc">请填写详细地址</text>

  <!-- 第四行:经营范围 -->
  <text x="120" y="540" font-size="14" fill="#4a5568">经营范围 <tspan fill="#e91e63">*</tspan></text>
  <rect x="120" y="550" width="560" height="60" rx="6" fill="#fafbfc" stroke="#e0e4ec"/>
  <text x="135" y="575" font-size="14" fill="#b0bbcc">系统识别或手动输入,建议不超过200字</text>

  <!-- 第五行:主要产品(可添加多个) -->
  <text x="120" y="640" font-size="14" fill="#4a5568">主要产品 <tspan fill="#e91e63">*</tspan></text>
  <rect x="120" y="650" width="300" height="40" rx="6" fill="#fafbfc" stroke="#e0e4ec"/>
  <text x="135" y="676" font-size="14" fill="#b0bbcc">如:工业阀门、管道</text>
  <rect x="440" y="650" width="100" height="40" rx="6" fill="#e3f2fd" stroke="#1565c0"/>
  <text x="490" y="676" text-anchor="middle" font-size="13" fill="#1565c0">+ 添加</text>
  <!-- 已添加的标签 -->
  <rect x="560" y="650" width="120" height="40" rx="20" fill="#fce4ec" stroke="#c2185b"/>
  <text x="620" y="676" text-anchor="middle" font-size="13" fill="#c2185b">工业阀门 ✕</text>
  <rect x="690" y="650" width="120" height="40" rx="20" fill="#fce4ec" stroke="#c2185b"/>
  <text x="750" y="676" text-anchor="middle" font-size="13" fill="#c2185b">管道配件 ✕</text>

  <!-- ===== 底部按钮 ===== -->
  <line x1="120" y1="730" x2="980" y2="730" stroke="#f0f2f7" stroke-width="2"/>
  
  <rect x="740" y="750" width="120" height="40" rx="6" fill="#e0e4ec"/>
  <text x="800" y="776" text-anchor="middle" font-size="14" fill="#8895aa">上一步</text>
  
  <rect x="880" y="750" width="140" height="40" rx="6" fill="url(#brandGrad)"/>
  <text x="950" y="776" text-anchor="middle" font-size="14" font-weight="bold" fill="#fff">下一步 →</text>

  <!-- 右侧提示浮窗 -->
  <rect x="720" y="140" width="260" height="180" rx="8" fill="#fff3e0" stroke="#ffcc80"/>
  <text x="740" y="168" font-size="14" font-weight="bold" fill="#e65100">📌 注册须知</text>
  <text x="740" y="195" font-size="12" fill="#bf360c">1. 请确保信息与营业执照一致</text>
  <text x="740" y="218" font-size="12" fill="#bf360c">2. 统一社会信用代码将作为唯一标识</text>
  <text x="740" y="241" font-size="12" fill="#bf360c">3. 提交后由供应商管理专员审核</text>
  <text x="740" y="264" font-size="12" fill="#bf360c">4. 审核通过后可参与投标报名</text>
  <text x="740" y="287" font-size="12" fill="#bf360c">5. 已有SRM账号请直接登录</text>
</svg>

布局说明:采用左右结构,左侧为表单(占比70%),右侧为“注册须知”浮窗(占比30%)。

表单字段明细(按顺序):

字段 组件类型 占位提示 备注
营业执照上传 拖拽/点击上传区 “点击或拖拽上传营业执照(JPG/PNG/PDF,≤10MB)” AI识别触发点,上传即自动OCR
企业全称 文本输入框 系统自动识别或手动输入” 最大长度128字符
统一社会信用代码 文本输入框 “18位统一社会信用代码”自动识别 自动转大写,格式校验
注册资本(万元) 数字输入框 “请输入数字” 保留2位小数,≥0
法定代表人 文本输入框 “请输入法定代表人姓名” 最大长度64字符
行业分类 下拉框+搜索 “请选择或搜索行业” 基于GB/T 4754-2017,三级分类
注册地址 文本输入框 “请填写详细地址” 最大长度256字符
经营范围 多行文本域 “系统自动识别或手动输入,不超过500字” 最大500字符
主要产品 标签输入组件 “输入产品名称,回车添加” 最多添加20个,每个≤30字符

OCR识别状态条(实时反馈):

  • 识别中:⏳ 正在识别营业执照...
  • 成功:✅ 识别完成,已自动回填以下字段:[企业全称]、[信用代码]、[法人]、[地址]、[经营范围]
  • 失败:❌ 识别失败,请手动填写(或检查图片是否清晰)

3.3 步骤二:联系人信息

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 1000" width="100%" height="100%">
    <defs>
        <style>
            .label { font-family: system-ui, -apple-system, sans-serif; font-size: 14px; font-weight: 600; fill: #374151; }
            .input-bg { fill: #FFFFFF; stroke: #D1D5DB; stroke-width: 1.5px; rx: 6px; transition: all 0.2s ease; }
            .input-bg:focus-within { stroke: #6366F1; stroke-width: 2px; }
            .input-text { font-family: system-ui, -apple-system, sans-serif; font-size: 14px; fill: #111827; }
            .placeholder { font-family: system-ui, -apple-system, sans-serif; font-size: 14px; fill: #9CA3AF; }
            .helper-text { font-family: system-ui, -apple-system, sans-serif; font-size: 12px; fill: #6B7280; }
            .required { font-family: system-ui, -apple-system, sans-serif; font-size: 16px; fill: #EF4444; }
            .btn-primary { fill: url(#brandGrad); rx: 6px; cursor: pointer; transition: all 0.2s ease; }
            .btn-primary:hover { fill: #4338CA; }
            .btn-secondary { fill: url(#brandGrad); rx: 6px; cursor: pointer; transition: all 0.2s ease; }
            .btn-secondary:hover { fill: url(#brandGrad); }
            .btn-text { font-family: system-ui, -apple-system, sans-serif; font-size: 14px; font-weight: 600; fill: #FFFFFF; text-anchor: middle; dominant-baseline: central; pointer-events: none; }
            .rule-pass { font-family: system-ui, -apple-system, sans-serif; font-size: 14px; fill: #10B981; }
            .rule-fail { font-family: system-ui, -apple-system, sans-serif; font-size: 14px; fill: #EF4444; }
            .rule-text { font-family: system-ui, -apple-system, sans-serif; font-size: 13px; fill: #374151; }
            .strength-meter-bg { fill: #E5E7EB; rx: 4px; }
            .strength-meter-fill { fill: #F59E0B; rx: 4px; }
            .strength-label { font-family: system-ui, -apple-system, sans-serif; font-size: 12px; fill: #9CA3AF; }
            .strength-label-active { font-family: system-ui, -apple-system, sans-serif; font-size: 12px; font-weight: bold; fill: #F59E0B; }
            .dot-inactive { fill: #FFFFFF; stroke: #D1D5DB; stroke-width: 1.5px; }
            .dot-active { fill: #F59E0B; stroke: #F59E0B; stroke-width: 1.5px; }
            .eye-icon { stroke: #9CA3AF; stroke-width: 2px; fill: none; stroke-linecap: round; cursor: pointer; }
            .eye-icon:hover { stroke: #4B5563; }
        </style>
        
        <!-- 卡片投影 -->
        <filter id="cardShadow" x="-5%" y="-5%" width="110%" height="110%">
            <feDropShadow dx="0" dy="8" stdDeviation="24" flood-color="#000000" flood-opacity="0.06"/>
            <feDropShadow dx="0" dy="2" stdDeviation="4" flood-color="#000000" flood-opacity="0.03"/>
        </filter>

        <!-- 输入框聚焦阴影 -->
        <filter id="inputFocus" x="-5%" y="-5%" width="110%" height="110%">
            <feDropShadow dx="0" dy="0" stdDeviation="6" flood-color="#6366F1" flood-opacity="0.15"/>
        </filter>
    </defs>

    <!-- 背景 -->
    <rect width="1200" height="1000" fill="#F3F4F6"/>

    <!-- 卡片容器 -->
    <rect x="100" y="40" width="1000" height="920" rx="16" fill="#FFFFFF" filter="url(#cardShadow)"/>

    <!-- 页面标题 -->
    <text x="140" y="90" font-family="system-ui, -apple-system, sans-serif" font-size="24" font-weight="700" fill="#1F2937" letter-spacing="0.5">联系人信息</text>

    <!-- ==================== 表单项 1:联系人姓名 ==================== -->
    <text x="280" y="167" class="label" text-anchor="end">联系人姓名</text>
    <text x="290" y="167" class="required">*</text>
    <rect x="300" y="145" width="720" height="44" class="input-bg"/>
    <text x="315" y="172" class="placeholder">请输入联系人姓名</text>
    <text x="315" y="208" class="helper-text">必填,最大64字符</text>

    <!-- ==================== 表单项 2:联系电话 ==================== -->
    <text x="280" y="257" class="label" text-anchor="end">联系电话</text>
    <text x="290" y="257" class="required">*</text>
    <!-- 聚焦状态演示 -->
    <rect x="300" y="235" width="720" height="44" class="input-bg" stroke="#6366F1" stroke-width="2" filter="url(#inputFocus)"/>
    <text x="315" y="262" class="input-text">13800138000</text>
    <text x="315" y="298" class="helper-text">必填,格式校验,全局唯一</text>

    <!-- ==================== 表单项 3:电子邮箱 ==================== -->
    <text x="280" y="347" class="label" text-anchor="end">电子邮箱</text>
    <text x="290" y="347" class="required">*</text>
    <rect x="300" y="325" width="720" height="44" class="input-bg"/>
    <text x="315" y="352" class="placeholder">请输入常用邮箱</text>
    <text x="315" y="388" class="helper-text">必填,格式校验,全局唯一</text>

    <!-- ==================== 表单项 4:短信验证码 ==================== -->
    <text x="280" y="437" class="label" text-anchor="end">短信验证码</text>
    <text x="290" y="437" class="required">*</text>
    <rect x="300" y="415" width="480" height="44" class="input-bg"/>
    <text x="315" y="442" class="placeholder">点击发送验证码</text>
    <rect x="800" y="415" width="120" height="44" class="btn-secondary"/>
    <text x="860" y="437" class="btn-text">发送验证码</text>
    <text x="315" y="478" class="helper-text">用于验证手机号真实性(注册必验)</text>

    <!-- ==================== 表单项 5:输入密码 ==================== -->
    <text x="280" y="527" class="label" text-anchor="end">输入密码</text>
    <rect x="300" y="505" width="720" height="44" class="input-bg"/>
    <!-- 密码占位圆点 -->
    <circle cx="315" cy="527" r="4" fill="#9CA3AF"/>
    <circle cx="335" cy="527" r="4" fill="#9CA3AF"/>
    <circle cx="355" cy="527" r="4" fill="#9CA3AF"/>
    <circle cx="375" cy="527" r="4" fill="#9CA3AF"/>
    <circle cx="395" cy="527" r="4" fill="#9CA3AF"/>
    <circle cx="415" cy="527" r="4" fill="#9CA3AF"/>
    <circle cx="435" cy="527" r="4" fill="#9CA3AF"/>
    <circle cx="455" cy="527" r="4" fill="#9CA3AF"/>
    <!-- 显示/隐藏按钮(眼睛图标) -->
    <path d="M 970 517 C 970 517, 980 527, 970 537 M 980 517 C 980 517, 990 527, 980 537" class="eye-icon"/>

    <!-- ==================== 表单项 6:确认密码 ==================== -->
    <text x="280" y="617" class="label" text-anchor="end">确认密码</text>
    <rect x="300" y="595" width="720" height="44" class="input-bg"/>
    <!-- 密码占位圆点 -->
    <circle cx="315" cy="617" r="4" fill="#9CA3AF"/>
    <circle cx="335" cy="617" r="4" fill="#9CA3AF"/>
    <circle cx="355" cy="617" r="4" fill="#9CA3AF"/>
    <circle cx="375" cy="617" r="4" fill="#9CA3AF"/>
    <circle cx="395" cy="617" r="4" fill="#9CA3AF"/>
    <circle cx="415" cy="617" r="4" fill="#9CA3AF"/>
    <circle cx="435" cy="617" r="4" fill="#9CA3AF"/>
    <circle cx="455" cy="617" r="4" fill="#9CA3AF"/>
    <!-- 显示/隐藏按钮(眼睛图标) -->
    <path d="M 970 607 C 970 607, 980 617, 970 627 M 980 607 C 980 607, 990 617, 980 627" class="eye-icon"/>

    <!-- ==================== 密码复杂度要求 ==================== -->
    <rect x="300" y="660" width="720" height="150" rx="8" fill="#F8FAFC" stroke="#E2E8F0" stroke-width="1"/>
    <text x="315" y="685" font-family="system-ui, -apple-system, sans-serif" font-size="14" font-weight="600" fill="#374151">密码复杂度要求</text>
    
    <!-- 规则 1:满足 -->
    <text x="315" y="715" class="rule-pass"></text>
    <text x="335" y="715" class="rule-text">长度 8~20 位</text>
    
    <!-- 规则 2:满足 -->
    <text x="315" y="740" class="rule-pass"></text>
    <text x="335" y="740" class="rule-text">至少包含 1 个大写字母(A-Z)和 1 个小写字母(a-z)</text>
    
    <!-- 规则 3:满足 -->
    <text x="315" y="765" class="rule-pass"></text>
    <text x="335" y="765" class="rule-text">至少包含 1 个数字(0-9)和 1 个特殊字符(!@#$%^&amp;*()_+-=</text>
    
    <!-- 规则 4:满足 -->
    <text x="315" y="790" class="rule-pass"></text>
    <text x="335" y="790" class="rule-text">禁止连续/重复字符(如 12345678, aaaaaaaa</text>
    
    <!-- 规则 5:不满足 -->
    <text x="315" y="815" class="rule-fail"></text>
    <text x="335" y="815" class="rule-text">禁止常见弱口令(内置弱密码字典)</text>

    <!-- ==================== 密码强度实时指示器 ==================== -->
    <text x="280" y="855" class="label" text-anchor="end">密码强度</text>
    
    <!-- 进度条背景 -->
    <rect x="300" y="845" width="300" height="8" class="strength-meter-bg"/>
    <!-- 进度条填充(演示中等级别,满足 4/5 项) -->
    <rect x="300" y="845" width="180" height="8" class="strength-meter-fill"/>

    <!-- 弱标签 -->
    <circle cx="320" cy="871" r="6" class="dot-inactive"/>
    <text x="335" y="875" class="strength-label"></text>
    
    <!-- 中标签(当前激活) -->
    <circle cx="390" cy="871" r="6" class="dot-active"/>
    <text x="405" y="875" class="strength-label-active"></text>
    
    <!-- 强标签 -->
    <circle cx="460" cy="871" r="6" class="dot-inactive"/>
    <text x="475" y="875" class="strength-label"></text>

    <!-- ==================== 提交按钮 ==================== -->
    <rect x="300" y="910" width="160" height="44" class="btn-primary"/>
    <text x="380" y="932" class="btn-text">提交</text>

</svg>
字段 组件类型 占位提示 备注
联系人姓名 文本输入框 “请输入联系人姓名” 必填,最大64字符
联系电话(手机号) 文本输入框 “请输入11位手机号” 必填,格式校验,全局唯一
电子邮箱 文本输入框 “请输入常用邮箱” 必填,格式校验,全局唯一
短信验证码 输入框+发送按钮 “点击发送验证码” 用于验证手机号真实性(注册必验)
输入密码 密码输入框
确认密码 密码输入框

密码复杂度要求

  • 长度 8~20 位
  • 至少包含 1 个大写字母(A-Z
  • 至少包含 1 个小写字母(a-z
  • 至少包含 1 个数字(0-9
  • 至少包含 1 个特殊字符(!@#$%^&*()_+-=
  • 禁止使用连续/重复字符(如 12345678aaaaaaaa
  • 禁止使用常见弱口令(内置弱密码字典,如 passwordadmin123

密码强度实时指示器

  • 弱(红色):< 3 项满足
  • 中(橙色):≥ 4 项满足
  • 强(绿色):全部满足 + 长度≥12

3.4 步骤三:SRM存量引导弹窗

当检测到SRM存量时,弹出如下引导窗(模态框):

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 380" font-family="'Microsoft YaHei', sans-serif">
  <defs><filter id="shadow"/><linearGradient id="brandGrad" x1="0%" y1="0%" x2="100%" y2="100%">
    <stop offset="0%" stop-color="#c2185b"/><stop offset="100%" stop-color="#e91e63"/>
  </linearGradient></defs>
  <rect width="600" height="380" fill="rgba(0,0,0,0.4)"/>
  <rect x="40" y="40" width="520" height="300" rx="16" fill="#fff" filter="url(#shadow)"/>
  
  <text x="300" y="85" text-anchor="middle" font-size="22" font-weight="bold" fill="#1a2332">🔍 检测到SRM存量供应商</text>
  <text x="300" y="120" text-anchor="middle" font-size="15" fill="#4a5568">该企业已在SRM系统中注册,您可以选择:</text>
  
  <rect x="80" y="150" width="200" height="44" rx="8" fill="#e3f2fd" stroke="#1565c0"/>
  <text x="180" y="177" text-anchor="middle" font-size="15" fill="#1565c0" font-weight="bold">使用SRM账号登录</text>
  
  <rect x="320" y="150" width="200" height="44" rx="8" fill="url(#brandGrad)"/>
  <text x="420" y="177" text-anchor="middle" font-size="15" fill="#fff" font-weight="bold">继续注册</text>
  
  <text x="300" y="225" text-anchor="middle" font-size="13" fill="#8895aa">选择“继续注册”将跳过资质审核,直接绑定SRM账号</text>
  <text x="300" y="250" text-anchor="middle" font-size="13" fill="#8895aa">选择“登录”将跳转至登录页,使用SRM账号密码登录</text>
  
  <rect x="220" y="280" width="160" height="30" rx="6" fill="#f5f5f5" stroke="#ccc"/>
  <text x="300" y="300" text-anchor="middle" font-size="13" fill="#666">取消</text>
</svg>

选择“继续注册”后的处理

  • 前端重新提交注册请求,携带参数 confirmSrmBinding: true
  • 后端跳过AI审核,直接创建STP账号并绑定SRM ID,返回成功(自动登录)。

选择“使用SRM账号登录”

  • 前端跳转至登录页,并自动填充企业名称/信用代码(可选),引导用户使用SRM账号密码登录(利用统一登录接口)。

3.5 步骤四:提交 & 自动审核

审核中(等待 3~8 秒) :


<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 300" font-family="'Microsoft YaHei', sans-serif">
  <rect width="600" height="300" fill="#f8f9fc"/>
  <rect x="60" y="40" width="480" height="220" rx="16" fill="#fff" filter="url(#shadow)"/>
  
  <!-- 旋转加载器 -->
  <circle cx="300" cy="120" r="40" fill="none" stroke="#e0e4ec" stroke-width="6"/>
  <path d="M 300 80 A 40 40 0 0 1 335 110" fill="none" stroke="#c2185b" stroke-width="6" stroke-linecap="round">
    <animateTransform attributeName="transform" type="rotate" from="0 300 120" to="360 300 120" dur="1s" repeatCount="indefinite"/>
  </path>
  
  <text x="300" y="185" text-anchor="middle" font-size="18" font-weight="bold" fill="#1a2332">⏳ AI 正在审核企业信息...</text>
  <text x="300" y="215" text-anchor="middle" font-size="14" fill="#8895aa">预计 3~8 秒,请勿关闭页面</text>
  <text x="300" y="240" text-anchor="middle" font-size="13" fill="#b0bbcc">✓ 工商信息核验  ✓ 风险扫描  ✓ 唯一性检查</text>
</svg>

审核通过(自动登录跳转) :

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 420" font-family="'Microsoft YaHei', sans-serif">
  <defs>
    <filter id="shadow"/>
    <linearGradient id="brandGrad" x1="0%" y1="0%" x2="100%" y2="100%">
      <stop offset="0%" stop-color="#c2185b"/><stop offset="100%" stop-color="#e91e63"/>
    </linearGradient>
  </defs>
  <rect width="600" height="420" fill="#f8f9fc"/>
  <rect x="60" y="30" width="480" height="360" rx="16" fill="#fff" filter="url(#shadow)"/>
  
  <!-- 成功图标 -->
  <circle cx="300" cy="100" r="50" fill="#e8f5e9"/>
  <path d="M270 100 L290 120 L330 75" stroke="#4caf50" stroke-width="6" fill="none" stroke-linecap="round"/>
  
  <text x="300" y="185" text-anchor="middle" font-size="26" font-weight="bold" fill="#1a2332">🎉 注册成功!</text>
  <text x="300" y="218" text-anchor="middle" font-size="15" fill="#4a5568">您的供应商账号已激活,正在自动登录...</text>
  
  <line x1="120" y1="245" x2="480" y2="245" stroke="#f0f2f7" stroke-width="2"/>
  <!-- 供应商信息摘要 -->
  <text x="300" y="278" text-anchor="middle" font-size="14" fill="#8895aa">供应商编号:<tspan fill="#1a2332" font-weight="bold">SUP_20260630_0158</tspan></text>
  <text x="300" y="308" text-anchor="middle" font-size="14" fill="#8895aa">登录账号:<tspan fill="#1a2332" font-weight="bold">138****8001</tspan></text>
  
  <!-- 温馨提示 -->
  <rect x="120" y="330" width="360" height="45" rx="6" fill="#fff3e0" stroke="#ffcc80"/>
  <text x="300" y="350" text-anchor="middle" font-size="12" fill="#e65100">📌 温馨提示:参与具体项目投标时,需按招标公告要求提交资质审核材料</text>
</svg>

审核不通过

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 420" font-family="'Microsoft YaHei', sans-serif">
  <!-- 背景和卡片 -->
  <rect width="600" height="420" fill="#f8f9fc"/>
  <rect x="60" y="30" width="480" height="370" rx="16" fill="#fff" filter="url(#shadow)"/>
  
  <!-- 失败图标 -->
  <circle cx="300" cy="90" r="50" fill="#ffcdd2"/>
  <text x="300" y="105" text-anchor="middle" font-size="48" fill="#c62828"></text>
  
  <text x="300" y="175" text-anchor="middle" font-size="24" font-weight="bold" fill="#c62828">审核未通过</text>
  
  <!-- 原因列表 -->
  <rect x="100" y="200" width="400" height="100" rx="8" fill="#fafafa" stroke="#e0e4ec"/>
  <text x="120" y="225" font-size="13" fill="#c62828">• 统一社会信用代码与工商登记信息不匹配</text>
  <text x="120" y="250" font-size="13" fill="#c62828">• 企业状态为“注销”,不符合注册条件</text>
  <text x="120" y="275" font-size="13" fill="#666">💡 请核对信息后重新提交,如有疑问请联系客服</text>
  
  <!-- 按钮 -->
  <rect x="160" y="330" width="280" height="42" rx="8" fill="#c2185b"/>
  <text x="300" y="357" text-anchor="middle" font-size="16" font-weight="bold" fill="#fff">修改后重新提交</text>
</svg>

4. 字段级校验规则(前后端双重校验)

字段 前端校验 后端校验 错误码
营业执照文件 格式(JPEG/PNG/PDF)、大小≤10MB 文件病毒扫描、图片清晰度检测 ERR_FILE_001
企业全称 非空,长度≤128 与OCR结果一致性比对 ERR_PARAM_001
统一社会信用代码 非空,格式正则^[0-9A-HJ-NPQRTUWXY]{2}\d{6}[0-9A-HJ-NPQRTUWXY]{10}$,自动转大写 唯一性校验;与工商API比对 ERR_PARAM_002 / ERR_REG_002
注册资本 数字,≥0,最多2位小数 数据类型校验 ERR_PARAM_003
法定代表人 非空,长度≤64 与OCR结果一致性比对 ERR_PARAM_004
行业分类 非空,必须为GB/T 4754叶子节点 枚举校验 ERR_PARAM_005
注册地址 非空,长度≤256 - ERR_PARAM_006
经营范围 非空,长度≤500 - ERR_PARAM_007
主要产品 数组非空,每个≤30字符,最多20个 - ERR_PARAM_008
联系人姓名 非空,长度≤64 - ERR_PARAM_009
联系电话 非空,格式^1[3-9]\d{9}$ 唯一性校验(contact_phone不可重复) ERR_PARAM_010 / ERR_REG_003
电子邮箱 非空,邮箱格式正则 唯一性校验 ERR_PARAM_011 / ERR_REG_003
短信验证码 非空,6位数字 匹配Redis缓存,有效期5分钟 ERR_AUTH_001
登录密码 非空,长度8-20 强度校验(大小写+数字+特殊字符+弱口令字典) ERR_PARAM_012
确认密码 非空,与密码一致 与密码字段比对 ERR_PARAM_013

5. AI自动审核详细设计

5.1 审核前置:SRM存量检查

graph TD
    A[接收注册请求] --> B{请求中是否包含<br>confirmSrmBinding=true?}
    B -->|是| C[跳过所有AI检查,直接执行SRM绑定流程]
    B -->|否| D[调用SRM查询接口<br>根据信用代码查询供应商]
    D --> E{SRM中存在?}
    E -->|是| F[返回特殊错误码ERR_SRM_EXISTS<br>附带SRM供应商基本信息]
    E -->|否| G[进入AI审核流程(原有7项检查)]
    C --> H[创建STP供应商记录status=ACTIVE<br>绑定srm_id]
    G --> I{综合仲裁}
    I -->|通过| H
    I -->|不通过| J[驳回]

5.2 各项检查详细规则

检查项 调用源 通过条件 硬性拒绝条件 超时处理
OCR完整性 内部OCR服务 成功提取「企业全称+信用代码+法人」 三项任一缺失 超时3s → 降级允许手动输入,但不自动通过
工商验真 天眼查/企查查API 输入名称与信用代码匹配,且置信度≥95% 不匹配 超时5s → 返回“服务繁忙,请稍后重试”
企业存续状态 天眼查API 状态为“存续(在营)” 注销/吊销/清算 使用缓存数据(缓存≤24h
严重违法 国家企业信用信息公示系统 不在“严重违法失信名单” 在名单中 若API不可用,默认通过(记录告警)
经营异常 天眼查API 不在“经营异常名录” 不硬性拒绝,仅标记 risk_tags 若API不可用,默认无异常
信用代码唯一性 本地DB 未注册(含ACTIVE/REJECTED/锁定) 已存在(不论状态) N/A
手机号唯一性 本地DB 未被其他ACTIVE供应商绑定 已绑定 N/A
SRM 存量供商应商

5.3 SRM存量绑定跳过项

当 confirmSrmBinding=true 时,跳过以下检查:

  • OCR完整性
  • 工商验真
  • 企业状态
  • 严重违法
  • 经营异常

仍保留的检查:

  • 信用代码唯一性(STP内)
  • 手机号/邮箱唯一性

5.3 综合仲裁逻辑(伪代码)

def audit_register(request):
    results = parallel_run([
        ocr_check(request.file),
        business_verify(request.credit_code, request.company_name),
        status_check(request.credit_code),
        fraud_check(request.credit_code),
        exception_check(request.credit_code),
        uniqueness_check(request.credit_code, request.phone, request.email)
    ])
    
    # 一票否决项
    fatal_checks = ['ocr', 'verify', 'status', 'fraud', 'uniqueness']
    for check in fatal_checks:
        if not results[check].passed:
            return reject(results[check].reason)
    
    # 经营异常仅标记,不阻止
    if results['exception'].has_exception:
        mark_risk_tag(request.supplier_id, '经营异常')
    
    return approve()

6. 完整业务流程(含状态机)

6.1 状态定义(精简)

状态码 名称 说明 可执行操作
DRAFT 草稿 用户正在填写,尚未提交 编辑、提交
SUBMITTED 提交审核中 AI正在执行检查(瞬时状态,<5s) 无(轮询等待)
ACTIVE 已激活/正常 AI全部通过,可登录报名 登录、报名、修改信息、变更联系人
REJECTED 审核驳回 至少一项一票否决未通过 查看原因、修改后重新提交(30天内)
LOCKED 已锁定 违规操作/被管理员冻结 联系管理员解封
ARCHIVED 已归档 长期未使用或主动注销 只读(不可登录)

6.2 状态流转图

stateDiagram-v2
    [*] --> DRAFT: 开始注册
    DRAFT --> SUBMITTED: 提交(不含SRM绑定确认)
    SUBMITTED --> SRM_EXISTS: 检测到SRM存量(返回ERR_SRM_EXISTS
    SRM_EXISTS --> DRAFT: 用户取消/关闭弹窗
    SRM_EXISTS --> ACTIVE: 用户选择“继续注册”(带confirmSrmBinding=true
    SRM_EXISTS --> [*]: 用户选择“使用SRM账号登录”(跳转登录)
    SUBMITTED --> ACTIVE: AI全部通过(新供应商)
    SUBMITTED --> REJECTED: AI不通过
    REJECTED --> DRAFT: 修改重提
    ACTIVE --> LOCKED: 管理员冻结
    LOCKED --> ACTIVE: 解封

注意:由于审核是实时的,SUBMITTED状态在数据库层面几乎不持久化(前端展示加载态即可)。

6.3 完整业务流程

flowchart TD
    subgraph 供应商端
        A[访问注册页] --> B[填写完整信息并提交]
        B --> C[等待审核结果(3-8秒)]
        C --> D{前端收到响应}
        D -->|成功(新供应商通过)| E[显示成功页+自动登录]
        D -->|错误码ERR_SRM_EXISTS| F[弹出SRM存量引导窗]
        F --> G{用户选择}
        G -->|“继续注册”| H[重新提交请求带confirmSrmBinding=true]
        G -->|“使用SRM账号登录”| I[跳转登录页]
        G -->|取消| J[返回注册页修改]
        D -->|其他驳回| K[显示驳回原因+修改]
        H --> L[立即成功+自动登录]
    end
flowchart TD
subgraph STP后端
        STP1[接收注册请求] --> STP2{是否有confirmSrmBinding=true?}
        STP2 -->|是| STP3[跳过AI审核,查询SRM获取srmId]
        STP2 -->|否| STP4[调用SRM查询接口检测存量]
        STP4 --> STP5{SRM存在?}
        STP5 -->|存在| STP6[返回ERR_SRM_EXISTS(含srmId+名称)]
        STP5 -->|不存在| STP7[执行AI审核(7项检查)]
        STP7 --> STP8{AI通过?}
        STP8 -->|通过| STP9[创建供应商status=ACTIVE]
        STP8 -->|不通过| STP10[创建供应商status=REJECTED]
        STP3 --> STP9
        STP9 --> STP11[创建用户账号+密码哈希]
        STP11 --> STP12[生成JWT Token]
        STP12 --> STP13[同步SRM(若已有srmId则更新绑定)]
        STP13 --> STP14[发送成功通知]
        STP10 --> STP15[发送驳回通知]
    end
    subgraph 外部系统
        EXT1[SRM查询接口]
        EXT2[SRM注册/绑定接口]
        EXT3[通知网关]
    end
    STP4 -.-> EXT1
    STP3 -.-> EXT2
    STP14 -.-> EXT3

7. 时序图

sequenceDiagram
    participant U as 供应商
    participant FE as 前端
    participant GW as API网关
    participant RegSvc as 注册服务
    participant AISvc as AI审核服务
    participant BizAPI as 天眼查API
    participant SRM as SRM系统
    participant DB as STP数据库
    participant Notify as 通知服务

    U->>FE: 填写完整信息(含密码)并提交
    FE->>GW: POST /register(无confirmSrmBinding
    GW->>RegSvc: 转发

    RegSvc->>DB: 校验信用代码是否已在STP注册
    alt 已注册
        DB-->>RegSvc: 已存在
        RegSvc-->>FE: 409 ERR_REG_002(已注册)
    else 未注册
        RegSvc->>SRM: GET /query/by-tax-id(查询存量)
        SRM-->>RegSvc: 返回结果(存在或不存在)
        alt SRM存在
            RegSvc-->>FE: 200 但 code=ERR_SRM_EXISTS,附带srmId和supplierName
            FE-->>U: 弹出引导窗
            U->>FE: 点击“继续注册”
            FE->>GW: POST /register + confirmSrmBinding=true
            GW->>RegSvc: 转发(携带srmId
            RegSvc->>DB: 创建供应商 status=ACTIVE,绑定srmId
            RegSvc->>RegSvc: 创建用户账号,密码哈希
            RegSvc->>RegSvc: 生成JWT Token
            RegSvc->>Notify: 发送成功通知(无需激活)
            RegSvc-->>FE: 200 成功 + accessToken
            FE->>FE: 存储Token
            FE-->>U: 自动跳转工作台
        else SRM不存在(新供应商)
            RegSvc->>AISvc: 执行AI审核(7项并行)
            AISvc->>BizAPI: 工商验真/状态/违法等
            BizAPI-->>AISvc: 结果
            AISvc-->>RegSvc: 审核结论
            alt 通过
                RegSvc->>DB: 创建供应商 status=ACTIVE
                RegSvc->>RegSvc: 创建用户账号、生成Token
                RegSvc->>SRM: POST /register(同步注册至SRM
                SRM-->>RegSvc: srmId
                RegSvc->>DB: 更新srmId
                RegSvc->>Notify: 发送成功通知
                RegSvc-->>FE: 200 成功 + Token
                FE-->>U: 自动登录
            else 不通过
                RegSvc->>DB: 创建供应商 status=REJECTED
                RegSvc->>Notify: 发送驳回通知
                RegSvc-->>FE: 400 失败(含原因)
                FE-->>U: 显示驳回页
            end
        end
    end

8. 数据模型完整定义

8.1 供应商主表 t_supplier_profile

字段名 类型 约束 说明
id BIGINT PK 自增主键
supplier_id VARCHAR(32) UNIQUE, NOT NULL 业务编号
user_id VARCHAR(32) INDEX 关联用户账号
srm_id VARCHAR(32) INDEX SRM系统ID(存量绑定或新注册同步后回填)
company_name VARCHAR(128) NOT NULL 企业全称
credit_code VARCHAR(128) NOT NULL, UNIQUE 信用代码(加密)
credit_code_md5 CHAR(32) UNIQUE MD5盲索引
registered_capital DECIMAL(15,2) 注册资本
legal_representative VARCHAR(64) 法定代表人
industry_code VARCHAR(16) 行业代码
industry_name VARCHAR(64) 行业名称
address VARCHAR(256) 注册地址
business_scope TEXT 经营范围
main_products JSON 主要产品
contact_name VARCHAR(64) NOT NULL 联系人姓名
contact_phone VARCHAR(128) NOT NULL, UNIQUE 手机号(加密)
contact_phone_md5 CHAR(32) UNIQUE MD5
contact_email VARCHAR(128) NOT NULL 邮箱
license_file_url VARCHAR(512) 营业执照URL
license_ocr_result JSON OCR结果
audit_result JSON AI审核报告(新供应商)
source_type VARCHAR(20) NOT NULL NEW / SRM_BINDING(标识注册来源)
srm_bind_time DATETIME SRM绑定时间(存量绑定)
status VARCHAR(20) NOT NULL DRAFT/SUBMITTED/ACTIVE/REJECTED/LOCKED
risk_tags JSON 风险标签
reject_reasons JSON 驳回原因
activated_at DATETIME 激活时间(即注册成功时间)
created_at DATETIME(3) 创建时间
updated_at DATETIME(3) 更新时间

8.2 用户账号表 t_user(新增字段)

字段名 类型 说明
user_id VARCHAR(32) PK
supplier_id VARCHAR(32) FK
login_name VARCHAR(64) UNIQUE(手机号)
password_hash VARCHAR(128) Argon2id哈希
user_type VARCHAR(20) 'SUPPLIER'
status VARCHAR(20) 'ACTIVE'
last_login_at DATETIME

9. API接口详细规范

9.1 提交供应商注册(支持SRM存量检测)

项目 内容
路径 /api/v1/supplier/register
方法 POST

请求体(第一次提交,无confirmSrmBinding

{
  "companyName": "滨化新材料有限公司",
  "creditCode": "91370100MA3XXXXXXX",
  "registeredCapital": 5000.00,
  "legalRepresentative": "张伟",
  "industryCode": "C2614",
  "address": "山东省滨州市黄河五路888号",
  "businessScope": "化工产品、新材料技术研发...",
  "mainProducts": ["聚丙烯", "环氧丙烷"],
  "contactName": "李强",
  "contactPhone": "13800138001",
  "contactEmail": "liqiang@example.com",
  "licenseFileUrl": "https://oss.stp.com/xxx.pdf",
  "smsCode": "123456",
  "password": "Abcd@2026#",
  "confirmPassword": "Abcd@2026#",
  "agreeTerms": true
}

特殊响应(检测到SRM存量)

{
  "code": "ERR_SRM_EXISTS",
  "message": "检测到该供应商已在SRM系统中注册",
  "data": {
    "srmId": "SRM_12345",
    "companyName": "滨化新材料有限公司",
    "creditCode": "91370100MA3XXXXXXX",
    "hint": "您可以选择继续注册(跳过资质审核)或使用SRM账号登录"
  }
}

第二次提交(用户选择继续注册)

{
  ...(同第一次请求),
  "confirmSrmBinding": true,
  "srmId": "SRM_12345"   // 可选,后端也可再次查询
}

成功响应(无论新注册还是存量绑定,均一致)

{
  "code": "0",
  "data": {
    "supplierId": "SUP_20260630_0158",
    "srmId": "SRM_12345",
    "userId": "U_...",
    "status": "ACTIVE",
    "accessToken": "eyJ...",
    "tokenType": "Bearer",
    "expiresIn": 1800,
    "sourceType": "NEW"  "SRM_BINDING",
    "message": "注册成功,账号已激活"
  }
}

9.2 营业执照OCR(预填)

项目 内容
路径 /api/v1/ocr/business-license
方法 POST
请求 multipart/form-data,字段 file
响应(成功) {"code":"0","data":{"companyName":"...","creditCode":"...","legalPerson":"...","registeredCapital":"...","address":"...","businessScope":"..."}}
响应(失败) {"code":"ERR_OCR_001","message":"图片识别失败,请确认图片清晰"}

9.3 发送短信验证码

项目 内容
路径 /api/v1/auth/sms/send
方法 POST
请求 {"phone":"13800138000","captchaToken":"图形验证码"}
响应 {"code":"0","data":{"expireSeconds":300,"resendAfterSeconds":60}}

其他错误码

  • ERR_REG_002:信用代码已注册(409
  • ERR_REG_003:手机号已被占用(409
  • ERR_REG_004:邮箱已被占用(409
  • ERR_REG_005:短信验证码错误或过期(401
  • ERR_REG_006:工商API服务繁忙,请稍后重试(503)

9.4 首次登录激活(设置密码)

项目 内容
路径 /api/v1/supplier/activate
方法 POST
请求 {"supplierId":"SUP_...","password":"Abcd@1234","confirmPassword":"Abcd@1234"}
成功 {"code":"0","message":"激活成功"}

10. 业务规则与约束

ID 规则 说明
R01 信用代码唯一性 无论来源,STP内信用代码唯一。
R02 SRM存量检测优先 每次注册请求首先查询SRM,除非已带confirmSrmBinding参数。
R03 存量绑定跳过AI confirmSrmBinding=true时,跳过OCR、工商验真、状态、违法检查,仅保留唯一性校验。
R04 存量绑定的SRM账号状态 不要求SRM账号必须激活,只要存在记录即可绑定。
R05 密码设置要求 存量绑定同样需要设置密码(与正常注册相同)。
R06 存量绑定后SRM同步 若srmId已存在,则无需再次调用SRM注册接口,只需在STP记录绑定关系。若srmId为空(异常),需补录。
R07 引导弹窗后取消 用户取消则回到注册页,可修改信息后再次提交(会再次触发SRM检测)。
R08 重复检测 若STP已存在同信用代码,直接返回已注册,不查询SRM。

11. 异常处理矩阵

异常场景 处理方式 用户侧表现 后端动作
SRM查询接口超时 降级:视为新供应商,进入AI审核 正常AI审核流程(可能延迟) 记录告警,超时5s后转AI
SRM查询返回错误 降级:视为新供应商 正常AI审核 记录错误日志
存量绑定后SRM绑定失败 异步重试,STP仍激活 用户无感知 标记同步失败,告警管理员
用户选择“继续注册”但信用代码已在STP注册 返回已注册错误 提示“该企业已注册” 返回ERR_REG_002

12. 通知策略

触发事件 通知方式 接收方 文案
新供应商注册成功 邮件+短信 联系人 “恭喜X公司注册成功!已自动激活,请直接登录。”
SRM存量绑定成功 邮件+短信 联系人 “恭喜X公司完成STP账号绑定,您已是滨化供应商,可直接登录参与投标。”
注册驳回 邮件+短信 联系人 “注册未通过,原因:...”

13. SRM双向同步机制

13.1 注册时正向同步(STP → SRM)

  • 触发时机AI审核通过,INSERT成功后立即执行。
  • 接口POST /api/v1/supplier/register(见接口方案3.2
  • 映射关系
STP字段 SRM字段
company_name supplierName
credit_code taxId
contact_name contactInfo.name
contact_phone contactInfo.phone
contact_email contactInfo.email
address address
  • 状态映射STP ACTIVE → SRM PENDING_CERTIFICATION(需后续补充资质文件完成认证)。

13.2 SRM存量供应商绑定(无需同步,仅获取srmId)

  • 调用SRM查询接口获取srmId,存入本地,不调用注册接口。
  • 如果SRM供应商状态为“未激活”等,不影响STP绑定。

13.3 反向同步(SRM → STP

若SRM侧修改供应商信息,通过定时增量同步接口更新STP(联系人等),与本注册模块无关。


14. 供应商联系人变更(注册后维护)

本模块为注册流程的必要延伸,确保企业联系人信息变更时账户安全与业务通知可达。

14.1 自助变更(旧手机号可用)

flowchart LR
    A[登录工作台] --> B[进入企业信息页]
    B --> C[点击修改联系人]
    C --> D[验证旧手机号/邮箱]
    D --> E[填写新联系人信息]
    E --> F[验证新手机号/邮箱]
    F --> G[提交变更]
    G --> H[即时生效 + 同步SRM]

14.2 人工辅助变更(旧手机号不可用)

flowchart LR
    A[点击“旧手机无法接收验证码?”] --> B[下载《变更申请函》模板]
    B --> C[填写+加盖公章]
    C --> D[上传盖章扫描件]
    D --> E[提交人工申请]
    E --> F[管理员审核(4h内)]
    F --> G[后台执行变更]

14.3 接口与数据(简略)

  • 变更接口PUT /api/v1/supplier/contact
  • 审计日志:写入t_supplier_contact_change_log(含旧值/新值/变更人/IP/哈希链)。
  • SRM同步:调用POST /api/v1/supplier/contact/update

详细设计参考《联系人变更补充设计》,此处仅作概要嵌入,确保完整性。


15. 安全与合规

安全维度 具体措施
传输安全 强制 HTTPS + TLS 1.3HSTS 头部强制。
敏感字段加密 credit_codecontact_phone 使用 AES-256-GCM 应用层加密,密钥由KMS托管,内存动态漂移(参见全局安全方案4.2)。
可搜索加密 唯一性校验使用字段的 MD5/SHA-256 盲索引(不可逆),不直接对密文进行SELECT
数据脱敏展示 后台展示信用代码为 913701**********,手机号为 138****8001
审计防篡改 所有审计日志采用 哈希链+数字签名(参见需求说明书4.8.1),保留≥7年。
防机器人 注册提交需验证图形验证码(极验),手机验证码发送每日限5次。
密码安全 首次激活密码强度≥8位,含大小写+数字+特殊字符,不得为弱口令(密码字典检测)。
合规性 满足《个人信息保护法》第13条(告知同意)、第17条(隐私政策),注册前勾选同意《用户协议》、《隐私政策》及《反商业贿赂承诺书》。

16. 附录

16.1 统一社会信用代码正则(前端+后端)

^[0-9A-HJ-NPQRTUWXY]{2}\d{6}[0-9A-HJ-NPQRTUWXY]{10}$

16.2 行业分类示例(GB/T 4754-2017 三级)

一级 二级 三级代码 三级名称
C 制造业 26 化学原料和化学制品制造业 2614 有机化学原料制造
C 制造业 29 橡胶和塑料制品业 2926 塑料包装箱及容器制造
E 建筑业 48 土木工程建筑业 4813 市政道路工程建筑

16.3 错误码速查表

错误码 HTTP状态 含义
0 200 成功
ERR_PARAM_001~011 400 参数校验失败(具体见第4章)
ERR_REG_001 400 注册审核不通过
ERR_REG_002 409 信用代码已注册
ERR_REG_003 409 手机号/邮箱已被占用
ERR_REG_004 503 工商API服务繁忙
ERR_AUTH_001 401 验证码错误/过期
ERR_FILE_001 400 文件格式/大小不符
ERR_OCR_001 400 OCR识别失败
ERR_SYS_001 500 系统内部异常