diff --git a/doc/sql/transport/blade_transport_cert_record_20261002.sql b/doc/sql/transport/blade_transport_cert_record_20261002.sql index e5c445e8..20d199e7 100644 --- a/doc/sql/transport/blade_transport_cert_record_20261002.sql +++ b/doc/sql/transport/blade_transport_cert_record_20261002.sql @@ -2,16 +2,9 @@ -- 认证记录数据模型:新建 blade_transport_cert_record,为司机表、车辆表补认证字段与 -- 生效快照指针,订正司机表排序规则,并新增认证审核菜单。 -- ---------------------------- --- 认证对象(司机 / 车辆)每次提交产生一条不可变记录,审核只改记录的状态, --- 不覆盖已提交的内容。司机与车辆共用本表,由 biz_type 区分。 --- --- effective_cert_record_id(生效快照指针)是判定「该对象是否已认证」的唯一依据: --- NULL = 从未审核通过;一经写入永不回退,提交、驳回、作废都不得修改它。 --- 因此「重新提交审核」不会让一辆已认证的车掉出可用池。 --- --- 幂等:全部语句可重复执行(建表 IF NOT EXISTS、加列先查 information_schema、 --- 改列/改排序规则/改菜单都先判定当前状态;菜单用 ON DUPLICATE KEY UPDATE)。 --- MySQL 5.7+ 兼容。 +-- 司机与车辆共用本表,由 biz_type 区分;每次提交产生一条不可变记录, +-- 审核只改状态,不覆盖已提交内容。 +-- 全部语句可重复执行。MySQL 5.7+ 兼容。 -- ---------------------------- -- 1. 认证记录表 @@ -54,9 +47,8 @@ BEGIN DECLARE db_name varchar(128); SET db_name = DATABASE(); - -- ---- 2. 司机表:认证字段 + 生效快照指针 ---- - -- certification_status 是「最新提交状态」的展示缓存;初始为 NULL 表示「从未提交」, - -- 与「审核中(0)」语义不同,故不可用 0 兜底。 + -- 司机表:认证字段 + 生效快照指针 + -- certification_status 为 NULL 表示「从未提交」,与「审核中(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; @@ -67,7 +59,7 @@ BEGIN 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; @@ -78,27 +70,20 @@ BEGIN 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, - -- 故在此一并订正,避免司机认证的关联查询重演同一故障。 + -- 司机表排序规则订正:建表未显式指定 COLLATE,MySQL 8+ 会落到服务器默认 + -- utf8mb4_0900_ai_ci;车辆表曾因此报 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,一条被逻辑删除的待审记录会继续占用唯一键, - -- 导致该认证对象永远无法再次提交。 - -- 建表语句已是正确版本;这里负责把按早期版本建过表的环境就地修正过来。 + -- 待审唯一键自修复:生成列必须排除已逻辑删除的行,否则被删的待审记录 + -- 会一直占用唯一键,该对象永远无法再次提交(removeById 只改 is_deleted)。 IF EXISTS ( SELECT 1 FROM information_schema.columns WHERE table_schema = db_name AND table_name = 'blade_transport_cert_record' @@ -108,12 +93,8 @@ BEGIN 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 个脚本如此)。 + -- tenant_id 收紧为 NOT NULL:它是待审唯一键的第一列,而唯一索引不对 NULL 去重, + -- 允许 NULL 就能并存两条待审记录,绕开「同对象至多一条待审」。 IF EXISTS ( SELECT 1 FROM information_schema.columns WHERE table_schema = db_name AND table_name = 'blade_transport_cert_record' @@ -124,11 +105,8 @@ BEGIN MODIFY COLUMN `tenant_id` varchar(12) NOT NULL DEFAULT '000000' COMMENT '租户ID'; END IF; - -- ---- 4.3 车辆认证状态缓存词表对齐 ---- - -- 改造前车辆侧是「0认证中 1认证通过 2认证驳回」,不含「已作废」; - -- 而新流程会把「被同对象再次提交取代」写成 3,届时该列无对应语义。 - -- 取值 0/1/2 在两套词表下含义一致(进行中 / 通过 / 驳回),故这里只补 3 并统一措辞, - -- 不改变任何既有数据的含义。仅改列注释(元数据),不动数据。 + -- 车辆认证状态缓存词表对齐:旧词表不含「已作废」,新流程会写入 3。 + -- 0/1/2 两套词表同义,故只补措辞,不改数据。 IF EXISTS ( SELECT 1 FROM information_schema.columns WHERE table_schema = db_name AND table_name = 'blade_transport_vehicle' @@ -154,13 +132,8 @@ DELIMITER ; -- ---------------------------- -- 5. 菜单与权限码 --- 挂在「运力管理」(2079000000000000001,与 blade_transport_driver.sql / --- blade_transport_vehicle.sql / blade_vehicle_dispatch.sql 用的是同一个 ID) 下, --- 与司机管理 / 车辆管理同级。 +-- 挂在「运力管理」2079000000000000001 下,与司机管理 / 车辆管理同级。 -- 列表页权限码 cert_certification_audit_{driver|vehicle},审核动作加 _audit 后缀。 --- --- 幂等:ON DUPLICATE KEY UPDATE 同时把 parent_id / name 等回写, --- 故对已存在(曾按早期版本建过菜单、或手工改过)的环境重跑即可收敛到本脚本的值。 -- ---------------------------- 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), diff --git a/doc/sql/transport/blade_transport_driver_driving_vehicle_widen_20261003.sql b/doc/sql/transport/blade_transport_driver_driving_vehicle_widen_20261003.sql index bbd9b162..48197fd1 100644 --- a/doc/sql/transport/blade_transport_driver_driving_vehicle_widen_20261003.sql +++ b/doc/sql/transport/blade_transport_driver_driving_vehicle_widen_20261003.sql @@ -1,17 +1,9 @@ -- ---------------------------- -- 司机「驾驶车辆」字段扩长:varchar(30) -> varchar(100) -- ---------------------------- --- 一个司机最多绑定 5 辆车(与小程序端「车辆认证一个司机最多添加 5 辆」一致), --- 该字段是逗号并列的车牌列表,5 个普通车牌连分隔符要 39 字符, --- 新能源号牌(8 位)要 44 字符 —— 30 字符连 4 辆车都放不下。 --- 超长写入的后果不是报错而是静默截断:字段里会留下半个车牌, --- 而拆车牌的规则会把这段残渣当成一辆车,司机名下于是多出一辆不存在的车。 --- --- 排序规则保持不变(utf8mb4_general_ci):车辆表与认证记录表都用这个规则, --- 三张表之间已有按车牌的关联查询,改规则会引发 Illegal mix of collations。 --- --- 幂等:已是目标长度时不再执行(MODIFY COLUMN 会重建表,重复执行无意义且有大表代价)。 --- MySQL 5.7+ 兼容。 +-- 该字段是逗号并列的车牌列表,一个司机最多 5 辆;30 字符连 4 辆都放不下, +-- 超长会静默截断成半个车牌,被拆车牌逻辑当成一辆不存在的车。 +-- 排序规则不变:与车辆表、认证记录表之间有按车牌的关联查询。 DELIMITER $$ diff --git a/doc/sql/transport/blade_transport_vehicle_owner_vin_20261003.sql b/doc/sql/transport/blade_transport_vehicle_owner_vin_20261003.sql index 982b4dbb..5209c445 100644 --- a/doc/sql/transport/blade_transport_vehicle_owner_vin_20261003.sql +++ b/doc/sql/transport/blade_transport_vehicle_owner_vin_20261003.sql @@ -1,17 +1,9 @@ -- ---------------------------- -- 车辆档案补两列:所有人、车辆识别代号(车架号) -- ---------------------------- --- 所有人:行驶证上登记的单位名称(如「桂物物流集团」),不是司机, --- 与「所属组织」也是两个字段——组织是内部管理归属,所有人是证件上的登记主体, --- 两者可能不同(挂靠车的所有人不是本组织)。 --- VIN:司机端车辆认证一直在收这个值并写进认证快照,但车辆表此前没有对应列, --- 于是它只存在于快照里、车辆档案上查不到。补列后档案与快照才一致。 --- --- 两列都允许为空:存量车辆(含订正补的那些)没有这两个值, --- 且 VIN 在原型里是选填项,不设默认值也不设 NOT NULL。 --- --- 幂等:逐列先查 information_schema,已存在则跳过(可重复执行)。 --- MySQL 5.7+ 兼容。 +-- owner_name 是行驶证上登记的单位名称,不是司机,与「所属组织」也是两个字段。 +-- vin 司机端认证一直在收并写入快照,车辆表此前没有对应列,补上后档案与快照才一致。 +-- 两列均可空:存量车辆没有值,VIN 在原型里也是选填。 DELIMITER $$