413 lines
34 KiB
SQL
413 lines
34 KiB
SQL
-- ==============================================================================
|
||||
|
|
-- RailwaySystem 数据库增量脚本: 023_open_exam_api.sql
|
|||
|
|
-- 模块: 外部实训系统数据接口(开放接口 /api/open/v1)
|
|||
|
|
-- 内容: 建表语句 + 约束/索引 + 字典 + 菜单 + 测试数据
|
|||
|
|
-- 数据库: MySQL 5.7(生产主库);KingbaseES 落地差异见 doc/外部实训系统数据接口设计(V1.0).md 3.9
|
|||
|
|
-- 说明:
|
|||
|
|
-- 1) MySQL 5.7 会解析但**不强制执行** CHECK 约束,业务校验由应用层(DTO + Service)兜底;
|
|||
|
|
-- 2) 脚本可重复执行:建表用 IF NOT EXISTS,字典/菜单/种子数据用 NOT EXISTS 或 ON DUPLICATE KEY;
|
|||
|
|
-- 3) 仅新增对象,不改动任何既有表结构与数据。
|
|||
|
|
-- 执行: mysql -h<host> -u<user> -p --default-character-set=utf8mb4 <db> < 023_open_exam_api.sql
|
|||
|
|
-- ==============================================================================
|
|||
|
|
|
|||
|
|
SET NAMES utf8mb4;
|
|||
|
|
|
|||
|
|
-- ------------------------------------------------------------------------------
|
|||
|
|
-- 1. 外部应用注册表
|
|||
|
|
-- ------------------------------------------------------------------------------
|
|||
|
|
CREATE TABLE IF NOT EXISTS `train_open_app` (
|
|||
|
|
`app_id` VARCHAR(64) NOT NULL COMMENT '应用标识(报文 appId)',
|
|||
|
|
`app_name` VARCHAR(100) NOT NULL COMMENT '应用名称',
|
|||
|
|
`app_type` VARCHAR(16) NOT NULL COMMENT '应用类型(VR/INSPECT3D/PRACTICE/CAPSTONE/OTHER)',
|
|||
|
|
`org_name` VARCHAR(100) DEFAULT NULL COMMENT '归属单位',
|
|||
|
|
`app_secret_hash` VARCHAR(128) NOT NULL COMMENT 'appSecret 散列(BCrypt,不存明文)',
|
|||
|
|
`app_secret_masked` VARCHAR(16) DEFAULT NULL COMMENT '密钥掩码(展示后4位)',
|
|||
|
|
`contact_name` VARCHAR(50) DEFAULT NULL COMMENT '联系人',
|
|||
|
|
`contact_phone` VARCHAR(20) DEFAULT NULL COMMENT '联系电话',
|
|||
|
|
`rate_limit` INT NOT NULL DEFAULT 20 COMMENT '每秒请求上限',
|
|||
|
|
`realtime_enabled` SMALLINT NOT NULL DEFAULT 1 COMMENT '是否启用实时上报(1启用 0关闭)',
|
|||
|
|
`status` SMALLINT NOT NULL DEFAULT 1 COMMENT '状态(1启用 0停用)',
|
|||
|
|
`create_by` VARCHAR(64) DEFAULT NULL COMMENT '创建者',
|
|||
|
|
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
|||
|
|
`update_by` VARCHAR(64) DEFAULT NULL COMMENT '更新者',
|
|||
|
|
`update_time` DATETIME DEFAULT NULL COMMENT '更新时间',
|
|||
|
|
`remark` VARCHAR(500) DEFAULT NULL COMMENT '备注',
|
|||
|
|
PRIMARY KEY (`app_id`),
|
|||
|
|
KEY `idx_open_app_status` (`status`)
|
|||
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='外部实训系统应用注册表';
|
|||
|
|
|
|||
|
|
-- ------------------------------------------------------------------------------
|
|||
|
|
-- 2. 应用授权范围表(班级 / 科目)
|
|||
|
|
-- ------------------------------------------------------------------------------
|
|||
|
|
CREATE TABLE IF NOT EXISTS `train_open_app_scope` (
|
|||
|
|
`scope_id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
|
|||
|
|
`app_id` VARCHAR(64) NOT NULL COMMENT '应用标识',
|
|||
|
|
`scope_type` VARCHAR(16) NOT NULL COMMENT '范围类型(CLASS 班级 / SUBJECT 科目)',
|
|||
|
|
`scope_value` VARCHAR(64) NOT NULL COMMENT '班级 plan_id 或科目 subject_code',
|
|||
|
|
`create_by` VARCHAR(64) DEFAULT NULL COMMENT '创建者',
|
|||
|
|
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
|||
|
|
PRIMARY KEY (`scope_id`),
|
|||
|
|
UNIQUE KEY `uk_open_app_scope` (`app_id`, `scope_type`, `scope_value`),
|
|||
|
|
KEY `idx_open_scope_value` (`scope_type`, `scope_value`),
|
|||
|
|
CONSTRAINT `fk_open_scope_app` FOREIGN KEY (`app_id`) REFERENCES `train_open_app` (`app_id`),
|
|||
|
|
CONSTRAINT `chk_open_scope_type` CHECK (`scope_type` IN ('CLASS', 'SUBJECT'))
|
|||
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='外部应用授权范围表';
|
|||
|
|
|
|||
|
|
-- ------------------------------------------------------------------------------
|
|||
|
|
-- 3. 访问令牌表(运行期以 Redis 为准,本表用于审计与吊销)
|
|||
|
|
-- ------------------------------------------------------------------------------
|
|||
|
|
CREATE TABLE IF NOT EXISTS `train_open_token` (
|
|||
|
|
`token_id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
|
|||
|
|
`app_id` VARCHAR(64) NOT NULL COMMENT '应用标识',
|
|||
|
|
`token_hash` VARCHAR(64) NOT NULL COMMENT '令牌 SHA-256',
|
|||
|
|
`issued_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '签发时间',
|
|||
|
|
`expire_time` DATETIME NOT NULL COMMENT '过期时间(签发 + 7200 秒)',
|
|||
|
|
`status` SMALLINT NOT NULL DEFAULT 1 COMMENT '状态(1有效 0失效)',
|
|||
|
|
`client_ip` VARCHAR(64) DEFAULT NULL COMMENT '签发来源 IP',
|
|||
|
|
`user_agent` VARCHAR(255) DEFAULT NULL COMMENT '客户端标识',
|
|||
|
|
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
|||
|
|
PRIMARY KEY (`token_id`),
|
|||
|
|
UNIQUE KEY `uk_open_token_hash` (`token_hash`),
|
|||
|
|
KEY `idx_open_token_app_status` (`app_id`, `status`),
|
|||
|
|
KEY `idx_open_token_expire` (`expire_time`),
|
|||
|
|
CONSTRAINT `fk_open_token_app` FOREIGN KEY (`app_id`) REFERENCES `train_open_app` (`app_id`)
|
|||
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='外部应用访问令牌表';
|
|||
|
|
|
|||
|
|
-- ------------------------------------------------------------------------------
|
|||
|
|
-- 4. 考试科目字典表
|
|||
|
|
-- ------------------------------------------------------------------------------
|
|||
|
|
CREATE TABLE IF NOT EXISTS `train_exam_subject` (
|
|||
|
|
`subject_id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
|
|||
|
|
`subject_code` VARCHAR(32) NOT NULL COMMENT '科目编码',
|
|||
|
|
`subject_name` VARCHAR(100) NOT NULL COMMENT '科目名称',
|
|||
|
|
`plan_id` VARCHAR(32) DEFAULT NULL COMMENT '所属培训班(空表示全局科目)',
|
|||
|
|
`score_item_id` BIGINT DEFAULT NULL COMMENT '归档考核项ID(train_score_item)',
|
|||
|
|
`status` SMALLINT NOT NULL DEFAULT 1 COMMENT '状态(1启用 0停用)',
|
|||
|
|
`sort_no` INT NOT NULL DEFAULT 0 COMMENT '展示顺序',
|
|||
|
|
`create_by` VARCHAR(64) DEFAULT NULL COMMENT '创建者',
|
|||
|
|
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
|||
|
|
`update_by` VARCHAR(64) DEFAULT NULL COMMENT '更新者',
|
|||
|
|
`update_time` DATETIME DEFAULT NULL COMMENT '更新时间',
|
|||
|
|
`remark` VARCHAR(200) DEFAULT NULL COMMENT '备注',
|
|||
|
|
PRIMARY KEY (`subject_id`),
|
|||
|
|
UNIQUE KEY `uk_exam_subject_code` (`subject_code`),
|
|||
|
|
UNIQUE KEY `uk_exam_subject_name` (`subject_name`),
|
|||
|
|
KEY `idx_exam_subject_plan` (`plan_id`, `status`)
|
|||
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='考试科目字典表';
|
|||
|
|
|
|||
|
|
-- ------------------------------------------------------------------------------
|
|||
|
|
-- 5. 上报批次表
|
|||
|
|
-- ------------------------------------------------------------------------------
|
|||
|
|
CREATE TABLE IF NOT EXISTS `train_exam_report_batch` (
|
|||
|
|
`batch_pk` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
|
|||
|
|
`app_id` VARCHAR(64) NOT NULL COMMENT '应用标识',
|
|||
|
|
`batch_id` VARCHAR(64) NOT NULL COMMENT '批次号(报文 batchId)',
|
|||
|
|
`report_time` BIGINT NOT NULL COMMENT '上报时间(毫秒)',
|
|||
|
|
`period_start` BIGINT NOT NULL COMMENT '覆盖窗口开始(毫秒,含)',
|
|||
|
|
`period_end` BIGINT NOT NULL COMMENT '覆盖窗口结束(毫秒,不含)',
|
|||
|
|
`resend` SMALLINT NOT NULL DEFAULT 0 COMMENT '补传标记(1补传 0正常)',
|
|||
|
|
`total` INT NOT NULL DEFAULT 0 COMMENT '本批记录数',
|
|||
|
|
`accepted` INT NOT NULL DEFAULT 0 COMMENT '校验通过并入库数',
|
|||
|
|
`duplicated` INT NOT NULL DEFAULT 0 COMMENT 'reportId 已存在被忽略数',
|
|||
|
|
`unmatched` INT NOT NULL DEFAULT 0 COMMENT '学员无法匹配数',
|
|||
|
|
`received_time` BIGINT NOT NULL COMMENT '平台接收时间(毫秒)',
|
|||
|
|
`req_id` VARCHAR(64) DEFAULT NULL COMMENT '请求标识',
|
|||
|
|
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
|||
|
|
PRIMARY KEY (`batch_pk`),
|
|||
|
|
UNIQUE KEY `uk_batch_app_batch` (`app_id`, `batch_id`),
|
|||
|
|
KEY `idx_batch_received` (`app_id`, `received_time`),
|
|||
|
|
KEY `idx_batch_period` (`period_start`, `period_end`),
|
|||
|
|
CONSTRAINT `fk_batch_app` FOREIGN KEY (`app_id`) REFERENCES `train_open_app` (`app_id`),
|
|||
|
|
CONSTRAINT `chk_batch_time_range` CHECK (`period_end` > `period_start`)
|
|||
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='考试成绩上报批次表';
|
|||
|
|
|
|||
|
|
-- ------------------------------------------------------------------------------
|
|||
|
|
-- 6. 成绩上报记录表(核心,reportId 永久幂等键)
|
|||
|
|
-- ------------------------------------------------------------------------------
|
|||
|
|
CREATE TABLE IF NOT EXISTS `train_exam_report` (
|
|||
|
|
`report_pk` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
|
|||
|
|
`report_id` VARCHAR(64) NOT NULL COMMENT '上报编号(永久幂等键)',
|
|||
|
|
`app_id` VARCHAR(64) NOT NULL COMMENT '应用标识',
|
|||
|
|
`batch_pk` BIGINT DEFAULT NULL COMMENT '所属批次(实时上报为空)',
|
|||
|
|
`batch_id` VARCHAR(64) DEFAULT NULL COMMENT '批次号冗余',
|
|||
|
|
`report_channel` VARCHAR(16) NOT NULL COMMENT '上报渠道(REALTIME/PERIODIC)',
|
|||
|
|
`biz_type` VARCHAR(16) NOT NULL DEFAULT 'PRACTICE' COMMENT '成绩类型',
|
|||
|
|
`student_id` VARCHAR(32) NOT NULL COMMENT '学员ID(匹配键)',
|
|||
|
|
`student_name` VARCHAR(50) DEFAULT NULL COMMENT '上报姓名',
|
|||
|
|
`id_card_masked` VARCHAR(32) DEFAULT NULL COMMENT '证件号掩码',
|
|||
|
|
`id_card_md5` CHAR(32) CHARACTER SET ascii DEFAULT NULL COMMENT '证件号MD5',
|
|||
|
|
`matched_enrollment_id` BIGINT DEFAULT NULL COMMENT '匹配到的参训档案ID',
|
|||
|
|
`matched_plan_id` VARCHAR(32) DEFAULT NULL COMMENT '匹配到的培训班ID',
|
|||
|
|
`match_status` VARCHAR(16) NOT NULL DEFAULT 'UNMATCHED' COMMENT '匹配状态(MATCHED/UNMATCHED)',
|
|||
|
|
`score_status` VARCHAR(16) NOT NULL DEFAULT 'RECEIVED' COMMENT '成绩状态(RECEIVED/ARCHIVED/LOCKED)',
|
|||
|
|
`subject_code` VARCHAR(32) DEFAULT NULL COMMENT '科目编码',
|
|||
|
|
`subject_name` VARCHAR(100) NOT NULL COMMENT '科目名称',
|
|||
|
|
`exam_start_time` BIGINT NOT NULL COMMENT '考试开始(毫秒)',
|
|||
|
|
`exam_end_time` BIGINT NOT NULL COMMENT '考试结束(毫秒)',
|
|||
|
|
`duration_seconds` INT DEFAULT NULL COMMENT '用时秒数',
|
|||
|
|
`score` DECIMAL(7,2) NOT NULL COMMENT '分数',
|
|||
|
|
`full_score` DECIMAL(7,2) NOT NULL DEFAULT 100.00 COMMENT '满分',
|
|||
|
|
`pass_flag` SMALLINT NOT NULL COMMENT '是否通过(1通过 0未通过)',
|
|||
|
|
`retake` SMALLINT NOT NULL DEFAULT 0 COMMENT '是否重考(1是 0否)',
|
|||
|
|
`retake_no` INT NOT NULL DEFAULT 0 COMMENT '重考序号',
|
|||
|
|
`station` VARCHAR(64) NOT NULL COMMENT '考试工位',
|
|||
|
|
`content` TEXT NOT NULL COMMENT '考试内容原始 JSON(≤32KB)',
|
|||
|
|
`content_size` INT DEFAULT NULL COMMENT '内容字节数',
|
|||
|
|
`content_md5` CHAR(32) CHARACTER SET ascii DEFAULT NULL COMMENT '内容摘要',
|
|||
|
|
`report_time` BIGINT DEFAULT NULL COMMENT '报文上报时间',
|
|||
|
|
`received_time` BIGINT NOT NULL COMMENT '平台接收时间',
|
|||
|
|
`resend` SMALLINT NOT NULL DEFAULT 0 COMMENT '补传标记',
|
|||
|
|
`claim_by` VARCHAR(64) DEFAULT NULL COMMENT '认领操作人',
|
|||
|
|
`claim_time` DATETIME DEFAULT NULL COMMENT '认领时间',
|
|||
|
|
`archive_time` DATETIME DEFAULT NULL COMMENT '归档时间',
|
|||
|
|
`lock_time` DATETIME DEFAULT NULL COMMENT '锁定时间',
|
|||
|
|
`lock_reason` VARCHAR(200) DEFAULT NULL COMMENT '锁定原因',
|
|||
|
|
`data_version` INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本',
|
|||
|
|
`remark` VARCHAR(500) DEFAULT NULL COMMENT '备注',
|
|||
|
|
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
|||
|
|
`update_time` DATETIME DEFAULT NULL COMMENT '更新时间',
|
|||
|
|
PRIMARY KEY (`report_pk`),
|
|||
|
|
UNIQUE KEY `uk_exam_report_id` (`report_id`),
|
|||
|
|
KEY `idx_report_app_time` (`app_id`, `received_time`),
|
|||
|
|
KEY `idx_report_app_batch` (`app_id`, `batch_id`),
|
|||
|
|
KEY `idx_report_student` (`app_id`, `student_id`, `exam_end_time`),
|
|||
|
|
KEY `idx_report_status` (`match_status`, `score_status`),
|
|||
|
|
KEY `idx_report_exam_end` (`exam_end_time`),
|
|||
|
|
CONSTRAINT `fk_report_app` FOREIGN KEY (`app_id`) REFERENCES `train_open_app` (`app_id`),
|
|||
|
|
CONSTRAINT `fk_report_batch` FOREIGN KEY (`batch_pk`) REFERENCES `train_exam_report_batch` (`batch_pk`),
|
|||
|
|
CONSTRAINT `chk_report_time_range` CHECK (`exam_end_time` > `exam_start_time`),
|
|||
|
|
CONSTRAINT `chk_report_score` CHECK (`score` >= 0 AND `score` <= `full_score`),
|
|||
|
|
CONSTRAINT `chk_report_match_status` CHECK (`match_status` IN ('MATCHED', 'UNMATCHED')),
|
|||
|
|
CONSTRAINT `chk_report_score_status` CHECK (`score_status` IN ('RECEIVED', 'ARCHIVED', 'LOCKED')),
|
|||
|
|
CONSTRAINT `chk_report_channel` CHECK (`report_channel` IN ('REALTIME', 'PERIODIC'))
|
|||
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='考试成绩上报记录表';
|
|||
|
|
|
|||
|
|
-- ------------------------------------------------------------------------------
|
|||
|
|
-- 7. 接口调用日志表
|
|||
|
|
-- ------------------------------------------------------------------------------
|
|||
|
|
CREATE TABLE IF NOT EXISTS `train_open_api_log` (
|
|||
|
|
`log_id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
|
|||
|
|
`req_id` VARCHAR(64) NOT NULL COMMENT '请求标识',
|
|||
|
|
`app_id` VARCHAR(64) DEFAULT NULL COMMENT '应用标识',
|
|||
|
|
`api_path` VARCHAR(128) NOT NULL COMMENT '请求路径',
|
|||
|
|
`http_method` VARCHAR(8) NOT NULL COMMENT 'HTTP 方法',
|
|||
|
|
`biz_key` VARCHAR(128) DEFAULT NULL COMMENT '业务键(batchId/reportId/classId)',
|
|||
|
|
`code` INT NOT NULL COMMENT '业务返回码',
|
|||
|
|
`msg` VARCHAR(500) DEFAULT NULL COMMENT '返回描述',
|
|||
|
|
`cost_ms` INT DEFAULT NULL COMMENT '耗时(毫秒)',
|
|||
|
|
`client_ip` VARCHAR(64) DEFAULT NULL COMMENT '调用方 IP',
|
|||
|
|
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '记录时间',
|
|||
|
|
PRIMARY KEY (`log_id`),
|
|||
|
|
KEY `idx_open_log_req` (`req_id`),
|
|||
|
|
KEY `idx_open_log_app_time` (`app_id`, `create_time`)
|
|||
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='开放接口调用日志表';
|
|||
|
|
|
|||
|
|
-- ==============================================================================
|
|||
|
|
-- 8. 字典数据
|
|||
|
|
-- ==============================================================================
|
|||
|
|
INSERT INTO sys_dict_type (dict_name, dict_type, status, create_by, create_time, remark)
|
|||
|
|
SELECT '外部应用类型', 'train_open_app_type', '0', 'admin', NOW(), 'VR / 3D巡检 / 实操 / 帽石考核 / 其他'
|
|||
|
|
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_dict_type WHERE dict_type = 'train_open_app_type');
|
|||
|
|
|
|||
|
|
INSERT INTO sys_dict_type (dict_name, dict_type, status, create_by, create_time, remark)
|
|||
|
|
SELECT '成绩匹配状态', 'train_open_match_status', '0', 'admin', NOW(), '成绩与学员的匹配状态'
|
|||
|
|
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_dict_type WHERE dict_type = 'train_open_match_status');
|
|||
|
|
|
|||
|
|
INSERT INTO sys_dict_type (dict_name, dict_type, status, create_by, create_time, remark)
|
|||
|
|
SELECT '成绩归档状态', 'train_open_score_status', '0', 'admin', NOW(), '成绩接收 / 归档 / 锁定'
|
|||
|
|
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_dict_type WHERE dict_type = 'train_open_score_status');
|
|||
|
|
|
|||
|
|
INSERT INTO sys_dict_type (dict_name, dict_type, status, create_by, create_time, remark)
|
|||
|
|
SELECT '成绩上报渠道', 'train_open_report_channel', '0', 'admin', NOW(), '实时上报 / 周期批量上报'
|
|||
|
|
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_dict_type WHERE dict_type = 'train_open_report_channel');
|
|||
|
|
|
|||
|
|
INSERT INTO sys_dict_data (dict_sort, dict_label, dict_value, dict_type, list_class, is_default, status, create_by, create_time, remark)
|
|||
|
|
SELECT 1, 'VR实训', 'VR', 'train_open_app_type', 'primary', 'Y', '0', 'admin', NOW(), 'VR 实训系统'
|
|||
|
|
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_dict_data WHERE dict_type = 'train_open_app_type' AND dict_value = 'VR');
|
|||
|
|
INSERT INTO sys_dict_data (dict_sort, dict_label, dict_value, dict_type, list_class, is_default, status, create_by, create_time, remark)
|
|||
|
|
SELECT 2, '3D巡检', 'INSPECT3D', 'train_open_app_type', 'success', 'N', '0', 'admin', NOW(), '3D 数字孪生巡检系统'
|
|||
|
|
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_dict_data WHERE dict_type = 'train_open_app_type' AND dict_value = 'INSPECT3D');
|
|||
|
|
INSERT INTO sys_dict_data (dict_sort, dict_label, dict_value, dict_type, list_class, is_default, status, create_by, create_time, remark)
|
|||
|
|
SELECT 3, '实操实训', 'PRACTICE', 'train_open_app_type', 'info', 'N', '0', 'admin', NOW(), '实操实训系统'
|
|||
|
|
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_dict_data WHERE dict_type = 'train_open_app_type' AND dict_value = 'PRACTICE');
|
|||
|
|
INSERT INTO sys_dict_data (dict_sort, dict_label, dict_value, dict_type, list_class, is_default, status, create_by, create_time, remark)
|
|||
|
|
SELECT 4, '帽石考核', 'CAPSTONE', 'train_open_app_type', 'warning', 'N', '0', 'admin', NOW(), '帽石安装考核系统'
|
|||
|
|
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_dict_data WHERE dict_type = 'train_open_app_type' AND dict_value = 'CAPSTONE');
|
|||
|
|
INSERT INTO sys_dict_data (dict_sort, dict_label, dict_value, dict_type, list_class, is_default, status, create_by, create_time, remark)
|
|||
|
|
SELECT 5, '其他', 'OTHER', 'train_open_app_type', 'info', 'N', '0', 'admin', NOW(), '其他实训考核系统'
|
|||
|
|
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_dict_data WHERE dict_type = 'train_open_app_type' AND dict_value = 'OTHER');
|
|||
|
|
|
|||
|
|
INSERT INTO sys_dict_data (dict_sort, dict_label, dict_value, dict_type, list_class, is_default, status, create_by, create_time, remark)
|
|||
|
|
SELECT 1, '已匹配', 'MATCHED', 'train_open_match_status', 'success', 'Y', '0', 'admin', NOW(), '成绩已匹配到学员'
|
|||
|
|
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_dict_data WHERE dict_type = 'train_open_match_status' AND dict_value = 'MATCHED');
|
|||
|
|
INSERT INTO sys_dict_data (dict_sort, dict_label, dict_value, dict_type, list_class, is_default, status, create_by, create_time, remark)
|
|||
|
|
SELECT 2, '待认领', 'UNMATCHED', 'train_open_match_status', 'warning', 'N', '0', 'admin', NOW(), '学员无法匹配,进入待认领池'
|
|||
|
|
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_dict_data WHERE dict_type = 'train_open_match_status' AND dict_value = 'UNMATCHED');
|
|||
|
|
|
|||
|
|
INSERT INTO sys_dict_data (dict_sort, dict_label, dict_value, dict_type, list_class, is_default, status, create_by, create_time, remark)
|
|||
|
|
SELECT 1, '已接收', 'RECEIVED', 'train_open_score_status', 'info', 'Y', '0', 'admin', NOW(), '上报已接收,尚未归档'
|
|||
|
|
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_dict_data WHERE dict_type = 'train_open_score_status' AND dict_value = 'RECEIVED');
|
|||
|
|
INSERT INTO sys_dict_data (dict_sort, dict_label, dict_value, dict_type, list_class, is_default, status, create_by, create_time, remark)
|
|||
|
|
SELECT 2, '已归档', 'ARCHIVED', 'train_open_score_status', 'success', 'N', '0', 'admin', NOW(), '已写入学员得分'
|
|||
|
|
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_dict_data WHERE dict_type = 'train_open_score_status' AND dict_value = 'ARCHIVED');
|
|||
|
|
INSERT INTO sys_dict_data (dict_sort, dict_label, dict_value, dict_type, list_class, is_default, status, create_by, create_time, remark)
|
|||
|
|
SELECT 3, '已锁定', 'LOCKED', 'train_open_score_status', 'danger', 'N', '0', 'admin', NOW(), '成绩已锁定,需解冻后重传'
|
|||
|
|
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_dict_data WHERE dict_type = 'train_open_score_status' AND dict_value = 'LOCKED');
|
|||
|
|
|
|||
|
|
INSERT INTO sys_dict_data (dict_sort, dict_label, dict_value, dict_type, list_class, is_default, status, create_by, create_time, remark)
|
|||
|
|
SELECT 1, '实时上报', 'REALTIME', 'train_open_report_channel', 'primary', 'N', '0', 'admin', NOW(), '考试结束后即时上报'
|
|||
|
|
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_dict_data WHERE dict_type = 'train_open_report_channel' AND dict_value = 'REALTIME');
|
|||
|
|
INSERT INTO sys_dict_data (dict_sort, dict_label, dict_value, dict_type, list_class, is_default, status, create_by, create_time, remark)
|
|||
|
|
SELECT 2, '周期上报', 'PERIODIC', 'train_open_report_channel', 'info', 'Y', '0', 'admin', NOW(), '按时间窗口批量上报'
|
|||
|
|
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_dict_data WHERE dict_type = 'train_open_report_channel' AND dict_value = 'PERIODIC');
|
|||
|
|
|
|||
|
|
-- ==============================================================================
|
|||
|
|
-- 9. 菜单与按钮权限
|
|||
|
|
-- ==============================================================================
|
|||
|
|
INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, query, route_name, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark)
|
|||
|
|
SELECT '外部实训接入', '2265', '9', 'openexam', NULL, '', '', 1, 0, 'M', '0', '0', '', 'education', 'admin', NOW(), '外部实训系统数据接口'
|
|||
|
|
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_menu WHERE menu_name = '外部实训接入' AND parent_id = 2265);
|
|||
|
|
|
|||
|
|
SET @openexam_dir = (SELECT menu_id FROM sys_menu WHERE menu_name = '外部实训接入' AND parent_id = 2265 LIMIT 1);
|
|||
|
|
|
|||
|
|
INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, query, route_name, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark)
|
|||
|
|
SELECT '应用管理', @openexam_dir, '1', 'openApp', 'train/openApp/index', '', '', 1, 0, 'C', '0', '0', 'train:openApp:list', 'component', 'admin', NOW(), '外部应用与授权范围'
|
|||
|
|
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_menu WHERE perms = 'train:openApp:list');
|
|||
|
|
SET @openapp_menu = (SELECT menu_id FROM sys_menu WHERE perms = 'train:openApp:list' LIMIT 1);
|
|||
|
|
|
|||
|
|
INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, query, route_name, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark)
|
|||
|
|
SELECT '考试科目', @openexam_dir, '2', 'examSubject', 'train/examSubject/index', '', '', 1, 0, 'C', '0', '0', 'train:examSubject:list', 'dict', 'admin', NOW(), '考试科目字典'
|
|||
|
|
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_menu WHERE perms = 'train:examSubject:list');
|
|||
|
|
SET @examsubject_menu = (SELECT menu_id FROM sys_menu WHERE perms = 'train:examSubject:list' LIMIT 1);
|
|||
|
|
|
|||
|
|
INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, query, route_name, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark)
|
|||
|
|
SELECT '上报成绩', @openexam_dir, '3', 'examReport', 'train/examReport/index', '', '', 1, 0, 'C', '0', '0', 'train:examReport:list', 'form', 'admin', NOW(), '外部实训上报成绩与待认领'
|
|||
|
|
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_menu WHERE perms = 'train:examReport:list');
|
|||
|
|
SET @examreport_menu = (SELECT menu_id FROM sys_menu WHERE perms = 'train:examReport:list' LIMIT 1);
|
|||
|
|
|
|||
|
|
-- 按钮权限:应用管理
|
|||
|
|
INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, query, route_name, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark)
|
|||
|
|
SELECT '应用查询', @openapp_menu, '1', '', NULL, '', '', 1, 0, 'F', '0', '0', 'train:openApp:query', '#', 'admin', NOW(), ''
|
|||
|
|
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_menu WHERE perms = 'train:openApp:query');
|
|||
|
|
INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, query, route_name, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark)
|
|||
|
|
SELECT '应用新增', @openapp_menu, '2', '', NULL, '', '', 1, 0, 'F', '0', '0', 'train:openApp:add', '#', 'admin', NOW(), ''
|
|||
|
|
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_menu WHERE perms = 'train:openApp:add');
|
|||
|
|
INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, query, route_name, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark)
|
|||
|
|
SELECT '应用修改', @openapp_menu, '3', '', NULL, '', '', 1, 0, 'F', '0', '0', 'train:openApp:edit', '#', 'admin', NOW(), ''
|
|||
|
|
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_menu WHERE perms = 'train:openApp:edit');
|
|||
|
|
INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, query, route_name, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark)
|
|||
|
|
SELECT '应用删除', @openapp_menu, '4', '', NULL, '', '', 1, 0, 'F', '0', '0', 'train:openApp:remove', '#', 'admin', NOW(), ''
|
|||
|
|
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_menu WHERE perms = 'train:openApp:remove');
|
|||
|
|
|
|||
|
|
-- 按钮权限:考试科目
|
|||
|
|
INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, query, route_name, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark)
|
|||
|
|
SELECT '科目新增', @examsubject_menu, '1', '', NULL, '', '', 1, 0, 'F', '0', '0', 'train:examSubject:add', '#', 'admin', NOW(), ''
|
|||
|
|
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_menu WHERE perms = 'train:examSubject:add');
|
|||
|
|
INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, query, route_name, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark)
|
|||
|
|
SELECT '科目修改', @examsubject_menu, '2', '', NULL, '', '', 1, 0, 'F', '0', '0', 'train:examSubject:edit', '#', 'admin', NOW(), ''
|
|||
|
|
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_menu WHERE perms = 'train:examSubject:edit');
|
|||
|
|
INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, query, route_name, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark)
|
|||
|
|
SELECT '科目删除', @examsubject_menu, '3', '', NULL, '', '', 1, 0, 'F', '0', '0', 'train:examSubject:remove', '#', 'admin', NOW(), ''
|
|||
|
|
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_menu WHERE perms = 'train:examSubject:remove');
|
|||
|
|
|
|||
|
|
-- 按钮权限:上报成绩
|
|||
|
|
INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, query, route_name, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark)
|
|||
|
|
SELECT '成绩认领', @examreport_menu, '1', '', NULL, '', '', 1, 0, 'F', '0', '0', 'train:examReport:claim', '#', 'admin', NOW(), ''
|
|||
|
|
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_menu WHERE perms = 'train:examReport:claim');
|
|||
|
|
INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, query, route_name, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark)
|
|||
|
|
SELECT '成绩删除', @examreport_menu, '2', '', NULL, '', '', 1, 0, 'F', '0', '0', 'train:examReport:remove', '#', 'admin', NOW(), ''
|
|||
|
|
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_menu WHERE perms = 'train:examReport:remove');
|
|||
|
|
|
|||
|
|
-- ==============================================================================
|
|||
|
|
-- 10. 测试数据(覆盖主要业务场景)
|
|||
|
|
-- 说明: appSecret 明文仅用于联调,值为 VR-TRAIN-01 / INSPECT3D-01;
|
|||
|
|
-- 散列使用 BCrypt(强度10),生产环境必须通过后台“重置密钥”生成。
|
|||
|
|
-- ==============================================================================
|
|||
|
|
INSERT INTO `train_open_app` (`app_id`, `app_name`, `app_type`, `org_name`, `app_secret_hash`, `app_secret_masked`, `contact_name`, `contact_phone`, `rate_limit`, `realtime_enabled`, `status`, `create_by`, `remark`)
|
|||
|
|
VALUES
|
|||
|
|
('VR-TRAIN-01', 'VR 安全实训系统', 'VR', '沈阳房建公寓段·职工培训基地',
|
|||
|
|
'$2a$10$7EqJtq98hPqEX7fNZaFWoO5uY3vJ0N2m1oQxZ0lQm3Qm9C2jK1sGa', '****2406', '王工', '13900000001', 20, 1, 1, 'admin', '联调样例:VR 实训'),
|
|||
|
|
('INSPECT3D-01', '3D 数字孪生巡检系统', 'INSPECT3D', '沈阳房建公寓段',
|
|||
|
|
'$2a$10$7EqJtq98hPqEX7fNZaFWoO5uY3vJ0N2m1oQxZ0lQm3Qm9C2jK1sGa', '****7788', '李工', '13900000002', 20, 0, 1, 'admin', '联调样例:3D 巡检(未开启实时上报)')
|
|||
|
|
ON DUPLICATE KEY UPDATE `app_name` = VALUES(`app_name`);
|
|||
|
|
|
|||
|
|
INSERT INTO `train_open_app_scope` (`app_id`, `scope_type`, `scope_value`, `create_by`)
|
|||
|
|
SELECT 'VR-TRAIN-01', 'CLASS', 'P2026001', 'admin' FROM DUAL
|
|||
|
|
WHERE NOT EXISTS (SELECT 1 FROM `train_open_app_scope` WHERE `app_id` = 'VR-TRAIN-01' AND `scope_type` = 'CLASS' AND `scope_value` = 'P2026001');
|
|||
|
|
|
|||
|
|
INSERT INTO `train_open_app_scope` (`app_id`, `scope_type`, `scope_value`, `create_by`)
|
|||
|
|
SELECT 'VR-TRAIN-01', 'SUBJECT', 'VR-SAFE', 'admin' FROM DUAL
|
|||
|
|
WHERE NOT EXISTS (SELECT 1 FROM `train_open_app_scope` WHERE `app_id` = 'VR-TRAIN-01' AND `scope_type` = 'SUBJECT' AND `scope_value` = 'VR-SAFE');
|
|||
|
|
|
|||
|
|
INSERT INTO `train_open_app_scope` (`app_id`, `scope_type`, `scope_value`, `create_by`)
|
|||
|
|
SELECT 'INSPECT3D-01', 'SUBJECT', 'CAP-POS', 'admin' FROM DUAL
|
|||
|
|
WHERE NOT EXISTS (SELECT 1 FROM `train_open_app_scope` WHERE `app_id` = 'INSPECT3D-01' AND `scope_type` = 'SUBJECT' AND `scope_value` = 'CAP-POS');
|
|||
|
|
|
|||
|
|
INSERT INTO `train_exam_subject` (`subject_code`, `subject_name`, `plan_id`, `status`, `sort_no`, `create_by`, `remark`)
|
|||
|
|
VALUES
|
|||
|
|
('VR-SAFE', '高处作业隐患排查', 'P2026001', 1, 1, 'admin', 'VR 实训科目'),
|
|||
|
|
('CAP-POS', '帽石安装定位', NULL, 1, 2, 'admin', '帽石考核科目'),
|
|||
|
|
('OPS-ELEC', '营业线施工用电安全', 'P2026001', 1, 3, 'admin', '实操科目'),
|
|||
|
|
('INS-ROOF', '屋面渗漏巡检', NULL, 0, 4, 'admin', '停用科目,用于校验 3001')
|
|||
|
|
ON DUPLICATE KEY UPDATE `subject_name` = VALUES(`subject_name`);
|
|||
|
|
|
|||
|
|
-- 参训档案(成绩匹配依赖):存在则跳过
|
|||
|
|
INSERT INTO `train_enrollment` (`plan_id`, `student_id`, `source_type`, `enrollment_status`, `accommodation_required`, `join_time`, `create_by`)
|
|||
|
|
SELECT 'P2026001', 'S20260001', 1, 1, 0, NOW(), 'admin' FROM DUAL
|
|||
|
|
WHERE NOT EXISTS (SELECT 1 FROM `train_enrollment` WHERE `plan_id` = 'P2026001' AND `student_id` = 'S20260001');
|
|||
|
|
|
|||
|
|
-- 批次(正常周期上报)
|
|||
|
|
INSERT INTO `train_exam_report_batch` (`batch_pk`, `app_id`, `batch_id`, `report_time`, `period_start`, `period_end`, `resend`, `total`, `accepted`, `duplicated`, `unmatched`, `received_time`, `req_id`)
|
|||
|
|
VALUES (1, 'VR-TRAIN-01', 'BATCH-202610281030-0001', 1793154600000, 1793152800000, 1793154600000, 0, 2, 1, 0, 1, 1793154600180, 'RQ-SEED-0001')
|
|||
|
|
ON DUPLICATE KEY UPDATE `batch_id` = VALUES(`batch_id`);
|
|||
|
|
|
|||
|
|
-- 上报记录:已匹配已归档 / 待认领 / 已锁定 / 重复批次内的幂等样例
|
|||
|
|
INSERT INTO `train_exam_report` (`report_id`, `app_id`, `batch_pk`, `batch_id`, `report_channel`, `biz_type`, `student_id`, `student_name`,
|
|||
|
|
`id_card_masked`, `id_card_md5`, `matched_enrollment_id`, `matched_plan_id`, `match_status`, `score_status`,
|
|||
|
|
`subject_code`, `subject_name`, `exam_start_time`, `exam_end_time`, `duration_seconds`, `score`, `full_score`,
|
|||
|
|
`pass_flag`, `retake`, `retake_no`, `station`, `content`, `content_size`, `content_md5`,
|
|||
|
|
`report_time`, `received_time`, `resend`, `archive_time`)
|
|||
|
|
VALUES
|
|||
|
|
('RPT-VR-20261028-0031', 'VR-TRAIN-01', 1, 'BATCH-202610281030-0001', 'PERIODIC', 'PRACTICE', 'S20260001', '张三',
|
|||
|
|
'210102********4321', '5d41402abc4b2a76b9719d911017c592',
|
|||
|
|
(SELECT enrollment_id FROM `train_enrollment` WHERE `student_id` = 'S20260001' ORDER BY join_time DESC LIMIT 1),
|
|||
|
|
'P2026001', 'MATCHED', 'ARCHIVED',
|
|||
|
|
'VR-SAFE', '高处作业隐患排查', 1793153580000, 1793154000000, 420, 86.50, 100.00,
|
|||
|
|
1, 0, 0, 'VR-A-02', '{"taskId":"VR-SAFE-012"}', 24, '0e4b1c9d8f2a7c6b5d4e3f2a1b0c9d8e',
|
|||
|
|
1793154600000, 1793154600180, 0, NOW()),
|
|||
|
|
('RPT-CAP-20261028-0032', 'VR-TRAIN-01', 1, 'BATCH-202610281030-0001', 'PERIODIC', 'PRACTICE', 'S20240399', '张伟',
|
|||
|
|
NULL, NULL, NULL, NULL, 'UNMATCHED', 'RECEIVED',
|
|||
|
|
'CAP-POS', '帽石安装定位', 1793153820000, 1793154180000, 360, 91.00, 100.00,
|
|||
|
|
1, 1, 1, 'MS-A-03', '{"taskId":"CAP-07"}', 20, '1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d',
|
|||
|
|
1793154600000, 1793154600180, 0, NULL),
|
|||
|
|
('RPT-VR-20261028-0033', 'VR-TRAIN-01', NULL, NULL, 'REALTIME', 'PRACTICE', 'S20260001', '张三',
|
|||
|
|
NULL, NULL,
|
|||
|
|
(SELECT enrollment_id FROM `train_enrollment` WHERE `student_id` = 'S20260001' ORDER BY join_time DESC LIMIT 1),
|
|||
|
|
'P2026001', 'MATCHED', 'LOCKED',
|
|||
|
|
'VR-SAFE', '高处作业隐患排查', 1793153400000, 1793153760000, 360, 92.00, 100.00,
|
|||
|
|
1, 0, 0, 'VR-A-03', '{"taskId":"VR-SAFE-012"}', 24, '2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e',
|
|||
|
|
1793154010000, 1793154010180, 0, NOW()),
|
|||
|
|
('RPT-INS-20261028-0034', 'INSPECT3D-01', NULL, NULL, 'REALTIME', 'PRACTICE', 'S20260001', '张三',
|
|||
|
|
NULL, NULL,
|
|||
|
|
(SELECT enrollment_id FROM `train_enrollment` WHERE `student_id` = 'S20260001' ORDER BY join_time DESC LIMIT 1),
|
|||
|
|
'P2026001', 'MATCHED', 'RECEIVED',
|
|||
|
|
'INS-ROOF', '屋面渗漏巡检', 1793153640000, 1793154000000, 360, 88.00, 100.00,
|
|||
|
|
1, 0, 0, 'INS-A-01', '{"taskId":"INS-01"}', 18, '3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f',
|
|||
|
|
1793154010000, 1793154010180, 0, NULL)
|
|||
|
|
ON DUPLICATE KEY UPDATE `subject_name` = VALUES(`subject_name`);
|
|||
|
|
|
|||
|
|
-- 令牌审计样例(无效散列,仅用于页面联调查看)
|
|||
|
|
INSERT INTO `train_open_token` (`app_id`, `token_hash`, `issued_time`, `expire_time`, `status`, `client_ip`, `user_agent`)
|
|||
|
|
SELECT 'VR-TRAIN-01', SHA2('sample-token-for-ui-preview', 256), NOW(), DATE_ADD(NOW(), INTERVAL 7200 SECOND), 0, '127.0.0.1', 'seed'
|
|||
|
|
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `train_open_token` WHERE `app_id` = 'VR-TRAIN-01' AND `status` = 0);
|
|||
|
|
|
|||
|
|
-- 调用日志样例
|
|||
|
|
INSERT INTO `train_open_api_log` (`req_id`, `app_id`, `api_path`, `http_method`, `biz_key`, `code`, `msg`, `cost_ms`, `client_ip`)
|
|||
|
|
SELECT 'RQ-SEED-0001', 'VR-TRAIN-01', '/api/open/v1/exam/report', 'POST', 'BATCH-202610281030-0001', 0, 'success', 38, '127.0.0.1'
|
|||
|
|
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `train_open_api_log` WHERE `req_id` = 'RQ-SEED-0001');
|
|||
|
|
|
|||
|
|
|
|||
|
|
-- 更新学生学号字段 2026-11-05
|
|||
|
|
UPDATE train_student
|
|||
|
|
SET person_no = REPLACE(person_no, '学号:', '')
|
|||
|
|
WHERE person_no LIKE '%学号:%';
|