befly 3.8.0 → 3.8.2

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/check.ts CHANGED
@@ -5,9 +5,9 @@
5
5
 
6
6
  import { basename } from 'pathe';
7
7
  import { Logger } from './lib/logger.js';
8
- import { parseRule } from './util.js';
9
8
  import { projectTableDir } from './paths.js';
10
9
  import { Addon } from './lib/addon.js';
10
+ import type { FieldDefinition } from './types/common.d.ts';
11
11
 
12
12
  /**
13
13
  * 表文件信息接口
@@ -112,9 +112,9 @@ export const checkDefault = async function (): Promise<void> {
112
112
  let fileRules = 0;
113
113
 
114
114
  // 检查 table 中的每个验证规则
115
- for (const [colKey, rule] of Object.entries(table)) {
116
- if (typeof rule !== 'string') {
117
- Logger.warn(`${fileType}表 ${fileName} 文件 ${colKey} 规则必须为字符串`);
115
+ for (const [colKey, fieldDef] of Object.entries(table)) {
116
+ if (typeof fieldDef !== 'object' || fieldDef === null || Array.isArray(fieldDef)) {
117
+ Logger.warn(`${fileType}表 ${fileName} 文件 ${colKey} 规则必须为对象`);
118
118
  fileValid = false;
119
119
  continue;
120
120
  }
@@ -129,17 +129,58 @@ export const checkDefault = async function (): Promise<void> {
129
129
  fileValid = false;
130
130
  }
131
131
 
132
- // 使用 parseRule 解析字段规则
133
- let parsed;
134
- try {
135
- parsed = parseRule(rule);
136
- } catch (error: any) {
137
- Logger.warn(`${fileType}表 ${fileName} 文件 ${colKey} 字段规则解析失败:${error.message}`);
132
+ // 直接使用字段对象
133
+ const field = fieldDef as FieldDefinition;
134
+
135
+ // 检查必填字段:name, type, min, max
136
+ if (!field.name || typeof field.name !== 'string') {
137
+ Logger.warn(`${fileType}表 ${fileName} 文件 ${colKey} 缺少必填字段 name 或类型错误`);
138
+ fileValid = false;
139
+ continue;
140
+ }
141
+ if (!field.type || typeof field.type !== 'string') {
142
+ Logger.warn(`${fileType}表 ${fileName} 文件 ${colKey} 缺少必填字段 type 或类型错误`);
143
+ fileValid = false;
144
+ continue;
145
+ }
146
+ if (field.min === undefined) {
147
+ Logger.warn(`${fileType}表 ${fileName} 文件 ${colKey} 缺少必填字段 min`);
148
+ fileValid = false;
149
+ continue;
150
+ }
151
+ if (field.max === undefined) {
152
+ Logger.warn(`${fileType}表 ${fileName} 文件 ${colKey} 缺少必填字段 max`);
138
153
  fileValid = false;
139
154
  continue;
140
155
  }
141
156
 
142
- const { name: fieldName, type: fieldType, min: fieldMin, max: fieldMax, default: fieldDefault, index: fieldIndex, regex: fieldRegx } = parsed;
157
+ // 检查可选字段的类型
158
+ if (field.detail !== undefined && typeof field.detail !== 'string') {
159
+ Logger.warn(`${fileType}表 ${fileName} 文件 ${colKey} 字段 detail 类型错误,必须为字符串`);
160
+ fileValid = false;
161
+ }
162
+ if (field.index !== undefined && typeof field.index !== 'boolean') {
163
+ Logger.warn(`${fileType}表 ${fileName} 文件 ${colKey} 字段 index 类型错误,必须为布尔值`);
164
+ fileValid = false;
165
+ }
166
+ if (field.unique !== undefined && typeof field.unique !== 'boolean') {
167
+ Logger.warn(`${fileType}表 ${fileName} 文件 ${colKey} 字段 unique 类型错误,必须为布尔值`);
168
+ fileValid = false;
169
+ }
170
+ if (field.nullable !== undefined && typeof field.nullable !== 'boolean') {
171
+ Logger.warn(`${fileType}表 ${fileName} 文件 ${colKey} 字段 nullable 类型错误,必须为布尔值`);
172
+ fileValid = false;
173
+ }
174
+ if (field.unsigned !== undefined && typeof field.unsigned !== 'boolean') {
175
+ Logger.warn(`${fileType}表 ${fileName} 文件 ${colKey} 字段 unsigned 类型错误,必须为布尔值`);
176
+ fileValid = false;
177
+ }
178
+ if (field.regexp !== undefined && field.regexp !== null && typeof field.regexp !== 'string') {
179
+ Logger.warn(`${fileType}表 ${fileName} 文件 ${colKey} 字段 regexp 类型错误,必须为 null 或字符串`);
180
+ fileValid = false;
181
+ }
182
+
183
+ const { name: fieldName, type: fieldType, min: fieldMin, max: fieldMax, default: fieldDefault, index: fieldIndex, regexp: fieldRegexp } = field;
143
184
 
144
185
  // 第1个值:名称必须为中文、数字、字母、下划线、短横线、空格
145
186
  if (!FIELD_NAME_REGEX.test(fieldName)) {
@@ -171,18 +212,9 @@ export const checkDefault = async function (): Promise<void> {
171
212
  }
172
213
  }
173
214
 
174
- // 第6个值:是否创建索引必须为0或1
175
- if (fieldIndex !== 0 && fieldIndex !== 1) {
176
- Logger.warn(`${fileType}表 ${fileName} 文件 ${colKey} 索引标识 "${fieldIndex}" 格式错误,必须为0或1`);
177
- fileValid = false;
178
- }
179
-
180
- // 第7个值:必须为null或正则表达式(parseRule已经验证过了)
181
- // parseRule 已经将正则字符串转换为 RegExp 或 null,这里不需要再验证
182
-
183
215
  // 第4个值与类型联动校验 + 默认值规则
184
216
  if (fieldType === 'text') {
185
- // text:min/max 必须为 null,默认值必须为 'null'
217
+ // text:min/max 必须为 null,默认值必须为 null
186
218
  if (fieldMin !== null) {
187
219
  Logger.warn(`${fileType}表 ${fileName} 文件 ${colKey} 的 text 类型最小值必须为 null,当前为 "${fieldMin}"`);
188
220
  fileValid = false;
@@ -191,7 +223,7 @@ export const checkDefault = async function (): Promise<void> {
191
223
  Logger.warn(`${fileType}表 ${fileName} 文件 ${colKey} 的 text 类型最大长度必须为 null,当前为 "${fieldMax}"`);
192
224
  fileValid = false;
193
225
  }
194
- if (fieldDefault !== 'null') {
226
+ if (fieldDefault !== null) {
195
227
  Logger.warn(`${fileType}表 ${fileName} 文件 ${colKey} 为 text 类型,默认值必须为 null,当前为 "${fieldDefault}"`);
196
228
  fileValid = false;
197
229
  }
@@ -204,8 +236,9 @@ export const checkDefault = async function (): Promise<void> {
204
236
  fileValid = false;
205
237
  }
206
238
  } else if (fieldType === 'number') {
207
- if (fieldDefault !== 'null' && typeof fieldDefault !== 'number') {
208
- Logger.warn(`${fileType}表 ${fileName} 文件 ${colKey} number 类型,` + `默认值必须为数字或null,当前为 "${fieldDefault}"`);
239
+ // number 类型:default 如果存在,必须为 null number
240
+ if (fieldDefault !== undefined && fieldDefault !== null && typeof fieldDefault !== 'number') {
241
+ Logger.warn(`${fileType}表 ${fileName} 文件 ${colKey} 为 number 类型,` + `默认值必须为数字或 null,当前为 "${fieldDefault}"`);
209
242
  fileValid = false;
210
243
  }
211
244
  }
@@ -0,0 +1,169 @@
1
+ /**
2
+ * 缓存助手 - TypeScript 版本
3
+ * 负责在服务器启动时缓存接口、菜单和角色权限到 Redis
4
+ */
5
+
6
+ import { Logger } from './logger.js';
7
+ import type { BeflyContext } from '../types/befly.js';
8
+
9
+ /**
10
+ * 缓存助手类
11
+ */
12
+ export class CacheHelper {
13
+ private befly: BeflyContext;
14
+
15
+ /**
16
+ * 构造函数
17
+ * @param befly - Befly 上下文
18
+ */
19
+ constructor(befly: BeflyContext) {
20
+ this.befly = befly;
21
+ }
22
+
23
+ /**
24
+ * 缓存所有接口到 Redis
25
+ */
26
+ async cacheApis(): Promise<void> {
27
+ try {
28
+ // 检查表是否存在
29
+ const tableExists = await this.befly.db.tableExists('core_api');
30
+ if (!tableExists) {
31
+ Logger.warn('⚠️ 接口表不存在,跳过接口缓存');
32
+ return;
33
+ }
34
+
35
+ // 从数据库查询所有接口(与 apiAll.ts 保持一致)
36
+ const apiList = await this.befly.db.getAll({
37
+ table: 'core_api',
38
+ fields: ['id', 'name', 'path', 'method', 'description', 'addonName', 'addonTitle'],
39
+ orderBy: ['addonName#ASC', 'path#ASC']
40
+ });
41
+
42
+ // 缓存到 Redis
43
+ const result = await this.befly.redis.setObject('apis:all', apiList);
44
+
45
+ if (result === null) {
46
+ Logger.warn('⚠️ 接口缓存失败');
47
+ } else {
48
+ Logger.info(`✅ 已缓存 ${apiList.length} 个接口到 Redis (Key: apis:all)`);
49
+ }
50
+ } catch (error: any) {
51
+ Logger.error('⚠️ 接口缓存异常:', error);
52
+ }
53
+ }
54
+
55
+ /**
56
+ * 缓存所有菜单到 Redis(从数据库读取)
57
+ */
58
+ async cacheMenus(): Promise<void> {
59
+ try {
60
+ // 检查表是否存在
61
+ const tableExists = await this.befly.db.tableExists('core_menu');
62
+ if (!tableExists) {
63
+ Logger.warn('⚠️ 菜单表不存在,跳过菜单缓存');
64
+ return;
65
+ }
66
+
67
+ // 从数据库查询所有菜单
68
+ const menus = await this.befly.db.getAll({
69
+ table: 'core_menu',
70
+ fields: ['id', 'pid', 'name', 'path', 'icon', 'type', 'sort'],
71
+ orderBy: ['sort#ASC', 'id#ASC']
72
+ });
73
+
74
+ // 缓存到 Redis
75
+ const result = await this.befly.redis.setObject('menus:all', menus);
76
+
77
+ if (result === null) {
78
+ Logger.warn('⚠️ 菜单缓存失败');
79
+ } else {
80
+ Logger.info(`✅ 已缓存 ${menus.length} 个菜单到 Redis (Key: menus:all)`);
81
+ }
82
+ } catch (error: any) {
83
+ const errorMessage = error?.message || error?.toString?.() || String(error);
84
+ Logger.warn('⚠️ 菜单缓存异常:', errorMessage);
85
+ }
86
+ }
87
+
88
+ /**
89
+ * 缓存所有角色的接口权限到 Redis
90
+ */
91
+ async cacheRolePermissions(): Promise<void> {
92
+ try {
93
+ // 检查表是否存在
94
+ const apiTableExists = await this.befly.db.tableExists('core_api');
95
+ const roleTableExists = await this.befly.db.tableExists('core_role');
96
+
97
+ if (!apiTableExists || !roleTableExists) {
98
+ Logger.warn('⚠️ 接口或角色表不存在,跳过角色权限缓存');
99
+ return;
100
+ }
101
+
102
+ // 查询所有角色
103
+ const roles = await this.befly.db.getAll({
104
+ table: 'core_role',
105
+ fields: ['id', 'code', 'apis']
106
+ });
107
+
108
+ // 查询所有接口(用于权限映射)
109
+ const allApis = await this.befly.db.getAll({
110
+ table: 'core_api',
111
+ fields: ['id', 'name', 'path', 'method', 'description', 'addonName']
112
+ });
113
+
114
+ // 为每个角色缓存接口权限
115
+ let cachedRoles = 0;
116
+ for (const role of roles) {
117
+ if (!role.apis) continue;
118
+
119
+ // 解析角色的接口 ID 列表
120
+ const apiIds = role.apis
121
+ .split(',')
122
+ .map((id: string) => parseInt(id.trim()))
123
+ .filter((id: number) => !isNaN(id));
124
+
125
+ // 根据 ID 过滤出接口路径
126
+ const roleApiPaths = allApis.filter((api: any) => apiIds.includes(api.id)).map((api: any) => `${api.method}${api.path}`);
127
+
128
+ if (roleApiPaths.length === 0) continue;
129
+
130
+ // 使用 Redis Set 缓存角色权限(性能优化:SADD + SISMEMBER)
131
+ const redisKey = `role:apis:${role.code}`;
132
+
133
+ // 先删除旧数据
134
+ await this.befly.redis.del(redisKey);
135
+
136
+ // 批量添加到 Set
137
+ const result = await this.befly.redis.sadd(redisKey, roleApiPaths);
138
+
139
+ if (result > 0) {
140
+ cachedRoles++;
141
+ Logger.debug(` └ 角色 ${role.code}: ${result} 个接口`);
142
+ }
143
+ }
144
+
145
+ Logger.info(`✅ 已缓存 ${cachedRoles} 个角色的接口权限`);
146
+ } catch (error: any) {
147
+ const errorMessage = error?.message || error?.toString?.() || String(error);
148
+ Logger.warn('⚠️ 角色权限缓存异常:', errorMessage);
149
+ }
150
+ }
151
+
152
+ /**
153
+ * 缓存所有数据
154
+ */
155
+ async cacheAll(): Promise<void> {
156
+ Logger.info('========== 开始缓存数据到 Redis ==========');
157
+
158
+ // 1. 缓存接口
159
+ await this.cacheApis();
160
+
161
+ // 2. 缓存菜单
162
+ await this.cacheMenus();
163
+
164
+ // 3. 缓存角色权限
165
+ await this.cacheRolePermissions();
166
+
167
+ Logger.info('========== 数据缓存完成 ==========\n');
168
+ }
169
+ }
@@ -14,22 +14,22 @@ import { Database } from './database.js';
14
14
  const prefix = Env.REDIS_KEY_PREFIX ? `${Env.REDIS_KEY_PREFIX}:` : '';
15
15
 
16
16
  /**
17
- * 获取 Redis 客户端
18
- * @returns Redis 客户端实例
19
- * @throws 如果客户端未初始化
17
+ * Redis 助手类
20
18
  */
21
- function getClient(): RedisClient {
22
- const client = Database.getRedis();
23
- if (!client) {
24
- throw new Error('Redis 客户端未初始化,请先调用 Database.connectRedis()');
19
+ export class RedisHelper {
20
+ private client: RedisClient;
21
+
22
+ /**
23
+ * 构造函数
24
+ */
25
+ constructor() {
26
+ const client = Database.getRedis();
27
+ if (!client) {
28
+ throw new Error('Redis 客户端未初始化,请先调用 Database.connectRedis()');
29
+ }
30
+ this.client = client;
25
31
  }
26
- return client;
27
- }
28
32
 
29
- /**
30
- * Redis 助手对象
31
- */
32
- export const RedisHelper = {
33
33
  /**
34
34
  * 设置对象到 Redis
35
35
  * @param key - 键名
@@ -39,19 +39,18 @@ export const RedisHelper = {
39
39
  */
40
40
  async setObject<T = any>(key: string, obj: T, ttl: number | null = null): Promise<string | null> {
41
41
  try {
42
- const client = getClient();
43
42
  const data = JSON.stringify(obj);
44
43
  const pkey = `${prefix}${key}`;
45
44
 
46
45
  if (ttl) {
47
- return await client.setex(pkey, ttl, data);
46
+ return await this.client.setex(pkey, ttl, data);
48
47
  }
49
- return await client.set(pkey, data);
48
+ return await this.client.set(pkey, data);
50
49
  } catch (error: any) {
51
50
  Logger.error('Redis setObject 错误', error);
52
51
  return null;
53
52
  }
54
- },
53
+ }
55
54
 
56
55
  /**
57
56
  * 从 Redis 获取对象
@@ -60,15 +59,14 @@ export const RedisHelper = {
60
59
  */
61
60
  async getObject<T = any>(key: string): Promise<T | null> {
62
61
  try {
63
- const client = getClient();
64
62
  const pkey = `${prefix}${key}`;
65
- const data = await client.get(pkey);
63
+ const data = await this.client.get(pkey);
66
64
  return data ? JSON.parse(data) : null;
67
65
  } catch (error: any) {
68
66
  Logger.error('Redis getObject 错误', error);
69
67
  return null;
70
68
  }
71
- },
69
+ }
72
70
 
73
71
  /**
74
72
  * 从 Redis 删除对象
@@ -76,13 +74,12 @@ export const RedisHelper = {
76
74
  */
77
75
  async delObject(key: string): Promise<void> {
78
76
  try {
79
- const client = getClient();
80
77
  const pkey = `${prefix}${key}`;
81
- await client.del(pkey);
78
+ await this.client.del(pkey);
82
79
  } catch (error: any) {
83
80
  Logger.error('Redis delObject 错误', error);
84
81
  }
85
- },
82
+ }
86
83
 
87
84
  /**
88
85
  * 生成基于时间的唯一 ID
@@ -92,17 +89,16 @@ export const RedisHelper = {
92
89
  * @returns 唯一 ID (14位纯数字)
93
90
  */
94
91
  async genTimeID(): Promise<number> {
95
- const client = getClient();
96
92
  const timestamp = Math.floor(Date.now() / 1000); // 秒级时间戳
97
93
  const key = `${prefix}time_id_counter:${timestamp}`;
98
94
 
99
- const counter = await client.incr(key);
100
- await client.expire(key, 1);
95
+ const counter = await this.client.incr(key);
96
+ await this.client.expire(key, 1);
101
97
 
102
98
  const counterSuffix = (counter % 10000).toString().padStart(4, '0');
103
99
 
104
100
  return Number(`${timestamp}${counterSuffix}`);
105
- },
101
+ }
106
102
 
107
103
  /**
108
104
  * 批量生成基于时间的唯一 ID
@@ -121,13 +117,12 @@ export const RedisHelper = {
121
117
  throw new Error(`批量大小 ${count} 超过最大限制 ${MAX_BATCH_SIZE}`);
122
118
  }
123
119
 
124
- const client = getClient();
125
120
  const timestamp = Math.floor(Date.now() / 1000); // 秒级时间戳
126
121
  const key = `${prefix}time_id_counter:${timestamp}`;
127
122
 
128
123
  // 使用 INCRBY 一次性获取 N 个连续计数
129
- const startCounter = await client.incrby(key, count);
130
- await client.expire(key, 1);
124
+ const startCounter = await this.client.incrby(key, count);
125
+ await this.client.expire(key, 1);
131
126
 
132
127
  // 生成 ID 数组
133
128
  const ids: number[] = [];
@@ -138,7 +133,7 @@ export const RedisHelper = {
138
133
  }
139
134
 
140
135
  return ids;
141
- },
136
+ }
142
137
 
143
138
  /**
144
139
  * 设置字符串值
@@ -148,17 +143,16 @@ export const RedisHelper = {
148
143
  */
