chanjs 2.7.4 → 2.7.6
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/USAGE.md +533 -0
- package/config/index.js +37 -6
- package/core/App.js +166 -0
- package/core/BaseComponent.js +27 -0
- package/core/Container.js +68 -0
- package/core/Controller.js +29 -0
- package/core/Database.js +93 -0
- package/core/Repository.js +323 -0
- package/core/Service.js +11 -0
- package/core/bootstrap/error-handler.js +101 -0
- package/core/bootstrap/hook-runner.js +64 -0
- package/core/bootstrap/middleware.js +35 -0
- package/core/bootstrap/router-loader.js +53 -0
- package/core/errors.js +251 -0
- package/core/loader.js +89 -0
- package/core/registry.js +17 -0
- package/doc/Cache.md +279 -106
- package/doc/Common.md +590 -134
- package/doc/Controller.md +166 -95
- package/doc/Help.md +299 -698
- package/doc/QuickStart.md +116 -0
- package/doc/Repository.md +560 -0
- package/doc/Service.md +201 -527
- package/index.js +61 -37
- package/middleware/body.js +17 -0
- package/middleware/cookie.js +7 -15
- package/middleware/cors.js +9 -27
- package/middleware/favicon.js +15 -17
- package/middleware/header.js +15 -16
- package/middleware/index.js +11 -11
- package/middleware/log.js +26 -56
- package/middleware/static.js +15 -28
- package/middleware/template.js +75 -115
- package/middleware/validate.js +79 -0
- package/middleware/waf.js +176 -197
- package/package.json +9 -2
- package/response/code.js +73 -0
- package/response/index.js +9 -6
- package/response/response.js +82 -236
- package/security/checker.js +26 -74
- package/security/index.js +4 -9
- package/security/jwt.js +84 -139
- package/security/keywords.js +33 -137
- package/security/rate-limit.js +38 -80
- package/security/sign.js +83 -176
- package/security/xss-filter.js +21 -53
- package/storage/cache.js +58 -198
- package/storage/index.js +3 -6
- package/storage/redis.js +124 -181
- package/storage/store.js +163 -188
- package/utils/data-parse.js +42 -186
- package/utils/file.js +73 -244
- package/utils/filter.js +22 -25
- package/utils/html.js +49 -33
- package/utils/index.js +20 -7
- package/utils/ip.js +31 -71
- package/utils/logger.js +117 -0
- package/utils/pages.js +55 -0
- package/utils/paths.js +18 -0
- package/utils/request.js +95 -136
- package/utils/signal.js +87 -0
- package/utils/time.js +33 -75
- package/utils/tree.js +112 -104
- package/App.js +0 -533
- package/base/Aop.js +0 -195
- package/base/Container.js +0 -161
- package/base/Controller.js +0 -65
- package/base/Database.js +0 -133
- package/base/Event.js +0 -61
- package/base/Repository.js +0 -644
- package/common/api.js +0 -35
- package/common/code.js +0 -52
- package/common/email.js +0 -191
- package/common/index.js +0 -5
- package/common/pages.js +0 -120
- package/common/utils.js +0 -73
- package/config/code.js +0 -166
- package/config/paths.js +0 -60
- package/doc/Aop.md +0 -269
- package/doc/Email.md +0 -114
- package/doc/Event.md +0 -232
- package/global/env.js +0 -11
- package/global/import.js +0 -39
- package/global/index.js +0 -8
- package/helper/index.js +0 -79
- package/loader/index.js +0 -6
- package/loader/loader.js +0 -138
- package/middleware/compress.js +0 -185
- package/middleware/setBody.js +0 -32
- package/realtime/index.js +0 -7
- package/realtime/sse.js +0 -424
- package/realtime/websocket.js +0 -540
- package/schedule/index.js +0 -6
- package/schedule/schedule.js +0 -491
package/doc/Common.md
CHANGED
|
@@ -1,182 +1,638 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Common 公共工具模块
|
|
2
|
+
|
|
2
3
|
## 概述
|
|
3
|
-
`chanjs/common/index.js` 是 `chanjs` 框架的通用工具模块出口文件,聚合了 API 响应处理、分类操作、状态码、邮件、页面处理、短信、通用工具等多个子模块的核心方法/常量,提供统一的导出入口,简化模块引用流程。
|
|
4
|
-
|
|
5
|
-
## 导出内容总览
|
|
6
|
-
该文件通过 ES6 导出语法,批量导出以下子模块的核心成员:
|
|
7
|
-
|
|
8
|
-
| 导出来源文件 | 导出成员 | 功能分类 |
|
|
9
|
-
|--------------|----------|----------|
|
|
10
|
-
| `./api.js` | `success`, `fail`, `error` | API 响应格式化 |
|
|
11
|
-
| `./category.js` | `getChildrenId` | 分类数据处理 |
|
|
12
|
-
| `./code.js` | `CODE` | 业务状态码常量 |
|
|
13
|
-
| `./email.js` | `sendMail`, `genRegEmailHtml`, `genResetPasswordEmail` | 邮件发送与模板生成 |
|
|
14
|
-
| `./pages.js` | `pages`, `getHtmlFilesSync` | 页面/HTML 文件处理 |
|
|
15
|
-
| `./sms.js` | `createSmsClient` | 短信客户端创建 |
|
|
16
|
-
| `./utils.js` | `filterBody`, `pc`, `filterImgFromStr` | 通用工具函数 |
|
|
17
|
-
|
|
18
|
-
## 详细导出成员说明
|
|
19
|
-
### 1. 来自 `./api.js`:API 响应格式化
|
|
20
|
-
| 成员名 | 类型 | 说明 |
|
|
21
|
-
|--------|------|------|
|
|
22
|
-
| `success` | 函数 | 生成「成功」类型的 API 响应数据(如包含 `code: 200`、`data`、`msg` 等字段) |
|
|
23
|
-
| `fail` | 函数 | 生成「业务失败」类型的 API 响应数据(如包含 `code: 非200`、`msg` 等字段,适用于参数错误、业务逻辑失败等场景) |
|
|
24
|
-
| `error` | 函数 | 生成「系统错误」类型的 API 响应数据(如包含 `code: 500`、`msg` 等字段,适用于服务器内部异常场景) |
|
|
25
|
-
|
|
26
|
-
**使用示例**:
|
|
27
|
-
```javascript
|
|
28
|
-
import { success, fail } from 'chanjs/common';
|
|
29
|
-
|
|
30
|
-
// 接口返回成功响应
|
|
31
|
-
export const getUser = (req, res) => {
|
|
32
|
-
res.json(success({ name: '张三' }, '获取用户信息成功'));
|
|
33
|
-
};
|
|
34
4
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
5
|
+
`common` 模块是 chanjs 框架的公共工具集合,提供响应格式化、数据解析、HTML 处理、文件操作等常用功能。
|
|
6
|
+
|
|
7
|
+
## 引入方式
|
|
8
|
+
|
|
9
|
+
```javascript
|
|
10
|
+
import { helper } from 'chanjs';
|
|
11
|
+
|
|
12
|
+
// 或从子模块精确引用
|
|
13
|
+
import { getIp } from 'chanjs/utils/ip.js';
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## 核心工具
|
|
17
|
+
|
|
18
|
+
### 1. 响应格式化
|
|
19
|
+
|
|
20
|
+
#### success - 成功响应
|
|
21
|
+
|
|
22
|
+
```javascript
|
|
23
|
+
helper.success({ data, msg })
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
**参数**
|
|
27
|
+
|
|
28
|
+
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|
|
29
|
+
|------|------|------|--------|------|
|
|
30
|
+
| data | any | 否 | {} | 响应数据 |
|
|
31
|
+
| msg | string | 否 | "操作成功" | 提示信息 |
|
|
32
|
+
|
|
33
|
+
**示例**
|
|
34
|
+
|
|
35
|
+
```javascript
|
|
36
|
+
import { helper } from 'chanjs';
|
|
37
|
+
|
|
38
|
+
const response = helper.success({
|
|
39
|
+
data: { id: 1, name: '张三' },
|
|
40
|
+
msg: '查询成功'
|
|
41
|
+
});
|
|
42
|
+
// { success: true, code: 0, msg: '查询成功', data: {...} }
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
#### fail - 失败响应
|
|
46
|
+
|
|
47
|
+
```javascript
|
|
48
|
+
helper.fail({ msg, code, data })
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
**参数**
|
|
52
|
+
|
|
53
|
+
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|
|
54
|
+
|------|------|------|--------|------|
|
|
55
|
+
| msg | string | 否 | "操作失败" | 错误提示 |
|
|
56
|
+
| code | number | 否 | 1008 | 错误码 |
|
|
57
|
+
| data | any | 否 | {} | 附加数据 |
|
|
58
|
+
|
|
59
|
+
**示例**
|
|
60
|
+
|
|
61
|
+
```javascript
|
|
62
|
+
const response = helper.fail({
|
|
63
|
+
msg: '参数错误',
|
|
64
|
+
code: 1006
|
|
65
|
+
});
|
|
66
|
+
// { success: false, code: 1006, msg: '参数错误', data: {} }
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### 2. IP 获取
|
|
70
|
+
|
|
71
|
+
#### getIp - 获取客户端真实 IP
|
|
72
|
+
|
|
73
|
+
```javascript
|
|
74
|
+
helper.getIp(req)
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
**参数**
|
|
78
|
+
|
|
79
|
+
| 参数 | 类型 | 必填 | 说明 |
|
|
80
|
+
|------|------|------|------|
|
|
81
|
+
| req | object | 是 | Express 请求对象 |
|
|
82
|
+
|
|
83
|
+
**返回值**
|
|
84
|
+
|
|
85
|
+
客户端 IP 地址(string)
|
|
86
|
+
|
|
87
|
+
**示例**
|
|
88
|
+
|
|
89
|
+
```javascript
|
|
90
|
+
app.get('/api/user', (req, res) => {
|
|
91
|
+
const ip = helper.getIp(req);
|
|
92
|
+
console.log('客户端 IP:', ip);
|
|
93
|
+
});
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### 3. 时间处理
|
|
97
|
+
|
|
98
|
+
#### formatDateFields - 格式化日期字段
|
|
99
|
+
|
|
100
|
+
```javascript
|
|
101
|
+
helper.formatDateFields(data, fields, format)
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
**参数**
|
|
105
|
+
|
|
106
|
+
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|
|
107
|
+
|------|------|------|--------|------|
|
|
108
|
+
| data | object/array | 是 | - | 待处理的数据 |
|
|
109
|
+
| fields | string[] | 是 | - | 需要格式化的字段名列表 |
|
|
110
|
+
| format | string | 否 | 'YYYY-MM-DD HH:mm:ss' | 日期格式 |
|
|
111
|
+
|
|
112
|
+
**示例**
|
|
113
|
+
|
|
114
|
+
```javascript
|
|
115
|
+
const user = {
|
|
116
|
+
id: 1,
|
|
117
|
+
name: '张三',
|
|
118
|
+
createdAt: '2024-01-01T00:00:00.000Z'
|
|
38
119
|
};
|
|
120
|
+
|
|
121
|
+
const formatted = helper.formatDateFields(user, ['createdAt']);
|
|
122
|
+
// { id: 1, name: '张三', createdAt: '2024-01-01 00:00:00' }
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### 4. 文件操作
|
|
126
|
+
|
|
127
|
+
#### delImg - 删除图片
|
|
128
|
+
|
|
129
|
+
```javascript
|
|
130
|
+
helper.delImg(filePath)
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
**参数**
|
|
134
|
+
|
|
135
|
+
| 参数 | 类型 | 必填 | 说明 |
|
|
136
|
+
|------|------|------|------|
|
|
137
|
+
| filePath | string | 是 | 图片文件路径 |
|
|
138
|
+
|
|
139
|
+
**返回值**
|
|
140
|
+
|
|
141
|
+
- `true`:删除成功
|
|
142
|
+
- `false`:删除失败
|
|
143
|
+
|
|
144
|
+
**示例**
|
|
145
|
+
|
|
146
|
+
```javascript
|
|
147
|
+
const success = helper.delImg('/uploads/avatar.jpg');
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
#### readFileContent - 读取文件内容
|
|
151
|
+
|
|
152
|
+
```javascript
|
|
153
|
+
helper.readFileContent(filePath, encoding)
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
**参数**
|
|
157
|
+
|
|
158
|
+
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|
|
159
|
+
|------|------|------|--------|------|
|
|
160
|
+
| filePath | string | 是 | - | 文件路径 |
|
|
161
|
+
| encoding | string | 否 | 'utf-8' | 文件编码 |
|
|
162
|
+
|
|
163
|
+
**返回值**
|
|
164
|
+
|
|
165
|
+
文件内容(string)
|
|
166
|
+
|
|
167
|
+
**示例**
|
|
168
|
+
|
|
169
|
+
```javascript
|
|
170
|
+
const content = helper.readFileContent('/config/app.json');
|
|
171
|
+
const config = JSON.parse(content);
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
#### saveFileContent - 保存文件内容
|
|
175
|
+
|
|
176
|
+
```javascript
|
|
177
|
+
helper.saveFileContent(filePath, content, encoding)
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
**参数**
|
|
181
|
+
|
|
182
|
+
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|
|
183
|
+
|------|------|------|--------|------|
|
|
184
|
+
| filePath | string | 是 | - | 文件路径 |
|
|
185
|
+
| content | string | 是 | - | 文件内容 |
|
|
186
|
+
| encoding | string | 否 | 'utf-8' | 文件编码 |
|
|
187
|
+
|
|
188
|
+
**示例**
|
|
189
|
+
|
|
190
|
+
```javascript
|
|
191
|
+
helper.saveFileContent('/logs/app.log', '日志内容');
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
#### getFolders - 获取文件夹列表
|
|
195
|
+
|
|
196
|
+
```javascript
|
|
197
|
+
helper.getFolders(dirPath)
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
**参数**
|
|
201
|
+
|
|
202
|
+
| 参数 | 类型 | 必填 | 说明 |
|
|
203
|
+
|------|------|------|------|
|
|
204
|
+
| dirPath | string | 是 | 目录路径 |
|
|
205
|
+
|
|
206
|
+
**返回值**
|
|
207
|
+
|
|
208
|
+
文件夹名称数组(string[])
|
|
209
|
+
|
|
210
|
+
**示例**
|
|
211
|
+
|
|
212
|
+
```javascript
|
|
213
|
+
const folders = helper.getFolders('/uploads');
|
|
214
|
+
// ['images', 'videos', 'documents']
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
#### getHtmlFilesSync - 同步获取 HTML 文件列表
|
|
218
|
+
|
|
219
|
+
```javascript
|
|
220
|
+
helper.getHtmlFilesSync(dirPath)
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
**参数**
|
|
224
|
+
|
|
225
|
+
| 参数 | 类型 | 必填 | 说明 |
|
|
226
|
+
|------|------|------|------|
|
|
227
|
+
| dirPath | string | 是 | 目录路径 |
|
|
228
|
+
|
|
229
|
+
**返回值**
|
|
230
|
+
|
|
231
|
+
HTML 文件路径数组(string[])
|
|
232
|
+
|
|
233
|
+
**示例**
|
|
234
|
+
|
|
235
|
+
```javascript
|
|
236
|
+
const htmlFiles = helper.getHtmlFilesSync('/templates');
|
|
237
|
+
// ['index.html', 'about.html', 'contact.html']
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### 5. HTML 处理
|
|
241
|
+
|
|
242
|
+
#### htmlEncode - HTML 编码
|
|
243
|
+
|
|
244
|
+
```javascript
|
|
245
|
+
helper.htmlEncode(str)
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
**参数**
|
|
249
|
+
|
|
250
|
+
| 参数 | 类型 | 必填 | 说明 |
|
|
251
|
+
|------|------|------|------|
|
|
252
|
+
| str | string | 是 | 待编码的字符串 |
|
|
253
|
+
|
|
254
|
+
**返回值**
|
|
255
|
+
|
|
256
|
+
编码后的字符串(string)
|
|
257
|
+
|
|
258
|
+
**示例**
|
|
259
|
+
|
|
260
|
+
```javascript
|
|
261
|
+
const encoded = helper.htmlEncode('<script>alert("xss")</script>');
|
|
262
|
+
// <script>alert("xss")</script>
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
#### htmlDecode - HTML 解码
|
|
266
|
+
|
|
267
|
+
```javascript
|
|
268
|
+
helper.htmlDecode(str)
|
|
39
269
|
```
|
|
40
270
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
271
|
+
**参数**
|
|
272
|
+
|
|
273
|
+
| 参数 | 类型 | 必填 | 说明 |
|
|
274
|
+
|------|------|------|------|
|
|
275
|
+
| str | string | 是 | 待解码的字符串 |
|
|
276
|
+
|
|
277
|
+
**返回值**
|
|
278
|
+
|
|
279
|
+
解码后的字符串(string)
|
|
280
|
+
|
|
281
|
+
**示例**
|
|
45
282
|
|
|
46
|
-
**使用示例**:
|
|
47
283
|
```javascript
|
|
48
|
-
|
|
284
|
+
const decoded = helper.htmlDecode('<div>内容</div>');
|
|
285
|
+
// <div>内容</div>
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
#### escapeScript - 转义脚本标签
|
|
289
|
+
|
|
290
|
+
```javascript
|
|
291
|
+
helper.escapeScript(str)
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
**参数**
|
|
295
|
+
|
|
296
|
+
| 参数 | 类型 | 必填 | 说明 |
|
|
297
|
+
|------|------|------|------|
|
|
298
|
+
| str | string | 是 | 待转义的字符串 |
|
|
299
|
+
|
|
300
|
+
**返回值**
|
|
301
|
+
|
|
302
|
+
转义后的字符串(string)
|
|
303
|
+
|
|
304
|
+
**示例**
|
|
305
|
+
|
|
306
|
+
```javascript
|
|
307
|
+
const safe = helper.escapeScript('<script>alert("xss")</script>');
|
|
308
|
+
// <script>alert("xss")</script>
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
#### filterImgFromStr - 从文本中提取图片 URL
|
|
312
|
+
|
|
313
|
+
```javascript
|
|
314
|
+
helper.filterImgFromStr(str)
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
**参数**
|
|
318
|
+
|
|
319
|
+
| 参数 | 类型 | 必填 | 说明 |
|
|
320
|
+
|------|------|------|------|
|
|
321
|
+
| str | string | 是 | 包含 img 标签的文本 |
|
|
322
|
+
|
|
323
|
+
**返回值**
|
|
324
|
+
|
|
325
|
+
图片 URL 数组(string[])
|
|
326
|
+
|
|
327
|
+
**示例**
|
|
328
|
+
|
|
329
|
+
```javascript
|
|
330
|
+
const content = '<p>内容<img src="image1.jpg">更多<img src="image2.png"></p>';
|
|
331
|
+
const images = helper.filterImgFromStr(content);
|
|
332
|
+
// ['image1.jpg', 'image2.png']
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
### 6. 数据解析
|
|
49
336
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
337
|
+
#### arrToObj - 数组转对象
|
|
338
|
+
|
|
339
|
+
```javascript
|
|
340
|
+
helper.arrToObj(arr, key)
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
**参数**
|
|
344
|
+
|
|
345
|
+
| 参数 | 类型 | 必填 | 说明 |
|
|
346
|
+
|------|------|------|------|
|
|
347
|
+
| arr | array | 是 | 源数组 |
|
|
348
|
+
| key | string | 是 | 作为对象键的字段名 |
|
|
349
|
+
|
|
350
|
+
**返回值**
|
|
351
|
+
|
|
352
|
+
转换后的对象(object)
|
|
353
|
+
|
|
354
|
+
**示例**
|
|
355
|
+
|
|
356
|
+
```javascript
|
|
357
|
+
const users = [
|
|
358
|
+
{ id: 1, name: '张三' },
|
|
359
|
+
{ id: 2, name: '李四' }
|
|
54
360
|
];
|
|
55
|
-
|
|
56
|
-
const
|
|
57
|
-
|
|
361
|
+
|
|
362
|
+
const userMap = helper.arrToObj(users, 'id');
|
|
363
|
+
// { 1: { id: 1, name: '张三' }, 2: { id: 2, name: '李四' } }
|
|
58
364
|
```
|
|
59
365
|
|
|
60
|
-
|
|
61
|
-
| 成员名 | 类型 | 说明 |
|
|
62
|
-
|--------|------|------|
|
|
63
|
-
| `CODE` | 对象 | 聚合了项目中所有业务状态码的常量对象(如 `CODE.SUCCESS = 200`、`CODE.PARAM_ERROR = 400`、`CODE.LOGIN_EXPIRE = 401` 等),统一管理状态码,避免硬编码 |
|
|
366
|
+
#### getChildrenId - 获取子分类 ID
|
|
64
367
|
|
|
65
|
-
**使用示例**:
|
|
66
368
|
```javascript
|
|
67
|
-
|
|
369
|
+
helper.getChildrenId(categories, parentId)
|
|
370
|
+
```
|
|
68
371
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
372
|
+
**参数**
|
|
373
|
+
|
|
374
|
+
| 参数 | 类型 | 必填 | 说明 |
|
|
375
|
+
|------|------|------|------|
|
|
376
|
+
| categories | array | 是 | 分类树结构 |
|
|
377
|
+
| parentId | number | 是 | 父分类 ID |
|
|
378
|
+
|
|
379
|
+
**返回值**
|
|
380
|
+
|
|
381
|
+
子分类 ID 数组(number[])
|
|
382
|
+
|
|
383
|
+
**示例**
|
|
384
|
+
|
|
385
|
+
```javascript
|
|
386
|
+
const categories = [
|
|
387
|
+
{ id: 1, children: [{ id: 2 }, { id: 3 }] },
|
|
388
|
+
{ id: 4, children: [] }
|
|
389
|
+
];
|
|
390
|
+
|
|
391
|
+
const childIds = helper.getChildrenId(categories, 1);
|
|
392
|
+
// [2, 3]
|
|
76
393
|
```
|
|
77
394
|
|
|
78
|
-
###
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
| `sendMail` | 函数 | 封装邮件发送逻辑,接收收件人、邮件标题、邮件内容等参数,调用底层邮件服务发送邮件 |
|
|
82
|
-
| `genRegEmailHtml` | 函数 | 生成「用户注册验证」的邮件 HTML 模板(包含验证链接/验证码等动态内容) |
|
|
83
|
-
| `genResetPasswordEmail` | 函数 | 生成「密码重置」的邮件 HTML 模板(包含重置链接/验证码等动态内容) |
|
|
395
|
+
### 7. 树形结构
|
|
396
|
+
|
|
397
|
+
#### tree - 构建树形结构
|
|
84
398
|
|
|
85
|
-
**使用示例**:
|
|
86
399
|
```javascript
|
|
87
|
-
|
|
400
|
+
helper.tree(list, idKey, parentKey, childrenKey)
|
|
401
|
+
```
|
|
88
402
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
403
|
+
**参数**
|
|
404
|
+
|
|
405
|
+
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|
|
406
|
+
|------|------|------|--------|------|
|
|
407
|
+
| list | array | 是 | - | 扁平列表 |
|
|
408
|
+
| idKey | string | 否 | 'id' | ID 字段名 |
|
|
409
|
+
| parentKey | string | 否 | 'parentId' | 父 ID 字段名 |
|
|
410
|
+
| childrenKey | string | 否 | 'children' | 子节点字段名 |
|
|
411
|
+
|
|
412
|
+
**返回值**
|
|
413
|
+
|
|
414
|
+
树形结构(array)
|
|
415
|
+
|
|
416
|
+
**示例**
|
|
417
|
+
|
|
418
|
+
```javascript
|
|
419
|
+
const menus = [
|
|
420
|
+
{ id: 1, parentId: 0, name: '首页' },
|
|
421
|
+
{ id: 2, parentId: 1, name: '子菜单1' },
|
|
422
|
+
{ id: 3, parentId: 1, name: '子菜单2' }
|
|
423
|
+
];
|
|
424
|
+
|
|
425
|
+
const tree = helper.tree(menus);
|
|
426
|
+
// [
|
|
427
|
+
// { id: 1, parentId: 0, name: '首页', children: [
|
|
428
|
+
// { id: 2, parentId: 1, name: '子菜单1' },
|
|
429
|
+
// { id: 3, parentId: 1, name: '子菜单2' }
|
|
430
|
+
// ]}
|
|
431
|
+
// ]
|
|
98
432
|
```
|
|
99
433
|
|
|
100
|
-
|
|
101
|
-
| 成员名 | 类型 | 说明 |
|
|
102
|
-
|--------|------|------|
|
|
103
|
-
| `pages` | 对象/函数 | 页面相关配置/工具(如页面路由映射、页面模板配置等,具体需结合子模块实现) |
|
|
104
|
-
| `getHtmlFilesSync` | 函数 | 同步读取指定目录下所有 HTML 文件的路径/内容,返回文件列表(适用于静态页面生成、模板扫描等场景) |
|
|
434
|
+
#### treeById - 根据 ID 查找树节点
|
|
105
435
|
|
|
106
|
-
**使用示例**:
|
|
107
436
|
```javascript
|
|
108
|
-
|
|
437
|
+
helper.treeById(tree, id)
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
**参数**
|
|
441
|
+
|
|
442
|
+
| 参数 | 类型 | 必填 | 说明 |
|
|
443
|
+
|------|------|------|------|
|
|
444
|
+
| tree | array | 是 | 树形结构 |
|
|
445
|
+
| id | number | 是 | 节点 ID |
|
|
446
|
+
|
|
447
|
+
**返回值**
|
|
448
|
+
|
|
449
|
+
节点对象或 null
|
|
109
450
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
451
|
+
**示例**
|
|
452
|
+
|
|
453
|
+
```javascript
|
|
454
|
+
const node = helper.treeById(tree, 2);
|
|
455
|
+
// { id: 2, parentId: 1, name: '子菜单1' }
|
|
113
456
|
```
|
|
114
457
|
|
|
115
|
-
###
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
| `createSmsClient` | 函数 | 创建并返回短信服务客户端实例(封装了短信服务商 SDK,如阿里云短信、腾讯云短信等),支持配置密钥、签名等参数 |
|
|
458
|
+
### 8. 字段过滤
|
|
459
|
+
|
|
460
|
+
#### filterFields - 过滤对象字段
|
|
119
461
|
|
|
120
|
-
**使用示例**:
|
|
121
462
|
```javascript
|
|
122
|
-
|
|
463
|
+
helper.filterFields(obj, fields, mode)
|
|
464
|
+
```
|
|
123
465
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
466
|
+
**参数**
|
|
467
|
+
|
|
468
|
+
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|
|
469
|
+
|------|------|------|--------|------|
|
|
470
|
+
| obj | object | 是 | - | 源对象 |
|
|
471
|
+
| fields | string[] | 是 | - | 字段名列表 |
|
|
472
|
+
| mode | string | 否 | 'include' | 模式:'include' 保留指定字段,'exclude' 排除指定字段 |
|
|
473
|
+
|
|
474
|
+
**返回值**
|
|
475
|
+
|
|
476
|
+
过滤后的对象(object)
|
|
477
|
+
|
|
478
|
+
**示例**
|
|
479
|
+
|
|
480
|
+
```javascript
|
|
481
|
+
const user = { id: 1, name: '张三', password: '123', age: 25 };
|
|
482
|
+
|
|
483
|
+
// 保留指定字段
|
|
484
|
+
const safe1 = helper.filterFields(user, ['id', 'name'], 'include');
|
|
485
|
+
// { id: 1, name: '张三' }
|
|
486
|
+
|
|
487
|
+
// 排除指定字段
|
|
488
|
+
const safe2 = helper.filterFields(user, ['password'], 'exclude');
|
|
489
|
+
// { id: 1, name: '张三', age: 25 }
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
### 9. 分页工具
|
|
493
|
+
|
|
494
|
+
#### pages - 分页计算
|
|
495
|
+
|
|
496
|
+
```javascript
|
|
497
|
+
helper.pages(total, current, pageSize)
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
**参数**
|
|
501
|
+
|
|
502
|
+
| 参数 | 类型 | 必填 | 说明 |
|
|
503
|
+
|------|------|------|------|
|
|
504
|
+
| total | number | 是 | 总记录数 |
|
|
505
|
+
| current | number | 是 | 当前页码 |
|
|
506
|
+
| pageSize | number | 是 | 每页条数 |
|
|
507
|
+
|
|
508
|
+
**返回值**
|
|
509
|
+
|
|
510
|
+
分页信息对象(object)
|
|
511
|
+
|
|
512
|
+
**示例**
|
|
513
|
+
|
|
514
|
+
```javascript
|
|
515
|
+
const pageInfo = helper.pages(100, 2, 10);
|
|
516
|
+
// {
|
|
517
|
+
// total: 100,
|
|
518
|
+
// current: 2,
|
|
519
|
+
// pageSize: 10,
|
|
520
|
+
// totalPages: 10,
|
|
521
|
+
// hasPrev: true,
|
|
522
|
+
// hasNext: true,
|
|
523
|
+
// offset: 10
|
|
524
|
+
// }
|
|
525
|
+
```
|
|
526
|
+
|
|
527
|
+
## 安全工具
|
|
130
528
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
529
|
+
### 1. XSS 过滤
|
|
530
|
+
|
|
531
|
+
#### filterXSS - 过滤 XSS 攻击
|
|
532
|
+
|
|
533
|
+
```javascript
|
|
534
|
+
import { filterXSS } from 'chanjs';
|
|
535
|
+
|
|
536
|
+
filterXSS(data)
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
**参数**
|
|
540
|
+
|
|
541
|
+
| 参数 | 类型 | 必填 | 说明 |
|
|
542
|
+
|------|------|------|------|
|
|
543
|
+
| data | any | 是 | 待过滤的数据(支持字符串、对象、数组) |
|
|
544
|
+
|
|
545
|
+
**返回值**
|
|
546
|
+
|
|
547
|
+
过滤后的数据
|
|
548
|
+
|
|
549
|
+
**示例**
|
|
550
|
+
|
|
551
|
+
```javascript
|
|
552
|
+
const safe = filterXSS('<script>alert("xss")</script>');
|
|
553
|
+
// <script>alert("xss")</script>
|
|
554
|
+
|
|
555
|
+
const safeObj = filterXSS({
|
|
556
|
+
name: '<script>alert("xss")</script>',
|
|
557
|
+
age: 25
|
|
136
558
|
});
|
|
559
|
+
// { name: '<script>alert("xss")</script>', age: 25 }
|
|
137
560
|
```
|
|
138
561
|
|
|
139
|
-
###
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
| `filterBody` | 函数 | 过滤请求体(req.body)中的敏感字段/空值字段,返回清洗后的对象(适用于接口入参校验,避免无效/敏感数据传入业务层) |
|
|
143
|
-
| `pc` | 函数/对象 | 设备判断工具,通常用于检测请求是否来自 PC 端(如返回 `true/false`,或包含 `isPc`、`isMobile` 等方法) |
|
|
144
|
-
| `filterImgFromStr` | 函数 | 从字符串(如 HTML 文本、富文本内容)中提取所有图片 URL,返回图片链接数组 |
|
|
562
|
+
### 2. 关键词检测
|
|
563
|
+
|
|
564
|
+
#### checkKeywords - 检测恶意关键词
|
|
145
565
|
|
|
146
|
-
**使用示例**:
|
|
147
566
|
```javascript
|
|
148
|
-
import {
|
|
567
|
+
import { checkKeywords } from 'chanjs';
|
|
568
|
+
|
|
569
|
+
checkKeywords(text)
|
|
570
|
+
```
|
|
149
571
|
|
|
150
|
-
|
|
151
|
-
const cleanBody = filterBody(req.body, ['name', 'age']); // 仅保留name、age字段,且过滤空值
|
|
572
|
+
**参数**
|
|
152
573
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
}
|
|
574
|
+
| 参数 | 类型 | 必填 | 说明 |
|
|
575
|
+
|------|------|------|------|
|
|
576
|
+
| text | string | 是 | 待检测的文本 |
|
|
157
577
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
578
|
+
**返回值**
|
|
579
|
+
|
|
580
|
+
- `null`:未检测到恶意关键词
|
|
581
|
+
- `{ category: string, keyword: string }`:检测到恶意关键词
|
|
582
|
+
|
|
583
|
+
**示例**
|
|
584
|
+
|
|
585
|
+
```javascript
|
|
586
|
+
const result = checkKeywords('SELECT * FROM users');
|
|
587
|
+
// { category: 'sqlInjection', keyword: 'SELECT' }
|
|
162
588
|
```
|
|
163
589
|
|
|
164
|
-
|
|
165
|
-
|
|
590
|
+
### 3. 限流中间件
|
|
591
|
+
|
|
592
|
+
#### createRateLimitMiddleware - 创建限流中间件
|
|
593
|
+
|
|
166
594
|
```javascript
|
|
167
|
-
import {
|
|
595
|
+
import { createRateLimitMiddleware } from 'chanjs';
|
|
596
|
+
|
|
597
|
+
createRateLimitMiddleware(config)
|
|
168
598
|
```
|
|
169
599
|
|
|
170
|
-
|
|
600
|
+
**参数**
|
|
601
|
+
|
|
602
|
+
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|
|
603
|
+
|------|------|------|--------|------|
|
|
604
|
+
| config.windowMs | number/string | 否 | 60000 | 时间窗口(毫秒或 '1m' 格式) |
|
|
605
|
+
| config.max | number | 否 | 60 | 窗口内最大请求数 |
|
|
606
|
+
| config.ignorePaths | string[] | 否 | [] | 忽略的路径列表 |
|
|
607
|
+
|
|
608
|
+
**返回值**
|
|
609
|
+
|
|
610
|
+
Express 中间件函数
|
|
611
|
+
|
|
612
|
+
**示例**
|
|
613
|
+
|
|
171
614
|
```javascript
|
|
172
|
-
|
|
615
|
+
const rateLimit = createRateLimitMiddleware({
|
|
616
|
+
windowMs: '1m', // 1 分钟
|
|
617
|
+
max: 100, // 最多 100 次请求
|
|
618
|
+
ignorePaths: ['/api/public']
|
|
619
|
+
});
|
|
173
620
|
|
|
174
|
-
|
|
175
|
-
common.success(data, '操作成功');
|
|
176
|
-
common.filterBody(req.body);
|
|
621
|
+
app.use(rateLimit);
|
|
177
622
|
```
|
|
178
623
|
|
|
179
624
|
## 注意事项
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
625
|
+
|
|
626
|
+
1. `helper` 是工具函数的聚合对象,不包含业务逻辑
|
|
627
|
+
2. 文件操作函数需要注意路径权限
|
|
628
|
+
3. 安全工具(filterXSS、checkKeywords)建议在中间件层统一调用
|
|
629
|
+
4. 分页工具的 `total` 参数必须是数字类型
|
|
630
|
+
5. 树形结构工具假设数据中存在循环引用,会自动处理
|
|
631
|
+
|
|
632
|
+
## 相关文档
|
|
633
|
+
|
|
634
|
+
- [QuickStart](./QuickStart.md) - 快速入门
|
|
635
|
+
- [Controller](./Controller.md) - 控制器基类
|
|
636
|
+
- [Service](./Service.md) - 服务基类
|
|
637
|
+
- [Repository](./Repository.md) - 数据访问层
|
|
638
|
+
- [Cache](./Cache.md) - 缓存工具
|