Files
tuanwei-java/sql/20260912_create_openplat_sync_tables.sql
weicw1996 cd54039f28 接入医科大开放平台数据同步
新增 com.gxwebsoft.gxmu.openplat:开放平台客户端(oauth 鉴权、token 缓存与失效
重取、分页拉取)、部门/教师/班级/学生四段同步、异步编排与手动同步接口、学生认领、
学生名册查询与导出、每天 03:30 的定时任务、同步记录。

关键设计:
- 名册与登录账号分离,学生通过「认领」(手机号自动 / 学号姓名自助)关联 sys_user
- 组织数据以 sys_organization 为唯一载体,gxmu_college 废弃
- 平台无可用增量字段,只做全量拉取 + 幂等 upsert
- 上游消失只停用不删除,且只作用于同步来源的记录(避免误停用人工维护的研究生班)
- 平台权威字段按白名单覆盖,人工字段不触碰
- 码表可配置并保留原始码,码值实测存在两套编码混用,不做硬编码
- 手动同步为异步:提交返回批次号,前端轮询 /status 看分段进度

性能:
- 班级/部门由逐条 update 改为多行 upsert,班级 1584 条 41s -> 0.19s
- 码表解析加进程内缓存,学生同步由 >17 分钟不完成 -> 170 秒完成 98187 行

迁移脚本需手动执行(可重复执行):
  sql/20260912_create_openplat_sync_tables.sql
  sql/20260912_add_openplat_menu.sql

离线单测 43 个;另有联网集成测试 OpenPlatformClientIT(需 -Dopenplat.it=true)。
2026-09-15 15:54:49 +08:00