149
144
  async setString(key: string, value: string, ttl: number | null = null): Promise<string | null> {
150
145
  try {
151
- const client = getClient();
152
146
  const pkey = `${prefix}${key}`;
153
147
  if (ttl) {
154
- return await client.setex(pkey, ttl, value);
148
+ return await this.client.setex(pkey, ttl, value);
155
149
  }
156
- return await client.set(pkey, value);
150
+ return await this.client.set(pkey, value);
157
151
  } catch (error: any) {
158
152
  Logger.error('Redis setString 错误', error);
159
153
  return null;
160
154
  }
161
- },
155
+ }
162
156
 
163
157
  /**
164
158
  * 获取字符串值
@@ -166,14 +160,13 @@ export const RedisHelper = {
166
160
  */
167
161
  async getString(key: string): Promise<string | null> {
168
162
  try {
169
- const client = getClient();
170
163
  const pkey = `${prefix}${key}`;
171
- return await client.get(pkey);
164
+ return await this.client.get(pkey);
172
165
  } catch (error: any) {
173
166
  Logger.error('Redis getString 错误', error);
174
167
  return null;
175
168
  }
176
- },
169
+ }
177
170
 
178
171
  /**
179
172
  * 检查键是否存在
@@ -181,14 +174,13 @@ export const RedisHelper = {
181
174
  */
182
175
  async exists(key: string): Promise<number> {
183
176
  try {
184
- const client = getClient();
185
177
  const pkey = `${prefix}${key}`;
186
- return await client.exists(pkey);
178
+ return await this.client.exists(pkey);
187
179
  } catch (error: any) {
188
180
  Logger.error('Redis exists 错误', error);
189
181
  return 0;
190
182
  }
191
- },
183
+ }
192
184
 
193
185
  /**
194
186
  * 设置过期时间
@@ -197,14 +189,13 @@ export const RedisHelper = {
197
189
  */
198
190
  async expire(key: string, seconds: number): Promise<number> {
199
191
  try {
200
- const client = getClient();
201
192
  const pkey = `${prefix}${key}`;
202
- return await client.expire(pkey, seconds);
193
+ return await this.client.expire(pkey, seconds);
203
194
  } catch (error: any) {
204
195
  Logger.error('Redis expire 错误', error);
205
196
  return 0;
206
197
  }
207
- },
198
+ }
208
199
 
209
200
  /**
210
201
  * 获取剩余过期时间
@@ -212,14 +203,13 @@ export const RedisHelper = {
212
203
  */
213
204
  async ttl(key: string): Promise<number> {
214
205
  try {
215
- const client = getClient();
216
206
  const pkey = `${prefix}${key}`;
217
- return await client.ttl(pkey);
207
+ return await this.client.ttl(pkey);
218
208
  } catch (error: any) {
219
209
  Logger.error('Redis ttl 错误', error);
220
210
  return -1;
221
211
  }
222
- },
212
+ }
223
213
 
