befly 3.24.19 → 3.25.0

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.
Files changed (68) hide show
  1. package/apis/_apis.js +20 -0
  2. package/apis/admin/delete.js +3 -1
  3. package/apis/admin/detail.js +1 -3
  4. package/apis/admin/select.js +9 -7
  5. package/apis/admin/update.js +2 -2
  6. package/apis/api/all.js +6 -11
  7. package/apis/api/select.js +18 -19
  8. package/apis/dict/_dict.js +24 -0
  9. package/apis/dict/all.js +6 -4
  10. package/apis/dict/detail.js +9 -5
  11. package/apis/dict/insert.js +4 -11
  12. package/apis/dict/items.js +5 -6
  13. package/apis/dict/select.js +13 -9
  14. package/apis/dict/update.js +9 -13
  15. package/apis/dictType/select.js +4 -4
  16. package/apis/email/config.js +9 -11
  17. package/apis/email/logList.js +14 -4
  18. package/apis/email/send.js +10 -3
  19. package/apis/email/verify.js +9 -7
  20. package/apis/loginLog/select.js +11 -4
  21. package/apis/menu/all.js +13 -19
  22. package/apis/menu/select.js +19 -14
  23. package/apis/operateLog/select.js +13 -4
  24. package/apis/role/_role.js +21 -0
  25. package/apis/role/all.js +1 -3
  26. package/apis/role/apiSave.js +8 -15
  27. package/apis/role/apis.js +4 -10
  28. package/apis/role/delete.js +28 -36
  29. package/apis/role/detail.js +4 -10
  30. package/apis/role/insert.js +12 -10
  31. package/apis/role/menuSave.js +9 -15
  32. package/apis/role/menus.js +4 -10
  33. package/apis/role/save.js +19 -23
  34. package/apis/role/select.js +12 -9
  35. package/apis/role/update.js +14 -15
  36. package/apis/source/imageList.js +3 -3
  37. package/apis/sysConfig/get.js +11 -23
  38. package/apis/sysConfig/insert.js +22 -27
  39. package/apis/sysConfig/select.js +11 -5
  40. package/apis/sysConfig/update.js +33 -38
  41. package/apis/tongJi/_tongJi.js +41 -0
  42. package/apis/tongJi/cacheHealth.js +8 -30
  43. package/apis/tongJi/errorList.js +26 -27
  44. package/apis/tongJi/errorReport.js +26 -43
  45. package/apis/tongJi/errorStats.js +17 -48
  46. package/apis/tongJi/fallbackReset.js +7 -15
  47. package/apis/tongJi/infoReport.js +20 -32
  48. package/apis/tongJi/infoStats.js +5 -17
  49. package/apis/tongJi/onlineReport.js +50 -56
  50. package/apis/tongJi/onlineStats.js +97 -111
  51. package/checks/config.js +44 -1
  52. package/configs/beflyConfig.json +10 -1
  53. package/index.js +25 -0
  54. package/lib/dbHelper.js +1 -1
  55. package/lib/dbParse.js +61 -99
  56. package/lib/dbUtil.js +101 -21
  57. package/lib/redisHelper.js +25 -0
  58. package/lib/sqlBuilder.js +6 -0
  59. package/package.json +1 -1
  60. package/plugins/email.js +3 -6
  61. package/router/api.js +0 -7
  62. package/utils/email.js +3 -0
  63. package/apis/admin/cacheRefresh.js +0 -122
  64. package/apis/dashboard/configStatus.js +0 -39
  65. package/apis/dashboard/performanceMetrics.js +0 -23
  66. package/apis/dashboard/permissionStats.js +0 -27
  67. package/apis/dashboard/systemInfo.js +0 -19
  68. package/lib/requestMetrics.js +0 -203
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
+ };
@@ -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: { name: "ID", input: "integer", min: 1, max: null }
9
+ id: adminTable.id
8
10
  },
9
11
  required: ["id"],
10
12
  handler: async (befly, ctx) => {
@@ -3,9 +3,7 @@ export default {
3
3
  method: "POST",
4
4
  body: "none",
5
5
  auth: true,
6
- fields: {
7
- id: { name: "ID", input: "integer", min: 1, max: null }
8
- },
6
+ fields: {},
9
7
  required: [],
10
8
  handler: async (befly, ctx) => {
11
9
  const adminData = await befly.mysql.getOne({
@@ -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
- page: { name: "页码", input: "integer", min: 1, max: 9999 },
8
- limit: { name: "每页数量", input: "integer", min: 1, max: 100 },
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
- roleCode: {
20
- $not: "dev"
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
  });
@@ -34,7 +34,7 @@ export default {
34
34
  table: "beflyAdmin",
35
35
  where: {
36
36
  username: ctx.body.username,
37
- id: { $not: ctx.body.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: { $not: ctx.body.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
- try {
10
- const allApis = await befly.cache.getApis();
9
+ const allApis = await befly.cache.getApis();
11
10
 
12
- if (allApis.length === 0) {
13
- return befly.tool.No("接口缓存不存在,请刷新缓存", { lists: [] });
14
- }
11
+ if (allApis.length === 0) {
12
+ return befly.tool.No("接口缓存不存在,请刷新缓存", { lists: [] });
13
+ }
15
14
 
16
- const lists = allApis.filter((api) => api && typeof api === "object");
15
+ const lists = allApis.filter((api) => api && typeof api === "object");
17
16
 
18
- return befly.tool.Yes("操作成功", { lists: lists });
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
  };
@@ -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
- page: { name: "页码", input: "integer", min: 1, max: 9999 },
8
- limit: { name: "每页数量", input: "integer", min: 1, max: 100 },
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
- try {
15
- const result = await befly.mysql.getList({
16
- table: "beflyApi",
17
- where: {
18
- $or: [{ name$like: ctx.body.keyword }, { path$like: ctx.body.keyword }]
19
- },
20
- orderBy: ["id#ASC"],
21
- page: ctx.body.page,
22
- limit: ctx.body.limit
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
- return befly.tool.Yes("操作成功", result.data);
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
  };
@@ -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: ["beflyDict", "beflyDictType"],
14
- leftJoin: ["beflyDict.typeCode beflyDictType.code"],
15
- fields: ["beflyDict.id", "beflyDict.typeCode", "beflyDict.key", "beflyDict.label", "beflyDict.sort", "beflyDict.remark", "beflyDict.createdAt", "beflyDict.updatedAt", "beflyDictType.name typeName"],
16
- orderBy: ["beflyDict.sort#ASC", "beflyDict.id#ASC"]
15
+ table: dictReadTable,
16
+ leftJoin: dictReadLeftJoin,
17
+ fields: dictReadFields,
18
+ orderBy: dictReadOrderBy
17
19
  });
18
20
 
19
21
  return befly.tool.Yes("获取成功", result.data);
@@ -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: { name: "ID", input: "integer", min: 1, max: null }
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: ["beflyDict", "beflyDictType"],
13
- leftJoin: ["beflyDict.typeCode beflyDictType.code"],
14
- fields: ["beflyDict.id", "beflyDict.typeCode", "beflyDict.key", "beflyDict.label", "beflyDict.sort", "beflyDict.remark", "beflyDict.createdAt", "beflyDict.updatedAt", "beflyDictType.name typeName"],
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 || !dict.data.id) {
22
+ if (!dict.data?.id) {
19
23
  return befly.tool.No("字典项不存在");
20
24
  }
21
25
 
@@ -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.mysql.getOne({
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.mysql.getOne({
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("该类型下已存在相同的键名");
@@ -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.mysql.getOne({
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 || !dictType.data.id) {
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: ["sort#ASC", "id#ASC"]
24
+ orderBy: dictReadOrderBy
26
25
  });
27
26
 
28
27
  return befly.tool.Yes("获取成功", items.data);
@@ -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
- page: { name: "页码", input: "integer", min: 1, max: 9999 },
10
- limit: { name: "每页数量", input: "integer", min: 1, max: 100 },
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: ["beflyDict", "beflyDictType"],
18
- leftJoin: ["beflyDict.typeCode beflyDictType.code"],
19
- fields: ["beflyDict.id", "beflyDict.typeCode", "beflyDict.key", "beflyDict.label", "beflyDict.sort", "beflyDict.remark", "beflyDict.createdAt", "beflyDict.updatedAt", "beflyDictType.name typeName"],
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: ["beflyDict.sort#ASC", "beflyDict.id#ASC"]
29
+ orderBy: dictReadOrderBy
26
30
  });
27
31
 
28
32
  return befly.tool.Yes("获取成功", result.data);
@@ -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: { name: "ID", input: "integer", min: 1, max: null },
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.mysql.getOne({
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
- const existing = await befly.mysql.getOne({
36
- table: "beflyDict",
37
- where: {
38
- typeCode: ctx.body.typeCode !== undefined ? ctx.body.typeCode : current.data?.typeCode,
39
- key: ctx.body.key !== undefined ? ctx.body.key : current.data?.key,
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("该类型下已存在相同的键名");
@@ -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
- page: { name: "页码", input: "integer", min: 1, max: 9999 },
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
- $or: [{ name$like: ctx.body.keyword }, { code$like: ctx.body.keyword }],
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"],
@@ -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
- if (!befly.email) {
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
- fromName: config.fromName,
22
- configured: Boolean(config.user)
17
+ user: config.user || "",
18
+ pass: config.pass || "",
19
+ label: config.label || "",
20
+ configured: hasEmailConfig(config)
23
21
  });
24
22
  }
25
23
  };
@@ -1,13 +1,14 @@
1
+ import { queryFields } from "#root/apis/_apis.js";
2
+ import emailLogTable from "#root/tables/emailLog.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
- page: { name: "页码", input: "integer", min: 1, max: 9999 },
8
- limit: { name: "每页数量", input: "integer", min: 1, max: 100 },
9
- keyword: { name: "关键词", input: "string", min: 0, max: 50 },
10
- state: { name: "状态", input: "integer", min: 0, max: 2 }
10
+ ...queryFields,
11
+ state: emailLogTable.state
11
12
  },
12
13
  required: [],
13
14
  handler: async (befly, ctx) => {
@@ -15,6 +16,15 @@ export default {
15
16
  table: "beflyEmailLog",
16
17
  page: ctx.body.page,
17
18
  limit: ctx.body.limit,
19
+ where: {
20
+ username$like$or: ctx.body.keyword,
21
+ nickname$like$or: ctx.body.keyword,
22
+ toEmail$like$or: ctx.body.keyword,
23
+ subject$like$or: ctx.body.keyword,
24
+ failReason$like$or: ctx.body.keyword,
25
+ messageId$like$or: ctx.body.keyword,
26
+ state: ctx.body.state
27
+ },
18
28
  orderBy: ["sendTime#DESC"]
19
29
  });
20
30
 
@@ -1,4 +1,5 @@
1
1
  import emailLogTable from "#root/tables/emailLog.json";
2
+ import { hasEmailConfig } from "#root/utils/email.js";
2
3
 
3
4
  export default {
4
5
  name: "发送邮件",
@@ -20,6 +21,12 @@ export default {
20
21
  },
21
22
  required: ["to", "subject", "content"],
22
23
  handler: async (befly, ctx) => {
24
+ const emailConfig = befly.config.email || {};
25
+
26
+ if (!hasEmailConfig(emailConfig)) {
27
+ return befly.tool.No("邮件未配置,请检查 SMTP 配置");
28
+ }
29
+
23
30
  if (!befly.email) {
24
31
  return befly.tool.No("邮件插件未加载,请检查配置");
25
32
  }
@@ -31,15 +38,15 @@ export default {
31
38
  subject: ctx.body.subject,
32
39
  html: ctx.body.isHtml ? ctx.body.content : undefined,
33
40
  text: ctx.body.isHtml ? undefined : ctx.body.content,
34
- cc: ctx.body.cc || undefined,
35
- bcc: ctx.body.bcc || undefined
41
+ cc: ctx.body.cc,
42
+ bcc: ctx.body.bcc
36
43
  });
37
44
 
38
45
  try {
39
46
  await befly.mysql.insData({
40
47
  table: "beflyEmailLog",
41
48
  data: {
42
- adminId: ctx.userId || 0,
49
+ adminId: ctx.userId,
43
50
  username: "",
44
51
  nickname: ctx.nickname || "",
45
52
  toEmail: ctx.body.to,
@@ -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,16 +8,16 @@ export default {
6
8
  fields: {},
7
9
  required: [],
8
10
  handler: async (befly) => {
9
- if (!befly.email) {
10
- return befly.tool.No("邮件插件未加载,请检查配置");
11
- }
11
+ const emailConfig = befly?.config?.email || {};
12
12
 
13
- const isValid = await befly.email.verify();
13
+ if (!hasEmailConfig(emailConfig)) {
14
+ return befly.tool.No("邮件未配置,请检查 SMTP 配置");
15
+ }
14
16
 
15
- if (isValid) {
16
- return befly.tool.Yes("邮件服务配置正常");
17
+ if (!befly.email) {
18
+ return befly.tool.No("邮件插件未加载,请检查配置");
17
19
  }
18
20
 
19
- return befly.tool.No("邮件服务配置异常,请检查 SMTP 设置");
21
+ return befly.tool.Yes("邮件配置已启用");
20
22
  }
21
23
  };
@@ -1,13 +1,14 @@
1
+ import { queryFields } from "#root/apis/_apis.js";
2
+ import loginLogTable from "#root/tables/loginLog.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
- page: { name: "页码", input: "integer", min: 1, max: 9999 },
8
- limit: { name: "每页数量", input: "integer", min: 1, max: 100 },
9
- keyword: { name: "关键词", input: "string", min: 0, max: 50 },
10
- state: { name: "状态", input: "integer", min: 0, max: 2 }
10
+ ...queryFields,
11
+ state: loginLogTable.state
11
12
  },
12
13
  required: [],
13
14
  handler: async (befly, ctx) => {
@@ -15,6 +16,12 @@ export default {
15
16
  table: "beflyLoginLog",
16
17
  page: ctx.body.page,
17
18
  limit: ctx.body.limit,
19
+ where: {
20
+ username$like$or: ctx.body.keyword,
21
+ nickname$like$or: ctx.body.keyword,
22
+ ip$like$or: ctx.body.keyword,
23
+ state: ctx.body.state
24
+ },
18
25
  orderBy: ["loginTime#DESC"]
19
26
  });
20
27
 
package/apis/menu/all.js CHANGED
@@ -6,29 +6,23 @@ export default {
6
6
  fields: {},
7
7
  required: [],
8
8
  handler: async (befly, ctx) => {
9
- try {
10
- const menuPaths = await befly.cache.getRoleMenus(ctx.roleCode);
9
+ const menuPaths = await befly.cache.getRoleMenus(ctx.roleCode);
11
10
 
12
- if (menuPaths.length === 0) {
13
- return befly.tool.Yes("菜单为空", { lists: [] });
14
- }
11
+ if (menuPaths.length === 0) {
12
+ return befly.tool.Yes("菜单为空", { lists: [] });
13
+ }
15
14
 
16
- const allMenus = await befly.cache.getMenus();
15
+ const allMenus = await befly.cache.getMenus();
17
16
 
18
- if (allMenus.length === 0) {
19
- return befly.tool.No("菜单缓存不存在,请刷新缓存", { lists: [] });
20
- }
17
+ if (allMenus.length === 0) {
18
+ return befly.tool.No("菜单缓存不存在,请刷新缓存", { lists: [] });
19
+ }
21
20
 
22
- const menuPathSet = new Set(menuPaths);
23
- const authorizedMenus = allMenus.filter((menu) => {
24
- const path = menu["path"];
25
- return menuPathSet.has(path);
26
- });
21
+ const menuPathSet = new Set(menuPaths);
22
+ const authorizedMenus = allMenus.filter((menu) => {
23
+ return menuPathSet.has(menu.path);
24
+ });
27
25
 
28
- return befly.tool.Yes("获取菜单成功", { lists: authorizedMenus });
29
- } catch (error) {
30
- befly.logger.error("获取用户菜单失败", error);
31
- return befly.tool.No("获取菜单失败");
32
- }
26
+ return befly.tool.Yes("获取菜单成功", { lists: authorizedMenus });
33
27
  }
34
28
  };