144 lines
8.6 KiB
SQL
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
-- ============================================================================
-- 医科大开放平台数据同步:名册表、同步记录表、唯一键、码表字典
-- 参见 .scratch/openplat-sync/spec.md 与 docs/adr/0001、0006
-- 可重复执行
-- ============================================================================
-- ---------------------------------------------------------------------------
-- 1. 学生名册(与 sys_user 账号分离,见 ADR-0001
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS `gxmu_student` (
`id` INT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`xh` VARCHAR(32) NOT NULL COMMENT '学号(开放平台外部键)',
`xm` VARCHAR(64) DEFAULT NULL COMMENT '姓名',
`xbm` VARCHAR(8) DEFAULT NULL COMMENT '性别码(平台原始)',
`sex` VARCHAR(16) DEFAULT NULL COMMENT '性别名称',
`mzm` VARCHAR(8) DEFAULT NULL COMMENT '民族码(平台原始)',
`nation` VARCHAR(32) DEFAULT NULL COMMENT '民族名称',
`zzmmm` VARCHAR(8) DEFAULT NULL COMMENT '政治面貌码(平台原始)',
`politics` VARCHAR(64) DEFAULT NULL COMMENT '政治面貌名称',
`sfzjh` VARCHAR(32) DEFAULT NULL COMMENT '身份证件号',
`sjh` VARCHAR(32) DEFAULT NULL COMMENT '手机号(认领键)',
`bjm` VARCHAR(64) DEFAULT NULL COMMENT '平台班级码(原始)',
`bh` VARCHAR(64) DEFAULT NULL COMMENT '平台班号(学籍库原始)',
`class_id` INT DEFAULT NULL COMMENT '解析出的班级ID',
`college_id` INT DEFAULT NULL COMMENT '解析出的学院ID',
`dwh` VARCHAR(64) DEFAULT NULL COMMENT '单位号(平台原始)',
`zyh` VARCHAR(32) DEFAULT NULL COMMENT '专业号',
`zymc` VARCHAR(128) DEFAULT NULL COMMENT '专业名称',
`pyccmc` VARCHAR(32) DEFAULT NULL COMMENT '培养层次',
`sfzx` VARCHAR(8) DEFAULT NULL COMMENT '是否在校',
`xjzt` VARCHAR(32) DEFAULT NULL COMMENT '学籍状态',
`xsdqzt` VARCHAR(32) DEFAULT NULL COMMENT '学生当前状态',
`csrq` VARCHAR(20) DEFAULT NULL COMMENT '出生日期',
`user_id` INT DEFAULT NULL COMMENT '认领后的 sys_user.user_id',
`claim_time` DATETIME DEFAULT NULL COMMENT '认领时间',
`status` TINYINT NOT NULL DEFAULT 1 COMMENT '状态:1在校 0毕业/结业/休学',
`sync_time` DATETIME DEFAULT NULL COMMENT '最近同步时间',
`tenant_id` INT DEFAULT NULL COMMENT '租户ID',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` TINYINT NOT NULL DEFAULT 0 COMMENT '删除标记:0未删 1已删',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_gxmu_student_xh` (`tenant_id`, `xh`),
KEY `idx_gxmu_student_xh` (`xh`),
KEY `idx_gxmu_student_sjh` (`sjh`),
KEY `idx_gxmu_student_class` (`class_id`),
KEY `idx_gxmu_student_college` (`college_id`),
KEY `idx_gxmu_student_uid` (`user_id`),
KEY `idx_gxmu_student_status` (`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='学生名册(开放平台同步)';
-- ---------------------------------------------------------------------------
-- 2. 教师名册
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS `gxmu_teacher` (
`id` INT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`jgh` VARCHAR(32) NOT NULL COMMENT '教工号(开放平台外部键)',
`xm` VARCHAR(64) DEFAULT NULL COMMENT '姓名',
`xbm` VARCHAR(8) DEFAULT NULL COMMENT '性别码(平台原始)',
`sex` VARCHAR(16) DEFAULT NULL COMMENT '性别名称',
`dwh` VARCHAR(64) DEFAULT NULL COMMENT '单位号(平台原始)',
`college_id` INT DEFAULT NULL COMMENT '解析出的学院ID',
`ksjybh` VARCHAR(64) DEFAULT NULL COMMENT '科室教研室编号',
`sjh` VARCHAR(32) DEFAULT NULL COMMENT '手机号(敏感字段, 不对外输出)',
`status` TINYINT NOT NULL DEFAULT 1 COMMENT '状态:1启用 0停用',
`sync_time` DATETIME DEFAULT NULL COMMENT '最近同步时间',
`tenant_id` INT DEFAULT NULL COMMENT '租户ID',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` TINYINT NOT NULL DEFAULT 0 COMMENT '删除标记:0未删 1已删',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_gxmu_teacher_jgh` (`tenant_id`, `jgh`),
KEY `idx_gxmu_teacher_jgh` (`jgh`),
KEY `idx_gxmu_teacher_college` (`college_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='教师名册(开放平台同步)';
-- ---------------------------------------------------------------------------
-- 3. 同步记录
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS `gxmu_sync_record` (
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`batch_id` VARCHAR(64) DEFAULT NULL COMMENT '批次号(同一次触发的各段共享)',
`sync_type` VARCHAR(32) NOT NULL COMMENT '同步类型:dept/teacher/class/student',
`trigger_type` VARCHAR(16) NOT NULL COMMENT '触发方式:schedule/manual',
`trigger_user` VARCHAR(100) DEFAULT NULL COMMENT '触发人(手动触发时)',
`start_time` DATETIME DEFAULT NULL COMMENT '开始时间',
`end_time` DATETIME DEFAULT NULL COMMENT '结束时间',
`success_count` INT NOT NULL DEFAULT 0 COMMENT '成功条数',
`fail_count` INT NOT NULL DEFAULT 0 COMMENT '失败条数',
`skip_count` INT NOT NULL DEFAULT 0 COMMENT '跳过条数',
`status` TINYINT NOT NULL DEFAULT 0 COMMENT '状态:0成功 1失败',
`error_msg` VARCHAR(1000) DEFAULT NULL COMMENT '错误摘要(不含手机号/身份证)',
`tenant_id` INT DEFAULT NULL COMMENT '租户ID',
`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`),
KEY `idx_gxmu_sync_record_batch` (`batch_id`),
KEY `idx_gxmu_sync_record_start` (`start_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='开放平台同步记录';
-- ---------------------------------------------------------------------------
-- 4. 唯一键(幂等 upsert 的前提)
-- 先把手写的空串规范成 NULL,否则唯一键会被一堆 '' 互撞。
-- ---------------------------------------------------------------------------
UPDATE `gxmu_class` SET `class_code` = NULL WHERE `class_code` = '';
UPDATE `sys_organization` SET `organization_code` = NULL WHERE `organization_code` = '';
SET @exist := (SELECT COUNT(*) FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'gxmu_class'
AND INDEX_NAME = 'uk_gxmu_class_code');
SET @stmt := IF(@exist = 0,
'ALTER TABLE `gxmu_class` ADD UNIQUE KEY `uk_gxmu_class_code` (`tenant_id`, `class_code`)',
'SELECT 1');
PREPARE s FROM @stmt; EXECUTE s; DEALLOCATE PREPARE s;
SET @exist := (SELECT COUNT(*) FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'sys_organization'
AND INDEX_NAME = 'uk_sys_organization_code');
SET @stmt := IF(@exist = 0,
'ALTER TABLE `sys_organization` ADD UNIQUE KEY `uk_sys_organization_code` (`tenant_id`, `organization_code`)',
'SELECT 1');
PREPARE s FROM @stmt; EXECUTE s; DEALLOCATE PREPARE s;
-- ---------------------------------------------------------------------------
-- 5. 码表字典
-- 平台只返回代码不返回名称,且平台本身没有任何码表接口(见 ADR-0006)。
-- dict_data_code = 平台原始码,dict_data_name = 解析后的名称。
-- ---------------------------------------------------------------------------
INSERT INTO `sys_dict` (`dict_id`, `dict_code`, `dict_name`, `sort_number`, `comments`, `tenant_id`)
VALUES
(9001, 'openplat_sex', '开放平台-性别码', 1, '1=男 2=女(已由实测确认)', 10049),
(9002, 'openplat_nation', '开放平台-民族码', 2, '待 RS_JZGXX 授权后用 MZM/MZM1 反推回填', 10049),
(9003, 'openplat_politics', '开放平台-政治面貌码', 3, '待 RS_JZGXX 授权后用 ZZZTM/ZZZTM1 反推回填', 10049)
ON DUPLICATE KEY UPDATE `dict_code` = VALUES(`dict_code`), `dict_name` = VALUES(`dict_name`);
INSERT INTO `sys_dict_data` (`dict_data_code`, `dict_data_name`, `dict_id`, `sort_number`, `tenant_id`)
SELECT t.c, t.n, t.d, t.s, t.t
FROM (
SELECT '1' AS c, '男' AS n, 9001 AS d, 1 AS s, 10049 AS t
UNION ALL SELECT '2', '女', 9001, 2, 10049
) t
LEFT JOIN `sys_dict_data` d ON d.`dict_id` = t.d AND d.`dict_data_code` = t.c
WHERE d.`dict_data_id` IS NULL;