befly-tpl 3.2.6 → 3.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.development +3 -3
- package/apis/article/articleDel.ts +2 -2
- package/apis/article/articleDetail.ts +2 -2
- package/apis/article/articleList.ts +2 -4
- package/apis/article/articleUpd.ts +2 -2
- package/apis/article/increment.ts +2 -2
- package/apis/user/login.ts +3 -3
- package/apis/user/userList.ts +3 -5
- package/package.json +6 -10
- package/pm2.config.cjs +3 -3
- package/tables/user.json +1 -1
- package/addons/_template/README.md +0 -123
- package/addons/_template/addon.config.json +0 -17
- package/addons/_template/apis/example.ts +0 -33
- package/addons/_template/checks/example.ts +0 -23
- package/addons/_template/config/default.ts +0 -12
- package/addons/_template/plugins/example.ts +0 -39
- package/addons/_template/tables/example.json +0 -7
- package/addons/_template/types/index.d.ts +0 -21
- package/addons/admin/README.md +0 -179
- package/addons/admin/addon.config.json +0 -13
- package/addons/admin/apis/adminDel.ts +0 -37
- package/addons/admin/apis/adminInfo.ts +0 -50
- package/addons/admin/apis/adminIns.ts +0 -70
- package/addons/admin/apis/adminList.ts +0 -24
- package/addons/admin/apis/adminRoleDetail.ts +0 -38
- package/addons/admin/apis/adminRoleSave.ts +0 -40
- package/addons/admin/apis/adminUpd.ts +0 -54
- package/addons/admin/apis/apiAll.ts +0 -38
- package/addons/admin/apis/cacheRefresh.ts +0 -36
- package/addons/admin/apis/dashboardAddonList.ts +0 -16
- package/addons/admin/apis/dashboardChangelog.ts +0 -41
- package/addons/admin/apis/dashboardConfigStatus.ts +0 -56
- package/addons/admin/apis/dashboardEnvironmentInfo.ts +0 -48
- package/addons/admin/apis/dashboardPerformanceMetrics.ts +0 -25
- package/addons/admin/apis/dashboardPermissionStats.ts +0 -33
- package/addons/admin/apis/dashboardServiceStatus.ts +0 -84
- package/addons/admin/apis/dashboardSystemInfo.ts +0 -34
- package/addons/admin/apis/dashboardSystemOverview.ts +0 -34
- package/addons/admin/apis/dashboardSystemResources.ts +0 -119
- package/addons/admin/apis/dictAll.ts +0 -26
- package/addons/admin/apis/dictDel.ts +0 -27
- package/addons/admin/apis/dictDetail.ts +0 -28
- package/addons/admin/apis/dictIns.ts +0 -38
- package/addons/admin/apis/dictList.ts +0 -27
- package/addons/admin/apis/dictUpd.ts +0 -44
- package/addons/admin/apis/login.ts +0 -123
- package/addons/admin/apis/logout.ts +0 -23
- package/addons/admin/apis/menuAll.ts +0 -70
- package/addons/admin/apis/menuDel.ts +0 -40
- package/addons/admin/apis/menuIns.ts +0 -31
- package/addons/admin/apis/menuList.ts +0 -26
- package/addons/admin/apis/menuUpd.ts +0 -41
- package/addons/admin/apis/register.ts +0 -50
- package/addons/admin/apis/roleApiDetail.ts +0 -34
- package/addons/admin/apis/roleApiSave.ts +0 -44
- package/addons/admin/apis/roleDel.ts +0 -48
- package/addons/admin/apis/roleDetail.ts +0 -28
- package/addons/admin/apis/roleIns.ts +0 -40
- package/addons/admin/apis/roleList.ts +0 -18
- package/addons/admin/apis/roleMenuDetail.ts +0 -33
- package/addons/admin/apis/roleMenuSave.ts +0 -39
- package/addons/admin/apis/roleSave.ts +0 -45
- package/addons/admin/apis/roleUpd.ts +0 -53
- package/addons/admin/apis/sendSmsCode.ts +0 -36
- package/addons/admin/checks/admin.ts +0 -36
- package/addons/admin/config/index.ts +0 -45
- package/addons/admin/config/menu.json +0 -44
- package/addons/admin/scripts/syncApi.ts +0 -285
- package/addons/admin/scripts/syncDev.ts +0 -203
- package/addons/admin/scripts/syncMenu.ts +0 -210
- package/addons/admin/tables/admin.json +0 -14
- package/addons/admin/tables/api.json +0 -8
- package/addons/admin/tables/dict.json +0 -8
- package/addons/admin/tables/menu.json +0 -8
- package/addons/admin/tables/role.json +0 -8
- package/addons/admin/types/index.ts +0 -44
- package/addons/admin/util.ts +0 -266
- package/addons/befly/addon.config.json +0 -13
- package/addons/befly/apis/health/info.ts +0 -77
- package/addons/befly/apis/tool/tokenCheck.ts +0 -52
- package/addons/demo/README.md +0 -62
- package/addons/demo/addon.config.json +0 -13
- package/addons/demo/apis/demoIns.ts +0 -36
- package/addons/demo/apis/demoList.ts +0 -36
- package/addons/demo/checks/demo.ts +0 -30
- package/addons/demo/config/default.ts +0 -17
- package/addons/demo/plugins/tool.ts +0 -61
- package/addons/demo/tables/todo.json +0 -6
- package/addons/demo/types/index.d.ts +0 -56
- package/tests/core.test.ts +0 -13
|
@@ -1,203 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 同步开发者管理员到数据库(使用 dbHelper)
|
|
3
|
-
* - 邮箱: dev@qq.com
|
|
4
|
-
* - 姓名: 开发者
|
|
5
|
-
* - 密码: 使用 bcrypt 加密
|
|
6
|
-
* - 角色: roleCode=dev, roleType=admin
|
|
7
|
-
* - 表名: addon_admin_admin
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import { Env, Logger, Crypto2, initDatabase, closeDatabase } from 'befly';
|
|
11
|
-
|
|
12
|
-
// CLI 参数类型
|
|
13
|
-
interface CliArgs {
|
|
14
|
-
DRY_RUN: boolean;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
// 解析命令行参数
|
|
18
|
-
const ARGV = Array.isArray(process.argv) ? process.argv : [];
|
|
19
|
-
const CLI: CliArgs = { DRY_RUN: ARGV.includes('--plan') };
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* 同步开发管理员账号(使用统一的 database 工具)
|
|
23
|
-
* 表名: addon_admin_admin
|
|
24
|
-
* 邮箱: dev@qq.com
|
|
25
|
-
* 用户名: dev
|
|
26
|
-
* 姓名: 开发者
|
|
27
|
-
* 角色: roleCode=dev, roleType=admin
|
|
28
|
-
* @returns 是否成功
|
|
29
|
-
*/
|
|
30
|
-
export async function SyncDev(): Promise<boolean> {
|
|
31
|
-
let dbInitialized = false;
|
|
32
|
-
|
|
33
|
-
try {
|
|
34
|
-
if (CLI.DRY_RUN) {
|
|
35
|
-
Logger.info('[计划] 同步完成后将初始化/更新开发管理员账号(plan 模式不执行)');
|
|
36
|
-
return true;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
if (!Env.DEV_PASSWORD || !Env.MD5_SALT) {
|
|
40
|
-
Logger.warn('跳过开发管理员初始化:缺少 DEV_PASSWORD 或 MD5_SALT 配置');
|
|
41
|
-
return false;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// 初始化数据库连接(Redis + SQL + DbHelper)
|
|
45
|
-
const { helper } = await initDatabase({ max: 1 });
|
|
46
|
-
dbInitialized = true;
|
|
47
|
-
|
|
48
|
-
// 检查 addon_admin_admin 表是否存在(使用 helper.query 执行元数据查询)
|
|
49
|
-
const existAdmin = await helper.tableExists('addon_admin_admin');
|
|
50
|
-
if (!existAdmin) {
|
|
51
|
-
Logger.warn('跳过开发管理员初始化:未检测到 addon_admin_admin 表');
|
|
52
|
-
return false;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// 检查 addon_admin_role 表是否存在
|
|
56
|
-
const existRole = await helper.tableExists('addon_admin_role');
|
|
57
|
-
if (!existRole) {
|
|
58
|
-
Logger.warn('跳过开发管理员初始化:未检测到 addon_admin_role 表');
|
|
59
|
-
return false;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// 检查 addon_admin_menu 表是否存在
|
|
63
|
-
const existMenu = await helper.tableExists('addon_admin_menu');
|
|
64
|
-
if (!existMenu) {
|
|
65
|
-
Logger.warn('跳过开发管理员初始化:未检测到 addon_admin_menu 表');
|
|
66
|
-
return false;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// 查询所有菜单 ID
|
|
70
|
-
const allMenus = await helper.getAll({
|
|
71
|
-
table: 'addon_admin_menu',
|
|
72
|
-
fields: ['id']
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
if (!allMenus || !Array.isArray(allMenus)) {
|
|
76
|
-
Logger.warn('查询菜单失败或菜单表为空');
|
|
77
|
-
return false;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
const menuIds = allMenus.length > 0 ? allMenus.map((m: any) => m.id).join(',') : '';
|
|
81
|
-
Logger.info(`查询到 ${allMenus.length} 个菜单,ID 列表: ${menuIds || '(空)'}`);
|
|
82
|
-
|
|
83
|
-
// 查询所有接口 ID
|
|
84
|
-
const existApi = await helper.tableExists('addon_admin_api');
|
|
85
|
-
let apiIds = '';
|
|
86
|
-
if (existApi) {
|
|
87
|
-
const allApis = await helper.getAll({
|
|
88
|
-
table: 'addon_admin_api',
|
|
89
|
-
fields: ['id']
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
if (allApis && Array.isArray(allApis) && allApis.length > 0) {
|
|
93
|
-
apiIds = allApis.map((a: any) => a.id).join(',');
|
|
94
|
-
Logger.info(`查询到 ${allApis.length} 个接口,ID 列表: ${apiIds}`);
|
|
95
|
-
} else {
|
|
96
|
-
Logger.info('未查询到接口数据');
|
|
97
|
-
}
|
|
98
|
-
} else {
|
|
99
|
-
Logger.info('接口表不存在,跳过接口权限配置');
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// 查询或创建 dev 角色
|
|
103
|
-
let devRole = await helper.getOne({
|
|
104
|
-
table: 'addon_admin_role',
|
|
105
|
-
where: { code: 'dev' }
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
if (devRole) {
|
|
109
|
-
// 更新 dev 角色的菜单和接口权限
|
|
110
|
-
await helper.updData({
|
|
111
|
-
table: 'addon_admin_role',
|
|
112
|
-
where: { code: 'dev' },
|
|
113
|
-
data: {
|
|
114
|
-
name: '开发者角色',
|
|
115
|
-
description: '拥有所有菜单和接口权限的开发者角色',
|
|
116
|
-
menus: menuIds,
|
|
117
|
-
apis: apiIds
|
|
118
|
-
}
|
|
119
|
-
});
|
|
120
|
-
Logger.info('dev 角色菜单和接口权限已更新');
|
|
121
|
-
} else {
|
|
122
|
-
// 创建 dev 角色
|
|
123
|
-
const roleId = await helper.insData({
|
|
124
|
-
table: 'addon_admin_role',
|
|
125
|
-
data: {
|
|
126
|
-
name: '开发者角色',
|
|
127
|
-
code: 'dev',
|
|
128
|
-
description: '拥有所有菜单和接口权限的开发者角色',
|
|
129
|
-
menus: menuIds,
|
|
130
|
-
apis: apiIds,
|
|
131
|
-
sort: 0
|
|
132
|
-
}
|
|
133
|
-
});
|
|
134
|
-
devRole = { id: roleId };
|
|
135
|
-
Logger.info('dev 角色已创建');
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// 使用 bcrypt 加密密码(与登录验证一致)
|
|
139
|
-
const hashed = await Crypto2.hashPassword(Env.DEV_PASSWORD);
|
|
140
|
-
|
|
141
|
-
// 准备开发管理员数据
|
|
142
|
-
const devData = {
|
|
143
|
-
name: '开发者',
|
|
144
|
-
nickname: '开发者',
|
|
145
|
-
email: 'dev@qq.com',
|
|
146
|
-
username: 'dev',
|
|
147
|
-
password: hashed,
|
|
148
|
-
roleId: devRole.id,
|
|
149
|
-
roleCode: 'dev',
|
|
150
|
-
roleType: 'admin' // 小驼峰,自动转换为 role_type
|
|
151
|
-
};
|
|
152
|
-
|
|
153
|
-
// 查询现有账号
|
|
154
|
-
const existing = await helper.getOne({
|
|
155
|
-
table: 'addon_admin_admin',
|
|
156
|
-
where: { email: 'dev@qq.com' }
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
if (existing) {
|
|
160
|
-
// 更新现有账号
|
|
161
|
-
await helper.updData({
|
|
162
|
-
table: 'addon_admin_admin',
|
|
163
|
-
where: { email: 'dev@qq.com' },
|
|
164
|
-
data: devData
|
|
165
|
-
});
|
|
166
|
-
Logger.info('开发管理员已更新:email=dev@qq.com, username=dev, roleCode=dev, roleType=admin');
|
|
167
|
-
} else {
|
|
168
|
-
// 插入新账号
|
|
169
|
-
await helper.insData({
|
|
170
|
-
table: 'addon_admin_admin',
|
|
171
|
-
data: devData
|
|
172
|
-
});
|
|
173
|
-
Logger.info('开发管理员已初始化:email=dev@qq.com, username=dev, roleCode=dev, roleType=admin');
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
return true;
|
|
177
|
-
} catch (error: any) {
|
|
178
|
-
Logger.warn(`开发管理员初始化步骤出错:${error.message}`);
|
|
179
|
-
return false;
|
|
180
|
-
} finally {
|
|
181
|
-
// 清理资源:关闭所有数据库连接
|
|
182
|
-
if (dbInitialized) {
|
|
183
|
-
await closeDatabase();
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
/**
|
|
189
|
-
* 允许直接运行该脚本
|
|
190
|
-
*/
|
|
191
|
-
if (import.meta.main) {
|
|
192
|
-
SyncDev()
|
|
193
|
-
.then((ok: boolean) => {
|
|
194
|
-
if (CLI.DRY_RUN) {
|
|
195
|
-
process.exit(0);
|
|
196
|
-
}
|
|
197
|
-
process.exit(ok ? 0 : 1);
|
|
198
|
-
})
|
|
199
|
-
.catch((err: Error) => {
|
|
200
|
-
Logger.error('❌ 开发管理员同步失败:', err);
|
|
201
|
-
process.exit(1);
|
|
202
|
-
});
|
|
203
|
-
}
|
|
@@ -1,210 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bun
|
|
2
|
-
/**
|
|
3
|
-
* 同步菜单数据到数据库
|
|
4
|
-
* 说明:根据 menu.json 配置文件增量同步菜单数据(最多2级:父级和子级)
|
|
5
|
-
*
|
|
6
|
-
* 流程:
|
|
7
|
-
* 1. 读取 menu.json 配置文件
|
|
8
|
-
* 2. 根据菜单的 path 字段检查是否存在
|
|
9
|
-
* 3. 存在则更新其他字段(name、icon、sort、type、pid)
|
|
10
|
-
* 4. 不存在则新增菜单记录
|
|
11
|
-
* 5. 处理两层菜单结构(父级和子级,不支持多层嵌套)
|
|
12
|
-
* 注:state 字段由框架自动管理(1=正常,2=禁用,0=删除)
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
import { Env, Logger, initDatabase, closeDatabase } from 'befly';
|
|
16
|
-
import path from 'node:path';
|
|
17
|
-
import { fileURLToPath } from 'node:url';
|
|
18
|
-
import menuConfig from '../config/menu.json';
|
|
19
|
-
import { collectPaths, checkTableExists, deleteObsoleteRecords, logSyncStats } from '../util';
|
|
20
|
-
|
|
21
|
-
// CLI 参数类型
|
|
22
|
-
interface CliArgs {
|
|
23
|
-
DRY_RUN: boolean;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
// 解析命令行参数
|
|
27
|
-
const CLI: CliArgs = {
|
|
28
|
-
DRY_RUN: process.argv.includes('--plan')
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
32
|
-
const __dirname = path.dirname(__filename);
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* 同步菜单(两层结构:父级和子级)
|
|
36
|
-
* @param helper - DbHelper 实例
|
|
37
|
-
* @param menus - 菜单数组
|
|
38
|
-
* @returns 同步统计信息
|
|
39
|
-
*/
|
|
40
|
-
async function syncMenus(helper: any, menus: any[]): Promise<{ created: number; updated: number }> {
|
|
41
|
-
const stats = { created: 0, updated: 0 };
|
|
42
|
-
|
|
43
|
-
for (const menu of menus) {
|
|
44
|
-
try {
|
|
45
|
-
// 1. 同步父级菜单
|
|
46
|
-
const existingParent = await helper.getOne({
|
|
47
|
-
table: 'addon_admin_menu',
|
|
48
|
-
where: { path: menu.path || '' }
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
let parentId: number;
|
|
52
|
-
|
|
53
|
-
if (existingParent) {
|
|
54
|
-
// 存在则更新
|
|
55
|
-
await helper.updData({
|
|
56
|
-
table: 'addon_admin_menu',
|
|
57
|
-
where: { id: existingParent.id },
|
|
58
|
-
data: {
|
|
59
|
-
pid: 0,
|
|
60
|
-
name: menu.name,
|
|
61
|
-
icon: menu.icon || '',
|
|
62
|
-
sort: menu.sort || 0,
|
|
63
|
-
type: menu.type || 1
|
|
64
|
-
}
|
|
65
|
-
});
|
|
66
|
-
parentId = existingParent.id;
|
|
67
|
-
stats.updated++;
|
|
68
|
-
Logger.info(` └ 更新父级菜单: ${menu.name} (ID: ${parentId}, Path: ${menu.path})`);
|
|
69
|
-
} else {
|
|
70
|
-
// 不存在则新增
|
|
71
|
-
parentId = await helper.insData({
|
|
72
|
-
table: 'addon_admin_menu',
|
|
73
|
-
data: {
|
|
74
|
-
pid: 0,
|
|
75
|
-
name: menu.name,
|
|
76
|
-
path: menu.path || '',
|
|
77
|
-
icon: menu.icon || '',
|
|
78
|
-
sort: menu.sort || 0,
|
|
79
|
-
type: menu.type || 1
|
|
80
|
-
}
|
|
81
|
-
});
|
|
82
|
-
stats.created++;
|
|
83
|
-
Logger.info(` └ 新增父级菜单: ${menu.name} (ID: ${parentId}, Path: ${menu.path})`);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// 2. 同步子级菜单
|
|
87
|
-
if (menu.children && menu.children.length > 0) {
|
|
88
|
-
for (const child of menu.children) {
|
|
89
|
-
const existingChild = await helper.getOne({
|
|
90
|
-
table: 'addon_admin_menu',
|
|
91
|
-
where: { path: child.path || '' }
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
if (existingChild) {
|
|
95
|
-
// 存在则更新
|
|
96
|
-
await helper.updData({
|
|
97
|
-
table: 'addon_admin_menu',
|
|
98
|
-
where: { id: existingChild.id },
|
|
99
|
-
data: {
|
|
100
|
-
pid: parentId,
|
|
101
|
-
name: child.name,
|
|
102
|
-
icon: child.icon || '',
|
|
103
|
-
sort: child.sort || 0,
|
|
104
|
-
type: child.type || 1
|
|
105
|
-
}
|
|
106
|
-
});
|
|
107
|
-
stats.updated++;
|
|
108
|
-
Logger.info(` └ 更新子级菜单: ${child.name} (ID: ${existingChild.id}, PID: ${parentId}, Path: ${child.path})`);
|
|
109
|
-
} else {
|
|
110
|
-
// 不存在则新增
|
|
111
|
-
const childId = await helper.insData({
|
|
112
|
-
table: 'addon_admin_menu',
|
|
113
|
-
data: {
|
|
114
|
-
pid: parentId,
|
|
115
|
-
name: child.name,
|
|
116
|
-
path: child.path || '',
|
|
117
|
-
icon: child.icon || '',
|
|
118
|
-
sort: child.sort || 0,
|
|
119
|
-
type: child.type || 1
|
|
120
|
-
}
|
|
121
|
-
});
|
|
122
|
-
stats.created++;
|
|
123
|
-
Logger.info(` └ 新增子级菜单: ${child.name} (ID: ${childId}, PID: ${parentId}, Path: ${child.path})`);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
} catch (error: any) {
|
|
128
|
-
Logger.error(`同步菜单 "${menu.name}" 失败:`, error.message || String(error));
|
|
129
|
-
throw error;
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
return stats;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* 同步菜单主函数
|
|
138
|
-
*/
|
|
139
|
-
async function syncMenu(): Promise<boolean> {
|
|
140
|
-
let dbInitialized = false;
|
|
141
|
-
|
|
142
|
-
try {
|
|
143
|
-
if (CLI.DRY_RUN) {
|
|
144
|
-
Logger.info('[计划] 同步菜单配置到数据库(plan 模式不执行)');
|
|
145
|
-
Logger.info('[计划] 1. 读取 menu.json 配置文件');
|
|
146
|
-
Logger.info('[计划] 2. 根据 path 检查菜单是否存在');
|
|
147
|
-
Logger.info('[计划] 3. 存在则更新,不存在则新增');
|
|
148
|
-
Logger.info('[计划] 4. 处理两层菜单结构(父级和子级)');
|
|
149
|
-
Logger.info('[计划] 5. 显示菜单结构预览');
|
|
150
|
-
return true;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
Logger.info('开始同步菜单配置到数据库...\n');
|
|
154
|
-
|
|
155
|
-
// 初始化数据库连接(Redis + SQL + DbHelper)
|
|
156
|
-
const { helper } = await initDatabase({ max: 1 });
|
|
157
|
-
dbInitialized = true;
|
|
158
|
-
|
|
159
|
-
// 1. 检查表是否存在
|
|
160
|
-
if (!(await checkTableExists(helper, 'addon_admin_menu'))) {
|
|
161
|
-
return false;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
// 2. 收集配置文件中所有菜单的 path
|
|
165
|
-
Logger.info('\n=== 步骤 2: 收集配置菜单路径 ===');
|
|
166
|
-
const configPaths = collectPaths(menuConfig);
|
|
167
|
-
Logger.info(`✅ 配置文件中共有 ${configPaths.size} 个菜单路径`);
|
|
168
|
-
|
|
169
|
-
// 3. 同步菜单(新增和更新)
|
|
170
|
-
Logger.info('\n=== 步骤 3: 同步菜单数据(新增/更新) ===');
|
|
171
|
-
const stats = await syncMenus(helper, menuConfig);
|
|
172
|
-
|
|
173
|
-
// 4. 删除文件中不存在的菜单
|
|
174
|
-
const deletedCount = await deleteObsoleteRecords(helper, 'addon_admin_menu', configPaths);
|
|
175
|
-
|
|
176
|
-
// 5. 构建树形结构预览
|
|
177
|
-
Logger.info('\n=== 步骤 5: 菜单结构预览 ===');
|
|
178
|
-
const allMenus = await helper.getAll({
|
|
179
|
-
table: 'addon_admin_menu',
|
|
180
|
-
fields: ['id', 'pid', 'name', 'path', 'type'],
|
|
181
|
-
orderBy: ['pid#ASC', 'sort#ASC', 'id#ASC']
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
// 6. 输出统计信息
|
|
185
|
-
logSyncStats(stats, deletedCount, '菜单');
|
|
186
|
-
Logger.info(`当前父级菜单: ${allMenus.filter((m: any) => m.pid === 0).length} 个`);
|
|
187
|
-
Logger.info(`当前子级菜单: ${allMenus.filter((m: any) => m.pid !== 0).length} 个`);
|
|
188
|
-
Logger.info('提示: 菜单缓存将在服务器启动时自动完成');
|
|
189
|
-
|
|
190
|
-
return true;
|
|
191
|
-
} catch (error: any) {
|
|
192
|
-
console.log('🔥[ error ]-262', error);
|
|
193
|
-
Logger.error('菜单同步失败:', { message: error.message, stack: error.stack });
|
|
194
|
-
return false;
|
|
195
|
-
} finally {
|
|
196
|
-
if (dbInitialized) {
|
|
197
|
-
await closeDatabase();
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
// 执行同步
|
|
203
|
-
syncMenu()
|
|
204
|
-
.then((success) => {
|
|
205
|
-
process.exit(success ? 0 : 1);
|
|
206
|
-
})
|
|
207
|
-
.catch((error) => {
|
|
208
|
-
Logger.error('执行失败:', error);
|
|
209
|
-
process.exit(1);
|
|
210
|
-
});
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "姓名|string|2|50|null|0|null",
|
|
3
|
-
"nickname": "昵称|string|2|50|null|0|null",
|
|
4
|
-
"email": "邮箱|string|5|100|null|1|^[\\w.-]+@[\\w.-]+\\.\\w+$",
|
|
5
|
-
"phone": "手机号|string|11|11|null|0|^1[3-9]\\d{9}$",
|
|
6
|
-
"username": "用户名|string|3|30|null|0|^[a-zA-Z0-9_]+$",
|
|
7
|
-
"password": "密码|string|6|255|null|0|null",
|
|
8
|
-
"avatar": "头像|string|0|500|null|0|null",
|
|
9
|
-
"roleId": "角色ID|number|1|999999999999999|null|1|null",
|
|
10
|
-
"roleCode": "角色编码|string|2|50|null|0|^[a-zA-Z0-9_]+$",
|
|
11
|
-
"roleType": "角色类型|string|4|5|user|1|^(admin|user)$",
|
|
12
|
-
"lastLoginTime": "最后登录时间|number|0|null|0|0|null",
|
|
13
|
-
"lastLoginIp": "最后登录IP|string|0|50|null|0|null"
|
|
14
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "接口名称|string|2|100|null|1|null",
|
|
3
|
-
"path": "接口路径|string|1|200|null|1|null",
|
|
4
|
-
"method": "请求方法|string|3|10|POST|1|^(GET|POST|PUT|DELETE|PATCH)$",
|
|
5
|
-
"description": "接口描述|string|0|500|null|0|null",
|
|
6
|
-
"addonName": "所属插件|string|0|50|null|0|null",
|
|
7
|
-
"addonTitle": "插件标题|string|0|100|null|0|null"
|
|
8
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "字典名称|string|2|50|null|1|null",
|
|
3
|
-
"code": "字典代码|string|2|50|null|1|^[a-zA-Z0-9_]+$",
|
|
4
|
-
"value": "字典值|string|0|200|null|1|null",
|
|
5
|
-
"sort": "排序|number|0|9999|0|0|null",
|
|
6
|
-
"pid": "父级ID|number|0|999999999999999|0|1|null",
|
|
7
|
-
"description": "描述|string|0|200|null|0|null"
|
|
8
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "角色名称|string|2|50|null|1|null",
|
|
3
|
-
"code": "角色编码|string|2|50|null|1|^[a-zA-Z0-9_]+$",
|
|
4
|
-
"description": "角色描述|string|0|200|null|0|null",
|
|
5
|
-
"menus": "菜单权限|array_text|null|null|null|0|null",
|
|
6
|
-
"apis": "接口权限|array_text|null|null|null|0|null",
|
|
7
|
-
"sort": "排序|number|0|9999|0|0|null"
|
|
8
|
-
}
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Admin 相关的类型定义
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
// 管理员信息
|
|
6
|
-
export interface Admin {
|
|
7
|
-
id: number;
|
|
8
|
-
name: string;
|
|
9
|
-
email: string;
|
|
10
|
-
phone?: string;
|
|
11
|
-
password: string;
|
|
12
|
-
role: 'admin' | 'user';
|
|
13
|
-
state: 0 | 1 | 2; // 0=删除, 1=正常, 2=禁用
|
|
14
|
-
last_login_time?: string;
|
|
15
|
-
last_login_ip?: string;
|
|
16
|
-
created_at?: string;
|
|
17
|
-
updated_at?: string;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
// 登录请求
|
|
21
|
-
export interface LoginRequest {
|
|
22
|
-
email?: string;
|
|
23
|
-
password?: string;
|
|
24
|
-
phone?: string;
|
|
25
|
-
code?: string;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// 登录响应
|
|
29
|
-
export interface LoginResponse {
|
|
30
|
-
token: string;
|
|
31
|
-
userInfo: Omit<Admin, 'password'>;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// 注册请求
|
|
35
|
-
export interface RegisterRequest {
|
|
36
|
-
name: string;
|
|
37
|
-
email: string;
|
|
38
|
-
password: string;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// 发送验证码请求
|
|
42
|
-
export interface SendSmsCodeRequest {
|
|
43
|
-
phone: string;
|
|
44
|
-
}
|