-- IAM 服务表结构(P2 身份阶段) CREATE TABLE IF NOT EXISTS `iam_users` ( `id` CHAR(36) NOT NULL, `email` VARCHAR(255) NOT NULL, `password_hash` VARCHAR(255) NOT NULL, `name` VARCHAR(100) NOT NULL, `status` VARCHAR(20) NOT NULL DEFAULT 'active', `data_scope` ENUM('self','class','grade','school','district','all') NOT NULL DEFAULT 'self', `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `iam_users_email_unique` (`email`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE IF NOT EXISTS `iam_roles` ( `id` CHAR(36) NOT NULL, `name` VARCHAR(50) NOT NULL, `description` VARCHAR(255) NULL, PRIMARY KEY (`id`), UNIQUE KEY `iam_roles_name_unique` (`name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE IF NOT EXISTS `iam_user_roles` ( `user_id` CHAR(36) NOT NULL, `role_id` CHAR(36) NOT NULL, `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`user_id`, `role_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE IF NOT EXISTS `iam_permissions` ( `id` CHAR(36) NOT NULL, `name` VARCHAR(100) NOT NULL, `resource` VARCHAR(50) NOT NULL, `action` VARCHAR(50) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `iam_permissions_name_unique` (`name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE IF NOT EXISTS `iam_role_permissions` ( `role_id` CHAR(36) NOT NULL, `permission_id` CHAR(36) NOT NULL, PRIMARY KEY (`role_id`, `permission_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE IF NOT EXISTS `iam_refresh_tokens` ( `id` CHAR(36) NOT NULL, `user_id` CHAR(36) NOT NULL, `token_hash` VARCHAR(255) NOT NULL, `expires_at` TIMESTAMP NOT NULL, `revoked_at` TIMESTAMP NULL, `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), INDEX `idx_iam_refresh_tokens_user_id` (`user_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -- 视口配置表(4 层模型:L1 导航 / L2 路由 / L3 组件 / L4 数据) CREATE TABLE IF NOT EXISTS `iam_role_viewports` ( `id` CHAR(36) NOT NULL, `role_id` CHAR(36) NOT NULL, `viewport_key` VARCHAR(50) NOT NULL, `label` VARCHAR(100) NOT NULL, `route` VARCHAR(200) NOT NULL, `icon` VARCHAR(50) NULL, `sort_order` VARCHAR(10) NOT NULL DEFAULT '0', `required_permission` VARCHAR(100) NULL, `component_config` TEXT NULL, PRIMARY KEY (`id`), INDEX `idx_iam_role_viewports_role_id` (`role_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -- 种子数据:默认角色 INSERT IGNORE INTO `iam_roles` (`id`, `name`, `description`) VALUES ('00000000-0000-0000-0000-000000000001', 'teacher', '教师角色'), ('00000000-0000-0000-0000-000000000002', 'admin', '管理员角色'); -- 种子数据:权限点(固定 UUID 便于 role_permissions 引用) INSERT IGNORE INTO `iam_permissions` (`id`, `name`, `resource`, `action`) VALUES ('00000000-0000-0000-0000-000000000101', 'classes:read', 'classes', 'read'), ('00000000-0000-0000-0000-000000000102', 'classes:create', 'classes', 'create'), ('00000000-0000-0000-0000-000000000103', 'classes:update', 'classes', 'update'), ('00000000-0000-0000-0000-000000000104', 'classes:delete', 'classes', 'delete'), ('00000000-0000-0000-0000-000000000201', 'iam:user:read', 'iam', 'user:read'), ('00000000-0000-0000-0000-000000000202', 'iam:user:manage', 'iam', 'user:manage'), ('00000000-0000-0000-0000-000000000203', 'iam:role:manage', 'iam', 'role:manage'); -- 种子数据:teacher 角色权限(classes CRUD + user:read) INSERT IGNORE INTO `iam_role_permissions` (`role_id`, `permission_id`) VALUES ('00000000-0000-0000-0000-000000000001', '00000000-0000-0000-0000-000000000101'), ('00000000-0000-0000-0000-000000000001', '00000000-0000-0000-0000-000000000102'), ('00000000-0000-0000-0000-000000000001', '00000000-0000-0000-0000-000000000103'), ('00000000-0000-0000-0000-000000000001', '00000000-0000-0000-0000-000000000104'), ('00000000-0000-0000-0000-000000000001', '00000000-0000-0000-0000-000000000201'); -- 种子数据:admin 角色权限(全部权限) INSERT IGNORE INTO `iam_role_permissions` (`role_id`, `permission_id`) VALUES ('00000000-0000-0000-0000-000000000002', '00000000-0000-0000-0000-000000000101'), ('00000000-0000-0000-0000-000000000002', '00000000-0000-0000-0000-000000000102'), ('00000000-0000-0000-0000-000000000002', '00000000-0000-0000-0000-000000000103'), ('00000000-0000-0000-0000-000000000002', '00000000-0000-0000-0000-000000000104'), ('00000000-0000-0000-0000-000000000002', '00000000-0000-0000-0000-000000000201'), ('00000000-0000-0000-0000-000000000002', '00000000-0000-0000-0000-000000000202'), ('00000000-0000-0000-0000-000000000002', '00000000-0000-0000-0000-000000000203'); -- 种子数据:teacher 角色视口(L1 导航) INSERT IGNORE INTO `iam_role_viewports` (`id`, `role_id`, `viewport_key`, `label`, `route`, `icon`, `sort_order`, `required_permission`) VALUES ('00000000-0000-0000-0000-000000000a01', '00000000-0000-0000-0000-000000000001', 'dashboard', '仪表盘', '/dashboard', 'home', '0', NULL), ('00000000-0000-0000-0000-000000000a02', '00000000-0000-0000-0000-000000000001', 'classes', '班级管理', '/classes', 'users', '1', 'classes:read'), ('00000000-0000-0000-0000-000000000a03', '00000000-0000-0000-0000-000000000001', 'profile', '个人中心', '/profile', 'user', '9', NULL); -- 种子数据:admin 角色视口(L1 导航) INSERT IGNORE INTO `iam_role_viewports` (`id`, `role_id`, `viewport_key`, `label`, `route`, `icon`, `sort_order`, `required_permission`) VALUES ('00000000-0000-0000-0000-000000000b01', '00000000-0000-0000-0000-000000000002', 'dashboard', '仪表盘', '/dashboard', 'home', '0', NULL), ('00000000-0000-0000-0000-000000000b02', '00000000-0000-0000-0000-000000000002', 'classes', '班级管理', '/classes', 'users', '1', 'classes:read'), ('00000000-0000-0000-0000-000000000b03', '00000000-0000-0000-0000-000000000002', 'iam', '用户管理', '/iam/users', 'shield', '2', 'iam:user:read'), ('00000000-0000-0000-0000-000000000b04', '00000000-0000-0000-0000-000000000002', 'profile', '个人中心', '/profile', 'user', '9', NULL);