-- ============================================================================= -- 平板刷脸照片(叫乘作业留痕) -- 定位:平板在「刷脸确认成功(ANSWERED + VERIFIED)」后上传的抓拍原图, -- 库里只存「存储路径 + 校验信息 + 状态」,图像本体落在文件/对象存储,不进 BLOB。 -- 关联:apt_tablet_call_result (result_id) → gy_jcxx (jcid),一结果最多一张有效照片。 -- 路径规范(相对路径入库,根目录随环境配置 apt.photo.root): -- face/{gyid}/{yyyy}/{MM}/{dd}/{jcid}/{photoId}.{jpg|png} -- 例:face/APT-REV01-001/2026/11/12/JC-20261112-093000/PH-3F9A1C2B7D01.jpg -- 幂等:UNIQUE (gyid, result_id) —— 同一结果重传覆盖同一行(retry_count+1),不产生多张。 -- 失败留痕:upload_state=FAILED + fail_reason,结果表 face_photo_state=FAILED, -- 不影响 ryzt=3(状态机已在结果受理时完成),平板可原样重试。 -- ============================================================================= SET NAMES utf8mb4; CREATE TABLE IF NOT EXISTS apt_tablet_face_photo ( id BIGINT NOT NULL AUTO_INCREMENT, gyid VARCHAR(32) NOT NULL, photo_id VARCHAR(64) NOT NULL COMMENT '照片业务键,PH-<12位十六进制>', jcid VARCHAR(64) NOT NULL COMMENT '叫乘作业号(关联 gy_jcxx.jcid)', task_id VARCHAR(64) NOT NULL COMMENT '平板任务号', result_id VARCHAR(64) NOT NULL COMMENT '平板结果号(apt_tablet_call_result.result_id)', ryid VARCHAR(64) NULL COMMENT '刷脸命中人员(verified_ryid)', device_code VARCHAR(64) NOT NULL, storage_target VARCHAR(20) NOT NULL DEFAULT 'LOCAL' COMMENT 'LOCAL / OSS', storage_path VARCHAR(512) NOT NULL COMMENT '相对路径,不含根目录与域名', file_name VARCHAR(128) NOT NULL, content_type VARCHAR(64) NOT NULL COMMENT 'image/jpeg / image/png', file_size BIGINT NOT NULL DEFAULT 0, sha256 CHAR(64) NULL COMMENT '落盘后校验和,用于完整性核验', upload_state VARCHAR(20) NOT NULL DEFAULT 'PENDING' COMMENT 'PENDING/STORED/FAILED/PURGED', fail_reason VARCHAR(255) NULL, retry_count INT NOT NULL DEFAULT 0, captured_at DATETIME(3) NULL COMMENT '平板抓拍时间(occurred_at)', uploaded_at DATETIME(3) NULL, deleted TINYINT NOT NULL DEFAULT 0, create_time DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), update_time DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3), PRIMARY KEY (id), UNIQUE KEY uk_facephoto_gyid_id (gyid, photo_id), UNIQUE KEY uk_facephoto_gyid_result (gyid, result_id), KEY idx_facephoto_gyid_jcid (gyid, jcid, upload_state), KEY idx_facephoto_gyid_state (gyid, upload_state), CONSTRAINT ck_facephoto_state CHECK (upload_state IN ('PENDING','STORED','FAILED','PURGED')), CONSTRAINT ck_facephoto_target CHECK (storage_target IN ('LOCAL','OSS')) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='平板刷脸照片(只存路径与校验信息,图像落文件/对象存储)'; -- ----------------------------------------------------------------------------- -- 结果表补指针列:便于按 result 直接回显,不必每次 join -- ----------------------------------------------------------------------------- CALL apt_add_column_if_missing('apt_tablet_call_result', 'face_photo_id', "face_photo_id VARCHAR(64) NULL COMMENT '最近一次上传的刷脸照片(apt_tablet_face_photo.photo_id)'"); CALL apt_add_column_if_missing('apt_tablet_call_result', 'face_photo_state', "face_photo_state VARCHAR(20) NULL COMMENT '照片态:PENDING/STORED/FAILED,未上传为 NULL'"); -- ----------------------------------------------------------------------------- -- 校验 -- ----------------------------------------------------------------------------- SELECT '=== 40. 照片表列数(应 22)===' AS section; SELECT COUNT(*) AS photo_columns FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'apt_tablet_face_photo'; SELECT '=== 41. 唯一键(应 3:主键 + photo_id + result_id)===' AS section; SELECT INDEX_NAME, GROUP_CONCAT(COLUMN_NAME ORDER BY SEQ_IN_INDEX) AS cols FROM information_schema.STATISTICS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'apt_tablet_face_photo' AND NON_UNIQUE = 0 GROUP BY INDEX_NAME; SELECT '=== 42. 结果表照片指针列(应 2)===' AS section; SELECT COLUMN_NAME, COLUMN_TYPE FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'apt_tablet_call_result' AND COLUMN_NAME IN ('face_photo_id','face_photo_state'); SELECT '=== 43. 现有照片记录 ===' AS section; SELECT upload_state, COUNT(*) AS cnt FROM apt_tablet_face_photo WHERE deleted = 0 GROUP BY upload_state;