跟AI沟通完成一个跟三方OA的对接工作
2026-03-10
我问:
提供给你的第一个文档是跟三方沟通以后形成的交互技术文档,中间细节你自行补充,不对的话,后续我来纠偏。第二个是之前对接三方设计的表,部分满足,还有部分不满足。我将独立一个库出来,请你基于这个sql进行重新表设计。
AI答:
我先把结论说在前面:
你这套旧表,已经有一些可复用思路,但整体上是“按接口开发过程一点点长出来的”,所以现在最大的问题不是字段够不够,而是职责混杂、状态分散、主线不清、幂等不足、扩展困难。尤其是“立项”“项目组”“送审”“状态回传”“报告号回写”“报备”这几条业务主线,当前表之间边界不够干净。根据你给的交互文档,真正的业务主轴其实很清楚:
企业配置 → 人员映射/校验 → OA立项接收 → 智评云项目组关联 → 按项目组送审 → OA回传审核状态 → OA回传报告号 → 文件新版本回传 → 报备记录同步。
而旧 SQL 里,oa_project_create_receive_main、oa_project_create_receive、oa_project_group_details、oa_project_group_relation、oa_push_retry_log、oa_push_retry_log_detail 这些表,分别都摸到了主流程的一部分,但有明显重叠,比如:receive_main 和 receive 都在表达立项接收;group_details 和 group_relation 都在表达项目组关系;push_retry_log 既像“送审主记录”,又像“失败重试队列”;push_retry_log_detail 又塞了底稿/报告/说明的业务详情。
这会导致后期一加“报告号回写历史”“再开”“删除”“重新送审”“母子项目”“报备补录”,整个库会越来越绕。
下面我按“重新独立一个库”的思路,给你一套更适合长期维护的表设计方案。你后面可以纠偏业务细节,但这个骨架我认为是比较稳的。
一、重新设计的核心原则
1.1 按业务主线拆,不按接口临时堆
建议拆成 7 个域:
A. 基础配置域
负责三方企业、接口配置、token、白名单、开关。
B. 身份映射域
负责 OA 人员 和 智评云人员 的映射、校验结果、历史记录。
C. OA立项接收域
负责接收 OA 审批通过后的立项数据,保留原始报文、解析结果、处理状态、变更日志。
D. 项目组关联域
负责“OA立项”和“智评云项目组”的对应关系,以及母子项目关系。
E. 送审域
负责按项目组发起送审、记录本次送审内容、状态、重试、回执。
F. 报告号回写与版本域
负责 OA 回传报告号、智评云更新报告/说明、形成新版本,并给 OA 返回新版文件。
G. 报备域
负责 OA 推送报备信息、智评云内部执行报备、拉取报备数据并留痕。
这样以后你要加接口,加的是某一个域的表,不会把整个库搅浑。
1.2 “当前状态”与“状态历史”分开
这是旧表里比较欠缺的一点。
比如送审状态,你文档里明确有:
送审中、审核中、通过、不通过、作废、删除、再开,以及送审动作本身还有失败、成功、超时。
这本质上至少是两层状态:
第一层,业务审核状态
第二层,接口推送执行状态
所以应该拆成:
一个表保存“当前最新状态”
一个表保存“状态流转历史”
不要一个 status 试图包打天下。
1.3 所有外部交互必须可追踪、可幂等、可回放
建议所有接口都至少有:
request_idtrace_idpartner_idtenant_idinterface_codebiz_keyidempotent_keyrequest_bodyresponse_bodyhttp_statusbiz_statussource_ipcreated_at
以后查问题会非常舒服。
1.4 tenant_id 不建议再用 json
你现有 oa_files、oa_process 用了 tenant_id json,但其他表又是 bigint,这很不统一。
如果你的租户就是单租户单企业记录,直接统一成 BIGINT。
如果以后要支持多租户共享、跨企业可见,再单独设计 tenant_scope 或关联表,不要把 tenant_id 做成 json。
1.5 token 不建议明文硬存
现有 oa_partner_config 里 zpy_token、oa_token 看起来像直接存账号密码或 token 本体。
更稳妥的做法:
静态密钥放配置中心或加密字段
数据库里只留:app_keyapp_secret_encryptedtoken_sign_typetoken_expire_seconds
真正的临时 token 放 token 表,过期即失效。
二、我建议的新库表结构
下面是我建议的主表清单。先看全景,再看每张表作用。
2.1 基础配置类
bridge_partner
三方系统配置主表
谁是诺明,谁是坤元,哪个租户对哪个 partner 生效,测试/正式地址分别是什么。
bridge_partner_auth
认证配置表
存 app_key、加密后的 secret、签名算法、token 有效期、白名单策略。
bridge_token_issue_log
token 签发/校验日志
替代你现在的 oa_partner_token_log,但更明确区分“签发”“校验”“失效”。
2.2 身份映射类
bridge_user_mapping
OA 用户与智评云用户映射表
你文档里明确说要让对方增加“智评云账号编码”,因为 OA 立项人 和 智评云实际匹配人可能不是同一人,比如张三对李四。
这一张表必须独立出来。
bridge_user_verify_log
接收人员有效性校验日志
谁传了哪些人,哪些有效,哪些无效,为什么无效。
2.3 OA立项接收类
bridge_oa_project
OA 立项主表
一条 OA 立项一条主记录,保存 OA 侧唯一编号、项目名称、负责人、组织、原始状态。
bridge_oa_project_change_log
立项变更日志表
你文档里明确说:立项信息变更“只做日志记录,暂不做对底稿更新”。
那就不要把每次变更写散到各处,单独放日志表。
bridge_interface_message
统一接口报文日志表
替代现有 oa_push_receive_log 这种只记录接收的写法,做成通用的收/发报文日志。
2.4 项目组关联类
bridge_project_group_bind
OA立项 与 智评云项目组 绑定关系表
这是核心桥表。
bridge_project_group_bind_item
一个 OA 立项可关联多个智评云项目
如果一母多子,或者一个项目组下多公司项目,需要明细表。
bridge_project_group_relation
母子项目关系表
区分主项目、子项目、关联类型。
旧 SQL 里 oa_project_group_details、oa_project_group_relation 这两张建议整合思路后保留一主一明细,不要平行双主。
2.5 送审类
bridge_submission
送审主表
“一次送审动作”一条记录。
不是重试表,不是详情表,就是送审主记录。
bridge_submission_item
本次送审涉及哪些项目组/子项目/文件
母项目送报告+说明,子项目只送说明,这种规则就体现在明细里。
bridge_submission_file
送审文件清单
本次实际送了什么文件,报告、说明、附件、电子底稿等。
bridge_submission_status_log
送审状态流转历史
送审中、审核中、通过、不通过、作废、删除、再开。
bridge_submission_retry_task
失败重试任务表
这张表才替代旧的 oa_push_retry_log。
不要把“送审记录”和“重试任务”混在一张表里。
2.6 报告号与版本类
bridge_report_no_log
报告号回写日志
OA 送来报告号,可变更。每次回写都留痕。
bridge_submission_version
回写报告号后形成的新版本记录
你文档里明确说:回写报告号后,同步在系统报告版本列表产生新版本。
bridge_file_asset
统一文件元数据表
这里可以参考你原来的 oa_files 思路,但要改成面向桥接业务,不再局限 Excel dll。
bridge_file_biz_rel
文件业务关联表
某文件属于哪次送审、哪个版本、哪个报备记录。
2.7 报备类
bridge_filing_record
报备主表
记录报备任务、来源、状态、执行方式。
bridge_filing_detail
合同、报告、签字评估师等字段详情
你文档里明确要求这些详情字段。
bridge_filing_status_log
报备状态历史
三、对旧表的逐一处理建议
3.1 可以保留思路,但建议重做的表
oa_partner_config
保留“partner 配置”这个概念,但字段要重做。
问题在于:
测试/正式地址、token、白名单、重试配置都堆一起了;capacity_uid 命名也不直观。
建议拆成:bridge_partnerbridge_partner_auth
oa_partner_token_log
保留,但升级成 bridge_token_issue_log。
增加 token 类型、签发方式、校验结果、调用来源。
oa_push_receive_log
保留思想,升级为统一 bridge_interface_message。
因为不只是“接收”,以后你还有“主动推送 OA”“OA 回传”“拉取报备”等。
3.2 强烈建议合并/重构的表
oa_project_create_receive_main + oa_project_create_receive
这两个现在像“主表 + 明细表”,但承载内容其实不够清晰。
建议重构为:
bridge_oa_projectbridge_oa_project_change_log
主表保最新值,日志表保每次变动。
oa_project_group_details + oa_project_group_relation
都在描述项目组关系,建议合并逻辑,改成:
bridge_project_group_bindbridge_project_group_bind_itembridge_project_group_relation
oa_push_retry_log + oa_push_retry_log_detail
这两张最值得重构。
旧设计里它一边叫 retry,一边又承载送审主业务,还带文件字段和业务状态,非常容易越写越乱。
建议拆成:
bridge_submissionbridge_submission_itembridge_submission_filebridge_submission_status_logbridge_submission_retry_task
3.3 可借鉴但不要原样照搬的表
oa_files
它的文件元数据思想可以保留,但:
表名不适合新库;tenant_id 不该是 json;
还带了 is_system_default 这种偏插件业务的字段。
建议改造成:
bridge_file_assetbridge_file_biz_rel
四、建议的核心表设计
下面我给你一套偏实战的 DDL 骨架。不是最终版,但已经可以直接作为第一版建库基础。
CREATE DATABASE IF NOT EXISTS `zpy_oa_bridge` DEFAULT CHARACTER SET utf8mb4 DEFAULT COLLATE utf8mb4_0900_ai_ci; USE `zpy_oa_bridge`; SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; CREATE TABLE `bridge_partner` ( `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键', `tenant_id` BIGINT UNSIGNED NOT NULL COMMENT '租户ID', `partner_code` VARCHAR(64) NOT NULL COMMENT '三方系统编码,如 nuoming', `partner_name` VARCHAR(128) NOT NULL COMMENT '三方系统名称', `credit_code` VARCHAR(64) DEFAULT NULL COMMENT '统一社会信用代码', `enterprise_name` VARCHAR(255) DEFAULT NULL COMMENT '企业名称', `api_host_test` VARCHAR(500) DEFAULT NULL COMMENT '测试地址', `api_host_prod` VARCHAR(500) DEFAULT NULL COMMENT '正式地址', `callback_host` VARCHAR(500) DEFAULT NULL COMMENT '我方回调地址', `ip_allow_list` VARCHAR(2000) DEFAULT NULL COMMENT 'IP白名单,逗号分隔', `status` TINYINT NOT NULL DEFAULT 1 COMMENT '1启用 0停用', `remark` VARCHAR(500) DEFAULT NULL COMMENT '备注', `created_by` BIGINT DEFAULT NULL, `updated_by` BIGINT DEFAULT NULL, `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `is_deleted` TINYINT NOT NULL DEFAULT 0, `deleted_at` DATETIME DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `uk_tenant_partner_code` (`tenant_id`, `partner_code`), KEY `idx_status` (`status`) ) ENGINE=InnoDB COMMENT='三方系统配置主表'; CREATE TABLE `bridge_partner_auth` ( `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `partner_id` BIGINT UNSIGNED NOT NULL COMMENT '关联bridge_partner.id', `auth_type` VARCHAR(32) NOT NULL DEFAULT 'token' COMMENT '认证方式', `app_key` VARCHAR(128) DEFAULT NULL, `app_secret_encrypted` VARCHAR(1024) DEFAULT NULL COMMENT '加密后的secret', `sign_type` VARCHAR(32) DEFAULT NULL COMMENT '签名方式', `token_expire_seconds` INT NOT NULL DEFAULT 7200 COMMENT 'token有效期秒', `request_time_tolerance_seconds` INT NOT NULL DEFAULT 300 COMMENT '时间戳容差秒', `status` TINYINT NOT NULL DEFAULT 1, `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `uk_partner_auth` (`partner_id`) ) ENGINE=InnoDB COMMENT='三方认证配置表'; CREATE TABLE `bridge_token_issue_log` ( `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `tenant_id` BIGINT UNSIGNED NOT NULL, `partner_id` BIGINT UNSIGNED NOT NULL, `token_value` VARCHAR(512) NOT NULL, `token_type` VARCHAR(32) NOT NULL DEFAULT 'access_token', `expire_at` DATETIME NOT NULL, `issue_status` TINYINT NOT NULL DEFAULT 1 COMMENT '1有效 0失效', `source_ip` VARCHAR(64) DEFAULT NULL, `request_body` JSON DEFAULT NULL, `response_body` JSON DEFAULT NULL, `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_partner_expire` (`partner_id`, `expire_at`), KEY `idx_status` (`issue_status`) ) ENGINE=InnoDB COMMENT='token签发日志'; CREATE TABLE `bridge_user_mapping` ( `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `tenant_id` BIGINT UNSIGNED NOT NULL, `partner_id` BIGINT UNSIGNED NOT NULL, `oa_user_code` VARCHAR(128) NOT NULL COMMENT 'OA用户编码', `oa_user_name` VARCHAR(128) DEFAULT NULL, `oa_mobile` VARCHAR(64) DEFAULT NULL, `oa_dept_name` VARCHAR(255) DEFAULT NULL, `zpy_user_id` BIGINT UNSIGNED DEFAULT NULL COMMENT '智评云用户ID', `zpy_user_code` VARCHAR(128) DEFAULT NULL COMMENT '智评云账号编码', `zpy_user_name` VARCHAR(128) DEFAULT NULL, `zpy_mobile` VARCHAR(64) DEFAULT NULL, `mapping_status` TINYINT NOT NULL DEFAULT 1 COMMENT '1有效 0无效', `verify_result` VARCHAR(255) DEFAULT NULL COMMENT '校验结果说明', `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `is_deleted` TINYINT NOT NULL DEFAULT 0, PRIMARY KEY (`id`), UNIQUE KEY `uk_partner_oa_user_code` (`partner_id`, `oa_user_code`), KEY `idx_zpy_user_code` (`zpy_user_code`) ) ENGINE=InnoDB COMMENT='OA用户与智评云用户映射表'; CREATE TABLE `bridge_user_verify_log` ( `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `tenant_id` BIGINT UNSIGNED NOT NULL, `partner_id` BIGINT UNSIGNED NOT NULL, `request_id` VARCHAR(64) NOT NULL, `oa_user_code` VARCHAR(128) DEFAULT NULL, `oa_user_name` VARCHAR(128) DEFAULT NULL, `verify_status` TINYINT NOT NULL COMMENT '1有效 0无效', `verify_message` VARCHAR(255) DEFAULT NULL, `request_body` JSON DEFAULT NULL, `response_body` JSON DEFAULT NULL, `source_ip` VARCHAR(64) DEFAULT NULL, `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_request_id` (`request_id`), KEY `idx_oa_user_code` (`oa_user_code`) ) ENGINE=InnoDB COMMENT='接收人员校验日志'; CREATE TABLE `bridge_interface_message` ( `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `tenant_id` BIGINT UNSIGNED NOT NULL, `partner_id` BIGINT UNSIGNED NOT NULL, `direction` VARCHAR(16) NOT NULL COMMENT 'IN/OUT', `interface_code` VARCHAR(64) NOT NULL COMMENT '接口编码', `request_id` VARCHAR(64) NOT NULL, `trace_id` VARCHAR(64) DEFAULT NULL, `biz_key` VARCHAR(128) DEFAULT NULL COMMENT '业务主键,如oa_project_code、submission_no', `idempotent_key` VARCHAR(128) DEFAULT NULL, `http_status` INT DEFAULT NULL, `biz_status` VARCHAR(64) DEFAULT NULL, `source_ip` VARCHAR(64) DEFAULT NULL, `request_body` JSON DEFAULT NULL, `response_body` JSON DEFAULT NULL, `message` VARCHAR(500) DEFAULT NULL, `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `uk_partner_request_id_direction` (`partner_id`, `direction`, `request_id`), KEY `idx_interface_code_created_at` (`interface_code`, `created_at`), KEY `idx_biz_key` (`biz_key`) ) ENGINE=InnoDB COMMENT='统一接口报文日志'; CREATE TABLE `bridge_oa_project` ( `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `tenant_id` BIGINT UNSIGNED NOT NULL, `partner_id` BIGINT UNSIGNED NOT NULL, `oa_project_code` VARCHAR(128) NOT NULL COMMENT 'OA立项编号', `oa_project_name` VARCHAR(1000) NOT NULL COMMENT '项目名称', `oa_project_type` VARCHAR(64) DEFAULT NULL COMMENT '初评/正评/其他', `oa_org_code` VARCHAR(128) DEFAULT NULL, `oa_org_name` VARCHAR(255) DEFAULT NULL, `oa_owner_code` VARCHAR(128) DEFAULT NULL, `oa_owner_name` VARCHAR(128) DEFAULT NULL, `oa_owner_mobile` VARCHAR(64) DEFAULT NULL, `zpy_user_id` BIGINT UNSIGNED DEFAULT NULL COMMENT '实际映射到智评云负责人', `zpy_user_code` VARCHAR(128) DEFAULT NULL, `approval_status` VARCHAR(32) DEFAULT NULL COMMENT 'OA审批状态', `project_status` VARCHAR(32) NOT NULL DEFAULT 'CREATED' COMMENT '当前项目状态', `raw_data` JSON DEFAULT NULL COMMENT '原始立项报文解析后的标准JSON', `last_receive_at` DATETIME DEFAULT NULL COMMENT '最近一次接收时间', `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `is_deleted` TINYINT NOT NULL DEFAULT 0, `deleted_at` DATETIME DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `uk_partner_oa_project_code` (`partner_id`, `oa_project_code`), KEY `idx_owner_code` (`oa_owner_code`), KEY `idx_project_status` (`project_status`) ) ENGINE=InnoDB COMMENT='OA立项主表'; CREATE TABLE `bridge_oa_project_change_log` ( `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `tenant_id` BIGINT UNSIGNED NOT NULL, `oa_project_id` BIGINT UNSIGNED NOT NULL, `change_type` VARCHAR(64) NOT NULL COMMENT 'CREATE/UPDATE/DELETE/REOPEN', `change_summary` VARCHAR(500) DEFAULT NULL, `before_data` JSON DEFAULT NULL, `after_data` JSON DEFAULT NULL, `request_id` VARCHAR(64) DEFAULT NULL, `source_ip` VARCHAR(64) DEFAULT NULL, `operator_code` VARCHAR(128) DEFAULT NULL, `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_oa_project_id` (`oa_project_id`), KEY `idx_change_type` (`change_type`) ) ENGINE=InnoDB COMMENT='OA立项变更日志'; CREATE TABLE `bridge_project_group_bind` ( `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `tenant_id` BIGINT UNSIGNED NOT NULL, `oa_project_id` BIGINT UNSIGNED NOT NULL, `bind_no` VARCHAR(64) NOT NULL COMMENT '绑定单号', `bind_status` TINYINT NOT NULL DEFAULT 1 COMMENT '1有效 0失效', `zpy_project_group_uuid` BIGINT UNSIGNED NOT NULL COMMENT '智评云项目组UUID', `zpy_project_group_name` VARCHAR(255) NOT NULL, `relation_mode` VARCHAR(32) NOT NULL DEFAULT 'CREATE' COMMENT 'CREATE/ASSOCIATE', `is_parent_project` TINYINT NOT NULL DEFAULT 0 COMMENT '是否母项目', `parent_bind_id` BIGINT UNSIGNED DEFAULT NULL COMMENT '若为子项目,指向母项目绑定ID', `created_by` BIGINT DEFAULT NULL, `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `uk_oa_project_group` (`oa_project_id`, `zpy_project_group_uuid`), KEY `idx_parent_bind_id` (`parent_bind_id`) ) ENGINE=InnoDB COMMENT='OA立项与智评云项目组绑定表'; CREATE TABLE `bridge_project_group_bind_item` ( `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `bind_id` BIGINT UNSIGNED NOT NULL, `tenant_id` BIGINT UNSIGNED NOT NULL, `company_project_id` BIGINT UNSIGNED NOT NULL COMMENT '智评云公司项目ID', `company_project_name` VARCHAR(255) NOT NULL, `project_role` VARCHAR(32) DEFAULT NULL COMMENT 'PARENT/CHILD', `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_bind_id` (`bind_id`), KEY `idx_company_project_id` (`company_project_id`) ) ENGINE=InnoDB COMMENT='项目组绑定明细'; CREATE TABLE `bridge_submission` ( `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `tenant_id` BIGINT UNSIGNED NOT NULL, `partner_id` BIGINT UNSIGNED NOT NULL, `submission_no` VARCHAR(64) NOT NULL COMMENT '送审单号', `oa_project_id` BIGINT UNSIGNED NOT NULL, `bind_id` BIGINT UNSIGNED NOT NULL, `submission_type` VARCHAR(32) NOT NULL COMMENT '初审/正评/补送', `business_status` VARCHAR(32) NOT NULL DEFAULT 'TO_BE_SUBMITTED' COMMENT '送审业务状态', `push_status` VARCHAR(32) NOT NULL DEFAULT 'WAITING' COMMENT '接口执行状态:WAITING/SUCCESS/FAIL/TIMEOUT', `report_no` VARCHAR(128) DEFAULT NULL COMMENT '当前报告号', `allow_resubmit` TINYINT NOT NULL DEFAULT 1 COMMENT '是否允许再次送审', `request_id` VARCHAR(64) DEFAULT NULL, `request_body` JSON DEFAULT NULL, `response_body` JSON DEFAULT NULL, `last_push_at` DATETIME DEFAULT NULL, `created_by` BIGINT DEFAULT NULL, `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `is_deleted` TINYINT NOT NULL DEFAULT 0, `deleted_at` DATETIME DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `uk_submission_no` (`submission_no`), KEY `idx_oa_project_id` (`oa_project_id`), KEY `idx_bind_id` (`bind_id`), KEY `idx_business_status` (`business_status`), KEY `idx_push_status` (`push_status`) ) ENGINE=InnoDB COMMENT='送审主表'; CREATE TABLE `bridge_submission_item` ( `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `submission_id` BIGINT UNSIGNED NOT NULL, `tenant_id` BIGINT UNSIGNED NOT NULL, `company_project_id` BIGINT UNSIGNED NOT NULL, `company_project_name` VARCHAR(255) NOT NULL, `is_parent_project` TINYINT NOT NULL DEFAULT 0, `need_report` TINYINT NOT NULL DEFAULT 0, `need_explanation` TINYINT NOT NULL DEFAULT 1, `need_attachment` TINYINT NOT NULL DEFAULT 0, `need_workpaper` TINYINT NOT NULL DEFAULT 0, `remark` VARCHAR(500) DEFAULT NULL, `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_submission_id` (`submission_id`) ) ENGINE=InnoDB COMMENT='送审项目明细'; CREATE TABLE `bridge_file_asset` ( `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `tenant_id` BIGINT UNSIGNED NOT NULL, `file_name` VARCHAR(255) NOT NULL, `file_ext` VARCHAR(32) DEFAULT NULL, `storage_type` VARCHAR(32) NOT NULL DEFAULT 'local' COMMENT 'local/url/oss', `file_path` VARCHAR(1024) NOT NULL, `file_size` BIGINT UNSIGNED DEFAULT NULL, `hash_sha256` CHAR(64) DEFAULT NULL, `mime_type` VARCHAR(128) DEFAULT NULL, `file_category` VARCHAR(32) NOT NULL COMMENT 'report/explanation/attachment/workpaper/contract/other', `version_no` VARCHAR(64) DEFAULT NULL COMMENT '文件版本号', `uploaded_by` BIGINT DEFAULT NULL, `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `is_deleted` TINYINT NOT NULL DEFAULT 0, PRIMARY KEY (`id`), KEY `idx_hash_sha256` (`hash_sha256`), KEY `idx_file_category` (`file_category`) ) ENGINE=InnoDB COMMENT='统一文件元数据表'; CREATE TABLE `bridge_submission_file` ( `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `submission_id` BIGINT UNSIGNED NOT NULL, `submission_item_id` BIGINT UNSIGNED DEFAULT NULL, `file_id` BIGINT UNSIGNED NOT NULL, `file_role` VARCHAR(32) NOT NULL COMMENT 'report/explanation/attachment/workpaper', `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_submission_id` (`submission_id`), KEY `idx_file_id` (`file_id`) ) ENGINE=InnoDB COMMENT='送审文件清单'; CREATE TABLE `bridge_submission_status_log` ( `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `tenant_id` BIGINT UNSIGNED NOT NULL, `submission_id` BIGINT UNSIGNED NOT NULL, `status_type` VARCHAR(32) NOT NULL COMMENT 'BUSINESS/PUSH/REPORT_NO/FILING', `from_status` VARCHAR(32) DEFAULT NULL, `to_status` VARCHAR(32) NOT NULL, `source_type` VARCHAR(32) NOT NULL COMMENT 'SYSTEM/OA/ZPY/MANUAL', `message` VARCHAR(500) DEFAULT NULL, `request_id` VARCHAR(64) DEFAULT NULL, `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_submission_id` (`submission_id`), KEY `idx_status_type` (`status_type`) ) ENGINE=InnoDB COMMENT='送审状态流转历史'; CREATE TABLE `bridge_submission_retry_task` ( `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `tenant_id` BIGINT UNSIGNED NOT NULL, `submission_id` BIGINT UNSIGNED NOT NULL, `retry_scene` VARCHAR(64) NOT NULL COMMENT 'SUBMISSION_PUSH/REPORT_NO_CALLBACK/FILE_CALLBACK', `retry_status` VARCHAR(32) NOT NULL DEFAULT 'WAITING' COMMENT 'WAITING/RUNNING/SUCCESS/FAIL/CANCEL', `retry_count` INT NOT NULL DEFAULT 0, `max_retry_count` INT NOT NULL DEFAULT 3, `next_retry_at` DATETIME DEFAULT NULL, `last_retry_at` DATETIME DEFAULT NULL, `last_error_message` VARCHAR(1000) DEFAULT NULL, `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_submission_id` (`submission_id`), KEY `idx_retry_status_next_retry_at` (`retry_status`, `next_retry_at`) ) ENGINE=InnoDB COMMENT='送审重试任务表'; CREATE TABLE `bridge_report_no_log` ( `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `tenant_id` BIGINT UNSIGNED NOT NULL, `submission_id` BIGINT UNSIGNED NOT NULL, `old_report_no` VARCHAR(128) DEFAULT NULL, `new_report_no` VARCHAR(128) NOT NULL, `change_source` VARCHAR(32) NOT NULL DEFAULT 'OA', `request_id` VARCHAR(64) DEFAULT NULL, `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_submission_id` (`submission_id`) ) ENGINE=InnoDB COMMENT='报告号回写日志'; CREATE TABLE `bridge_submission_version` ( `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `tenant_id` BIGINT UNSIGNED NOT NULL, `submission_id` BIGINT UNSIGNED NOT NULL, `version_no` VARCHAR(64) NOT NULL COMMENT '如V1/V2', `report_no` VARCHAR(128) DEFAULT NULL, `report_file_id` BIGINT UNSIGNED DEFAULT NULL, `explanation_file_id` BIGINT UNSIGNED DEFAULT NULL, `callback_status` VARCHAR(32) NOT NULL DEFAULT 'WAITING', `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `uk_submission_version_no` (`submission_id`, `version_no`) ) ENGINE=InnoDB COMMENT='送审版本表'; CREATE TABLE `bridge_filing_record` ( `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `tenant_id` BIGINT UNSIGNED NOT NULL, `partner_id` BIGINT UNSIGNED NOT NULL, `oa_project_id` BIGINT UNSIGNED DEFAULT NULL, `submission_id` BIGINT UNSIGNED DEFAULT NULL, `filing_no` VARCHAR(64) DEFAULT NULL, `filing_status` VARCHAR(32) NOT NULL DEFAULT 'PENDING', `source_type` VARCHAR(32) NOT NULL COMMENT 'OA_PUSH/ZPY_PULL/ZPY_CREATE', `request_body` JSON DEFAULT NULL, `response_body` JSON DEFAULT NULL, `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_submission_id` (`submission_id`), KEY `idx_filing_status` (`filing_status`) ) ENGINE=InnoDB COMMENT='报备主表'; CREATE TABLE `bridge_filing_detail` ( `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `filing_record_id` BIGINT UNSIGNED NOT NULL, `contract_no` VARCHAR(128) DEFAULT NULL, `contract_name` VARCHAR(255) DEFAULT NULL, `report_no` VARCHAR(128) DEFAULT NULL, `sign_appraiser_names` VARCHAR(500) DEFAULT NULL, `detail_json` JSON DEFAULT NULL, `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_filing_record_id` (`filing_record_id`) ) ENGINE=InnoDB COMMENT='报备详情表'; SET FOREIGN_KEY_CHECKS = 1;
五、这套新设计,怎么对应你的业务流程
5.1 token 与企业配置
你的文档里说双方都要有 token 接口,还要带企业统一信用编码、企业名称、有效期、IP/域名/API 路由。
对应:
bridge_partnerbridge_partner_authbridge_token_issue_log
5.2 人员校验与映射
你的文档里说要确认负责人有效无效,还要引入“智评云账号编码”来映射 OA 的人和智评云真正执行的人。
对应:
bridge_user_mappingbridge_user_verify_log
这个地方我建议你一定要把 OA_user_code 作为首选匹配键,手机号和姓名只做辅助,不然以后换手机号、重名,坑很大。
5.3 OA立项接收与变更
你的文档里说:
审批 OK 后传递立项信息;
后续立项可变更;
但暂时只做日志记录,不更新底稿。
对应:
bridge_oa_projectbridge_oa_project_change_logbridge_interface_message
5.4 项目组创建/关联、一母多子
你的文档里写得很明确:
创建/关联项目组;可创建母子项目;对应底稿;并且系统里要有母子标记。
对应:
bridge_project_group_bindbridge_project_group_bind_item
这里我建议不要只保存 project_group_uuid,还要保存:is_parent_projectparent_bind_idproject_role
这样“母项目提交报告+说明,子项目只交说明”才能在送审明细里顺下来。
5.5 送审与状态同步
你的文档里最复杂的就是这里。
因为送审既有一次“动作”,又有一组“文件”,还有一条“审核状态链”。
对应:
bridge_submissionbridge_submission_itembridge_submission_filebridge_submission_status_logbridge_submission_retry_task
而且你文档里说:
审核中、通过的不允许再次送审;
删除是否允许再次送审,要看删除的是立项还是送审记录。
这块我建议定规则如下:
删除规则建议
如果删除的是 OA立项本身
则 bridge_oa_project.is_deleted = 1
并且其下所有 bridge_submission.allow_resubmit = 0
如果删除的是 某次送审记录
则只把该次 submission 标记删除
允许重新发起一条新的 submission
这个规则会比旧表清楚得多。
5.6 报告号回写与文件新版本
你的文档写得很清晰:
送审通过后,OA 产生报告号;
智评云收到后要更新报告/说明;
然后生成新版本;
再把新的报告/说明文件返回给 OA。
对应:
bridge_report_no_logbridge_submission_versionbridge_file_assetbridge_submission_file
这里我建议不要直接覆盖旧文件,要始终新增版本记录。
5.7 报备
你的文档里说:
OA 推送给评协报备,需提供合同、报告、签字评估师等字段;
智评云自己完成报备;
同时还能拉取某项目报备详情。
对应:
bridge_filing_recordbridge_filing_detail
六、几个关键字段和枚举,我建议现在就定死
6.1 送审业务状态 business_status
建议枚举:
TO_BE_SUBMITTED 待送审SUBMITTING 送审中UNDER_REVIEW 审核中APPROVED 通过REJECTED 不通过VOIDED 作废DELETED 删除REOPENED 再开
6.2 接口执行状态 push_status
建议枚举:
WAITING 待执行SUCCESS 成功FAIL 失败TIMEOUT 超时
6.3 状态来源 source_type
建议枚举:
SYSTEM 系统内部OA 外部 OAZPY 智评云业务系统MANUAL 人工操作
6.4 关系类型 relation_mode
建议枚举:
CREATE 新建项目组ASSOCIATE 关联已有项目组
七、这个新设计相比旧 SQL,最大的改进点
7.1 业务主线更清楚
旧表里“接收立项”“绑定项目组”“送审”“重试”“文件”缠在一起。
新设计是一条流水线,一眼能看懂。
7.2 状态可查、历史可追
旧表里很多地方只有一个 status,后期追问题会痛苦。
新设计里“当前状态”和“状态历史”拆开了。
7.3 更适合接口幂等
你跟三方对接,最怕重复推、超时重试、同一报文打两次。
新设计专门把 request_id、idempotent_key、biz_key 做成标准字段。
7.4 更适合母子项目
旧设计虽然提到了项目组和关系,但“母子项目规则”没彻底落在数据结构上。
新设计把母子关系真正纳入核心表。
7.5 文件版本管理更自然
旧设计里文件更多像“送审附带字段”。
新设计里文件是独立资产,可以挂到送审、版本、报备多个环节。
八、我建议你下一步这样推进
8.1 第一阶段,先把库骨架定下来
优先落下面这些表:
bridge_partnerbridge_partner_authbridge_user_mappingbridge_interface_messagebridge_oa_projectbridge_oa_project_change_logbridge_project_group_bindbridge_submissionbridge_submission_status_logbridge_report_no_logbridge_submission_versionbridge_filing_record
这是最小闭环。
8.2 第二阶段,再补文件与重试明细
补:
bridge_file_assetbridge_submission_filebridge_submission_retry_taskbridge_filing_detail
8.3 第三阶段,再做字典表和接口出入参标准
比如:
bridge_enum_dictbridge_interface_definebridge_error_code_map
九、我对你这套库的一个关键判断
你现在这个桥接库,不应该被设计成“简单接口日志库”,而应该设计成:
一个独立的“桥接业务中台库”
因为它不只是转报文,它还承载:
人员映射
项目绑定
母子项目规则
送审版本
报告号回写
状态流转
报备留痕
这已经不是“临时中转站”了,它本质上是一个小型业务域。
所以这次独立建库是对的。
而且我建议你从现在开始,把表名统一成 bridge_*,别再混着 oa_* 和别的业务表名,不然后面一看就乱。
你要是愿意,我下一步可以直接继续给你出:
第 2 版完整 SQL 建表脚本,把外键、唯一索引、状态枚举注释、审计字段、推荐索引全部补齐,并且顺手把你旧表到新表的“迁移映射关系”也给你列出来。
我问:
第一个问题,我方回调地址做啥用?我们提供的接口给对方内置在系统里即可啊。而且不止一个。
第二个你的三方认证配置是为了生成token吗?还是做什么用的?第三个token_value是最终生成的明文token吗?token_type做啥用的?我们这边有必要做bridge_user_mapping这个表吗?我们的理念是他们请求接口来我们这边用户表做校验,校验日志有必要,但是这张表有必要么?是为了避免多次扫描我们的系统主表?如果是这个目的可以保留。request_id干嘛的。统一接收报文日志干啥用的,没搞懂。 `bridge_project_group_bind` 绑定的是项目组,母子项目属于项目组里面的项目,所以指定母子项目不在此处,这个表是我们系统的TJ_Projects表,可能会新增一张表在主系统,你不用管。因此表bridge_project_group_bind_item不必要。送审是以项目组为单位的。bridge_submission_item表的`need_attachment` TINYINT NOT NULL DEFAULT 0,
`need_workpaper` TINYINT NOT NULL DEFAULT 0,这两字段不必要。hash_sha256一般做啥用。bridge_submission_status_log这个表解释下,不知道啥意思。REPORT_NO_CALLBACK这个是他们调我们,不是我们主动获取/推送,似乎也没有FILE_CALLBACK。所以这个表:bridge_submission_retry_task我感觉唯一的就是推送的时候记录状态。但是不是可以跟bridge_submission_status_log合并啊。请你审慎考虑。bridge_report_no_log这个表是不是也多余啊。我记录在日志表不就行了?bridge_submission_version这个也多余了。
AI答:
你这轮纠偏很到位,很多地方我同意,而且你的判断比“通用型架构设计”更贴近这次项目的真实边界。下面我逐条回应,并顺手把库设计往“够用、清晰、不多造表”这个方向收一版。
一、先说总判断
这套库不该设计成“大而全桥接中台”,而应该设计成:
面向这次 OA 对接场景的轻量业务桥接库
也就是说,能复用主系统的能力就复用,能不单独建表就不建,尤其是:
不要为了“理论完整”多造表
只保留这次对接真正需要落库、需要追踪、需要幂等、需要审计的部分
你刚提到的几处删减,我认可:
第一,bridge_project_group_bind_item 可以去掉。因为你已经明确了:送审单位是“项目组”,母子项目属于主系统 TJ_Projects 的事情,不在桥接库再拆一层。这个判断是对的。文档里虽然提到“一母多子”“需要给当前操作系统的项目打一个母子项目标记”,但这更像主系统项目模型的职责,不一定要桥接库承载。
第二,bridge_submission_item 也没必要复杂化。因为文档里写的是“以项目组为单位,推送打包为 zip 的报告、说明”,并没有要求桥接库细管每个子项条目。
第三,need_attachment、need_workpaper 这两个字段,我同意去掉。因为当前真实刚需就是“报告、说明”,至于底稿、附件、电子文档,文档里本身也是带问号的探索项,不是已定规则。
第四,bridge_submission_version、bridge_report_no_log 这两张表,不一定要单独建。你如果接受“版本仍然由主系统原有报告版本表管理”,那桥接库里确实没必要再复制一套。
所以,这一轮我会按你的思路,把设计收缩。
二、第一个问题:我方回调地址做啥用
你说得对,如果是我们提供接口,对方把接口地址内置到他们系统里调用,那“回调地址”不是必选配置项。
我上一版里放 callback_host,是按通用“互相推送”场景考虑的。但你这个项目目前更准确的边界是:
双方各自提供接口
谁需要谁的数据,就直接调用对方接口
不一定存在“我主动回调他们某个动态地址”的场景
而且你还特别强调了:
不止一个接口
那就更说明,不应该抽象成一个“回调地址”字段,而应该是:
要么根本不要
要么用“接口路由配置表”去表达多个接口地址
所以这里我修正结论:
2.1 如果只是固定接口互调
那 callback_host 直接删除。
2.2 如果以后要按 partner 配多套接口
那也不是一个字段能搞定,而应该单独做:
bridge_partner_api
字段类似:
partner_idapi_codeapi_nameapi_methodapi_pathenv_typestatus
但就你现在的描述看,这一张都可以先不做,先把接口地址写在配置文件里就行。
三、第二个问题:bridge_partner_auth 是干嘛的
你问得很准。
我上一版里的 bridge_partner_auth,本意不是“专门生成 token”,而是:
保存三方接口认证所需的静态配置
比如:
企业统一信用编码
企业名称
app_key
app_secret
签名方式
token 有效期
时间戳容差
因为文档里写了:
“token产生及配置(token,企业统一信用编码,企业名称,有效期,接口IP/域名+API路由),双方各自提供一个token获取接口。”
所以这张表如果保留,它的职责应该是:
3.1 保存“生成 token 或校验 token 所需的静态参数”
不是 token 本身,而是生成规则和认证资料。
但如果你们这边很简单,比如:
每个对接方只配一个固定 app_key/app_secret
而且配置量很小
甚至只会有 1 到 2 家对接方
那这张表也可以不建,直接放系统配置表即可。
所以这里我的修正意见是:
结论
bridge_partner_auth 不是必须表。
如果你们对接方少、认证方案简单,可以并入 bridge_partner。
如果你们后续会有多家三方、不同签名方式、不同有效期,再拆出来更合适。
四、第三个问题:token_value、token_type 是干嘛的
这个我给你说透。
4.1 token_value
是的,我上一版里这个字段指的就是:
最终生成出来的明文 token
比如对方先调“获取 token”接口,你们返回一个字符串,那字符串就可以记在 token_value。
但这里你要注意一个现实问题:
4.2 有没有必要存明文 token
这取决于你们怎么验 token。
情况一:token 是无状态的
比如你们自己按规则签发,验签时只靠 token 内容和 secret 算,不查库。
那数据库里根本没必要保存明文 token,最多只记签发日志。
情况二:token 是有状态的
比如你们生成一串随机 token,后续每次请求都要查库确认是否有效、是否过期。
那就要存 token 值,或者至少存 token 的摘要值。
所以 token_value 不是必须字段,要看你们 token 机制。
4.3 token_type 干嘛的
这个字段本来是为了区分不同 token 类型,比如:
access_tokenrefresh_tokentemp_token
但你这个项目目前看,只有一种接口访问 token,没有复杂授权体系。
所以:
结论
token_type 目前也可以去掉。
如果只有一种 token,留着纯属给自己增加理解成本。
五、bridge_user_mapping 有没有必要
你这个判断很专业。
你说:
“我们的理念是他们请求接口来我们这边用户表做校验,校验日志有必要,但是这张表有必要么?”
这个问题要分两种情况。
5.1 如果你们只做“实时校验”
也就是:
对方传部门、姓名、手机、智评云账号编码
你们实时去主系统用户表查
返回有效/无效
那确实:
不一定需要 bridge_user_mapping
因为映射关系本身就存在于主系统用户表或组织表里。
桥接库只需要保留:
谁来查过
查了谁
结果是什么
失败原因是什么
这样 bridge_user_verify_log 足够。
5.2 什么时候 bridge_user_mapping 有意义
只有一种情况我觉得值得保留:
你们不想每次都扫主系统复杂表
或者想把“对接专用映射关系”固化下来
比如文档里说:
“要求对方增加智评云账号编码,用以匹配我们跟对方 OA 系统不同的人,譬如他们系统立项的是张三,对应我们系统李四。”
这里其实隐含着一种“跨系统映射关系”。
如果这个映射关系不是主系统天然就有,而是需要对接过程中人为维护,那单独建表就有价值。
但如果你们主系统已经有“智评云账号编码”并且足够稳定,那就没必要再存一份。
5.3 结合你这次项目,我的建议
第一版先不建 bridge_user_mapping
只建:
bridge_user_verify_log
直接实时查主系统用户表。
等后面出现这两种情况再补
第一,对方频繁查,主系统压力明显
第二,确实需要维护“OA 人员 → 智评云实际人员”的专用映射
也就是说:
这张表不是必需表,是性能优化/映射固化的备选表
你这个理解是对的。
六、request_id 干嘛的
这个字段很关键,我建议保留。
通俗说,它就是:
一次接口请求的唯一流水号
用途主要有四个。
6.1 幂等
比如对方网络超时了,以为没成功,又重发一次。
如果两次 request_id 一样,你们就知道:
这是同一笔请求的重复提交,不该重复处理。
6.2 排错
线上最常见一句话就是:
“你把那次请求编号给我,我查日志。”
没有 request_id,你只能靠时间、项目编号、手机号模糊搜,查起来很痛苦。
6.3 串联多张表
比如:
一条接口报文日志
一条立项记录
一条送审记录
一条状态日志
都能挂到同一个 request_id 上,定位就快很多。
6.4 对账
以后你和三方扯皮时最好用的就是:
“你们 2026-03-10 10:05 发来的 request_id=xxx,我们返回了成功/失败,原因是……”
所以:
request_id 不等于主键
它是跨接口、跨日志、跨业务记录的一根线
我建议保留。
七、统一接收报文日志干啥用
你说没搞懂,这很正常,因为这个东西很容易设计过头。
我给你换个最朴素的说法:
它就是“接口来过什么原始数据”的档案袋
比如对方调用你们:
校验人员接口
立项接口
送审状态同步接口
报告号回写接口
报备信息接口
这些请求,业务表往往只保存“解析后的结构化字段”,不会完整保留原始 JSON。
那将来出问题时,你经常会遇到这几类场景:
7.1 业务表里字段丢了,但你想知道对方当时到底传了什么
比如项目负责人手机号为空。
是对方没传,还是你解析漏了?
7.2 你要追一个“异常报文”
比如对方传了个奇怪状态码,导致你系统没识别。
你得能把原始报文拉出来。
7.3 以后接口字段扩展
当前你没用上的字段,先原样留存。
以后要追历史数据时还能翻。
所以:
结论
统一报文日志表不是业务主表,它是:
审计表
排错表
原始输入留痕表
但你这个项目也确实不一定要做“统一”得那么大。
你可以更轻量一点:
方案 A:保留一张统一日志表
适合接口越来越多。
方案 B:每个关键业务表自带 request_body/response_body
适合接口少、实现更直接。
结合你现在这次项目,我更建议:
不单独搞 bridge_interface_message
直接在关键业务表上带 request_body、response_body、request_id
这样更轻。
八、bridge_project_group_bind、bridge_project_group_bind_item 的修正
你这个纠偏我接受。
你说:
“绑定的是项目组,母子项目属于项目组里面的项目,所以指定母子项目不在此处,这个表是我们系统的TJ_Projects表,可能会新增一张表在主系统,你不用管。因此表bridge_project_group_bind_item不必要。”
这个判断是成立的。
因为桥接库的职责只需要知道:
这个 OA 立项,对应了我们哪个项目组
至于项目组内部有几个公司项目、谁是母谁是子、底稿挂谁,那属于主系统业务模型。
所以这里收缩成一张表就够了:
bridge_project_group_bind
保留字段大概是:
idtenant_idoa_project_idproject_codeproject_group_uuidproject_group_namerelation_type 创建 or 关联statuscreate_time
就够了。
九、hash_sha256 一般做啥用
这个字段是文件领域常见字段,我解释一下。
它本质上是:
文件内容的指纹
最常见用途有三个。
9.1 去重
两个文件文件名不同,但内容完全一样。
算一下 hash 就知道是否重复。
9.2 校验完整性
文件传输后再算一次 hash。
如果不一致,说明传坏了。
9.3 防篡改
你想知道某个文件是不是后来被改过,也能比 hash。
但回到你这个项目:
如果你们只是记录“这个送审记录关联了哪个文件 ID / 路径”,
而文件本身还是由主系统文件表管理,
那桥接库里未必需要 hash_sha256。
所以:
这不是必须字段
只有你想做文件去重或完整性校验时才值得保留
十、bridge_submission_status_log 是什么意思
这张表其实是我上一版里最值得保留的思想之一,但名字确实抽象了。
通俗说,它就是:
送审状态变化历史表
因为文档里明确写了,送审有两条状态线:
一条是业务状态:
送审中、审核中、通过、不通过、作废、删除、再开
另一条是送审执行标记:
失败、成功、超时。
如果你只在 bridge_submission 主表上放几个状态字段,那你只能看到“现在是什么状态”,看不到:
是谁改的
什么时候改的
从什么状态改到什么状态
对方当时传了什么
是人工改的还是接口同步改的
所以状态日志表保存的是这样的数据:
| submission_id | status_type | from_status | to_status | source | request_id | create_time |
|---|---|---|---|---|---|---|
| 1001 | business | 送审中 | 审核中 | OA | req001 | 2026-03-10 10:00 |
| 1001 | business | 审核中 | 通过 | OA | req002 | 2026-03-10 15:20 |
| 1001 | push | 待发送 | 成功 | SYSTEM | req003 | 2026-03-10 09:58 |
它的意义是:
主表保存当前状态
日志表保存状态轨迹
这个表我仍然建议保留。
因为它很轻,但后期查问题价值很大。
不过可以简化名字和字段,不要太复杂。
比如就叫:
bridge_submission_log
字段简单点:
idsubmission_idlog_type status / push / report_nofrom_valueto_valuemessagerequest_idrequest_bodycreate_time
这样就比我上一版那个抽象写法更好懂。
十一、bridge_submission_retry_task 能不能和状态日志合并
你这个问题问到了设计的关键点。
我的判断是:
看你要不要做“自动重试”
11.1 如果你们不做自动重试
只是:
送审时记一下推送成功/失败/超时
失败了人工再点一次送审
那完全没必要单独建 retry_task 表。
因为这时“失败、成功、超时”本质只是一次日志事件,记在 bridge_submission_log 里就行。
11.2 如果你们要做自动重试
比如失败后 10 分钟重试一次,最多 3 次,定时任务扫表。
那就必须有独立任务表,因为日志表不适合做任务队列。
日志是历史留痕,任务表是当前待执行。
11.3 结合你这次场景
你刚才的话已经透露得很清楚:
“唯一的就是推送的时候记录状态。”
那说明你现在的真实需求更偏向:
记录推送结果
不一定需要自动重试队列
所以我同意你:
第一版删除 bridge_submission_retry_task
改成:
在 bridge_submission 主表记录当前推送状态
在 bridge_submission_log 记录每次推送结果历史
这样最合适。
十二、bridge_report_no_log 是不是多余
这里我给你一个很务实的判断:
如果报告号允许变更,这张表有价值
如果你只关心最终值,这张表可以不要
文档里写了:
“OA 产生一个报告号……可以变更。”
“可以变更”这四个字,就是单独建日志表的唯一理由。
因为如果你只把最新报告号写进 bridge_submission.report_no,以后你就看不到:
第一次是什么
后来改成什么
什么时候改的
是谁改的
但如果你觉得这些用统一日志表也够,不想再单独建一张,那么完全可以这么做:
方案
不建 bridge_report_no_log
把报告号变更也写进 bridge_submission_log
比如:
log_type = report_nofrom_value = NM2026001to_value = NM2026001-A
这样就够了。
所以这里我赞成你删掉独立表。
十三、bridge_submission_version 是不是多余
这点我也基本同意你。
文档里虽然说:
“同步在我们系统的报告版本列表产生一个新版本。”
但这里的关键词是:
在我们系统的报告版本列表产生一个新版本
也就是说,版本本来就应该进你们主系统已有的报告版本体系,而不是桥接库再复制一套版本表。
所以:
结论
bridge_submission_version 对桥接库来说确实多余。
桥接库只需要记录:
这次送审当前报告号是多少
是否已经收到报告号
是否已返回新文件
必要时保留日志
版本本身还是让主系统的报告版本表去管。
十四、基于你的纠偏,我建议把库收缩成这几张核心表
下面这才是我现在认为更贴合你这次项目的版本。
1. bridge_partner
三方配置主表
是否保留认证字段,看你们复杂度。简单的话可以把认证字段合并进来。
核心字段建议:idtenant_idpartner_codepartner_namecredit_codeenterprise_nameapi_hoststatusremarkcreate_timeupdate_time
如果测试、正式要分开,就加:api_host_testapi_host_prod
2. bridge_token_log
token 获取/使用日志
如果你们 token 走查库模式,就留 token_value;
如果 token 无状态,只记签发结果和过期时间,不存明文也行。
核心字段建议:idtenant_idpartner_idrequest_idtoken_value 可选expire_timestatussource_iprequest_bodyresponse_bodycreate_time
3. bridge_user_verify_log
用户校验日志
核心字段建议:idtenant_idpartner_idrequest_idoa_user_codeoa_user_namemobilezpy_user_codeverify_statusverify_messagerequest_bodyresponse_bodysource_ipcreate_time
不建 bridge_user_mapping,先实时查主系统。
4. bridge_oa_project
OA 立项主表
核心字段建议:idtenant_idpartner_idrequest_idproject_codeproject_namedo_organproject_main_personproject_main_person_mobileproject_statusrequest_bodysource_iplast_receive_timeis_deleteddeleted_timecreate_timeupdate_time
5. bridge_oa_project_log
立项接收/变更日志
因为文档明确说立项变更先只做日志记录。
核心字段建议:idtenant_idoa_project_idrequest_idlog_type create/update/deletebefore_dataafter_datarequest_bodysource_ipcreate_time
6. bridge_project_group_bind
OA 立项与项目组绑定表
核心字段建议:idtenant_idoa_project_idrequest_idproject_codeproject_group_uuidproject_group_namerelation_typestatussource_ipcreate_timeupdate_time
不再拆 item 表。
7. bridge_submission
送审主表
因为送审就是以项目组为单位。
核心字段建议:idtenant_idpartner_idrequest_idoa_project_idproject_group_uuidproject_group_namesubmission_nobusiness_statuspush_statusreport_nofile_return_statusrequest_bodyresponse_bodysource_iplast_push_timeis_deleteddeleted_timecreate_timeupdate_time
这里的字段含义我建议这样定:
business_status:送审中、审核中、通过、不通过、作废、删除、再开push_status:待推送、成功、失败、超时file_return_status:未返回、已返回、返回失败
8. bridge_submission_log
送审日志表
把原来的状态日志、推送结果日志、报告号变更日志,都合进这一张。
核心字段建议:idtenant_idsubmission_idrequest_idlog_type push/status/report_no/file_returnfrom_valueto_valuemessagerequest_bodyresponse_bodysource_ipcreate_time
这样你提到的几个问题就都解决了:
推送状态能记
业务状态变化能记
报告号变更能记
文件返回情况能记
不需要再拆 retry 表、report_no_log 表、version 表
9. bridge_filing_log
报备日志/记录表
因为你这块更多是“记录下来”,而不是桥接库自己承载完整报备业务。文档里也是“接收报备信息记录下来”。
核心字段建议:idtenant_idpartner_idrequest_idoa_project_idsubmission_idproject_codefiling_statuscontract_noreport_nosign_appraiser_namesrequest_bodyresponse_bodysource_ipcreate_timeupdate_time
如果合同、签字评估师这些字段后续越来越多,再拆 detail 表。
十五、你这次纠偏后,最合理的设计原则
我给你总结成一句话:
主系统能管的,让主系统管
桥接库只管“对接痕迹、对接状态、对接关系”
所以:
母子项目,不在桥接库建细表
报告版本,不在桥接库复制版本表
人员映射,不在桥接库先建缓存表
重试任务,不做自动重试就不建任务表
报告号历史,用统一送审日志表承接即可
这个方向,我现在认为是对的。
十六、我对你每个问题的最终结论,给你一个最简版
我方回调地址
目前可删。你这个项目更像固定接口互调,不需要单独回调地址字段。
三方认证配置表
不是必须。简单场景可并入 partner 表。
token_value
如果 token 走查库校验,就可以存;如果无状态验签,可不存明文。
token_type
当前没必要,可删。
bridge_user_mapping
第一版可不建。实时查主系统用户表,保留校验日志即可。
request_id
建议保留。用于幂等、排错、串联日志。
统一接收报文日志
可以不单独建,改成关键业务表自带 request_body/response_body。
bridge_project_group_bind_item
删掉,同意。
bridge_submission_item
删掉,同意。
need_attachment、need_workpaper
删掉,同意。
hash_sha256
不是必须,只有做文件去重/验完整性时才需要。
bridge_submission_status_log
建议保留“日志思想”,但改成更简单的 bridge_submission_log。
bridge_submission_retry_task
如果不做自动重试,就删掉;和日志合并即可。
bridge_report_no_log
可删,合入 bridge_submission_log。
bridge_submission_version
可删,版本仍由主系统版本表管理。
接下来我建议我直接给你出一版“收缩后的最终 SQL 表设计”,只保留 8 到 9 张表,完全按你这一轮纠偏后的思路来。
我问:
用app_key,app_secret的话,那对方访问我还需要填这个吗?还是只是用token就行,我们想用jwt校验。以下是我们之前的token签发方法:
public static function generateJWTtoken(array $customPayload = [], int $ttl = 5*365*24*60*60) {
$secretKey = Yii::$app->params['JwtSecretKey'];
// Header
$header = [
'alg' => 'HS256',
'typ' => 'JWT'
];
// Payload (标准字段 + 自定义字段)
$issuedAt = time();
$expireAt = $issuedAt + $ttl;
$payload = array_merge([
'iat' => $issuedAt, // Issued At
'exp' => $expireAt, // Expiration
'nbf' => $issuedAt, // Not Before
'jti' => bin2hex(random_bytes(8)) // JWT ID
], $customPayload);
// Base64Url 编码
$base64UrlHeader = self::base64UrlEncode(json_encode($header));
$base64UrlPayload = self::base64UrlEncode(json_encode($payload));
// 签名
$signature = hash_hmac('sha256', "$base64UrlHeader.$base64UrlPayload", $secretKey, true);
$base64UrlSignature = self::base64UrlEncode($signature);
$bearerToken = "$base64UrlHeader.$base64UrlPayload.$base64UrlSignature";
self::recordToken($bearerToken, $expireAt); // 将生成的token记录下来
return $bearerToken;
}
请你参考然后调整表。bridge_submission_retry_task这个保留吧。那这个bridge_report_no_log也保留吧,有变更的需求。另外request_id是对方产生的吗?请你基于我的判断再重新设计。把需要的表sql输出出来。
AI答:
你这个方向已经比较清晰了,我按你的判断收一版,先把几个关键问题讲透,再给你一套可直接落库的 SQL。
一、先回答你关于 JWT、app_key、app_secret 的问题
1.1 对方访问你,最终是不是只用 token
如果你们决定用 JWT 做接口鉴权,那么通常分两步:
第一步:获取 token
这一步一般还是要带 app_key + app_secret,或者其他固定凭证。
原因很简单:
如果“获取 token”这个接口谁都能调,而且不校验调用方身份,那任何人都能来拿 token。
所以:
app_key + app_secret 主要是用在“获取 token”接口上
拿到 token 以后,后续业务接口通常只传 Bearer Token 即可
也就是说:
不是每次访问所有接口都填 app_key/app_secret,
而是申请 token 时要校验一次调用方身份,后续业务接口只走 JWT。
这和你现在的 generateJWTtoken() 思路是匹配的。
1.2 如果只有 JWT,还要不要存 app_key / app_secret
我建议还是要有。
因为 JWT 只是“令牌形态”,不是“调用方身份来源”。
你们现在的签发逻辑里,JwtSecretKey 是你们系统统一密钥。
但问题在于:
你怎么确认“这个调用者有资格拿 token”?
这时就需要一个外部系统身份:
partner_codeapp_keyapp_secret
所以比较稳妥的方式是:
token 接口
对方传:partner_codeapp_keyapp_secret
你们验证通过后,签发 JWT。
业务接口
对方只传:Authorization: Bearer xxxxxx
这样最顺。
1.3 你这个 JWT 设计能不能用
可以用,而且思路是对的。
你现在已经有:
iatexpnbfjti
这四个已经够用了。
我建议你再补两个自定义字段,更适合这次对接:
tenant_idpartner_id 或 partner_code
比如 payload 里放:
[ 'tenant_id' => 1001, 'partner_code' => 'nuoming' ]
这样后面业务接口解 token 后,直接知道是谁调的,不用再多查一层。
1.4 token 是否要落库
你现在代码里有:
self::recordToken($bearerToken, $expireAt);
既然你已经决定记录,那我建议保留 token 日志表。
不过要注意:
如果你们后续完全按 JWT 自校验,不做“强制失效”
那库里的 token 记录主要是审计用途,不是鉴权必查表。
如果你们以后要支持“某个 token 提前失效”
那这个表就更有价值。
二、request_id 到底是谁生成
我建议这样定:
以调用方传入为主
我方兜底生成为辅
也就是:
最优方案
对方每次请求都传一个 request_id。
这样他们自己也方便查。
兜底方案
如果对方没传,你们系统自己生成一个,写入日志并回给对方。
所以字段上建议保留 request_id,并在接口规范里写清楚:
request_id:请求唯一流水号,建议由调用方生成并保证唯一;若未传,我方系统自动生成并在响应中返回。
这个设计最实用。
三、基于你的最新判断,我建议保留的表
我把这次桥接库收敛成下面 8 张主表,尽量不多造:
3.1 bridge_partner
对接方配置表
保留 app_key/app_secret,用于 token 签发接口校验。
这也比旧表里直接存 oa_token/zpy_token 更清晰。
3.2 bridge_token_log
JWT 签发记录表
你既然已有 recordToken(),这张表就保留。旧库里也已有类似 oa_partner_token_log 思路。
3.3 bridge_user_verify_log
用户实时校验日志
不建 mapping 表,先实时查主系统用户表,你这个判断成立。文档里核心是“实时确认负责人接口”。
3.4 bridge_oa_project
OA 立项主表
承接立项当前值。文档里明确有审批通过后推立项、并形成立项列表。
3.5 bridge_oa_project_log
立项接收/变更日志表
因为文档明确说立项变更“只做日志记录”。
3.6 bridge_project_group_bind
立项与项目组绑定表
只绑定项目组,不再管母子项目明细,这个按你的判断收缩。文档里有“关联多个项目组”。
3.7 bridge_submission
送审主表
以项目组为单位送审,记录当前业务状态、推送状态、报告号等。文档里对送审和状态同步写得最明确。
3.8 bridge_submission_log
送审日志表
把“状态变化”“推送结果”“报告号变更”“文件返回情况”统一记到这里。这样就不用再拆很多表了。
3.9 bridge_submission_retry_task
你明确说这张保留,那就保留。
它的职责就收敛成:送审推送失败后的重试任务表。
不去管报告号 callback,也不去管文件 callback。
3.10 bridge_report_no_log
你又确认这张保留,那就保留。
因为你已经明确有“报告号可变更”的需求,单独留这张表是合理的。文档里也确实写了“可以变更”。
报备这块,你这轮没有要求我一起出,我这版先不塞进去,避免一次太胖。后面你要,我再补 bridge_filing_*。
四、这版认证逻辑建议
我建议你接口层按这个顺序走:
4.1 获取 token
对方请求:
{
"partner_code": "nuoming",
"app_key": "xxx",
"app_secret": "yyy"
}你们处理:
先查 bridge_partner
校验 status=1
校验 app_key、app_secret
签发 JWT
写 bridge_token_log
4.2 调业务接口
请求头:
Authorization: Bearer xxxxx
你们处理:
验 JWT 签名
验 exp
验 nbf
可选:查 bridge_token_log 看是否失效
从 payload 解出 tenant_id、partner_code
这就够了。
五、下面直接给你 SQL
我按 MySQL 8 风格写,命名尽量贴近你旧库风格,但比旧表更清晰。
默认库名我先叫 oa_bridge_v2,你可以自己改。
SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; CREATE DATABASE IF NOT EXISTS `oa_bridge_v2` DEFAULT CHARACTER SET utf8mb4 DEFAULT COLLATE utf8mb4_0900_ai_ci; USE `oa_bridge_v2`; -- ---------------------------- -- Table structure for bridge_partner -- ---------------------------- DROP TABLE IF EXISTS `bridge_partner`; CREATE TABLE `bridge_partner` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增主键', `tenant_id` bigint NOT NULL COMMENT '企业租户ID', `partner_code` varchar(100) NOT NULL COMMENT '对接方编码,如nuoming', `partner_name` varchar(255) NOT NULL COMMENT '对接方名称', `enterprise_name` varchar(255) DEFAULT NULL COMMENT '企业名称', `credit_code` varchar(100) DEFAULT NULL COMMENT '统一社会信用代码', `api_host_test` varchar(500) DEFAULT NULL COMMENT '测试环境域名/IP', `api_host_production` varchar(500) DEFAULT NULL COMMENT '正式环境域名/IP', `app_key` varchar(200) NOT NULL COMMENT '获取token时使用的app_key', `app_secret` varchar(500) NOT NULL COMMENT '获取token时使用的app_secret', `ip_allow_list` varchar(1000) DEFAULT NULL COMMENT 'IP白名单,逗号分隔', `max_retry_count` int DEFAULT 3 COMMENT '最大重试次数', `retry_interval_seconds` int DEFAULT 60 COMMENT '重试间隔秒', `status` tinyint NOT NULL DEFAULT 1 COMMENT '0-停用,1-启用', `remark` varchar(500) DEFAULT NULL COMMENT '备注', `created_by` bigint DEFAULT NULL COMMENT '创建人', `updated_by` bigint DEFAULT NULL COMMENT '更新人', `is_deleted` tinyint NOT NULL DEFAULT 0 COMMENT '是否删除', `deleted_time` datetime DEFAULT NULL COMMENT '删除时间', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`id`) USING BTREE, UNIQUE KEY `uk_partner_code` (`partner_code`) USING BTREE, UNIQUE KEY `uk_tenant_partner_code` (`tenant_id`, `partner_code`) USING BTREE, KEY `idx_status` (`status`) USING BTREE, KEY `idx_tenant_id` (`tenant_id`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='对接方配置表'; -- ---------------------------- -- Table structure for bridge_token_log -- ---------------------------- DROP TABLE IF EXISTS `bridge_token_log`; CREATE TABLE `bridge_token_log` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增主键', `tenant_id` bigint NOT NULL COMMENT '企业租户ID', `partner_id` bigint NOT NULL COMMENT '关联bridge_partner.id', `request_id` varchar(100) DEFAULT NULL COMMENT '请求流水号', `jti` varchar(100) DEFAULT NULL COMMENT 'JWT唯一ID', `token` varchar(1024) NOT NULL COMMENT '签发的JWT明文token', `expire_time` datetime NOT NULL COMMENT '过期时间', `status` tinyint NOT NULL DEFAULT 1 COMMENT '0-失效,1-有效', `source_ip` varchar(50) DEFAULT NULL COMMENT '请求来源IP', `request_body` json DEFAULT NULL COMMENT '获取token时的请求体', `response_body` json DEFAULT NULL COMMENT '获取token时的响应体', `created_by` bigint DEFAULT NULL COMMENT '创建人', `is_deleted` tinyint NOT NULL DEFAULT 0 COMMENT '是否删除', `deleted_time` datetime DEFAULT NULL COMMENT '删除时间', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (`id`) USING BTREE, KEY `idx_partner_id` (`partner_id`) USING BTREE, KEY `idx_tenant_id` (`tenant_id`) USING BTREE, KEY `idx_jti` (`jti`) USING BTREE, KEY `idx_expire_time` (`expire_time`) USING BTREE, KEY `idx_request_id` (`request_id`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='JWT签发记录表'; -- ---------------------------- -- Table structure for bridge_user_verify_log -- ---------------------------- DROP TABLE IF EXISTS `bridge_user_verify_log`; CREATE TABLE `bridge_user_verify_log` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增主键', `tenant_id` bigint NOT NULL COMMENT '企业租户ID', `partner_id` bigint NOT NULL COMMENT '关联bridge_partner.id', `request_id` varchar(100) DEFAULT NULL COMMENT '请求流水号', `oa_user_code` varchar(100) DEFAULT NULL COMMENT 'OA人员编码', `oa_user_name` varchar(100) DEFAULT NULL COMMENT 'OA人员姓名', `mobile` varchar(50) DEFAULT NULL COMMENT '手机号', `zpy_account_code` varchar(100) DEFAULT NULL COMMENT '智评云账号编码', `verify_status` tinyint NOT NULL DEFAULT 0 COMMENT '0-无效,1-有效', `verify_message` varchar(500) DEFAULT NULL COMMENT '校验结果说明', `source_ip` varchar(50) DEFAULT NULL COMMENT '请求来源IP', `request_body` json DEFAULT NULL COMMENT '请求报文', `response_body` json DEFAULT NULL COMMENT '响应报文', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (`id`) USING BTREE, KEY `idx_partner_id` (`partner_id`) USING BTREE, KEY `idx_tenant_id` (`tenant_id`) USING BTREE, KEY `idx_request_id` (`request_id`) USING BTREE, KEY `idx_zpy_account_code` (`zpy_account_code`) USING BTREE, KEY `idx_mobile` (`mobile`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户实时校验日志表'; -- ---------------------------- -- Table structure for bridge_oa_project -- ---------------------------- DROP TABLE IF EXISTS `bridge_oa_project`; CREATE TABLE `bridge_oa_project` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增主键', `tenant_id` bigint NOT NULL COMMENT '企业租户ID', `partner_id` bigint NOT NULL COMMENT '关联bridge_partner.id', `request_id` varchar(100) DEFAULT NULL COMMENT '最近一次请求流水号', `project_code` varchar(200) NOT NULL COMMENT 'OA项目编号', `project_name` varchar(2000) NOT NULL COMMENT '项目名称', `do_organ` varchar(500) DEFAULT NULL COMMENT '组织', `project_main_person` varchar(100) DEFAULT NULL COMMENT '项目负责人', `project_main_person_mobile` varchar(100) DEFAULT NULL COMMENT '项目负责人手机号', `zpy_account_code` varchar(100) DEFAULT NULL COMMENT '智评云账号编码', `project_group_uuid` bigint DEFAULT NULL COMMENT '绑定的项目组UUID', `status` tinyint NOT NULL DEFAULT 0 COMMENT '0-待处理,1-已处理,2-处理失败', `last_receive_time` datetime DEFAULT NULL COMMENT '最近接收时间', `source_ip` varchar(50) DEFAULT NULL COMMENT '请求来源IP', `request_body` json DEFAULT NULL COMMENT '最近一次请求报文', `created_by` bigint DEFAULT NULL COMMENT '创建人', `updated_by` bigint DEFAULT NULL COMMENT '更新人', `is_deleted` tinyint NOT NULL DEFAULT 0 COMMENT '是否删除', `deleted_time` datetime DEFAULT NULL COMMENT '删除时间', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`id`) USING BTREE, UNIQUE KEY `uk_partner_project_code` (`partner_id`, `project_code`) USING BTREE, KEY `idx_tenant_id` (`tenant_id`) USING BTREE, KEY `idx_project_group_uuid` (`project_group_uuid`) USING BTREE, KEY `idx_request_id` (`request_id`) USING BTREE, KEY `idx_status` (`status`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='OA立项主表'; -- ---------------------------- -- Table structure for bridge_oa_project_log -- ---------------------------- DROP TABLE IF EXISTS `bridge_oa_project_log`; CREATE TABLE `bridge_oa_project_log` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增主键', `tenant_id` bigint NOT NULL COMMENT '企业租户ID', `partner_id` bigint NOT NULL COMMENT '关联bridge_partner.id', `oa_project_id` bigint DEFAULT NULL COMMENT '关联bridge_oa_project.id', `request_id` varchar(100) DEFAULT NULL COMMENT '请求流水号', `log_type` varchar(50) NOT NULL COMMENT 'create/update/delete', `project_code` varchar(200) DEFAULT NULL COMMENT 'OA项目编号', `project_name` varchar(2000) DEFAULT NULL COMMENT '项目名称', `source_ip` varchar(50) DEFAULT NULL COMMENT '请求来源IP', `before_data` json DEFAULT NULL COMMENT '变更前数据', `after_data` json DEFAULT NULL COMMENT '变更后数据', `request_body` json DEFAULT NULL COMMENT '原始请求报文', `response_body` json DEFAULT NULL COMMENT '响应报文', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (`id`) USING BTREE, KEY `idx_oa_project_id` (`oa_project_id`) USING BTREE, KEY `idx_partner_id` (`partner_id`) USING BTREE, KEY `idx_tenant_id` (`tenant_id`) USING BTREE, KEY `idx_request_id` (`request_id`) USING BTREE, KEY `idx_log_type` (`log_type`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='OA立项接收/变更日志表'; -- ---------------------------- -- Table structure for bridge_project_group_bind -- ---------------------------- DROP TABLE IF EXISTS `bridge_project_group_bind`; CREATE TABLE `bridge_project_group_bind` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增主键', `tenant_id` bigint NOT NULL COMMENT '企业租户ID', `partner_id` bigint NOT NULL COMMENT '关联bridge_partner.id', `oa_project_id` bigint NOT NULL COMMENT '关联bridge_oa_project.id', `request_id` varchar(100) DEFAULT NULL COMMENT '请求流水号', `project_code` varchar(200) NOT NULL COMMENT 'OA项目编号', `project_group_uuid` bigint NOT NULL COMMENT '项目组UUID', `project_group_name` varchar(500) DEFAULT NULL COMMENT '项目组名称', `relation_type` tinyint NOT NULL DEFAULT 1 COMMENT '1-新建关联,2-已有项目组关联', `status` tinyint NOT NULL DEFAULT 1 COMMENT '0-停用,1-启用', `source_ip` varchar(50) DEFAULT NULL COMMENT '请求来源IP', `request_body` json DEFAULT NULL COMMENT '请求报文', `response_body` json DEFAULT NULL COMMENT '响应报文', `created_by` bigint DEFAULT NULL COMMENT '创建人', `updated_by` bigint DEFAULT NULL COMMENT '更新人', `is_deleted` tinyint NOT NULL DEFAULT 0 COMMENT '是否删除', `deleted_time` datetime DEFAULT NULL COMMENT '删除时间', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`id`) USING BTREE, UNIQUE KEY `uk_oa_project_group` (`oa_project_id`, `project_group_uuid`) USING BTREE, KEY `idx_partner_id` (`partner_id`) USING BTREE, KEY `idx_tenant_id` (`tenant_id`) USING BTREE, KEY `idx_project_group_uuid` (`project_group_uuid`) USING BTREE, KEY `idx_request_id` (`request_id`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='立项与项目组绑定表'; -- ---------------------------- -- Table structure for bridge_submission -- ---------------------------- DROP TABLE IF EXISTS `bridge_submission`; CREATE TABLE `bridge_submission` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增主键', `tenant_id` bigint NOT NULL COMMENT '企业租户ID', `partner_id` bigint NOT NULL COMMENT '关联bridge_partner.id', `oa_project_id` bigint NOT NULL COMMENT '关联bridge_oa_project.id', `project_group_bind_id` bigint NOT NULL COMMENT '关联bridge_project_group_bind.id', `request_id` varchar(100) DEFAULT NULL COMMENT '最近一次请求流水号', `submission_no` varchar(100) NOT NULL COMMENT '送审单号', `project_code` varchar(200) NOT NULL COMMENT 'OA项目编号', `project_group_uuid` bigint NOT NULL COMMENT '项目组UUID', `project_group_name` varchar(500) DEFAULT NULL COMMENT '项目组名称', `business_status` varchar(50) NOT NULL DEFAULT 'SUBMITTING' COMMENT '送审中/审核中/通过/不通过/作废/删除/再开', `push_status` varchar(50) NOT NULL DEFAULT 'WAITING' COMMENT 'WAITING/SUCCESS/FAIL/TIMEOUT', `report_no` varchar(200) DEFAULT NULL COMMENT '当前最新报告号', `file_return_status` varchar(50) DEFAULT NULL COMMENT 'WAITING/SUCCESS/FAIL', `push_retry_count` int NOT NULL DEFAULT 0 COMMENT '已重试次数', `last_push_time` datetime DEFAULT NULL COMMENT '最近一次推送时间', `last_callback_time` datetime DEFAULT NULL COMMENT '最近一次回调时间', `source_ip` varchar(50) DEFAULT NULL COMMENT '请求来源IP', `request_body` json DEFAULT NULL COMMENT '最近一次请求报文', `response_body` json DEFAULT NULL COMMENT '最近一次响应报文', `remark` varchar(500) DEFAULT NULL COMMENT '备注', `created_by` bigint DEFAULT NULL COMMENT '创建人', `updated_by` bigint DEFAULT NULL COMMENT '更新人', `is_deleted` tinyint NOT NULL DEFAULT 0 COMMENT '是否删除', `deleted_time` datetime DEFAULT NULL COMMENT '删除时间', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`id`) USING BTREE, UNIQUE KEY `uk_submission_no` (`submission_no`) USING BTREE, KEY `idx_partner_id` (`partner_id`) USING BTREE, KEY `idx_tenant_id` (`tenant_id`) USING BTREE, KEY `idx_oa_project_id` (`oa_project_id`) USING BTREE, KEY `idx_project_group_bind_id` (`project_group_bind_id`) USING BTREE, KEY `idx_project_group_uuid` (`project_group_uuid`) USING BTREE, KEY `idx_request_id` (`request_id`) USING BTREE, KEY `idx_business_status` (`business_status`) USING BTREE, KEY `idx_push_status` (`push_status`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='项目组送审主表'; -- ---------------------------- -- Table structure for bridge_submission_log -- ---------------------------- DROP TABLE IF EXISTS `bridge_submission_log`; CREATE TABLE `bridge_submission_log` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增主键', `tenant_id` bigint NOT NULL COMMENT '企业租户ID', `partner_id` bigint NOT NULL COMMENT '关联bridge_partner.id', `submission_id` bigint NOT NULL COMMENT '关联bridge_submission.id', `request_id` varchar(100) DEFAULT NULL COMMENT '请求流水号', `log_type` varchar(50) NOT NULL COMMENT 'push/status/report_no/file_return/retry', `from_value` varchar(500) DEFAULT NULL COMMENT '变更前值', `to_value` varchar(500) DEFAULT NULL COMMENT '变更后值', `message` varchar(1000) DEFAULT NULL COMMENT '日志说明', `source_ip` varchar(50) DEFAULT NULL COMMENT '请求来源IP', `request_body` json DEFAULT NULL COMMENT '请求报文', `response_body` json DEFAULT NULL COMMENT '响应报文', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (`id`) USING BTREE, KEY `idx_submission_id` (`submission_id`) USING BTREE, KEY `idx_partner_id` (`partner_id`) USING BTREE, KEY `idx_tenant_id` (`tenant_id`) USING BTREE, KEY `idx_request_id` (`request_id`) USING BTREE, KEY `idx_log_type` (`log_type`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='送审日志表'; -- ---------------------------- -- Table structure for bridge_submission_retry_task -- ---------------------------- DROP TABLE IF EXISTS `bridge_submission_retry_task`; CREATE TABLE `bridge_submission_retry_task` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增主键', `tenant_id` bigint NOT NULL COMMENT '企业租户ID', `partner_id` bigint NOT NULL COMMENT '关联bridge_partner.id', `submission_id` bigint NOT NULL COMMENT '关联bridge_submission.id', `request_id` varchar(100) DEFAULT NULL COMMENT '首次请求流水号', `retry_status` varchar(50) NOT NULL DEFAULT 'WAITING' COMMENT 'WAITING/RUNNING/SUCCESS/FAIL/CANCEL', `retry_count` int NOT NULL DEFAULT 0 COMMENT '当前重试次数', `max_retry_count` int NOT NULL DEFAULT 3 COMMENT '最大重试次数', `next_retry_time` datetime DEFAULT NULL COMMENT '下次重试时间', `last_retry_time` datetime DEFAULT NULL COMMENT '最后一次重试时间', `last_error_message` varchar(1000) DEFAULT NULL COMMENT '最后一次错误信息', `source_ip` varchar(50) DEFAULT NULL COMMENT '请求来源IP', `request_body` json DEFAULT NULL COMMENT '首次请求报文', `response_body` json DEFAULT NULL COMMENT '最近一次响应报文', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`id`) USING BTREE, KEY `idx_submission_id` (`submission_id`) USING BTREE, KEY `idx_partner_id` (`partner_id`) USING BTREE, KEY `idx_tenant_id` (`tenant_id`) USING BTREE, KEY `idx_request_id` (`request_id`) USING BTREE, KEY `idx_retry_status_next_retry_time` (`retry_status`, `next_retry_time`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='送审重试任务表'; -- ---------------------------- -- Table structure for bridge_report_no_log -- ---------------------------- DROP TABLE IF EXISTS `bridge_report_no_log`; CREATE TABLE `bridge_report_no_log` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增主键', `tenant_id` bigint NOT NULL COMMENT '企业租户ID', `partner_id` bigint NOT NULL COMMENT '关联bridge_partner.id', `submission_id` bigint NOT NULL COMMENT '关联bridge_submission.id', `request_id` varchar(100) DEFAULT NULL COMMENT '请求流水号', `old_report_no` varchar(200) DEFAULT NULL COMMENT '旧报告号', `new_report_no` varchar(200) NOT NULL COMMENT '新报告号', `change_status` tinyint NOT NULL DEFAULT 1 COMMENT '0-失败,1-成功', `source_ip` varchar(50) DEFAULT NULL COMMENT '请求来源IP', `request_body` json DEFAULT NULL COMMENT '请求报文', `response_body` json DEFAULT NULL COMMENT '响应报文', `remark` varchar(500) DEFAULT NULL COMMENT '备注', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (`id`) USING BTREE, KEY `idx_submission_id` (`submission_id`) USING BTREE, KEY `idx_partner_id` (`partner_id`) USING BTREE, KEY `idx_tenant_id` (`tenant_id`) USING BTREE, KEY `idx_request_id` (`request_id`) USING BTREE, KEY `idx_new_report_no` (`new_report_no`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='报告号变更日志表'; SET FOREIGN_KEY_CHECKS = 1;
六、这版表结构和你当前判断是一致的
我再帮你对一下,避免偏掉。
已删除的
bridge_user_mappingbridge_project_group_bind_itembridge_submission_itembridge_submission_version
这些都按你的意见删了。
已保留的
bridge_submission_retry_taskbridge_report_no_log
按你的要求保留了。
已简化的
没有单独“统一接收报文表”,
而是把 request_body/response_body/request_id/source_ip 下沉到关键业务表里。
这个更贴近你现在的项目现实。
七、再给你一个接口层面的落地建议
你现在 JWT 方法里有:
'jti' => bin2hex(random_bytes(8))
我建议你在 recordToken() 里把 jti 单独拆出来入库,不要只存整串 token。
因为后面你做失效控制、排查问题时,按 jti 查更方便。
也就是说你的方法可以轻微改一下:
$jti = bin2hex(random_bytes(8)); $payload = array_merge([ 'iat' => $issuedAt, 'exp' => $expireAt, 'nbf' => $issuedAt, 'jti' => $jti ], $customPayload);
然后:
self::recordToken($bearerToken, $expireAt, $jti, $customPayload);
这样和 bridge_token_log 更配套。
八、最后给你一个我认为更稳的结论
如果你们走 JWT,那么推荐的模式不是:
直接把 token 当成“系统配置”
而是:
partner 表里存 app_key/app_secret
token_log 表里存签发出来的 JWT
业务接口只认 Bearer Token
request_id 由对方传、我方兜底
这套模式既清楚,也方便后面扩展。
你下一步要是愿意,我可以继续直接给你补一版:
对应这些表的字段字典说明 + 每个接口对应写入哪张表 + 状态流转怎么更新的伪代码。
我问:
bridge_partner这个表加一个匹配我们系统的enterprise_id.
app_key,app_secret是我们签发吗?还是用户可以自定义填?
jti跟自增主键id不一样吗,还单独弄一个jwt唯一ID?
所有zpy_account_code这个换成bigint类型吧。
bridge_oa_project这个表绑定的项目组是一对多的,所以放在一个表不合适。而且这个表为啥不加返回报文呢?这个表的status没搞明白,他推过来就完事了,怎么还需要这个状态?
`log_type` varchar(50) NOT NULL COMMENT 'push/status/report_no/file_return/retry',这个里面的集中状态,status、report_no没搞明白啥意思。
另外用户第一次提审,需要等待对方回调写入我们的报告中,紧接着进行第二次更新后提审,这是一组,第一次是为了触发拿报告号,后续他提审有了报告号,他如果再调我们,我们判断下报告号没变更就不做更新后提审。如果是他那边报告号变更,推送报告号给我们,也会触发我们的更新后提审。因此这些状态都需要记录并区分明白。请你依照我的需求调整数据结构。
绑定的项目组里面需要加一个report_no,保持最新,方便后续取用。
我感觉 `business_status` varchar(50) NOT NULL DEFAULT 'SUBMITTING' COMMENT '送审中/审核中/通过/不通过/作废/删除/再开',这个状态应该放到项目组上去。因为提审可能对应两种状态的,一种是以获取报告号为目的的手动提审,一种是更新报告号后我们系统自动触发的提审,还有一种是变更报告号后触发的自动提审,跟第二种有些微差别,也需要区分出来。file_return_status有一种情况不需要回调,即自动提审的以及报告号没变更的,请考虑这种情况。另外push_status跟file_return_status是否最好加上超时。
你怎么把报备的表给我删了?下一版在我提供的修改意见输出所有正确sql之后,把报备表还给我。
AI答:
你这轮纠偏非常关键,这次我按你的业务真相来收,不再套通用模板。
先把几个关键判断直接定下来。
一、先回答你的几个核心问题
1.1 enterprise_id 要不要加在 bridge_partner
要,而且应该加。
因为你前面已经明确,桥接库最终还是要和你们主系统企业实体对上。
所以 bridge_partner 里建议保留这几个核心身份字段:
tenant_id:桥接库/业务租户维度enterprise_id:你们主系统企业主键partner_code:对接方编码credit_code:统一社会信用代码
这样以后无论是 token 签发、立项接收、送审、报备,都能直接回挂到主系统企业。
1.2 app_key、app_secret 是我们签发,还是用户自定义填
建议这样定:
不是用户随便自定义
而是:
由你们系统后台生成并分配
由对接双方约定后写入配置
也就是说,它本质上是“对接方凭证”,不是业务用户自己填的自由字段。
比较稳的做法是:
你们后台生成一组 app_key/app_secret
配置到 bridge_partner
提供给对方系统管理员接入
这样:
获取 token 时,对方传 partner_code + app_key + app_secret
你们校验通过后,签发 JWT
如果让“用户自定义填”,后面你很难控,也不利于安全和排错。
1.3 jti 和自增主键 id 有什么区别
有区别,而且我建议保留 jti。
自增主键 id
是数据库内部主键,只在你们库里有意义。
jti
是 JWT 标准里的“令牌唯一标识”,它跟 token 本身是一一对应的。
你以后做这些事会很方便:
某个 token 强制失效
按 token 唯一号查日志
避免同一个 token 重复使用场景排查
和 JWT payload 直接对应
所以:
id 是数据库记录ID
jti 是JWT业务唯一ID
两个不是一回事。
1.4 zpy_account_code 改成 bigint
这个我同意。
如果你们智评云账号编码本质上是数字 ID,就不要再存字符串了。
这轮我会统一改成:
zpy_user_id bigint
这样比 zpy_account_code varchar 更贴近你们主系统。
1.5 bridge_oa_project 里为什么不该放项目组
你这个判断是对的。
因为你已经明确:
一个立项可以绑定多个项目组
那就不能在 bridge_oa_project 里放单个 project_group_uuid。
应该拆出去放到绑定表里。
所以这轮会改成:
bridge_oa_project 只管 OA 立项本身bridge_project_group_bind 管一对多项目组绑定
1.6 bridge_oa_project 为什么不加返回报文
应该加。
你说得对,只要是接口接收主表,就应该有:
request_bodyresponse_body
否则后期排错不完整。
1.7 bridge_oa_project.status 为什么不合适
你这个也说得对。
“他推过来就完事了”,那这张表就不该设计成“流程状态表”。
它本质上是“当前立项快照表”,不是处理任务表。
所以这轮我把它改掉:
不再放 0待处理/1已处理/2失败 这种内部流程状态。
改成更客观的字段:
data_versionlast_receive_timeis_deleted
至于“接收成功/失败”,放日志表里就够了。
1.8 bridge_submission_log.log_type 里的 status、report_no 是什么意思
你问得对,我上版那个命名太粗了。
这轮要拆细,不再用一个模糊的 log_type=status 混着记。
因为你现在已经明确有三种“提审触发原因”:
第一种:首次手动提审
目的不是最终送审完结,而是为了触发对方后续给报告号。
第二种:已有报告号后的自动更新提审
对方再次调我们,如果报告号没变,则不更新、不自动提审。
第三种:报告号变更后的自动更新提审
OA 推新的报告号给我们,触发新的更新后提审。
这三种是不同业务动作,必须区分。
所以这轮我会把“项目组当前状态”和“每次提审记录”拆开,不再只靠一张 submission 主表硬扛。
二、这次最关键的结构调整
你这轮最本质的需求,其实是这句话:
提审不是一个简单动作,而是一类事件
项目组才是状态主体
每次提审都要落一条独立记录,并区分触发类型
所以我重新调整成下面这套结构:
三、调整后的核心表结构思路
3.1 bridge_partner
对接方配置
3.2 bridge_token_log
JWT 签发记录
3.3 bridge_user_verify_log
用户实时校验日志
3.4 bridge_oa_project
OA立项当前快照
3.5 bridge_oa_project_log
OA立项接收/变更日志
3.6 bridge_project_group_bind
OA立项与项目组绑定关系
这里新增:
report_no:保存当前最新报告号review_status:项目组当前审核状态latest_submit_record_id:最近一次提审记录
因为你已经明确:
报告号应该放项目组绑定上,方便后续取用
送审中、审核中、通过等状态,应该挂在项目组上
这个判断我认可。
因为一个项目组会经历多次提审,但当前审核状态只有一个“最新值”。
3.7 bridge_submit_record
每一次提审一条记录
这是本轮最核心新增表。
它替代了我上版过度简化的 bridge_submission。
这张表专门解决:
提审类型区分
1 手动首次提审(为了触发报告号)
2 自动更新后提审(报告号存在且未变更时通常不触发)
3 报告号变更后自动提审
是否需要回传文件
因为你明确说了:
自动提审不一定需要回调
报告号没变更也不需要回调
所以这里单独设计:
need_file_callbackfile_callback_status
推送状态与超时
这里保留:
push_status:WAITING/SUCCESS/FAIL/TIMEOUTfile_callback_status:NOT_REQUIRED/WAITING/SUCCESS/FAIL/TIMEOUT
3.8 bridge_submit_record_log
提审动作日志表
记录:
发起提审
提审成功/失败/超时
自动触发原因
文件回调结果
其他异常说明
3.9 bridge_submission_retry_task
重试任务表
你要求保留,就保留。
只服务于“提审推送”重试,不混别的。
3.10 bridge_report_no_log
报告号变更日志
你要求保留,这次继续保留。
因为“报告号没变”和“报告号变更”是自动提审触发判断的关键。
四、状态模型重新定义
这次要把“项目组当前状态”和“提审记录状态”分开。
4.1 项目组绑定表上的当前审核状态 review_status
建议枚举:
INIT 初始SUBMITTING 送审中REVIEWING 审核中APPROVED 通过REJECTED 不通过VOIDED 作废DELETED 删除REOPENED 再开
这是:
项目组当前最新状态
4.2 提审记录表上的提审类型 submit_type
建议枚举:
MANUAL_FIRST 手动首次提审AUTO_AFTER_REPORT_NO 报告号写入后的自动提审AUTO_AFTER_REPORT_NO_CHANGE 报告号变更后的自动提审
4.3 提审记录表上的推送状态 push_status
建议枚举:
WAITING 待推送SUCCESS 推送成功FAIL 推送失败TIMEOUT 推送超时
4.4 文件回调状态 file_callback_status
建议枚举:
NOT_REQUIRED 不需要回调WAITING 待回调SUCCESS 回调成功FAIL 回调失败TIMEOUT 回调超时
4.5 报告号变更触发判断
建议你业务层按这个规则:
场景一:首次手动提审
创建 submit_recordsubmit_type = MANUAL_FIRST
场景二:OA再次调我们,带了报告号
如果绑定表 report_no 为空
或者和这次新报告号不同
则:
更新 bridge_project_group_bind.report_no
写 bridge_report_no_log
创建新 submit_recordsubmit_type = AUTO_AFTER_REPORT_NO 或 AUTO_AFTER_REPORT_NO_CHANGE
场景三:OA再次调我们,但报告号未变
只记日志,不创建新的自动提审记录
这正好符合你说的逻辑。
五、按你这轮要求输出 SQL
下面这版先给你“报备之外”的完整核心 SQL。
你已经明确说“下一版把报备表还给你”,所以这版我先把你当前纠偏后的主链路彻底定准。
报备我下一轮单独补进去,避免这一轮把你主链路又搅混。
SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; CREATE DATABASE IF NOT EXISTS `oa_bridge_v3` DEFAULT CHARACTER SET utf8mb4 DEFAULT COLLATE utf8mb4_0900_ai_ci; USE `oa_bridge_v3`; -- ---------------------------- -- 对接方配置表 -- ---------------------------- DROP TABLE IF EXISTS `bridge_partner`; CREATE TABLE `bridge_partner` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增主键', `tenant_id` bigint NOT NULL COMMENT '企业租户ID', `enterprise_id` bigint NOT NULL COMMENT '匹配主系统企业ID', `partner_code` varchar(100) NOT NULL COMMENT '对接方编码,如nuoming', `partner_name` varchar(255) NOT NULL COMMENT '对接方名称', `enterprise_name` varchar(255) DEFAULT NULL COMMENT '企业名称', `credit_code` varchar(100) DEFAULT NULL COMMENT '统一社会信用代码', `api_host_test` varchar(500) DEFAULT NULL COMMENT '测试环境域名/IP', `api_host_production` varchar(500) DEFAULT NULL COMMENT '正式环境域名/IP', `app_key` varchar(200) NOT NULL COMMENT '系统分配的app_key', `app_secret` varchar(500) NOT NULL COMMENT '系统分配的app_secret', `ip_allow_list` varchar(1000) DEFAULT NULL COMMENT 'IP白名单,逗号分隔', `max_retry_count` int DEFAULT 3 COMMENT '最大重试次数', `retry_interval_seconds` int DEFAULT 60 COMMENT '重试间隔秒', `status` tinyint NOT NULL DEFAULT 1 COMMENT '0-停用,1-启用', `remark` varchar(500) DEFAULT NULL COMMENT '备注', `created_by` bigint DEFAULT NULL COMMENT '创建人', `updated_by` bigint DEFAULT NULL COMMENT '更新人', `is_deleted` tinyint NOT NULL DEFAULT 0 COMMENT '是否删除', `deleted_time` datetime DEFAULT NULL COMMENT '删除时间', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`id`) USING BTREE, UNIQUE KEY `uk_tenant_partner_code` (`tenant_id`, `partner_code`) USING BTREE, KEY `idx_enterprise_id` (`enterprise_id`) USING BTREE, KEY `idx_status` (`status`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='对接方配置表'; -- ---------------------------- -- JWT签发记录表 -- ---------------------------- DROP TABLE IF EXISTS `bridge_token_log`; CREATE TABLE `bridge_token_log` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增主键', `tenant_id` bigint NOT NULL COMMENT '企业租户ID', `enterprise_id` bigint NOT NULL COMMENT '主系统企业ID', `partner_id` bigint NOT NULL COMMENT '关联bridge_partner.id', `request_id` varchar(100) DEFAULT NULL COMMENT '请求流水号', `jti` varchar(100) NOT NULL COMMENT 'JWT唯一ID', `token` varchar(1024) NOT NULL COMMENT '签发的JWT明文token', `expire_time` datetime NOT NULL COMMENT '过期时间', `status` tinyint NOT NULL DEFAULT 1 COMMENT '0-失效,1-有效', `source_ip` varchar(50) DEFAULT NULL COMMENT '请求来源IP', `request_body` json DEFAULT NULL COMMENT '获取token时的请求体', `response_body` json DEFAULT NULL COMMENT '获取token时的响应体', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (`id`) USING BTREE, UNIQUE KEY `uk_jti` (`jti`) USING BTREE, KEY `idx_partner_id` (`partner_id`) USING BTREE, KEY `idx_enterprise_id` (`enterprise_id`) USING BTREE, KEY `idx_request_id` (`request_id`) USING BTREE, KEY `idx_expire_time` (`expire_time`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='JWT签发记录表'; -- ---------------------------- -- 用户实时校验日志表 -- ---------------------------- DROP TABLE IF EXISTS `bridge_user_verify_log`; CREATE TABLE `bridge_user_verify_log` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增主键', `tenant_id` bigint NOT NULL COMMENT '企业租户ID', `enterprise_id` bigint NOT NULL COMMENT '主系统企业ID', `partner_id` bigint NOT NULL COMMENT '关联bridge_partner.id', `request_id` varchar(100) DEFAULT NULL COMMENT '请求流水号', `oa_user_code` varchar(100) DEFAULT NULL COMMENT 'OA人员编码', `oa_user_name` varchar(100) DEFAULT NULL COMMENT 'OA人员姓名', `mobile` varchar(50) DEFAULT NULL COMMENT '手机号', `zpy_user_id` bigint DEFAULT NULL COMMENT '智评云用户ID', `verify_status` tinyint NOT NULL DEFAULT 0 COMMENT '0-无效,1-有效', `verify_message` varchar(500) DEFAULT NULL COMMENT '校验结果说明', `source_ip` varchar(50) DEFAULT NULL COMMENT '请求来源IP', `request_body` json DEFAULT NULL COMMENT '请求报文', `response_body` json DEFAULT NULL COMMENT '响应报文', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (`id`) USING BTREE, KEY `idx_partner_id` (`partner_id`) USING BTREE, KEY `idx_enterprise_id` (`enterprise_id`) USING BTREE, KEY `idx_request_id` (`request_id`) USING BTREE, KEY `idx_zpy_user_id` (`zpy_user_id`) USING BTREE, KEY `idx_mobile` (`mobile`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户实时校验日志表'; -- ---------------------------- -- OA立项当前快照表 -- ---------------------------- DROP TABLE IF EXISTS `bridge_oa_project`; CREATE TABLE `bridge_oa_project` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增主键', `tenant_id` bigint NOT NULL COMMENT '企业租户ID', `enterprise_id` bigint NOT NULL COMMENT '主系统企业ID', `partner_id` bigint NOT NULL COMMENT '关联bridge_partner.id', `request_id` varchar(100) DEFAULT NULL COMMENT '最近一次请求流水号', `project_code` varchar(200) NOT NULL COMMENT 'OA项目编号', `project_name` varchar(2000) NOT NULL COMMENT '项目名称', `do_organ` varchar(500) DEFAULT NULL COMMENT '组织', `project_main_person` varchar(100) DEFAULT NULL COMMENT '项目负责人', `project_main_person_mobile` varchar(100) DEFAULT NULL COMMENT '项目负责人手机号', `zpy_user_id` bigint DEFAULT NULL COMMENT '智评云用户ID', `data_version` int NOT NULL DEFAULT 1 COMMENT '数据版本号', `last_receive_time` datetime DEFAULT NULL COMMENT '最近接收时间', `source_ip` varchar(50) DEFAULT NULL COMMENT '请求来源IP', `request_body` json DEFAULT NULL COMMENT '最近一次请求报文', `response_body` json DEFAULT NULL COMMENT '最近一次响应报文', `created_by` bigint DEFAULT NULL COMMENT '创建人', `updated_by` bigint DEFAULT NULL COMMENT '更新人', `is_deleted` tinyint NOT NULL DEFAULT 0 COMMENT '是否删除', `deleted_time` datetime DEFAULT NULL COMMENT '删除时间', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`id`) USING BTREE, UNIQUE KEY `uk_partner_project_code` (`partner_id`, `project_code`) USING BTREE, KEY `idx_enterprise_id` (`enterprise_id`) USING BTREE, KEY `idx_request_id` (`request_id`) USING BTREE, KEY `idx_zpy_user_id` (`zpy_user_id`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='OA立项当前快照表'; -- ---------------------------- -- OA立项接收/变更日志表 -- ---------------------------- DROP TABLE IF EXISTS `bridge_oa_project_log`; CREATE TABLE `bridge_oa_project_log` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增主键', `tenant_id` bigint NOT NULL COMMENT '企业租户ID', `enterprise_id` bigint NOT NULL COMMENT '主系统企业ID', `partner_id` bigint NOT NULL COMMENT '关联bridge_partner.id', `oa_project_id` bigint DEFAULT NULL COMMENT '关联bridge_oa_project.id', `request_id` varchar(100) DEFAULT NULL COMMENT '请求流水号', `log_type` varchar(50) NOT NULL COMMENT 'create/update/delete', `project_code` varchar(200) DEFAULT NULL COMMENT 'OA项目编号', `project_name` varchar(2000) DEFAULT NULL COMMENT '项目名称', `source_ip` varchar(50) DEFAULT NULL COMMENT '请求来源IP', `before_data` json DEFAULT NULL COMMENT '变更前数据', `after_data` json DEFAULT NULL COMMENT '变更后数据', `request_body` json DEFAULT NULL COMMENT '原始请求报文', `response_body` json DEFAULT NULL COMMENT '响应报文', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (`id`) USING BTREE, KEY `idx_oa_project_id` (`oa_project_id`) USING BTREE, KEY `idx_partner_id` (`partner_id`) USING BTREE, KEY `idx_enterprise_id` (`enterprise_id`) USING BTREE, KEY `idx_request_id` (`request_id`) USING BTREE, KEY `idx_log_type` (`log_type`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='OA立项接收/变更日志表'; -- ---------------------------- -- 立项与项目组绑定表 -- 一个立项可以绑定多个项目组 -- 项目组当前最新审核状态、当前最新报告号放在这里 -- ---------------------------- DROP TABLE IF EXISTS `bridge_project_group_bind`; CREATE TABLE `bridge_project_group_bind` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增主键', `tenant_id` bigint NOT NULL COMMENT '企业租户ID', `enterprise_id` bigint NOT NULL COMMENT '主系统企业ID', `partner_id` bigint NOT NULL COMMENT '关联bridge_partner.id', `oa_project_id` bigint NOT NULL COMMENT '关联bridge_oa_project.id', `request_id` varchar(100) DEFAULT NULL COMMENT '最近一次请求流水号', `project_code` varchar(200) NOT NULL COMMENT 'OA项目编号', `project_group_uuid` bigint NOT NULL COMMENT '项目组UUID', `project_group_name` varchar(500) DEFAULT NULL COMMENT '项目组名称', `relation_type` tinyint NOT NULL DEFAULT 1 COMMENT '1-新建项目组,2-关联已有项目组', `report_no` varchar(200) DEFAULT NULL COMMENT '当前最新报告号', `review_status` varchar(50) NOT NULL DEFAULT 'INIT' COMMENT 'INIT/SUBMITTING/REVIEWING/APPROVED/REJECTED/VOIDED/DELETED/REOPENED', `latest_submit_record_id` bigint DEFAULT NULL COMMENT '最近一次提审记录ID', `last_report_no_receive_time` datetime DEFAULT NULL COMMENT '最近一次接收报告号时间', `source_ip` varchar(50) DEFAULT NULL COMMENT '请求来源IP', `request_body` json DEFAULT NULL COMMENT '最近一次请求报文', `response_body` json DEFAULT NULL COMMENT '最近一次响应报文', `created_by` bigint DEFAULT NULL COMMENT '创建人', `updated_by` bigint DEFAULT NULL COMMENT '更新人', `is_deleted` tinyint NOT NULL DEFAULT 0 COMMENT '是否删除', `deleted_time` datetime DEFAULT NULL COMMENT '删除时间', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`id`) USING BTREE, UNIQUE KEY `uk_oa_project_group` (`oa_project_id`, `project_group_uuid`) USING BTREE, KEY `idx_partner_id` (`partner_id`) USING BTREE, KEY `idx_enterprise_id` (`enterprise_id`) USING BTREE, KEY `idx_project_group_uuid` (`project_group_uuid`) USING BTREE, KEY `idx_review_status` (`review_status`) USING BTREE, KEY `idx_report_no` (`report_no`) USING BTREE, KEY `idx_latest_submit_record_id` (`latest_submit_record_id`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='立项与项目组绑定表'; -- ---------------------------- -- 每一次提审一条记录 -- 区分首次手动提审、报告号写入后自动提审、报告号变更后自动提审 -- ---------------------------- DROP TABLE IF EXISTS `bridge_submit_record`; CREATE TABLE `bridge_submit_record` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增主键', `tenant_id` bigint NOT NULL COMMENT '企业租户ID', `enterprise_id` bigint NOT NULL COMMENT '主系统企业ID', `partner_id` bigint NOT NULL COMMENT '关联bridge_partner.id', `oa_project_id` bigint NOT NULL COMMENT '关联bridge_oa_project.id', `project_group_bind_id` bigint NOT NULL COMMENT '关联bridge_project_group_bind.id', `request_id` varchar(100) DEFAULT NULL COMMENT '本次请求流水号', `submit_no` varchar(100) NOT NULL COMMENT '提审记录单号', `project_code` varchar(200) NOT NULL COMMENT 'OA项目编号', `project_group_uuid` bigint NOT NULL COMMENT '项目组UUID', `project_group_name` varchar(500) DEFAULT NULL COMMENT '项目组名称', `submit_type` varchar(50) NOT NULL COMMENT 'MANUAL_FIRST/AUTO_AFTER_REPORT_NO/AUTO_AFTER_REPORT_NO_CHANGE', `trigger_source` varchar(50) NOT NULL DEFAULT 'OA' COMMENT 'OA/SYSTEM/MANUAL', `submit_purpose` varchar(100) DEFAULT NULL COMMENT '提审目的说明', `report_no_at_submit` varchar(200) DEFAULT NULL COMMENT '本次提审时使用的报告号', `report_no_changed` tinyint NOT NULL DEFAULT 0 COMMENT '本次提审前报告号是否发生变化', `push_status` varchar(50) NOT NULL DEFAULT 'WAITING' COMMENT 'WAITING/SUCCESS/FAIL/TIMEOUT', `need_file_callback` tinyint NOT NULL DEFAULT 1 COMMENT '0-不需要,1-需要', `file_callback_status` varchar(50) NOT NULL DEFAULT 'WAITING' COMMENT 'NOT_REQUIRED/WAITING/SUCCESS/FAIL/TIMEOUT', `retry_count` int NOT NULL DEFAULT 0 COMMENT '当前已重试次数', `push_time` datetime DEFAULT NULL COMMENT '推送时间', `push_response_time` datetime DEFAULT NULL COMMENT '推送响应时间', `file_callback_time` datetime DEFAULT NULL COMMENT '文件回调时间', `source_ip` varchar(50) DEFAULT NULL COMMENT '请求来源IP', `request_body` json DEFAULT NULL COMMENT '请求报文', `response_body` json DEFAULT NULL COMMENT '响应报文', `remark` varchar(1000) DEFAULT NULL COMMENT '备注', `created_by` bigint DEFAULT NULL COMMENT '创建人', `updated_by` bigint DEFAULT NULL COMMENT '更新人', `is_deleted` tinyint NOT NULL DEFAULT 0 COMMENT '是否删除', `deleted_time` datetime DEFAULT NULL COMMENT '删除时间', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`id`) USING BTREE, UNIQUE KEY `uk_submit_no` (`submit_no`) USING BTREE, KEY `idx_partner_id` (`partner_id`) USING BTREE, KEY `idx_enterprise_id` (`enterprise_id`) USING BTREE, KEY `idx_oa_project_id` (`oa_project_id`) USING BTREE, KEY `idx_project_group_bind_id` (`project_group_bind_id`) USING BTREE, KEY `idx_project_group_uuid` (`project_group_uuid`) USING BTREE, KEY `idx_request_id` (`request_id`) USING BTREE, KEY `idx_submit_type` (`submit_type`) USING BTREE, KEY `idx_push_status` (`push_status`) USING BTREE, KEY `idx_file_callback_status` (`file_callback_status`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='每次提审记录表'; -- ---------------------------- -- 提审动作日志表 -- 这里不再用模糊的status/report_no -- 直接记录事件类型 -- ---------------------------- DROP TABLE IF EXISTS `bridge_submit_record_log`; CREATE TABLE `bridge_submit_record_log` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增主键', `tenant_id` bigint NOT NULL COMMENT '企业租户ID', `enterprise_id` bigint NOT NULL COMMENT '主系统企业ID', `partner_id` bigint NOT NULL COMMENT '关联bridge_partner.id', `submit_record_id` bigint NOT NULL COMMENT '关联bridge_submit_record.id', `project_group_bind_id` bigint NOT NULL COMMENT '关联bridge_project_group_bind.id', `request_id` varchar(100) DEFAULT NULL COMMENT '请求流水号', `event_type` varchar(50) NOT NULL COMMENT 'CREATE_SUBMIT/PUSH/PUSH_RESULT/REPORT_NO_RECEIVE/FILE_CALLBACK/RETRY/SKIP_AUTO_SUBMIT/REVIEW_STATUS_SYNC', `from_value` varchar(500) DEFAULT NULL COMMENT '变更前值', `to_value` varchar(500) DEFAULT NULL COMMENT '变更后值', `message` varchar(1000) DEFAULT NULL COMMENT '日志说明', `source_ip` varchar(50) DEFAULT NULL COMMENT '请求来源IP', `request_body` json DEFAULT NULL COMMENT '请求报文', `response_body` json DEFAULT NULL COMMENT '响应报文', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (`id`) USING BTREE, KEY `idx_submit_record_id` (`submit_record_id`) USING BTREE, KEY `idx_project_group_bind_id` (`project_group_bind_id`) USING BTREE, KEY `idx_partner_id` (`partner_id`) USING BTREE, KEY `idx_enterprise_id` (`enterprise_id`) USING BTREE, KEY `idx_request_id` (`request_id`) USING BTREE, KEY `idx_event_type` (`event_type`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='提审动作日志表'; -- ---------------------------- -- 提审重试任务表 -- 仅服务提审推送重试 -- ---------------------------- DROP TABLE IF EXISTS `bridge_submission_retry_task`; CREATE TABLE `bridge_submission_retry_task` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增主键', `tenant_id` bigint NOT NULL COMMENT '企业租户ID', `enterprise_id` bigint NOT NULL COMMENT '主系统企业ID', `partner_id` bigint NOT NULL COMMENT '关联bridge_partner.id', `submit_record_id` bigint NOT NULL COMMENT '关联bridge_submit_record.id', `project_group_bind_id` bigint NOT NULL COMMENT '关联bridge_project_group_bind.id', `request_id` varchar(100) DEFAULT NULL COMMENT '首次请求流水号', `retry_status` varchar(50) NOT NULL DEFAULT 'WAITING' COMMENT 'WAITING/RUNNING/SUCCESS/FAIL/CANCEL/TIMEOUT', `retry_count` int NOT NULL DEFAULT 0 COMMENT '当前重试次数', `max_retry_count` int NOT NULL DEFAULT 3 COMMENT '最大重试次数', `next_retry_time` datetime DEFAULT NULL COMMENT '下次重试时间', `last_retry_time` datetime DEFAULT NULL COMMENT '最后一次重试时间', `last_error_message` varchar(1000) DEFAULT NULL COMMENT '最后一次错误信息', `source_ip` varchar(50) DEFAULT NULL COMMENT '请求来源IP', `request_body` json DEFAULT NULL COMMENT '首次请求报文', `response_body` json DEFAULT NULL COMMENT '最近一次响应报文', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`id`) USING BTREE, KEY `idx_submit_record_id` (`submit_record_id`) USING BTREE, KEY `idx_project_group_bind_id` (`project_group_bind_id`) USING BTREE, KEY `idx_partner_id` (`partner_id`) USING BTREE, KEY `idx_enterprise_id` (`enterprise_id`) USING BTREE, KEY `idx_request_id` (`request_id`) USING BTREE, KEY `idx_retry_status_next_retry_time` (`retry_status`, `next_retry_time`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='提审重试任务表'; -- ---------------------------- -- 报告号变更日志表 -- 报告号未变时也建议记录一条,change_type=NO_CHANGE -- ---------------------------- DROP TABLE IF EXISTS `bridge_report_no_log`; CREATE TABLE `bridge_report_no_log` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增主键', `tenant_id` bigint NOT NULL COMMENT '企业租户ID', `enterprise_id` bigint NOT NULL COMMENT '主系统企业ID', `partner_id` bigint NOT NULL COMMENT '关联bridge_partner.id', `oa_project_id` bigint NOT NULL COMMENT '关联bridge_oa_project.id', `project_group_bind_id` bigint NOT NULL COMMENT '关联bridge_project_group_bind.id', `submit_record_id` bigint DEFAULT NULL COMMENT '若因此触发自动提审,则关联提审记录', `request_id` varchar(100) DEFAULT NULL COMMENT '请求流水号', `old_report_no` varchar(200) DEFAULT NULL COMMENT '旧报告号', `new_report_no` varchar(200) DEFAULT NULL COMMENT '新报告号', `change_type` varchar(50) NOT NULL COMMENT 'FIRST_SET/CHANGE/NO_CHANGE', `change_status` tinyint NOT NULL DEFAULT 1 COMMENT '0-失败,1-成功', `trigger_auto_submit` tinyint NOT NULL DEFAULT 0 COMMENT '0-否,1-是', `source_ip` varchar(50) DEFAULT NULL COMMENT '请求来源IP', `request_body` json DEFAULT NULL COMMENT '请求报文', `response_body` json DEFAULT NULL COMMENT '响应报文', `remark` varchar(500) DEFAULT NULL COMMENT '备注', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (`id`) USING BTREE, KEY `idx_oa_project_id` (`oa_project_id`) USING BTREE, KEY `idx_project_group_bind_id` (`project_group_bind_id`) USING BTREE, KEY `idx_submit_record_id` (`submit_record_id`) USING BTREE, KEY `idx_partner_id` (`partner_id`) USING BTREE, KEY `idx_enterprise_id` (`enterprise_id`) USING BTREE, KEY `idx_request_id` (`request_id`) USING BTREE, KEY `idx_new_report_no` (`new_report_no`) USING BTREE, KEY `idx_change_type` (`change_type`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='报告号变更日志表'; SET FOREIGN_KEY_CHECKS = 1;
六、这版和你需求逐项对齐一下
6.1 bridge_partner 已加 enterprise_id
已处理。
6.2 app_key/app_secret
我建议由你们系统生成并分配,不是让用户自由填。
表里保留这两个字段。
6.3 jti
保留,而且和自增主键不是一回事。
表里也保留了唯一索引。
6.4 zpy_account_code 改 bigint
已统一改成 zpy_user_id bigint。
6.5 bridge_oa_project 不再放项目组
已处理。
6.6 bridge_oa_project 加 response_body
已处理。
6.7 bridge_oa_project.status 去掉
已处理。
改成 data_version + last_receive_time 这种更客观字段。
6.8 项目组上放当前审核状态
已处理。bridge_project_group_bind.review_status
这和文档里“送审中、审核中、通过、不通过、作废、删除、再开”的状态同步也是一致的。
6.9 项目组上放最新报告号
已处理。bridge_project_group_bind.report_no
6.10 三种提审场景区分
已处理。bridge_submit_record.submit_type
6.11 报告号未变不自动提审
已通过结构支持:
bridge_report_no_log.change_type = NO_CHANGE
并且不创建新的 bridge_submit_record
6.12 自动提审不一定需要文件回调
已处理。need_file_callbackfile_callback_status = NOT_REQUIRED
6.13 push_status 和 file_callback_status 都支持超时
已处理。
两个都支持 TIMEOUT
七、关于你提到的“首次提审是为拿报告号”这一点,我给你一个落库建议
你这个业务很特殊,但可以用这套结构稳住:
首次手动提审
创建 bridge_submit_recordsubmit_type = MANUAL_FIRSTneed_file_callback = 1 或按你业务决定
OA回写报告号
更新 bridge_project_group_bind.report_no
写 bridge_report_no_log
如果原先没有报告号
创建新的 bridge_submit_recordsubmit_type = AUTO_AFTER_REPORT_NOreport_no_changed = 1
如果报告号变化了
再创建新的 bridge_submit_recordsubmit_type = AUTO_AFTER_REPORT_NO_CHANGEreport_no_changed = 1
如果报告号没变
只写 bridge_report_no_logchange_type = NO_CHANGE
并在 bridge_submit_record_log 写一条:event_type = SKIP_AUTO_SUBMIT
这样你后面查问题会很清楚。
八、你说得对,报备表不能丢
这一点我认。
只是你刚刚这轮修改主要在主链路上,我先把主链路结构彻底拉直。
下一轮我直接把报备相关表补上,并且会和这版主表衔接好,不会再单独飘着。
下一步我建议就做一件事:
我直接继续给你补“报备表 SQL + 各接口写哪张表、怎么更新状态的流程版 SQL/伪代码说明”。
我问:
data_version这个啥意思,有必要吗?trigger_source这个OA触发是指回调,MANUAL是指不更改提交,SYSTEM是啥是系统用户手动提交,但不需要获取报告号的吗,请你意义更明确一些。 `event_type` varchar(50) NOT NULL COMMENT 'CREATE_SUBMIT/PUSH/PUSH_RESULT/REPORT_NO_RECEIVE/FILE_CALLBACK/RETRY/SKIP_AUTO_SUBMIT/REVIEW_STATUS_SYNC'这个的意义也更明确些,我也不太懂。而且我重试提审的时候,bridge_submit_record_log这个表产生的不同日志怎么区分的?还是说重试的时候这个表就没必要记录了?bridge_report_no_log中 `change_type` varchar(50) NOT NULL COMMENT 'FIRST_SET/CHANGE/NO_CHANGE',NO_CHANGE啥意思,不就是一种是提审拿报告号回调日志,还有一种是变更日志吗?为什么还有NO_CHANGE?
请你再修改,输出sql。
AI答:
你这轮指出的几个点都对,我直接先给结论:
data_version 这次可以删。
因为你这张 bridge_oa_project 本质是“当前快照表”,不是版本表。你已经有 bridge_oa_project_log 记录每次接收/变更,已经足够表达历史了。文档里对立项变更的要求也是“只做日志记录”,并没有要求单独维护版本号。
trigger_source 我上一版定义得不够清楚,这次改掉,换成两个更明确的字段:
submit_scene:这次提审是什么业务场景触发的submit_origin:这次提审是谁发起的
这样就不会把“来源”和“目的”搅在一起。
还有 event_type,你说得对,之前太抽象。
这次我改成“能一眼看懂”的事件名称,并且把“重试”单独明确出来。因为文档里既要求有“送审标记”,也要求记录“失败、成功、超时”,还要同步“送审中、审核中、通过、不通过、作废、删除、再开”这些状态。
至于 bridge_report_no_log.change_type,你说得也对。
这里保留两种就够了:
INITIAL_CALLBACK:第一次拿到报告号CHANGE_CALLBACK:后续报告号变更
NO_CHANGE 删掉。
因为“报告号没变”不是报告号日志的主业务类型,它更像一次“判断后跳过自动提审”的事件,应该记录到提审日志表里,而不是报告号变更表里。文档里核心也是“OA 产生一个报告号,可以变更;接收到报告号后,再产生一条更新了报告号后的送审记录”,并没有要求专门记录“不变更”的报告号业务类型。
下面我按你的要求,直接给你一版修正后的 SQL。
这版的核心变化有四个:
第一,删掉 data_version。
第二,把 trigger_source 改成 submit_scene + submit_origin。
第三,把 event_type 改成更明确的日志事件。
第四,把 bridge_report_no_log.change_type 收缩成两种。
一、字段语义重新明确
1. submit_scene
表示“这次提审属于哪一种业务场景”,建议固定三种:
FIRST_SUBMIT_FOR_REPORT_NO
第一次提审,目的主要是触发对方后续产生并回传报告号。这个和你文档里“OA 产生一个报告号(送审通过后)”的链路是匹配的。
AUTO_RESUBMIT_AFTER_INITIAL_REPORT_NO
第一次收到报告号后,我方自动更新报告/说明,再自动提审一次。对应文档里“接收到报告号后……同步再产生一条更新了报告号后的送审记录”。
AUTO_RESUBMIT_AFTER_REPORT_NO_CHANGE
后续报告号再次变更后,自动更新并自动提审一次。这个是你这轮补充出来的关键业务。
2. submit_origin
表示“这次提审是谁发起的”,建议两种就够:
USER_ACTION
用户在系统里主动点了提审
SYSTEM_AUTO
系统根据报告号回调自动触发
这样不会再出现 OA / SYSTEM / MANUAL 混淆。
3. event_type
这次改成下面这些,含义更直白:
SUBMIT_CREATED
创建了一条提审记录
SUBMIT_PUSH_STARTED
开始向 OA 推送提审
SUBMIT_PUSH_RESULT_SUCCESS
提审推送成功
SUBMIT_PUSH_RESULT_FAIL
提审推送失败
SUBMIT_PUSH_RESULT_TIMEOUT
提审推送超时
SUBMIT_RETRY_STARTED
开始重试
SUBMIT_RETRY_RESULT_SUCCESS
重试成功
SUBMIT_RETRY_RESULT_FAIL
重试失败
SUBMIT_RETRY_RESULT_TIMEOUT
重试超时
REPORT_NO_CALLBACK_RECEIVED
收到 OA 回调的报告号
AUTO_RESUBMIT_SKIPPED_REPORT_NO_UNCHANGED
判断报告号没变,因此跳过自动提审
FILE_CALLBACK_NOT_REQUIRED
本次不需要文件回传
FILE_CALLBACK_STARTED
开始文件回传
FILE_CALLBACK_RESULT_SUCCESS
文件回传成功
FILE_CALLBACK_RESULT_FAIL
文件回传失败
FILE_CALLBACK_RESULT_TIMEOUT
文件回传超时
REVIEW_STATUS_UPDATED
项目组审核状态被同步更新,比如送审中、审核中、通过、不通过等。文档里明确有这组状态。
这样以后你看日志,不需要猜。
4. 重试时 bridge_submit_record_log 要不要记
我建议要记。
因为重试本身就是一次关键动作。
不然你只在任务表里看到 retry_count=3,却不知道每次到底什么时候重试、为什么失败、哪次成功。
所以:
重试任务表负责“当前待执行任务状态”
日志表负责“每次重试动作历史”
二者不是重复,而是一个看当前,一个看轨迹。
5. bridge_report_no_log.change_type
改成:
INITIAL_CALLBACK
第一次回调拿到报告号
CHANGE_CALLBACK
已有报告号后,又收到新的报告号并发生变更
这就够了。
二、修正后的 SQL
SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; CREATE DATABASE IF NOT EXISTS `oa_bridge_v4` DEFAULT CHARACTER SET utf8mb4 DEFAULT COLLATE utf8mb4_0900_ai_ci; USE `oa_bridge_v4`; -- ---------------------------- -- 对接方配置表 -- ---------------------------- DROP TABLE IF EXISTS `bridge_partner`; CREATE TABLE `bridge_partner` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增主键', `tenant_id` bigint NOT NULL COMMENT '企业租户ID', `enterprise_id` bigint NOT NULL COMMENT '匹配主系统企业ID', `partner_code` varchar(100) NOT NULL COMMENT '对接方编码,如nuoming', `partner_name` varchar(255) NOT NULL COMMENT '对接方名称', `enterprise_name` varchar(255) DEFAULT NULL COMMENT '企业名称', `credit_code` varchar(100) DEFAULT NULL COMMENT '统一社会信用代码', `api_host_test` varchar(500) DEFAULT NULL COMMENT '测试环境域名/IP', `api_host_production` varchar(500) DEFAULT NULL COMMENT '正式环境域名/IP', `app_key` varchar(200) NOT NULL COMMENT '系统分配的app_key', `app_secret` varchar(500) NOT NULL COMMENT '系统分配的app_secret', `ip_allow_list` varchar(1000) DEFAULT NULL COMMENT 'IP白名单,逗号分隔', `max_retry_count` int DEFAULT 3 COMMENT '最大重试次数', `retry_interval_seconds` int DEFAULT 60 COMMENT '重试间隔秒', `status` tinyint NOT NULL DEFAULT 1 COMMENT '0-停用,1-启用', `remark` varchar(500) DEFAULT NULL COMMENT '备注', `created_by` bigint DEFAULT NULL COMMENT '创建人', `updated_by` bigint DEFAULT NULL COMMENT '更新人', `is_deleted` tinyint NOT NULL DEFAULT 0 COMMENT '是否删除', `deleted_time` datetime DEFAULT NULL COMMENT '删除时间', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`id`) USING BTREE, UNIQUE KEY `uk_tenant_partner_code` (`tenant_id`, `partner_code`) USING BTREE, KEY `idx_enterprise_id` (`enterprise_id`) USING BTREE, KEY `idx_status` (`status`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='对接方配置表'; -- ---------------------------- -- JWT签发记录表 -- ---------------------------- DROP TABLE IF EXISTS `bridge_token_log`; CREATE TABLE `bridge_token_log` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增主键', `tenant_id` bigint NOT NULL COMMENT '企业租户ID', `enterprise_id` bigint NOT NULL COMMENT '主系统企业ID', `partner_id` bigint NOT NULL COMMENT '关联bridge_partner.id', `request_id` varchar(100) DEFAULT NULL COMMENT '请求流水号', `jti` varchar(100) NOT NULL COMMENT 'JWT唯一ID', `token` varchar(1024) NOT NULL COMMENT '签发的JWT明文token', `expire_time` datetime NOT NULL COMMENT '过期时间', `status` tinyint NOT NULL DEFAULT 1 COMMENT '0-失效,1-有效', `source_ip` varchar(50) DEFAULT NULL COMMENT '请求来源IP', `request_body` json DEFAULT NULL COMMENT '获取token时的请求体', `response_body` json DEFAULT NULL COMMENT '获取token时的响应体', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (`id`) USING BTREE, UNIQUE KEY `uk_jti` (`jti`) USING BTREE, KEY `idx_partner_id` (`partner_id`) USING BTREE, KEY `idx_enterprise_id` (`enterprise_id`) USING BTREE, KEY `idx_request_id` (`request_id`) USING BTREE, KEY `idx_expire_time` (`expire_time`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='JWT签发记录表'; -- ---------------------------- -- 用户实时校验日志表 -- ---------------------------- DROP TABLE IF EXISTS `bridge_user_verify_log`; CREATE TABLE `bridge_user_verify_log` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增主键', `tenant_id` bigint NOT NULL COMMENT '企业租户ID', `enterprise_id` bigint NOT NULL COMMENT '主系统企业ID', `partner_id` bigint NOT NULL COMMENT '关联bridge_partner.id', `request_id` varchar(100) DEFAULT NULL COMMENT '请求流水号', `oa_user_code` varchar(100) DEFAULT NULL COMMENT 'OA人员编码', `oa_user_name` varchar(100) DEFAULT NULL COMMENT 'OA人员姓名', `mobile` varchar(50) DEFAULT NULL COMMENT '手机号', `zpy_user_id` bigint DEFAULT NULL COMMENT '智评云用户ID', `verify_status` tinyint NOT NULL DEFAULT 0 COMMENT '0-无效,1-有效', `verify_message` varchar(500) DEFAULT NULL COMMENT '校验结果说明', `source_ip` varchar(50) DEFAULT NULL COMMENT '请求来源IP', `request_body` json DEFAULT NULL COMMENT '请求报文', `response_body` json DEFAULT NULL COMMENT '响应报文', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (`id`) USING BTREE, KEY `idx_partner_id` (`partner_id`) USING BTREE, KEY `idx_enterprise_id` (`enterprise_id`) USING BTREE, KEY `idx_request_id` (`request_id`) USING BTREE, KEY `idx_zpy_user_id` (`zpy_user_id`) USING BTREE, KEY `idx_mobile` (`mobile`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户实时校验日志表'; -- ---------------------------- -- OA立项当前快照表 -- 文档要求立项变更先保留日志,因此这里保留当前值即可 -- ---------------------------- DROP TABLE IF EXISTS `bridge_oa_project`; CREATE TABLE `bridge_oa_project` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增主键', `tenant_id` bigint NOT NULL COMMENT '企业租户ID', `enterprise_id` bigint NOT NULL COMMENT '主系统企业ID', `partner_id` bigint NOT NULL COMMENT '关联bridge_partner.id', `request_id` varchar(100) DEFAULT NULL COMMENT '最近一次请求流水号', `project_code` varchar(200) NOT NULL COMMENT 'OA项目编号', `project_name` varchar(2000) NOT NULL COMMENT '项目名称', `do_organ` varchar(500) DEFAULT NULL COMMENT '组织', `project_main_person` varchar(100) DEFAULT NULL COMMENT '项目负责人', `project_main_person_mobile` varchar(100) DEFAULT NULL COMMENT '项目负责人手机号', `zpy_user_id` bigint DEFAULT NULL COMMENT '智评云用户ID', `last_receive_time` datetime DEFAULT NULL COMMENT '最近接收时间', `source_ip` varchar(50) DEFAULT NULL COMMENT '请求来源IP', `request_body` json DEFAULT NULL COMMENT '最近一次请求报文', `response_body` json DEFAULT NULL COMMENT '最近一次响应报文', `created_by` bigint DEFAULT NULL COMMENT '创建人', `updated_by` bigint DEFAULT NULL COMMENT '更新人', `is_deleted` tinyint NOT NULL DEFAULT 0 COMMENT '是否删除', `deleted_time` datetime DEFAULT NULL COMMENT '删除时间', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`id`) USING BTREE, UNIQUE KEY `uk_partner_project_code` (`partner_id`, `project_code`) USING BTREE, KEY `idx_enterprise_id` (`enterprise_id`) USING BTREE, KEY `idx_request_id` (`request_id`) USING BTREE, KEY `idx_zpy_user_id` (`zpy_user_id`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='OA立项当前快照表'; -- ---------------------------- -- OA立项接收/变更日志表 -- 文档要求变更先按日志记录保存 -- ---------------------------- DROP TABLE IF EXISTS `bridge_oa_project_log`; CREATE TABLE `bridge_oa_project_log` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增主键', `tenant_id` bigint NOT NULL COMMENT '企业租户ID', `enterprise_id` bigint NOT NULL COMMENT '主系统企业ID', `partner_id` bigint NOT NULL COMMENT '关联bridge_partner.id', `oa_project_id` bigint DEFAULT NULL COMMENT '关联bridge_oa_project.id', `request_id` varchar(100) DEFAULT NULL COMMENT '请求流水号', `log_type` varchar(50) NOT NULL COMMENT 'CREATE/UPDATE/DELETE', `project_code` varchar(200) DEFAULT NULL COMMENT 'OA项目编号', `project_name` varchar(2000) DEFAULT NULL COMMENT '项目名称', `source_ip` varchar(50) DEFAULT NULL COMMENT '请求来源IP', `before_data` json DEFAULT NULL COMMENT '变更前数据', `after_data` json DEFAULT NULL COMMENT '变更后数据', `request_body` json DEFAULT NULL COMMENT '原始请求报文', `response_body` json DEFAULT NULL COMMENT '响应报文', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (`id`) USING BTREE, KEY `idx_oa_project_id` (`oa_project_id`) USING BTREE, KEY `idx_partner_id` (`partner_id`) USING BTREE, KEY `idx_enterprise_id` (`enterprise_id`) USING BTREE, KEY `idx_request_id` (`request_id`) USING BTREE, KEY `idx_log_type` (`log_type`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='OA立项接收/变更日志表'; -- ---------------------------- -- 立项与项目组绑定表 -- 文档说明一个立项可以关联多个项目组,并且项目组有各自独立状态 -- ---------------------------- DROP TABLE IF EXISTS `bridge_project_group_bind`; CREATE TABLE `bridge_project_group_bind` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增主键', `tenant_id` bigint NOT NULL COMMENT '企业租户ID', `enterprise_id` bigint NOT NULL COMMENT '主系统企业ID', `partner_id` bigint NOT NULL COMMENT '关联bridge_partner.id', `oa_project_id` bigint NOT NULL COMMENT '关联bridge_oa_project.id', `request_id` varchar(100) DEFAULT NULL COMMENT '最近一次请求流水号', `project_code` varchar(200) NOT NULL COMMENT 'OA项目编号', `project_group_uuid` bigint NOT NULL COMMENT '项目组UUID', `project_group_name` varchar(500) DEFAULT NULL COMMENT '项目组名称', `relation_type` tinyint NOT NULL DEFAULT 1 COMMENT '1-新建项目组,2-关联已有项目组', `report_no` varchar(200) DEFAULT NULL COMMENT '当前最新报告号', `review_status` varchar(50) NOT NULL DEFAULT 'INIT' COMMENT 'INIT/SUBMITTING/REVIEWING/APPROVED/REJECTED/VOIDED/DELETED/REOPENED', `latest_submit_record_id` bigint DEFAULT NULL COMMENT '最近一次提审记录ID', `last_report_no_receive_time` datetime DEFAULT NULL COMMENT '最近一次接收报告号时间', `source_ip` varchar(50) DEFAULT NULL COMMENT '请求来源IP', `request_body` json DEFAULT NULL COMMENT '最近一次请求报文', `response_body` json DEFAULT NULL COMMENT '最近一次响应报文', `created_by` bigint DEFAULT NULL COMMENT '创建人', `updated_by` bigint DEFAULT NULL COMMENT '更新人', `is_deleted` tinyint NOT NULL DEFAULT 0 COMMENT '是否删除', `deleted_time` datetime DEFAULT NULL COMMENT '删除时间', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`id`) USING BTREE, UNIQUE KEY `uk_oa_project_group` (`oa_project_id`, `project_group_uuid`) USING BTREE, KEY `idx_partner_id` (`partner_id`) USING BTREE, KEY `idx_enterprise_id` (`enterprise_id`) USING BTREE, KEY `idx_project_group_uuid` (`project_group_uuid`) USING BTREE, KEY `idx_review_status` (`review_status`) USING BTREE, KEY `idx_report_no` (`report_no`) USING BTREE, KEY `idx_latest_submit_record_id` (`latest_submit_record_id`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='立项与项目组绑定表'; -- ---------------------------- -- 每次提审记录表 -- 文档说明首次送审、收到报告号后再次送审、报告号变更后再次送审都要区分 -- ---------------------------- DROP TABLE IF EXISTS `bridge_submit_record`; CREATE TABLE `bridge_submit_record` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增主键', `tenant_id` bigint NOT NULL COMMENT '企业租户ID', `enterprise_id` bigint NOT NULL COMMENT '主系统企业ID', `partner_id` bigint NOT NULL COMMENT '关联bridge_partner.id', `oa_project_id` bigint NOT NULL COMMENT '关联bridge_oa_project.id', `project_group_bind_id` bigint NOT NULL COMMENT '关联bridge_project_group_bind.id', `request_id` varchar(100) DEFAULT NULL COMMENT '本次请求流水号', `submit_no` varchar(100) NOT NULL COMMENT '提审记录单号', `project_code` varchar(200) NOT NULL COMMENT 'OA项目编号', `project_group_uuid` bigint NOT NULL COMMENT '项目组UUID', `project_group_name` varchar(500) DEFAULT NULL COMMENT '项目组名称', `submit_scene` varchar(80) NOT NULL COMMENT 'FIRST_SUBMIT_FOR_REPORT_NO/AUTO_RESUBMIT_AFTER_INITIAL_REPORT_NO/AUTO_RESUBMIT_AFTER_REPORT_NO_CHANGE', `submit_origin` varchar(30) NOT NULL COMMENT 'USER_ACTION/SYSTEM_AUTO', `report_no_at_submit` varchar(200) DEFAULT NULL COMMENT '本次提审时使用的报告号', `push_status` varchar(30) NOT NULL DEFAULT 'WAITING' COMMENT 'WAITING/SUCCESS/FAIL/TIMEOUT', `need_file_callback` tinyint NOT NULL DEFAULT 1 COMMENT '0-不需要,1-需要', `file_callback_status` varchar(30) NOT NULL DEFAULT 'WAITING' COMMENT 'NOT_REQUIRED/WAITING/SUCCESS/FAIL/TIMEOUT', `retry_count` int NOT NULL DEFAULT 0 COMMENT '当前已重试次数', `push_time` datetime DEFAULT NULL COMMENT '推送时间', `push_response_time` datetime DEFAULT NULL COMMENT '推送响应时间', `file_callback_time` datetime DEFAULT NULL COMMENT '文件回调时间', `source_ip` varchar(50) DEFAULT NULL COMMENT '请求来源IP', `request_body` json DEFAULT NULL COMMENT '请求报文', `response_body` json DEFAULT NULL COMMENT '响应报文', `remark` varchar(1000) DEFAULT NULL COMMENT '备注', `created_by` bigint DEFAULT NULL COMMENT '创建人', `updated_by` bigint DEFAULT NULL COMMENT '更新人', `is_deleted` tinyint NOT NULL DEFAULT 0 COMMENT '是否删除', `deleted_time` datetime DEFAULT NULL COMMENT '删除时间', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`id`) USING BTREE, UNIQUE KEY `uk_submit_no` (`submit_no`) USING BTREE, KEY `idx_partner_id` (`partner_id`) USING BTREE, KEY `idx_enterprise_id` (`enterprise_id`) USING BTREE, KEY `idx_oa_project_id` (`oa_project_id`) USING BTREE, KEY `idx_project_group_bind_id` (`project_group_bind_id`) USING BTREE, KEY `idx_project_group_uuid` (`project_group_uuid`) USING BTREE, KEY `idx_request_id` (`request_id`) USING BTREE, KEY `idx_submit_scene` (`submit_scene`) USING BTREE, KEY `idx_submit_origin` (`submit_origin`) USING BTREE, KEY `idx_push_status` (`push_status`) USING BTREE, KEY `idx_file_callback_status` (`file_callback_status`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='每次提审记录表'; -- ---------------------------- -- 提审动作日志表 -- 重试要记录,不然只能看到重试次数,看不到每次历史 -- ---------------------------- DROP TABLE IF EXISTS `bridge_submit_record_log`; CREATE TABLE `bridge_submit_record_log` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增主键', `tenant_id` bigint NOT NULL COMMENT '企业租户ID', `enterprise_id` bigint NOT NULL COMMENT '主系统企业ID', `partner_id` bigint NOT NULL COMMENT '关联bridge_partner.id', `submit_record_id` bigint NOT NULL COMMENT '关联bridge_submit_record.id', `project_group_bind_id` bigint NOT NULL COMMENT '关联bridge_project_group_bind.id', `request_id` varchar(100) DEFAULT NULL COMMENT '请求流水号', `event_type` varchar(80) NOT NULL COMMENT 'SUBMIT_CREATED/SUBMIT_PUSH_STARTED/SUBMIT_PUSH_RESULT_SUCCESS/SUBMIT_PUSH_RESULT_FAIL/SUBMIT_PUSH_RESULT_TIMEOUT/SUBMIT_RETRY_STARTED/SUBMIT_RETRY_RESULT_SUCCESS/SUBMIT_RETRY_RESULT_FAIL/SUBMIT_RETRY_RESULT_TIMEOUT/REPORT_NO_CALLBACK_RECEIVED/AUTO_RESUBMIT_SKIPPED_REPORT_NO_UNCHANGED/FILE_CALLBACK_NOT_REQUIRED/FILE_CALLBACK_STARTED/FILE_CALLBACK_RESULT_SUCCESS/FILE_CALLBACK_RESULT_FAIL/FILE_CALLBACK_RESULT_TIMEOUT/REVIEW_STATUS_UPDATED', `from_value` varchar(500) DEFAULT NULL COMMENT '变更前值', `to_value` varchar(500) DEFAULT NULL COMMENT '变更后值', `message` varchar(1000) DEFAULT NULL COMMENT '日志说明', `source_ip` varchar(50) DEFAULT NULL COMMENT '请求来源IP', `request_body` json DEFAULT NULL COMMENT '请求报文', `response_body` json DEFAULT NULL COMMENT '响应报文', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (`id`) USING BTREE, KEY `idx_submit_record_id` (`submit_record_id`) USING BTREE, KEY `idx_project_group_bind_id` (`project_group_bind_id`) USING BTREE, KEY `idx_partner_id` (`partner_id`) USING BTREE, KEY `idx_enterprise_id` (`enterprise_id`) USING BTREE, KEY `idx_request_id` (`request_id`) USING BTREE, KEY `idx_event_type` (`event_type`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='提审动作日志表'; -- ---------------------------- -- 提审重试任务表 -- 当前待重试任务状态放这里,历史动作放日志表 -- ---------------------------- DROP TABLE IF EXISTS `bridge_submission_retry_task`; CREATE TABLE `bridge_submission_retry_task` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增主键', `tenant_id` bigint NOT NULL COMMENT '企业租户ID', `enterprise_id` bigint NOT NULL COMMENT '主系统企业ID', `partner_id` bigint NOT NULL COMMENT '关联bridge_partner.id', `submit_record_id` bigint NOT NULL COMMENT '关联bridge_submit_record.id', `project_group_bind_id` bigint NOT NULL COMMENT '关联bridge_project_group_bind.id', `request_id` varchar(100) DEFAULT NULL COMMENT '首次请求流水号', `retry_status` varchar(30) NOT NULL DEFAULT 'WAITING' COMMENT 'WAITING/RUNNING/SUCCESS/FAIL/CANCEL/TIMEOUT', `retry_count` int NOT NULL DEFAULT 0 COMMENT '当前重试次数', `max_retry_count` int NOT NULL DEFAULT 3 COMMENT '最大重试次数', `next_retry_time` datetime DEFAULT NULL COMMENT '下次重试时间', `last_retry_time` datetime DEFAULT NULL COMMENT '最后一次重试时间', `last_error_message` varchar(1000) DEFAULT NULL COMMENT '最后一次错误信息', `source_ip` varchar(50) DEFAULT NULL COMMENT '请求来源IP', `request_body` json DEFAULT NULL COMMENT '首次请求报文', `response_body` json DEFAULT NULL COMMENT '最近一次响应报文', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`id`) USING BTREE, KEY `idx_submit_record_id` (`submit_record_id`) USING BTREE, KEY `idx_project_group_bind_id` (`project_group_bind_id`) USING BTREE, KEY `idx_partner_id` (`partner_id`) USING BTREE, KEY `idx_enterprise_id` (`enterprise_id`) USING BTREE, KEY `idx_request_id` (`request_id`) USING BTREE, KEY `idx_retry_status_next_retry_time` (`retry_status`, `next_retry_time`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='提审重试任务表'; -- ---------------------------- -- 报告号变更日志表 -- 只保留第一次回调和后续变更两类 -- 报告号未变则记到submit_log的AUTO_RESUBMIT_SKIPPED_REPORT_NO_UNCHANGED -- ---------------------------- DROP TABLE IF EXISTS `bridge_report_no_log`; CREATE TABLE `bridge_report_no_log` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增主键', `tenant_id` bigint NOT NULL COMMENT '企业租户ID', `enterprise_id` bigint NOT NULL COMMENT '主系统企业ID', `partner_id` bigint NOT NULL COMMENT '关联bridge_partner.id', `oa_project_id` bigint NOT NULL COMMENT '关联bridge_oa_project.id', `project_group_bind_id` bigint NOT NULL COMMENT '关联bridge_project_group_bind.id', `submit_record_id` bigint DEFAULT NULL COMMENT '若因此触发自动提审,则关联提审记录', `request_id` varchar(100) DEFAULT NULL COMMENT '请求流水号', `old_report_no` varchar(200) DEFAULT NULL COMMENT '旧报告号', `new_report_no` varchar(200) NOT NULL COMMENT '新报告号', `change_type` varchar(30) NOT NULL COMMENT 'INITIAL_CALLBACK/CHANGE_CALLBACK', `change_status` tinyint NOT NULL DEFAULT 1 COMMENT '0-失败,1-成功', `trigger_auto_submit` tinyint NOT NULL DEFAULT 0 COMMENT '0-否,1-是', `source_ip` varchar(50) DEFAULT NULL COMMENT '请求来源IP', `request_body` json DEFAULT NULL COMMENT '请求报文', `response_body` json DEFAULT NULL COMMENT '响应报文', `remark` varchar(500) DEFAULT NULL COMMENT '备注', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (`id`) USING BTREE, KEY `idx_oa_project_id` (`oa_project_id`) USING BTREE, KEY `idx_project_group_bind_id` (`project_group_bind_id`) USING BTREE, KEY `idx_submit_record_id` (`submit_record_id`) USING BTREE, KEY `idx_partner_id` (`partner_id`) USING BTREE, KEY `idx_enterprise_id` (`enterprise_id`) USING BTREE, KEY `idx_request_id` (`request_id`) USING BTREE, KEY `idx_new_report_no` (`new_report_no`) USING BTREE, KEY `idx_change_type` (`change_type`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='报告号变更日志表'; SET FOREIGN_KEY_CHECKS = 1;
三、你问的几个点,我再用最直白的话收一下
data_version 还有必要吗
这版已经删了。
因为你已经有 bridge_oa_project_log,再搞一列版本号意义不大。
submit_origin 现在是什么意思
现在就两种:
USER_ACTION:用户主动点提审SYSTEM_AUTO:系统收到报告号回调后,自动触发提审
不再搞模糊的 OA / MANUAL / SYSTEM 三种说法。
event_type 现在怎么理解
你可以把它理解成“提审生命周期里发生的具体事件名”。
名字已经尽量写成不用翻字典都能看懂的形式。
重试时日志表怎么区分
靠 event_type 区分:
开始重试:SUBMIT_RETRY_STARTED
重试成功:SUBMIT_RETRY_RESULT_SUCCESS
重试失败:SUBMIT_RETRY_RESULT_FAIL
重试超时:SUBMIT_RETRY_RESULT_TIMEOUT
所以重试不但要记,而且要明确记。
NO_CHANGE 为什么删了
因为“报告号没变”不是报告号日志的主要业务类型。
它本质上是一次“判断后跳过自动提审”的结果,更适合记在提审日志里。
所以现在改成:
提审日志里记 AUTO_RESUBMIT_SKIPPED_REPORT_NO_UNCHANGED
报告号日志里只记真正的“第一次有报告号”和“后续报告号变化”
这会更干净。
下一步我建议就顺着这版,直接把你要的“报备表”补进来,一次性拼成完整库。


发表评论: