befly 3.24.18 → 3.24.20
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/apis/_apis.js +20 -0
- package/apis/admin/delete.js +3 -1
- package/apis/admin/detail.js +1 -3
- package/apis/admin/select.js +9 -7
- package/apis/admin/update.js +2 -2
- package/apis/api/all.js +6 -11
- package/apis/api/select.js +18 -19
- package/apis/dashboard/environmentInfo.js +6 -1
- package/apis/dashboard/serviceStatus.js +78 -60
- package/apis/dict/_dict.js +24 -0
- package/apis/dict/all.js +6 -4
- package/apis/dict/detail.js +9 -5
- package/apis/dict/insert.js +4 -11
- package/apis/dict/items.js +5 -6
- package/apis/dict/select.js +13 -9
- package/apis/dict/update.js +9 -13
- package/apis/dictType/select.js +4 -4
- package/apis/email/config.js +9 -11
- package/apis/email/logList.js +14 -4
- package/apis/email/send.js +10 -3
- package/apis/email/verify.js +9 -7
- package/apis/loginLog/select.js +11 -4
- package/apis/menu/all.js +13 -19
- package/apis/menu/select.js +19 -14
- package/apis/operateLog/select.js +13 -4
- package/apis/role/_role.js +21 -0
- package/apis/role/all.js +1 -3
- package/apis/role/apiSave.js +8 -15
- package/apis/role/apis.js +4 -10
- package/apis/role/delete.js +28 -36
- package/apis/role/detail.js +4 -10
- package/apis/role/insert.js +12 -10
- package/apis/role/menuSave.js +9 -15
- package/apis/role/menus.js +4 -10
- package/apis/role/save.js +19 -23
- package/apis/role/select.js +12 -9
- package/apis/role/update.js +14 -15
- package/apis/source/imageList.js +3 -3
- package/apis/sysConfig/get.js +11 -23
- package/apis/sysConfig/insert.js +22 -27
- package/apis/sysConfig/select.js +11 -5
- package/apis/sysConfig/update.js +33 -38
- package/apis/tongJi/_tongJi.js +41 -0
- package/apis/tongJi/cacheHealth.js +192 -0
- package/apis/tongJi/errorList.js +26 -27
- package/apis/tongJi/errorReport.js +72 -18
- package/apis/tongJi/errorStats.js +154 -30
- package/apis/tongJi/fallbackReset.js +61 -0
- package/apis/tongJi/infoReport.js +112 -24
- package/apis/tongJi/infoStats.js +164 -84
- package/apis/tongJi/onlineReport.js +58 -73
- package/apis/tongJi/onlineStats.js +140 -151
- package/checks/config.js +44 -1
- package/configs/beflyConfig.json +10 -1
- package/hooks/permission.js +6 -2
- package/hooks/rateLimit.js +245 -0
- package/index.js +25 -0
- package/lib/cacheHelper.js +105 -60
- package/lib/dbHelper.js +1 -1
- package/lib/dbParse.js +61 -99
- package/lib/dbUtil.js +101 -21
- package/lib/redisHelper.js +93 -0
- package/lib/sqlBuilder.js +6 -0
- package/package.json +2 -2
- package/plugins/email.js +4 -3
- package/utils/email.js +3 -0
- package/apis/admin/cacheRefresh.js +0 -122
- package/apis/dashboard/configStatus.js +0 -39
- package/apis/dashboard/performanceMetrics.js +0 -20
- package/apis/dashboard/permissionStats.js +0 -27
- package/apis/dashboard/systemInfo.js +0 -19
package/apis/_apis.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export const queryFields = {
|
|
2
|
+
page: {
|
|
3
|
+
name: "页码",
|
|
4
|
+
input: "integer",
|
|
5
|
+
min: 1,
|
|
6
|
+
max: 10000
|
|
7
|
+
},
|
|
8
|
+
limit: {
|
|
9
|
+
name: "每页数量",
|
|
10
|
+
input: "integer",
|
|
11
|
+
min: 1,
|
|
12
|
+
max: 100
|
|
13
|
+
},
|
|
14
|
+
keyword: {
|
|
15
|
+
name: "关键字",
|
|
16
|
+
input: "string",
|
|
17
|
+
min: 0,
|
|
18
|
+
max: 100
|
|
19
|
+
}
|
|
20
|
+
};
|
package/apis/admin/delete.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
import adminTable from "#root/tables/admin.json";
|
|
2
|
+
|
|
1
3
|
export default {
|
|
2
4
|
name: "删除管理员",
|
|
3
5
|
method: "POST",
|
|
4
6
|
body: "none",
|
|
5
7
|
auth: true,
|
|
6
8
|
fields: {
|
|
7
|
-
id:
|
|
9
|
+
id: adminTable.id
|
|
8
10
|
},
|
|
9
11
|
required: ["id"],
|
|
10
12
|
handler: async (befly, ctx) => {
|
package/apis/admin/detail.js
CHANGED
package/apis/admin/select.js
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
|
+
import { queryFields } from "#root/apis/_apis.js";
|
|
2
|
+
import adminTable from "#root/tables/admin.json";
|
|
3
|
+
|
|
1
4
|
export default {
|
|
2
5
|
name: "查询管理员列表",
|
|
3
6
|
method: "POST",
|
|
4
7
|
body: "none",
|
|
5
8
|
auth: true,
|
|
6
9
|
fields: {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
keyword: { name: "关键词", input: "string", min: 0, max: 50 },
|
|
10
|
-
state: { name: "状态", input: "integer", min: 0, max: 2 }
|
|
10
|
+
...queryFields,
|
|
11
|
+
state: adminTable.state
|
|
11
12
|
},
|
|
12
13
|
required: [],
|
|
13
14
|
handler: async (befly, ctx) => {
|
|
@@ -16,9 +17,10 @@ export default {
|
|
|
16
17
|
page: ctx.body.page,
|
|
17
18
|
limit: ctx.body.limit,
|
|
18
19
|
where: {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
username$like$or: ctx.body.keyword,
|
|
21
|
+
nickname$like$or: ctx.body.keyword,
|
|
22
|
+
state: ctx.body.state,
|
|
23
|
+
roleCode$not: "dev"
|
|
22
24
|
},
|
|
23
25
|
orderBy: ["createdAt#DESC"]
|
|
24
26
|
});
|
package/apis/admin/update.js
CHANGED
|
@@ -34,7 +34,7 @@ export default {
|
|
|
34
34
|
table: "beflyAdmin",
|
|
35
35
|
where: {
|
|
36
36
|
username: ctx.body.username,
|
|
37
|
-
id
|
|
37
|
+
id$not: ctx.body.id
|
|
38
38
|
}
|
|
39
39
|
});
|
|
40
40
|
|
|
@@ -48,7 +48,7 @@ export default {
|
|
|
48
48
|
table: "beflyAdmin",
|
|
49
49
|
where: {
|
|
50
50
|
nickname: ctx.body.nickname,
|
|
51
|
-
id
|
|
51
|
+
id$not: ctx.body.id
|
|
52
52
|
}
|
|
53
53
|
});
|
|
54
54
|
|
package/apis/api/all.js
CHANGED
|
@@ -6,19 +6,14 @@ export default {
|
|
|
6
6
|
fields: {},
|
|
7
7
|
required: [],
|
|
8
8
|
handler: async (befly) => {
|
|
9
|
-
|
|
10
|
-
const allApis = await befly.cache.getApis();
|
|
9
|
+
const allApis = await befly.cache.getApis();
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
if (allApis.length === 0) {
|
|
12
|
+
return befly.tool.No("接口缓存不存在,请刷新缓存", { lists: [] });
|
|
13
|
+
}
|
|
15
14
|
|
|
16
|
-
|
|
15
|
+
const lists = allApis.filter((api) => api && typeof api === "object");
|
|
17
16
|
|
|
18
|
-
|
|
19
|
-
} catch (error) {
|
|
20
|
-
befly.logger.error("获取接口列表失败", error);
|
|
21
|
-
return befly.tool.No("获取接口列表失败");
|
|
22
|
-
}
|
|
17
|
+
return befly.tool.Yes("操作成功", { lists: lists });
|
|
23
18
|
}
|
|
24
19
|
};
|
package/apis/api/select.js
CHANGED
|
@@ -1,31 +1,30 @@
|
|
|
1
|
+
import { queryFields } from "#root/apis/_apis.js";
|
|
2
|
+
import apiTable from "#root/tables/api.json";
|
|
3
|
+
|
|
1
4
|
export default {
|
|
2
5
|
name: "获取接口列表",
|
|
3
6
|
method: "POST",
|
|
4
7
|
body: "none",
|
|
5
8
|
auth: true,
|
|
6
9
|
fields: {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
keyword: { name: "关键词", input: "string", min: 0, max: 50 },
|
|
10
|
-
state: { name: "状态", input: "integer", min: 0, max: 2 }
|
|
10
|
+
...queryFields,
|
|
11
|
+
state: apiTable.state
|
|
11
12
|
},
|
|
12
13
|
required: [],
|
|
13
14
|
handler: async (befly, ctx) => {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
15
|
+
const result = await befly.mysql.getList({
|
|
16
|
+
table: "beflyApi",
|
|
17
|
+
where: {
|
|
18
|
+
name$like$or: ctx.body.keyword,
|
|
19
|
+
path$like$or: ctx.body.keyword,
|
|
20
|
+
parentPath$like$or: ctx.body.keyword,
|
|
21
|
+
state: ctx.body.state
|
|
22
|
+
},
|
|
23
|
+
orderBy: ["id#ASC"],
|
|
24
|
+
page: ctx.body.page,
|
|
25
|
+
limit: ctx.body.limit
|
|
26
|
+
});
|
|
24
27
|
|
|
25
|
-
|
|
26
|
-
} catch (error) {
|
|
27
|
-
befly.logger.error("获取接口列表失败", error);
|
|
28
|
-
return befly.tool.No("获取接口列表失败");
|
|
29
|
-
}
|
|
28
|
+
return befly.tool.Yes("操作成功", result.data);
|
|
30
29
|
}
|
|
31
30
|
};
|
|
@@ -10,6 +10,10 @@ export default {
|
|
|
10
10
|
fields: {},
|
|
11
11
|
required: [],
|
|
12
12
|
handler: async (befly) => {
|
|
13
|
+
const isBunRuntime = typeof Bun !== "undefined";
|
|
14
|
+
const runtimeVersion = isBunRuntime ? `Bun ${Bun.version}` : `Node.js ${process.version}`;
|
|
15
|
+
const nodeCompatVersion = process.version;
|
|
16
|
+
|
|
13
17
|
let databaseVersion = "Unknown";
|
|
14
18
|
try {
|
|
15
19
|
const versionResult = await befly.mysql.execute("SELECT VERSION() as version");
|
|
@@ -35,7 +39,8 @@ export default {
|
|
|
35
39
|
return befly.tool.Yes("获取成功", {
|
|
36
40
|
os: `${os.type()} ${os.arch()}`,
|
|
37
41
|
server: `${os.platform()} ${os.release()}`,
|
|
38
|
-
|
|
42
|
+
runtimeVersion: runtimeVersion,
|
|
43
|
+
nodeVersion: nodeCompatVersion,
|
|
39
44
|
database: `MySQL ${databaseVersion}`,
|
|
40
45
|
cache: `Redis ${redisVersion}`,
|
|
41
46
|
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone
|
|
@@ -1,3 +1,72 @@
|
|
|
1
|
+
import cacheHealthApi from "#root/apis/tongJi/cacheHealth.js";
|
|
2
|
+
|
|
3
|
+
function isEmailConfigured(emailConfig) {
|
|
4
|
+
if (!emailConfig || typeof emailConfig !== "object") {
|
|
5
|
+
return false;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
return Boolean(String(emailConfig.host || "").trim() && String(emailConfig.user || "").trim() && String(emailConfig.pass || "").trim());
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function buildServiceItem(name, status, responseTime) {
|
|
12
|
+
return {
|
|
13
|
+
name: name,
|
|
14
|
+
status: status,
|
|
15
|
+
responseTime: responseTime
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
async function probeMysqlService(befly) {
|
|
20
|
+
try {
|
|
21
|
+
const startTime = Date.now();
|
|
22
|
+
await befly.mysql.execute("SELECT 1");
|
|
23
|
+
const responseTime = Date.now() - startTime;
|
|
24
|
+
return buildServiceItem("数据库", "running", `${responseTime}ms`);
|
|
25
|
+
} catch (error) {
|
|
26
|
+
befly.logger.error("数据库状态检测失败", error);
|
|
27
|
+
return buildServiceItem("数据库", "stopped", "-");
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async function probeRedisService(befly) {
|
|
32
|
+
if (!befly.redis) {
|
|
33
|
+
return buildServiceItem("Redis", "stopped", "-");
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
try {
|
|
37
|
+
const startTime = Date.now();
|
|
38
|
+
await befly.redis.ping();
|
|
39
|
+
const responseTime = Date.now() - startTime;
|
|
40
|
+
return buildServiceItem("Redis", "running", `${responseTime}ms`);
|
|
41
|
+
} catch (error) {
|
|
42
|
+
befly.logger.error("Redis状态检测失败", error);
|
|
43
|
+
return buildServiceItem("Redis", "stopped", "-");
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function buildStaticServices(befly) {
|
|
48
|
+
return [buildServiceItem("文件系统", "running", "-"), buildServiceItem("邮件服务", isEmailConfigured(befly.config?.email) ? "running" : "unconfigured", "-"), buildServiceItem("OSS存储", "unconfigured", "-")];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function buildCacheHealthSummary(cacheHealthData) {
|
|
52
|
+
if (!cacheHealthData) {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return {
|
|
57
|
+
redisStatus: cacheHealthData.redis?.status || "unknown",
|
|
58
|
+
onlineReady: Boolean(cacheHealthData.online?.ready),
|
|
59
|
+
infoReady: Boolean(cacheHealthData.info?.ready),
|
|
60
|
+
errorReady: Boolean(cacheHealthData.error?.ready),
|
|
61
|
+
roleApisReady: Boolean(cacheHealthData.roleCache?.apis?.ready),
|
|
62
|
+
roleMenusReady: Boolean(cacheHealthData.roleCache?.menus?.ready),
|
|
63
|
+
infoFallbackCount: Number(cacheHealthData.fallback?.infoStats || 0),
|
|
64
|
+
errorFallbackCount: Number(cacheHealthData.fallback?.errorStats || 0),
|
|
65
|
+
infoFallbackTodayCount: Number(cacheHealthData.fallback?.today?.infoStats || 0),
|
|
66
|
+
errorFallbackTodayCount: Number(cacheHealthData.fallback?.today?.errorStats || 0)
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
1
70
|
export default {
|
|
2
71
|
name: "获取服务状态",
|
|
3
72
|
method: "POST",
|
|
@@ -6,70 +75,19 @@ export default {
|
|
|
6
75
|
fields: {},
|
|
7
76
|
required: [],
|
|
8
77
|
handler: async (befly) => {
|
|
9
|
-
const services = [];
|
|
78
|
+
const services = [await probeMysqlService(befly), await probeRedisService(befly), ...buildStaticServices(befly)];
|
|
79
|
+
|
|
80
|
+
let cacheHealthSummary = null;
|
|
10
81
|
|
|
11
82
|
try {
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
const responseTime = Date.now() - startTime;
|
|
15
|
-
services.push({
|
|
16
|
-
name: "数据库",
|
|
17
|
-
status: "running",
|
|
18
|
-
responseTime: `${responseTime}ms`
|
|
19
|
-
});
|
|
20
|
-
} catch (error) {
|
|
21
|
-
befly.logger.error("数据库状态检测失败", error);
|
|
22
|
-
services.push({
|
|
23
|
-
name: "数据库",
|
|
24
|
-
status: "stopped",
|
|
25
|
-
responseTime: "-"
|
|
26
|
-
});
|
|
27
|
-
}
|
|
83
|
+
const cacheHealthResult = await cacheHealthApi.handler(befly);
|
|
84
|
+
const cacheHealthData = cacheHealthResult?.data || null;
|
|
28
85
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
await befly.redis.ping();
|
|
33
|
-
const responseTime = Date.now() - startTime;
|
|
34
|
-
services.push({
|
|
35
|
-
name: "Redis",
|
|
36
|
-
status: "running",
|
|
37
|
-
responseTime: `${responseTime}ms`
|
|
38
|
-
});
|
|
39
|
-
} catch (error) {
|
|
40
|
-
befly.logger.error("Redis状态检测失败", error);
|
|
41
|
-
services.push({
|
|
42
|
-
name: "Redis",
|
|
43
|
-
status: "stopped",
|
|
44
|
-
responseTime: "-"
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
} else {
|
|
48
|
-
services.push({
|
|
49
|
-
name: "Redis",
|
|
50
|
-
status: "stopped",
|
|
51
|
-
responseTime: "-"
|
|
52
|
-
});
|
|
86
|
+
cacheHealthSummary = buildCacheHealthSummary(cacheHealthData);
|
|
87
|
+
} catch (error) {
|
|
88
|
+
befly.logger.error("缓存健康状态聚合失败", error);
|
|
53
89
|
}
|
|
54
90
|
|
|
55
|
-
|
|
56
|
-
name: "文件系统",
|
|
57
|
-
status: "running",
|
|
58
|
-
responseTime: "-"
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
services.push({
|
|
62
|
-
name: "邮件服务",
|
|
63
|
-
status: "unconfigured",
|
|
64
|
-
responseTime: "-"
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
services.push({
|
|
68
|
-
name: "OSS存储",
|
|
69
|
-
status: "unconfigured",
|
|
70
|
-
responseTime: "-"
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
return befly.tool.Yes("获取成功", { services: services });
|
|
91
|
+
return befly.tool.Yes("获取成功", { services: services, cacheHealth: cacheHealthSummary });
|
|
74
92
|
}
|
|
75
93
|
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export const dictReadTable = ["beflyDict", "beflyDictType"];
|
|
2
|
+
export const dictReadLeftJoin = ["beflyDict.typeCode beflyDictType.code"];
|
|
3
|
+
export const dictReadFields = ["beflyDict.id", "beflyDict.typeCode", "beflyDict.key", "beflyDict.label", "beflyDict.sort", "beflyDict.remark", "beflyDict.createdAt", "beflyDict.updatedAt", "beflyDictType.name typeName"];
|
|
4
|
+
export const dictReadOrderBy = ["beflyDict.sort#ASC", "beflyDict.id#ASC"];
|
|
5
|
+
|
|
6
|
+
export async function getDictTypeByCode(befly, typeCode) {
|
|
7
|
+
return await befly.mysql.getOne({
|
|
8
|
+
table: "beflyDictType",
|
|
9
|
+
where: {
|
|
10
|
+
code: typeCode
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export async function getDictByTypeCodeAndKey(befly, typeCode, key, dictId = undefined) {
|
|
16
|
+
return await befly.mysql.getOne({
|
|
17
|
+
table: "beflyDict",
|
|
18
|
+
where: {
|
|
19
|
+
typeCode: typeCode,
|
|
20
|
+
key: key,
|
|
21
|
+
id$not: dictId
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
}
|
package/apis/dict/all.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import dictTable from "#root/tables/dict.json";
|
|
2
|
+
|
|
3
|
+
import { dictReadFields, dictReadLeftJoin, dictReadOrderBy, dictReadTable } from "./_dict.js";
|
|
2
4
|
export default {
|
|
3
5
|
name: "获取所有字典",
|
|
4
6
|
method: "POST",
|
|
@@ -10,10 +12,10 @@ export default {
|
|
|
10
12
|
required: [],
|
|
11
13
|
handler: async (befly) => {
|
|
12
14
|
const result = await befly.mysql.getAll({
|
|
13
|
-
table:
|
|
14
|
-
leftJoin:
|
|
15
|
-
fields:
|
|
16
|
-
orderBy:
|
|
15
|
+
table: dictReadTable,
|
|
16
|
+
leftJoin: dictReadLeftJoin,
|
|
17
|
+
fields: dictReadFields,
|
|
18
|
+
orderBy: dictReadOrderBy
|
|
17
19
|
});
|
|
18
20
|
|
|
19
21
|
return befly.tool.Yes("获取成功", result.data);
|
package/apis/dict/detail.js
CHANGED
|
@@ -1,21 +1,25 @@
|
|
|
1
|
+
import dictTable from "#root/tables/dict.json";
|
|
2
|
+
|
|
3
|
+
import { dictReadFields, dictReadLeftJoin, dictReadTable } from "./_dict.js";
|
|
4
|
+
|
|
1
5
|
export default {
|
|
2
6
|
name: "获取字典详情",
|
|
3
7
|
method: "POST",
|
|
4
8
|
body: "none",
|
|
5
9
|
auth: false,
|
|
6
10
|
fields: {
|
|
7
|
-
id:
|
|
11
|
+
id: dictTable.id
|
|
8
12
|
},
|
|
9
13
|
required: ["id"],
|
|
10
14
|
handler: async (befly, ctx) => {
|
|
11
15
|
const dict = await befly.mysql.getOne({
|
|
12
|
-
table:
|
|
13
|
-
leftJoin:
|
|
14
|
-
fields:
|
|
16
|
+
table: dictReadTable,
|
|
17
|
+
leftJoin: dictReadLeftJoin,
|
|
18
|
+
fields: dictReadFields,
|
|
15
19
|
where: { "beflyDict.id": ctx.body.id }
|
|
16
20
|
});
|
|
17
21
|
|
|
18
|
-
if (!dict.data
|
|
22
|
+
if (!dict.data?.id) {
|
|
19
23
|
return befly.tool.No("字典项不存在");
|
|
20
24
|
}
|
|
21
25
|
|
package/apis/dict/insert.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import dictTable from "#root/tables/dict.json";
|
|
2
2
|
|
|
3
|
+
import { getDictByTypeCodeAndKey, getDictTypeByCode } from "./_dict.js";
|
|
4
|
+
|
|
3
5
|
export default {
|
|
4
6
|
name: "添加字典",
|
|
5
7
|
method: "POST",
|
|
@@ -14,22 +16,13 @@ export default {
|
|
|
14
16
|
},
|
|
15
17
|
required: ["typeCode", "key", "label"],
|
|
16
18
|
handler: async (befly, ctx) => {
|
|
17
|
-
const dictType = await befly.
|
|
18
|
-
table: "beflyDictType",
|
|
19
|
-
where: { code: ctx.body.typeCode }
|
|
20
|
-
});
|
|
19
|
+
const dictType = await getDictTypeByCode(befly, ctx.body.typeCode);
|
|
21
20
|
|
|
22
21
|
if (!dictType.data?.id) {
|
|
23
22
|
return befly.tool.No("字典类型不存在");
|
|
24
23
|
}
|
|
25
24
|
|
|
26
|
-
const existing = await befly.
|
|
27
|
-
table: "beflyDict",
|
|
28
|
-
where: {
|
|
29
|
-
typeCode: ctx.body.typeCode,
|
|
30
|
-
key: ctx.body.key
|
|
31
|
-
}
|
|
32
|
-
});
|
|
25
|
+
const existing = await getDictByTypeCodeAndKey(befly, ctx.body.typeCode, ctx.body.key);
|
|
33
26
|
|
|
34
27
|
if (existing.data?.id) {
|
|
35
28
|
return befly.tool.No("该类型下已存在相同的键名");
|
package/apis/dict/items.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import dictTable from "#root/tables/dict.json";
|
|
2
2
|
|
|
3
|
+
import { dictReadOrderBy, getDictTypeByCode } from "./_dict.js";
|
|
4
|
+
|
|
3
5
|
export default {
|
|
4
6
|
name: "获取字典项列表",
|
|
5
7
|
method: "POST",
|
|
@@ -10,19 +12,16 @@ export default {
|
|
|
10
12
|
},
|
|
11
13
|
required: ["typeCode"],
|
|
12
14
|
handler: async (befly, ctx) => {
|
|
13
|
-
const dictType = await befly.
|
|
14
|
-
table: "beflyDictType",
|
|
15
|
-
where: { code: ctx.body.typeCode }
|
|
16
|
-
});
|
|
15
|
+
const dictType = await getDictTypeByCode(befly, ctx.body.typeCode);
|
|
17
16
|
|
|
18
|
-
if (!dictType.data
|
|
17
|
+
if (!dictType.data?.id) {
|
|
19
18
|
return befly.tool.No("字典类型不存在");
|
|
20
19
|
}
|
|
21
20
|
|
|
22
21
|
const items = await befly.mysql.getAll({
|
|
23
22
|
table: "beflyDict",
|
|
24
23
|
where: { typeCode: ctx.body.typeCode },
|
|
25
|
-
orderBy:
|
|
24
|
+
orderBy: dictReadOrderBy
|
|
26
25
|
});
|
|
27
26
|
|
|
28
27
|
return befly.tool.Yes("获取成功", items.data);
|
package/apis/dict/select.js
CHANGED
|
@@ -1,28 +1,32 @@
|
|
|
1
|
+
import { queryFields } from "#root/apis/_apis.js";
|
|
1
2
|
import dictTable from "#root/tables/dict.json";
|
|
2
3
|
|
|
4
|
+
import { dictReadFields, dictReadLeftJoin, dictReadOrderBy, dictReadTable } from "./_dict.js";
|
|
5
|
+
|
|
3
6
|
export default {
|
|
4
7
|
name: "获取字典列表",
|
|
5
8
|
method: "POST",
|
|
6
9
|
body: "none",
|
|
7
10
|
auth: false,
|
|
8
11
|
fields: {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
typeCode: dictTable.typeCode,
|
|
12
|
-
keyword: { name: "关键词", input: "string", min: 0, max: 50 }
|
|
12
|
+
...queryFields,
|
|
13
|
+
typeCode: dictTable.typeCode
|
|
13
14
|
},
|
|
14
15
|
required: [],
|
|
15
16
|
handler: async (befly, ctx) => {
|
|
16
17
|
const result = await befly.mysql.getList({
|
|
17
|
-
table:
|
|
18
|
-
leftJoin:
|
|
19
|
-
fields:
|
|
18
|
+
table: dictReadTable,
|
|
19
|
+
leftJoin: dictReadLeftJoin,
|
|
20
|
+
fields: dictReadFields,
|
|
20
21
|
where: {
|
|
21
|
-
"beflyDict.typeCode": ctx.body.typeCode
|
|
22
|
+
"beflyDict.typeCode": ctx.body.typeCode,
|
|
23
|
+
"beflyDict.key$like$or": ctx.body.keyword,
|
|
24
|
+
"beflyDict.label$like$or": ctx.body.keyword,
|
|
25
|
+
"beflyDict.remark$like$or": ctx.body.keyword
|
|
22
26
|
},
|
|
23
27
|
page: ctx.body.page,
|
|
24
28
|
limit: ctx.body.limit,
|
|
25
|
-
orderBy:
|
|
29
|
+
orderBy: dictReadOrderBy
|
|
26
30
|
});
|
|
27
31
|
|
|
28
32
|
return befly.tool.Yes("获取成功", result.data);
|
package/apis/dict/update.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import dictTable from "#root/tables/dict.json";
|
|
2
2
|
|
|
3
|
+
import { getDictByTypeCodeAndKey, getDictTypeByCode } from "./_dict.js";
|
|
4
|
+
|
|
3
5
|
export default {
|
|
4
6
|
name: "更新字典",
|
|
5
7
|
method: "POST",
|
|
6
8
|
body: "none",
|
|
7
9
|
auth: true,
|
|
8
10
|
fields: {
|
|
9
|
-
id:
|
|
11
|
+
id: dictTable.id,
|
|
10
12
|
typeCode: dictTable.typeCode,
|
|
11
13
|
key: dictTable.key,
|
|
12
14
|
label: dictTable.label,
|
|
@@ -16,10 +18,7 @@ export default {
|
|
|
16
18
|
required: ["id"],
|
|
17
19
|
handler: async (befly, ctx) => {
|
|
18
20
|
if (ctx.body.typeCode !== undefined) {
|
|
19
|
-
const dictType = await befly.
|
|
20
|
-
table: "beflyDictType",
|
|
21
|
-
where: { code: ctx.body.typeCode }
|
|
22
|
-
});
|
|
21
|
+
const dictType = await getDictTypeByCode(befly, ctx.body.typeCode);
|
|
23
22
|
|
|
24
23
|
if (!dictType.data?.id) {
|
|
25
24
|
return befly.tool.No("字典类型不存在");
|
|
@@ -32,14 +31,11 @@ export default {
|
|
|
32
31
|
where: { id: ctx.body.id }
|
|
33
32
|
});
|
|
34
33
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
id$not: ctx.body.id
|
|
41
|
-
}
|
|
42
|
-
});
|
|
34
|
+
if (!current.data?.id) {
|
|
35
|
+
return befly.tool.No("字典项不存在");
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const existing = await getDictByTypeCodeAndKey(befly, ctx.body.typeCode !== undefined ? ctx.body.typeCode : current.data.typeCode, ctx.body.key !== undefined ? ctx.body.key : current.data.key, ctx.body.id);
|
|
43
39
|
|
|
44
40
|
if (existing.data?.id) {
|
|
45
41
|
return befly.tool.No("该类型下已存在相同的键名");
|
package/apis/dictType/select.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { queryFields } from "#root/apis/_apis.js";
|
|
1
2
|
import dictTypeTable from "#root/tables/dictType.json";
|
|
2
3
|
|
|
3
4
|
export default {
|
|
@@ -6,9 +7,7 @@ export default {
|
|
|
6
7
|
body: "none",
|
|
7
8
|
auth: true,
|
|
8
9
|
fields: {
|
|
9
|
-
|
|
10
|
-
limit: { name: "每页数量", input: "integer", min: 1, max: 100 },
|
|
11
|
-
keyword: { name: "关键词", input: "string", min: 0, max: 50 },
|
|
10
|
+
...queryFields,
|
|
12
11
|
state: dictTypeTable.state
|
|
13
12
|
},
|
|
14
13
|
required: [],
|
|
@@ -16,7 +15,8 @@ export default {
|
|
|
16
15
|
const result = await befly.mysql.getList({
|
|
17
16
|
table: "beflyDictType",
|
|
18
17
|
where: {
|
|
19
|
-
|
|
18
|
+
name$like$or: ctx.body.keyword,
|
|
19
|
+
code$like$or: ctx.body.keyword,
|
|
20
20
|
state: ctx.body.state
|
|
21
21
|
},
|
|
22
22
|
orderBy: ["sort#ASC", "id#ASC"],
|
package/apis/email/config.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { hasEmailConfig } from "#root/utils/email.js";
|
|
2
|
+
|
|
1
3
|
export default {
|
|
2
4
|
name: "获取邮件配置",
|
|
3
5
|
method: "POST",
|
|
@@ -6,20 +8,16 @@ export default {
|
|
|
6
8
|
fields: {},
|
|
7
9
|
required: [],
|
|
8
10
|
handler: async (befly) => {
|
|
9
|
-
|
|
10
|
-
return befly.tool.No("邮件插件未加载,请检查配置");
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const config = befly.email.getConfig();
|
|
11
|
+
const config = befly?.config?.email || {};
|
|
14
12
|
|
|
15
13
|
return befly.tool.Yes("获取成功", {
|
|
16
|
-
host: config.host,
|
|
17
|
-
port: config.port,
|
|
14
|
+
host: config.host || "",
|
|
15
|
+
port: config.port || 0,
|
|
18
16
|
secure: config.secure,
|
|
19
|
-
user: config.user,
|
|
20
|
-
pass: config.pass,
|
|
21
|
-
|
|
22
|
-
configured:
|
|
17
|
+
user: config.user || "",
|
|
18
|
+
pass: config.pass || "",
|
|
19
|
+
label: config.label || "",
|
|
20
|
+
configured: hasEmailConfig(config)
|
|
23
21
|
});
|
|
24
22
|
}
|
|
25
23
|
};
|