02_system_seed.sql
13.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
-- ============================================================================
-- parking-cloud · P1 系统管理种子数据
--
-- 执行前提:先执行 01_system_schema.sql
-- 幂等:全部 INSERT IGNORE + 显式主键,可重复执行(不会重复插、不会覆盖已改过的数据)
--
-- ⚠️ 本脚本**只用于本地/开发环境初始化**。上线前必须处理两处:
-- 1. admin 的初始密码(见 3. 的说明)
-- 2. OAuth2 客户端的 secret(见 8. 的说明)
-- 红线第 11 条:禁止把生产密钥提交进仓库。
--
-- 菜单 id 是**刻意固定**的(1 / 2 / 21~26),与 P0 占位实现
-- P0AuthController#buildP0Menus 下发的 id 完全一致,这样 P1 换成真实现后,
-- 前端的动态路由与已打开的标签页不会因为 id 变化而失配。
-- ============================================================================
USE parking_cloud;
-- ---------------------------------------------------------------------------
-- 1. 组织
-- ---------------------------------------------------------------------------
INSERT IGNORE INTO system_org (id, name, parent_id, sort, leader, mobile, email, status, remark, create_by, update_by)
VALUES (1, '总公司', 0, 1, '管理员', '', '', 0, '顶级组织(种子数据)', 'seed', 'seed');
-- ---------------------------------------------------------------------------
-- 2. 角色
-- ⚠️ 超级管理员的 **id 必须为 1** 且 **code 必须为 super_admin** —— 两处硬编码依赖它:
-- · 后端 PermissionServiceImpl 用 id=1 判定超管,超管直接拥有全部权限点
-- · 前端 store/modules/user.ts 的 isSuperAdmin 判定 roles.includes('super_admin')
-- 改动这一行会让「超管恒有权限」这条链路静默失效(表现为按钮消失但没有报错)。
-- ---------------------------------------------------------------------------
INSERT IGNORE INTO system_role (id, name, code, sort, data_scope, status, type, remark, create_by, update_by)
VALUES (1, '超级管理员', 'super_admin', 1, 1, 0, 1, '内置角色:拥有全部权限,不可删除', 'seed', 'seed');
-- ---------------------------------------------------------------------------
-- 3. 用户
-- admin / admin123
-- password 是 BCrypt 密文,已用 Spring Security 5.7.12 的
-- BCryptPasswordEncoder#matches("admin123", <该串>) 实测为 true
-- (密文以 $2y$ 开头,Spring 的 BCrypt 接受 $2a$/$2b$/$2y$ 三种版本前缀)。
-- ⚠️ admin123 是弱口令,仅供本地联调;上线前必须改密(走 /system/user/update-password)。
-- ---------------------------------------------------------------------------
INSERT IGNORE INTO system_users (id, username, password, nickname, remark, org_id, email, mobile, sex, status,
create_by, update_by)
VALUES (1, 'admin', '$2y$10$SG.m/uKIJpcEgJLnvPgZteLpU2PJ1Dv5EBp9krhSmBVASm45XSZ4C', '管理员',
'种子数据:初始超级管理员', 1, '', '', 0, 0, 'seed', 'seed');
-- ---------------------------------------------------------------------------
-- 4. 用户 ↔ 角色
-- ---------------------------------------------------------------------------
INSERT IGNORE INTO system_user_role (user_id, role_id, create_by)
VALUES (1, 1, 'seed');
-- ---------------------------------------------------------------------------
-- 5. 菜单树
-- type:1 目录,2 菜单,3 按钮(按钮只承载权限标识,不进前端菜单树)
-- component:相对 src/views 的路径,必须是**真实存在**的 .vue ——
-- 前端 store/modules/permission.ts 用 import.meta.glob('/src/views/**/*.vue') 解析,
-- 填错不会报错,只会让该菜单点开后是空白页。
-- 目录节点的 component 必须为 ''(前端只给有 component 的节点建路由),
-- 但目录**必须有 path**(/system)作为子菜单路由的前缀。
-- ---------------------------------------------------------------------------
-- 5.1 顶级:首页 + 系统管理
INSERT IGNORE INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, create_by, update_by) VALUES
(1, '首页', '', 2, 1, 0, '/dashboard', 'ep:home-filled', 'dashboard/index', 'Dashboard', 0, 1, 'seed', 'seed'),
(2, '系统管理', '', 1, 2, 0, '/system', 'ep:setting', '', '', 0, 1, 'seed', 'seed');
-- 5.2 一级菜单(系统管理下的 6 个页面)
INSERT IGNORE INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, create_by, update_by) VALUES
(21, '用户管理', '', 2, 1, 2, '/system/user', 'ep:user', 'system/user/index', 'SystemUser', 0, 1, 'seed', 'seed'),
(22, '角色管理', '', 2, 2, 2, '/system/role', 'ep:avatar', 'system/role/index', 'SystemRole', 0, 1, 'seed', 'seed'),
(23, '菜单管理', '', 2, 3, 2, '/system/menu', 'ep:menu', 'system/menu/index', 'SystemMenu', 0, 1, 'seed', 'seed'),
(24, '组织管理', '', 2, 4, 2, '/system/org', 'ep:office-building', 'system/org/index', 'SystemOrg', 0, 1, 'seed', 'seed'),
(25, '字典管理', '', 2, 5, 2, '/system/dict', 'ep:collection', 'system/dict/index', 'SystemDict', 0, 1, 'seed', 'seed'),
(26, '日志管理', '', 2, 6, 2, '/system/log', 'ep:document', 'system/log/index', 'SystemLog', 0, 1, 'seed', 'seed');
-- 5.3 按钮权限点
-- 命名规范 模块:资源:动作,与 Controller 上
-- @PreAuthorize("@ss.hasPermission('...')") 以及前端 v-hasPermi="'...'" 三处必须逐字一致。
-- 资源名与前端 API 文件的 BASE 路径对齐:标签用 dict,路径用 /system/dict-type。
INSERT IGNORE INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, create_by, update_by) VALUES
-- 用户管理
(101, '用户查询', 'system:user:query', 3, 1, 21, '', '', '', '', 0, 1, 'seed', 'seed'),
(102, '用户新增', 'system:user:create', 3, 2, 21, '', '', '', '', 0, 1, 'seed', 'seed'),
(103, '用户修改', 'system:user:update', 3, 3, 21, '', '', '', '', 0, 1, 'seed', 'seed'),
(104, '用户删除', 'system:user:delete', 3, 4, 21, '', '', '', '', 0, 1, 'seed', 'seed'),
(105, '用户导出', 'system:user:export', 3, 5, 21, '', '', '', '', 0, 1, 'seed', 'seed'),
(106, '重置密码', 'system:user:update-password', 3, 6, 21, '', '', '', '', 0, 1, 'seed', 'seed'),
-- 角色管理
(111, '角色查询', 'system:role:query', 3, 1, 22, '', '', '', '', 0, 1, 'seed', 'seed'),
(112, '角色新增', 'system:role:create', 3, 2, 22, '', '', '', '', 0, 1, 'seed', 'seed'),
(113, '角色修改', 'system:role:update', 3, 3, 22, '', '', '', '', 0, 1, 'seed', 'seed'),
(114, '角色删除', 'system:role:delete', 3, 4, 22, '', '', '', '', 0, 1, 'seed', 'seed'),
(115, '角色导出', 'system:role:export', 3, 5, 22, '', '', '', '', 0, 1, 'seed', 'seed'),
-- 菜单管理
(121, '菜单查询', 'system:menu:query', 3, 1, 23, '', '', '', '', 0, 1, 'seed', 'seed'),
(122, '菜单新增', 'system:menu:create', 3, 2, 23, '', '', '', '', 0, 1, 'seed', 'seed'),
(123, '菜单修改', 'system:menu:update', 3, 3, 23, '', '', '', '', 0, 1, 'seed', 'seed'),
(124, '菜单删除', 'system:menu:delete', 3, 4, 23, '', '', '', '', 0, 1, 'seed', 'seed'),
(125, '菜单导出', 'system:menu:export', 3, 5, 23, '', '', '', '', 0, 1, 'seed', 'seed'),
-- 组织管理
(131, '组织查询', 'system:org:query', 3, 1, 24, '', '', '', '', 0, 1, 'seed', 'seed'),
(132, '组织新增', 'system:org:create', 3, 2, 24, '', '', '', '', 0, 1, 'seed', 'seed'),
(133, '组织修改', 'system:org:update', 3, 3, 24, '', '', '', '', 0, 1, 'seed', 'seed'),
(134, '组织删除', 'system:org:delete', 3, 4, 24, '', '', '', '', 0, 1, 'seed', 'seed'),
(135, '组织导出', 'system:org:export', 3, 5, 24, '', '', '', '', 0, 1, 'seed', 'seed'),
-- 字典管理
(141, '字典查询', 'system:dict:query', 3, 1, 25, '', '', '', '', 0, 1, 'seed', 'seed'),
(142, '字典新增', 'system:dict:create', 3, 2, 25, '', '', '', '', 0, 1, 'seed', 'seed'),
(143, '字典修改', 'system:dict:update', 3, 3, 25, '', '', '', '', 0, 1, 'seed', 'seed'),
(144, '字典删除', 'system:dict:delete', 3, 4, 25, '', '', '', '', 0, 1, 'seed', 'seed'),
(145, '字典导出', 'system:dict:export', 3, 5, 25, '', '', '', '', 0, 1, 'seed', 'seed'),
-- 日志管理(操作日志只读,无 create/update/delete)
(151, '日志查询', 'system:operate-log:query', 3, 1, 26, '', '', '', '', 0, 1, 'seed', 'seed'),
(152, '日志导出', 'system:operate-log:export', 3, 2, 26, '', '', '', '', 0, 1, 'seed', 'seed');
-- ---------------------------------------------------------------------------
-- 6. 角色 ↔ 菜单:超管拿全部
-- 用 SELECT 而不是罗列 id,这样以后加菜单不必回来改本脚本。
-- 依赖 system_role_menu 的 uk_role_menu 唯一键做幂等去重。
-- ---------------------------------------------------------------------------
INSERT IGNORE INTO system_role_menu (role_id, menu_id, create_by)
SELECT 1, id, 'seed' FROM system_menu;
-- ---------------------------------------------------------------------------
-- 7. 字典
-- ---------------------------------------------------------------------------
INSERT IGNORE INTO system_dict_type (id, name, type, status, remark, create_by, update_by) VALUES
(1, '通用状态', 'system_common_status', 0, '0 开启 / 1 停用', 'seed', 'seed'),
(2, '用户性别', 'system_user_sex', 0, '', 'seed', 'seed'),
(3, '菜单类型', 'system_menu_type', 0, '1 目录 / 2 菜单 / 3 按钮', 'seed', 'seed'),
(4, '数据范围', 'system_data_scope', 0, '角色可访问的数据范围', 'seed', 'seed'),
(5, '操作类型', 'system_operate_type', 0, '操作日志的操作类型', 'seed', 'seed');
INSERT IGNORE INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, create_by, update_by) VALUES
(1, 1, '开启', '0', 'system_common_status', 0, 'success', '', '', 'seed', 'seed'),
(2, 2, '停用', '1', 'system_common_status', 0, 'danger', '', '', 'seed', 'seed'),
(11, 1, '未知', '0', 'system_user_sex', 0, 'info', '', '', 'seed', 'seed'),
(12, 2, '男', '1', 'system_user_sex', 0, 'info', '', '', 'seed', 'seed'),
(13, 3, '女', '2', 'system_user_sex', 0, 'info', '', '', 'seed', 'seed'),
(21, 1, '目录', '1', 'system_menu_type', 0, 'info', '', '', 'seed', 'seed'),
(22, 2, '菜单', '2', 'system_menu_type', 0, 'info', '', '', 'seed', 'seed'),
(23, 3, '按钮', '3', 'system_menu_type', 0, 'info', '', '', 'seed', 'seed'),
(31, 1, '全部', '1', 'system_data_scope', 0, 'info', '', '', 'seed', 'seed'),
(32, 2, '自定义', '2', 'system_data_scope', 0, 'info', '', '', 'seed', 'seed'),
(33, 3, '本组织', '3', 'system_data_scope', 0, 'info', '', '', 'seed', 'seed'),
(34, 4, '本组织及以下', '4', 'system_data_scope', 0, 'info', '', '', 'seed', 'seed'),
(35, 5, '仅本人', '5', 'system_data_scope', 0, 'info', '', '', 'seed', 'seed'),
-- 操作类型的 value 直接就是中文,与 system_operate_log.type 列存的**同一个字符串**:
-- 前端日志页 v1 是直接打印 row.type(没有 DictTag),所以列里必须是可直接展示的值;
-- 这里仍保留成字典,是为了将来换成 DictTag 渲染时不用改数据。
(41, 1, '查询', '查询', 'system_operate_type', 0, 'info', '', '', 'seed', 'seed'),
(42, 2, '新增', '新增', 'system_operate_type', 0, 'success', '', '', 'seed', 'seed'),
(43, 3, '修改', '修改', 'system_operate_type', 0, 'warning', '', '', 'seed', 'seed'),
(44, 4, '删除', '删除', 'system_operate_type', 0, 'danger', '', '', 'seed', 'seed');
-- ---------------------------------------------------------------------------
-- 8. OAuth2 客户端
-- client_id 与 P0 占位实现保持一致(parking-cloud-ui),改动会让已签发的 token 对不上。
--
-- ⚠️ secret 这里填的是**本地占位值**,不是密钥:管理后台是本方 SPA,
-- 浏览器里放任何 "客户端密钥" 都不构成秘密,所以登录接口(/system/auth/login)
-- 只收 username/password,**不校验 client secret**。该列留给以后接入第三方
-- 授权(authorization_code)时使用。生产环境请通过环境变量注入真实值。
-- ---------------------------------------------------------------------------
INSERT IGNORE INTO system_oauth2_client (id, client_id, secret, name, logo, description, status,
access_token_validity_seconds, refresh_token_validity_seconds,
redirect_uris, authorized_grant_types, scopes, auto_approve_scopes,
additional_information, create_by, update_by)
VALUES (1, 'parking-cloud-ui', 'local-dev-placeholder-not-a-secret', '停车云管理后台', '', 'parking-cloud-ui 前端使用',
0, 1800, 2592000, '', 'password,refresh_token', 'server', '', '', 'seed', 'seed');
-- ---------------------------------------------------------------------------
-- 校验
-- ---------------------------------------------------------------------------
SELECT '组织' AS 表, COUNT(*) AS 行数 FROM system_org
UNION ALL SELECT '角色', COUNT(*) FROM system_role
UNION ALL SELECT '用户', COUNT(*) FROM system_users
UNION ALL SELECT '用户角色', COUNT(*) FROM system_user_role
UNION ALL SELECT '菜单', COUNT(*) FROM system_menu
UNION ALL SELECT '菜单(按钮)', COUNT(*) FROM system_menu WHERE type = 3
UNION ALL SELECT '角色菜单', COUNT(*) FROM system_role_menu
UNION ALL SELECT '字典类型', COUNT(*) FROM system_dict_type
UNION ALL SELECT '字典数据', COUNT(*) FROM system_dict_data
UNION ALL SELECT 'OAuth2客户端', COUNT(*) FROM system_oauth2_client;