224
214
  /**
225
215
  * 向 Set 中添加一个或多个成员
@@ -231,14 +221,13 @@ export const RedisHelper = {
231
221
  try {
232
222
  if (members.length === 0) return 0;
233
223
 
234
- const client = getClient();
235
224
  const pkey = `${prefix}${key}`;
236
- return await client.sadd(pkey, ...members);
225
+ return await this.client.sadd(pkey, ...members);
237
226
  } catch (error: any) {
238
227
  Logger.error('Redis sadd 错误', error);
239
228
  return 0;
240
229
  }
241
- },
230
+ }
242
231
 
243
232
  /**
244
233
  * 判断成员是否在 Set 中
@@ -248,14 +237,13 @@ export const RedisHelper = {
248
237
  */
249
238
  async sismember(key: string, member: string): Promise<number> {
250
239
  try {
251
- const client = getClient();
252
240
  const pkey = `${prefix}${key}`;
253
- return await client.sismember(pkey, member);
241
+ return await this.client.sismember(pkey, member);
254
242
  } catch (error: any) {
255
243
  Logger.error('Redis sismember 错误', error);
256
244
  return 0;
257
245
  }
258
- },
246
+ }
259
247
 
260
248
  /**
261
249
  * 获取 Set 的成员数量
@@ -264,14 +252,13 @@ export const RedisHelper = {
264
252
  */
265
253
  async scard(key: string): Promise<number> {
266
254
  try {
267
- const client = getClient();
268
255
  const pkey = `${prefix}${key}`;
269
- return await client.scard(pkey);
256
+ return await this.client.scard(pkey);
270
257
  } catch (error: any) {
271
258
  Logger.error('Redis scard 错误', error);
272
259
  return 0;
273
260
  }
274
- },
261
+ }
275
262
 
276
263
  /**
277
264
  * 获取 Set 的所有成员
@@ -280,14 +267,13 @@ export const RedisHelper = {
280
267
  */
281
268
  async smembers(key: string): Promise<string[]> {
282
269
  try {
283
- const client = getClient();
284
270
  const pkey = `${prefix}${key}`;
285
- return await client.smembers(pkey);
271
+ return await this.client.smembers(pkey);
286
272
  } catch (error: any) {
287
273
  Logger.error('Redis smembers 错误', error);
288
274
  return [];
289
275
  }
290
- },
276
+ }
291
277
 
292
278
  /**
293
279
  * 删除键
@@ -296,14 +282,13 @@ export const RedisHelper = {
296
282
  */
297
283
  async del(key: string): Promise<number> {
298
284
  try {
299
- const client = getClient();
300
285
  const pkey = `${prefix}${key}`;
301
- return await client.del(pkey);
286
+ return await this.client.del(pkey);
302
287
  } catch (error: any) {
303
288
  Logger.error('Redis del 错误', error);
304
289
  return 0;
305
290
  }
306
- },
291
+ }
307
292
 
308
293
  /**
309
294
  * 测试 Redis 连接
@@ -311,11 +296,10 @@ export const RedisHelper = {
311
296
  */
312
297
  async ping(): Promise<string> {
313
298
  try {
314
- const client = getClient();
315
- return await client.ping();
299
+ return await this.client.ping();
316
300
  } catch (error: any) {
317
301
  Logger.error('Redis ping 错误', error);
318
302
  throw error;
319
303
  }
320
304
  }
321
- };
305
+ }