@@ -0,0 +1,176 @@
-- 认证记录数据模型:新建 blade_transport_cert_record,为司机表、车辆表补认证字段与
-- 生效快照指针,订正司机表排序规则,并新增认证审核菜单。
--
-- 认证对象(司机 / 车辆)每次提交产生一条不可变记录,审核只改记录的状态,
-- 不覆盖已提交的内容。司机与车辆共用本表,由 biz_type 区分。
--
-- ⚠️ effective_cert_record_id(生效快照指针)是判定「该对象是否已认证」的唯一依据:
-- NULL = 从未审核通过;一经写入永不回退,提交、驳回、作废都不得修改它。
-- 因此「重新提交审核」不会让一辆已认证的车掉出可用池。
--
-- 幂等:全部语句可重复执行(建表 IF NOT EXISTS、加列先查 information_schema)。
-- MySQL 5.7+ 兼容。
-- ----------------------------
-- 1. 认证记录表
-- ----------------------------
CREATE TABLE IF NOT EXISTS ` blade_transport_cert_record ` (
` id ` bigint ( 20 ) NOT NULL COMMENT ' 主键 ' ,
` tenant_id ` varchar ( 12 ) NOT NULL DEFAULT ' 000000 ' COMMENT ' 租户ID ' ,
` biz_type ` varchar ( 20 ) NOT NULL COMMENT ' 认证对象类型:driver-司机,vehicle-车辆 ' ,
` biz_id ` bigint ( 20 ) NOT NULL COMMENT ' 认证对象主键:司机ID或车辆ID(车辆按具体车辆,不是司机) ' ,
` biz_key ` varchar ( 100 ) DEFAULT NULL COMMENT ' 展示键:司机姓名/车牌号 ' ,
` status ` int ( 11 ) NOT NULL COMMENT ' 审核状态:0审核中 1已通过 2已驳回 3已作废 ' ,
` snapshot_json ` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT ' 该次提交的全量认证内容JSON,一经创建不可修改 ' ,
` reject_reason ` varchar ( 200 ) DEFAULT NULL COMMENT ' 驳回原因,仅状态为已驳回时有值 ' ,
` submit_time ` datetime DEFAULT NULL COMMENT ' 提交时间 ' ,
` submit_user ` bigint ( 20 ) DEFAULT NULL COMMENT ' 提交人 ' ,
` audit_time ` datetime DEFAULT NULL COMMENT ' 审核时间 ' ,
` audit_user ` bigint ( 20 ) DEFAULT NULL COMMENT ' 审核人 ' ,
` create_user ` bigint ( 20 ) DEFAULT NULL COMMENT ' 创建人 ' ,
` create_dept ` bigint ( 20 ) DEFAULT NULL COMMENT ' 创建部门 ' ,
` create_time ` datetime DEFAULT NULL COMMENT ' 创建时间 ' ,
` update_user ` bigint ( 20 ) DEFAULT NULL COMMENT ' 修改人 ' ,
` update_time ` datetime DEFAULT NULL COMMENT ' 修改时间 ' ,
` is_deleted ` int ( 11 ) DEFAULT ' 0 ' COMMENT ' 是否已删除 ' ,
` pending_biz_id ` bigint ( 20 ) GENERATED ALWAYS AS ( if ( ( ` status ` = 0 ) and ( ` is_deleted ` = 0 ) , ` biz_id ` , NULL ) ) STORED COMMENT ' 待审唯一键:仅未删除的审核中记录非空,用于保证同对象至多一条待审快照 ' ,
PRIMARY KEY ( ` id ` ) USING BTREE ,
UNIQUE KEY ` uk_cert_record_pending ` ( ` tenant_id ` , ` biz_type ` , ` pending_biz_id ` ) USING BTREE ,
KEY ` idx_cert_record_biz ` ( ` biz_type ` , ` biz_id ` , ` submit_time ` ) USING BTREE ,
KEY ` idx_cert_record_status ` ( ` biz_type ` , ` status ` , ` submit_time ` ) USING BTREE ,
KEY ` idx_cert_record_submit_time ` ( ` submit_time ` ) USING BTREE
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = ' 认证记录 ' ;
-- ----------------------------
-- 2~4. 加列与排序规则订正
-- ----------------------------
DELIMITER $ $
DROP PROCEDURE IF EXISTS ` upgrade_transport_cert_record_20261002 ` $ $
CREATE PROCEDURE ` upgrade_transport_cert_record_20261002 ` ( )
BEGIN
DECLARE db_name varchar ( 128 ) ;
SET db_name = DATABASE ( ) ;
-- ---- 2. 司机表:认证字段 + 生效快照指针 ----
-- certification_status 是「最新提交状态」的展示缓存;初始为 NULL 表示「从未提交」,
-- 与「审核中(0)」语义不同,故不可用 0 兜底。
IF NOT EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = db_name AND table_name = ' blade_transport_driver ' AND column_name = ' certification_status ' ) THEN
ALTER TABLE ` blade_transport_driver ` ADD COLUMN ` certification_status ` int ( 11 ) DEFAULT NULL COMMENT ' 最新提交状态展示缓存:0审核中 1已通过 2已驳回 3已作废,NULL为从未提交 ' AFTER ` remark ` ;
END IF ;
IF NOT EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = db_name AND table_name = ' blade_transport_driver ' AND column_name = ' certification_reject_reason ' ) THEN
ALTER TABLE ` blade_transport_driver ` ADD COLUMN ` certification_reject_reason ` varchar ( 200 ) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT ' 最新一次驳回原因展示缓存 ' AFTER ` certification_status ` ;
END IF ;
IF NOT EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = db_name AND table_name = ' blade_transport_driver ' AND column_name = ' effective_cert_record_id ' ) THEN
ALTER TABLE ` blade_transport_driver ` ADD COLUMN ` effective_cert_record_id ` bigint ( 20 ) DEFAULT NULL COMMENT ' 生效快照指针:指向 blade_transport_cert_record.id, NULL 表示从未认证通过;一经设置永不回退 ' AFTER ` certification_reject_reason ` ;
END IF ;
-- ---- 2.1 司机表:身份证有效期(小程序 person.vue 标为必填,原表缺列)----
IF NOT EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = db_name AND table_name = ' blade_transport_driver ' AND column_name = ' id_card_valid_start ' ) THEN
ALTER TABLE ` blade_transport_driver ` ADD COLUMN ` id_card_valid_start ` date DEFAULT NULL COMMENT ' 身份证有效期起 ' AFTER ` id_card_back ` ;
END IF ;
IF NOT EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = db_name AND table_name = ' blade_transport_driver ' AND column_name = ' id_card_valid_end ' ) THEN
ALTER TABLE ` blade_transport_driver ` ADD COLUMN ` id_card_valid_end ` date DEFAULT NULL COMMENT ' 身份证有效期止 ' AFTER ` id_card_valid_start ` ;
END IF ;
IF NOT EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = db_name AND table_name = ' blade_transport_driver ' AND column_name = ' id_card_long_term ' ) THEN
ALTER TABLE ` blade_transport_driver ` ADD COLUMN ` id_card_long_term ` int ( 11 ) DEFAULT ' 0 ' COMMENT ' 身份证长期有效:0否 1是 ' AFTER ` id_card_valid_end ` ;
END IF ;
-- ---- 3. 车辆表:生效快照指针 ----
-- 现有 certification_status / certification_reject_reason 保留,降级为「最新提交状态」展示缓存;
-- 车辆可用性判定改读本指针。
IF NOT EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = db_name AND table_name = ' blade_transport_vehicle ' AND column_name = ' effective_cert_record_id ' ) THEN
ALTER TABLE ` blade_transport_vehicle ` ADD COLUMN ` effective_cert_record_id ` bigint ( 20 ) DEFAULT NULL COMMENT ' 生效快照指针:指向 blade_transport_cert_record.id, NULL 表示从未认证通过;一经设置永不回退 ' AFTER ` certification_reject_reason ` ;
END IF ;
-- ---- 4. 司机表排序规则订正 ----
-- blade_transport_driver 建表未显式指定 COLLATE, MySQL 8+ 会落到服务器默认
-- utf8mb4_0900_ai_ci,与项目规范(utf8mb4_general_ci)不一致。
-- blade_transport_vehicle 曾因同类问题在 JOIN 时报 Illegal mix of collations,
-- 故在此一并订正,避免司机认证的关联查询重演同一故障。
IF EXISTS ( SELECT 1 FROM information_schema . tables WHERE table_schema = db_name AND table_name = ' blade_transport_driver ' AND table_collation < > ' utf8mb4_general_ci ' ) THEN
ALTER TABLE ` blade_transport_driver ` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci ;
END IF ;
-- ---- 4.1 待审唯一键自修复 ----
-- 生成列必须同时排除「已逻辑删除」的行:MyBatis-Plus 的 removeById 只把 is_deleted 置 1,
-- 不会改 status。若生成列只看 status = 0,一条被逻辑删除的待审记录会继续占用唯一键,
-- 导致该认证对象永远无法再次提交。
-- 建表语句已是正确版本;这里负责把按早期版本建过表的环境就地修正过来。
IF EXISTS (
SELECT 1 FROM information_schema . columns
WHERE table_schema = db_name AND table_name = ' blade_transport_cert_record '
AND column_name = ' pending_biz_id ' AND generation_expression NOT LIKE ' %is_deleted% '
) THEN
ALTER TABLE ` blade_transport_cert_record `
MODIFY COLUMN ` pending_biz_id ` bigint ( 20 ) GENERATED ALWAYS AS ( if ( ( ` status ` = 0 ) and ( ` is_deleted ` = 0 ) , ` biz_id ` , NULL ) ) STORED COMMENT ' 待审唯一键:仅未删除的审核中记录非空,用于保证同对象至多一条待审快照 ' ;
END IF ;
-- ---- 4.2 tenant_id 收紧为 NOT NULL ----
-- tenant_id 是待审唯一键 uk_cert_record_pending 的第一列,而 MySQL 的唯一索引不对 NULL 去重:
-- 若 tenant_id 允许为 NULL,两条 tenant_id IS NULL 的待审记录可以并存,
-- 「同一对象至多一条待审」的约束就被绕过了。
-- 本库三张表(driver / vehicle / waybill)实测均无 tenant_id 为 NULL 的行,
-- 且「NOT NULL DEFAULT '000000'」是项目既有写法(doc/sql/transport 下 23 个脚本如此)。
IF EXISTS (
SELECT 1 FROM information_schema . columns
WHERE table_schema = db_name AND table_name = ' blade_transport_cert_record '
AND column_name = ' tenant_id ' AND is_nullable = ' YES '
) THEN
UPDATE ` blade_transport_cert_record ` SET ` tenant_id ` = ' 000000 ' WHERE ` tenant_id ` IS NULL ;
ALTER TABLE ` blade_transport_cert_record `
MODIFY COLUMN ` tenant_id ` varchar ( 12 ) NOT NULL DEFAULT ' 000000 ' COMMENT ' 租户ID ' ;
END IF ;
-- ---- 4.3 车辆认证状态缓存词表对齐 ----
-- 改造前车辆侧是「0认证中 1认证通过 2认证驳回」,不含「已作废」;
-- 而新流程会把「被同对象再次提交取代」写成 3,届时该列无对应语义。
-- 取值 0/1/2 在两套词表下含义一致(进行中 / 通过 / 驳回),故这里只补 3 并统一措辞,
-- 不改变任何既有数据的含义。仅改列注释(元数据),不动数据。
IF EXISTS (
SELECT 1 FROM information_schema . columns
WHERE table_schema = db_name AND table_name = ' blade_transport_vehicle '
AND column_name = ' certification_status ' AND column_comment NOT LIKE ' %已作废% '
) THEN
ALTER TABLE ` blade_transport_vehicle `
MODIFY COLUMN ` certification_status ` int ( 11 ) DEFAULT ' 0 ' COMMENT ' 最新提交状态展示缓存:0审核中 1已通过 2已驳回 3已作废;可用性判定只看 effective_cert_record_id ' ;
END IF ;
IF EXISTS (
SELECT 1 FROM information_schema . columns
WHERE table_schema = db_name AND table_name = ' blade_transport_vehicle '
AND column_name = ' certification_reject_reason ' AND column_comment NOT LIKE ' %展示缓存% '
) THEN
ALTER TABLE ` blade_transport_vehicle `
MODIFY COLUMN ` certification_reject_reason ` varchar ( 200 ) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT ' 最新一次驳回原因展示缓存 ' ;
END IF ;
END $ $
CALL ` upgrade_transport_cert_record_20261002 ` ( ) $ $
DROP PROCEDURE ` upgrade_transport_cert_record_20261002 ` $ $
DELIMITER ;
-- ----------------------------
-- 5. 菜单与权限码
-- 挂在「运力管理」(2079000000000000001) 下,与司机管理 / 车辆管理同级。
-- 列表页权限码 cert_certification_audit_{driver|vehicle},审核动作加 _audit 后缀。
-- ----------------------------
INSERT INTO ` blade_menu ` ( ` id ` , ` parent_id ` , ` code ` , ` name ` , ` alias ` , ` path ` , ` source ` , ` sort ` , ` category ` , ` action ` , ` is_open ` , ` component ` , ` remark ` , ` is_deleted ` ) VALUES
( 2079000000000000300 , 2079000000000000001 , ' cert_certification_audit_driver ' , ' 司机审核 ' , ' cert_certification_audit_driver ' , ' /transportCapacity/cert-audit-driver ' , ' iconfont iconicon_doc ' , 4 , 1 , 0 , 1 , ' ' , ' 司机认证待审列表 ' , 0 ) ,
( 2079000000000000301 , 2079000000000000300 , ' cert_certification_audit_driver_audit ' , ' 审核 ' , ' cert_certification_audit_driver_audit ' , ' ' , ' ' , 1 , 2 , 0 , 1 , NULL , ' 通过/驳回司机认证 ' , 0 ) ,
( 2079000000000000310 , 2079000000000000001 , ' cert_certification_audit_vehicle ' , ' 车辆审核 ' , ' cert_certification_audit_vehicle ' , ' /transportCapacity/cert-audit-vehicle ' , ' iconfont iconicon_doc ' , 5 , 1 , 0 , 1 , ' ' , ' 车辆认证待审列表 ' , 0 ) ,
( 2079000000000000311 , 2079000000000000310 , ' cert_certification_audit_vehicle_audit ' , ' 审核 ' , ' cert_certification_audit_vehicle_audit ' , ' ' , ' ' , 1 , 2 , 0 , 1 , NULL , ' 通过/驳回车辆认证 ' , 0 )
ON DUPLICATE KEY UPDATE
` parent_id ` = VALUES ( ` parent_id ` ) ,
` code ` = VALUES ( ` code ` ) ,
` name ` = VALUES ( ` name ` ) ,
` alias ` = VALUES ( ` alias ` ) ,
` path ` = VALUES ( ` path ` ) ,
` source ` = VALUES ( ` source ` ) ,
` sort ` = VALUES ( ` sort ` ) ,
` category ` = VALUES ( ` category ` ) ,
` action ` = VALUES ( ` action ` ) ,
` is_open ` = VALUES ( ` is_open ` ) ,
` component ` = VALUES ( ` component ` ) ,
` remark ` = VALUES ( ` remark ` ) ,
` is_deleted ` = VALUES ( ` is_deleted ` ) ;