midway-fatcms 0.0.4 → 0.0.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/README.md +635 -352
- package/dist/controller/manage/CrudStandardDesignApi.d.ts +0 -2
- package/dist/controller/manage/CrudStandardDesignApi.js +11 -85
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/libs/crud-pro/CrudPro.d.ts +9 -1
- package/dist/libs/crud-pro/CrudPro.js +15 -0
- package/dist/libs/crud-pro/README.md +809 -0
- package/dist/libs/crud-pro/README_FUNC.md +193 -0
- package/dist/libs/crud-pro/exceptions.d.ts +2 -0
- package/dist/libs/crud-pro/exceptions.js +2 -0
- package/dist/libs/crud-pro/interfaces.d.ts +34 -1
- package/dist/libs/crud-pro/models/ExecuteContext.d.ts +3 -3
- package/dist/libs/crud-pro/models/ExecuteContext.js +2 -0
- package/dist/libs/crud-pro/models/RequestModel.d.ts +41 -1
- package/dist/libs/crud-pro/models/RequestModel.js +103 -39
- package/dist/libs/crud-pro/models/ResModel.d.ts +6 -4
- package/dist/libs/crud-pro/models/ServiceHub.d.ts +1 -0
- package/dist/libs/crud-pro/models/keys.d.ts +6 -1
- package/dist/libs/crud-pro/models/keys.js +5 -0
- package/dist/libs/crud-pro/services/CrudProDataTypeConvertService.d.ts +52 -0
- package/dist/libs/crud-pro/services/CrudProDataTypeConvertService.js +158 -0
- package/dist/libs/crud-pro/services/CrudProExecuteSqlService.js +20 -1
- package/dist/libs/crud-pro/services/CrudProFieldValidateService.d.ts +7 -0
- package/dist/libs/crud-pro/services/CrudProFieldValidateService.js +32 -0
- package/dist/libs/crud-pro/services/CrudProGenSqlService.d.ts +13 -0
- package/dist/libs/crud-pro/services/CrudProGenSqlService.js +44 -7
- package/dist/libs/crud-pro/services/CrudProOriginToExecuteSql.d.ts +43 -0
- package/dist/libs/crud-pro/services/CrudProOriginToExecuteSql.js +132 -1
- package/dist/libs/crud-pro/services/CrudProTableMetaService.d.ts +15 -1
- package/dist/libs/crud-pro/services/CrudProTableMetaService.js +107 -0
- package/dist/libs/crud-pro/services/CurdProServiceHub.d.ts +5 -1
- package/dist/libs/crud-pro/services/CurdProServiceHub.js +11 -0
- package/dist/libs/crud-pro/utils/DateTimeUtils.d.ts +1 -0
- package/dist/libs/crud-pro/utils/DateTimeUtils.js +3 -0
- package/dist/libs/crud-pro/utils/MixinUtils.d.ts +32 -0
- package/dist/libs/crud-pro/utils/MixinUtils.js +85 -1
- package/dist/libs/crud-pro/utils/ValidateUtils.js +1 -1
- package/dist/libs/crud-sharding/ROUTING_LOGIC.md +944 -0
- package/dist/libs/crud-sharding/ShardingConfig.d.ts +218 -0
- package/dist/libs/crud-sharding/ShardingConfig.js +32 -0
- package/dist/libs/crud-sharding/ShardingCountCache.d.ts +69 -0
- package/dist/libs/crud-sharding/ShardingCountCache.js +160 -0
- package/dist/libs/crud-sharding/ShardingCrudPro.d.ts +363 -0
- package/dist/libs/crud-sharding/ShardingCrudPro.js +699 -0
- package/dist/libs/crud-sharding/ShardingMerger.d.ts +130 -0
- package/dist/libs/crud-sharding/ShardingMerger.js +280 -0
- package/dist/libs/crud-sharding/ShardingRouter.d.ts +69 -0
- package/dist/libs/crud-sharding/ShardingRouter.js +377 -0
- package/dist/libs/crud-sharding/ShardingTableCreator.d.ts +146 -0
- package/dist/libs/crud-sharding/ShardingTableCreator.js +805 -0
- package/dist/libs/crud-sharding/ShardingUtils.d.ts +38 -0
- package/dist/libs/crud-sharding/ShardingUtils.js +77 -0
- package/dist/libs/crud-sharding/index.d.ts +45 -0
- package/dist/libs/crud-sharding/index.js +55 -0
- package/dist/models/StandardColumns.d.ts +71 -0
- package/dist/models/StandardColumns.js +28 -0
- package/dist/service/SysAppService.js +2 -2
- package/dist/service/SysConfigService.js +1 -1
- package/dist/service/SysDictDataService.js +2 -2
- package/dist/service/SysMenuService.js +1 -1
- package/dist/service/UserAccountService.d.ts +1 -1
- package/dist/service/crudstd/CrudStdService.d.ts +0 -1
- package/dist/service/crudstd/CrudStdService.js +0 -27
- package/dist/service/curd/CrudProQuick.d.ts +134 -4
- package/dist/service/curd/CrudProQuick.js +155 -3
- package/dist/service/curd/CurdMixService.d.ts +2 -1
- package/dist/service/curd/CurdMixService.js +5 -1
- package/dist/service/curd/CurdProService.d.ts +44 -2
- package/dist/service/curd/CurdProService.js +53 -1
- package/dist/service/curd/README.md +1001 -0
- package/dist/service/curd/fixSoftDelete.d.ts +14 -0
- package/dist/service/curd/fixSoftDelete.js +29 -11
- package/dist/service/flow/FlowConfigService.js +1 -1
- package/dist/service/flow/FlowInstanceCrudService.js +1 -1
- package/package.json +3 -1
- package/src/controller/gateway/AsyncTaskController.ts +1 -1
- package/src/controller/manage/CrudStandardDesignApi.ts +16 -100
- package/src/index.ts +3 -0
- package/src/libs/crud-pro/CrudPro.ts +19 -1
- package/src/libs/crud-pro/README.md +809 -0
- package/src/libs/crud-pro/README_FUNC.md +193 -0
- package/src/libs/crud-pro/exceptions.ts +2 -0
- package/src/libs/crud-pro/interfaces.ts +38 -1
- package/src/libs/crud-pro/models/ExecuteContext.ts +6 -3
- package/src/libs/crud-pro/models/RequestModel.ts +108 -44
- package/src/libs/crud-pro/models/ResModel.ts +10 -4
- package/src/libs/crud-pro/models/ServiceHub.ts +2 -0
- package/src/libs/crud-pro/models/keys.ts +5 -0
- package/src/libs/crud-pro/services/CrudProDataTypeConvertService.ts +171 -0
- package/src/libs/crud-pro/services/CrudProExecuteSqlService.ts +24 -1
- package/src/libs/crud-pro/services/CrudProFieldValidateService.ts +53 -1
- package/src/libs/crud-pro/services/CrudProGenSqlService.ts +51 -7
- package/src/libs/crud-pro/services/CrudProOriginToExecuteSql.ts +159 -2
- package/src/libs/crud-pro/services/CrudProTableMetaService.ts +139 -1
- package/src/libs/crud-pro/services/CurdProServiceHub.ts +16 -1
- package/src/libs/crud-pro/utils/DateTimeUtils.ts +3 -0
- package/src/libs/crud-pro/utils/MixinUtils.ts +97 -1
- package/src/libs/crud-pro/utils/ValidateUtils.ts +1 -1
- package/src/libs/crud-sharding/ROUTING_LOGIC.md +944 -0
- package/src/libs/crud-sharding/ShardingConfig.ts +240 -0
- package/src/libs/crud-sharding/ShardingCountCache.ts +200 -0
- package/src/libs/crud-sharding/ShardingCrudPro.ts +856 -0
- package/src/libs/crud-sharding/ShardingMerger.ts +382 -0
- package/src/libs/crud-sharding/ShardingRouter.ts +512 -0
- package/src/libs/crud-sharding/ShardingTableCreator.ts +1007 -0
- package/src/libs/crud-sharding/ShardingUtils.ts +84 -0
- package/src/libs/crud-sharding/index.ts +64 -0
- package/src/models/StandardColumns.ts +76 -0
- package/src/service/FileCenterService.ts +1 -1
- package/src/service/SysAppService.ts +2 -2
- package/src/service/SysConfigService.ts +1 -1
- package/src/service/SysDictDataService.ts +2 -2
- package/src/service/SysMenuService.ts +2 -2
- package/src/service/WorkbenchService.ts +1 -1
- package/src/service/anyapi/AnyApiService.ts +1 -1
- package/src/service/asyncTask/AsyncTaskRunnerService.ts +1 -1
- package/src/service/crudstd/CrudStdService.ts +0 -32
- package/src/service/curd/CrudProQuick.ts +164 -5
- package/src/service/curd/CurdMixService.ts +7 -2
- package/src/service/curd/CurdProService.ts +62 -3
- package/src/service/curd/README.md +1001 -0
- package/src/service/curd/fixCfgModel.ts +1 -2
- package/src/service/curd/fixSoftDelete.ts +38 -16
- package/src/service/flow/FlowConfigService.ts +1 -1
- package/src/service/flow/FlowInstanceCrudService.ts +1 -1
|
@@ -0,0 +1,809 @@
|
|
|
1
|
+
# CrudPro 使用指南
|
|
2
|
+
|
|
3
|
+
CrudPro 是一个功能强大的 CRUD 操作库,支持多种数据库(MySQL、PostgreSQL、SQL Server),提供了配置化的 SQL 执行方式,包括简单 SQL 模式和自定义 SQL 模式。
|
|
4
|
+
|
|
5
|
+
## 目录
|
|
6
|
+
|
|
7
|
+
- [快速开始](#快速开始)
|
|
8
|
+
- [核心概念](#核心概念)
|
|
9
|
+
- [配置详解](#配置详解)
|
|
10
|
+
- [使用示例](#使用示例)
|
|
11
|
+
- [高级特性](#高级特性)
|
|
12
|
+
- [API 参考](#api-参考)
|
|
13
|
+
|
|
14
|
+
## 快速开始
|
|
15
|
+
|
|
16
|
+
### 1. 基础初始化
|
|
17
|
+
|
|
18
|
+
```typescript
|
|
19
|
+
import { CrudPro } from './CrudPro';
|
|
20
|
+
import { Transaction } from './models/Transaction';
|
|
21
|
+
import { IConnectionPool } from './interfaces';
|
|
22
|
+
|
|
23
|
+
// 创建 CrudPro 实例
|
|
24
|
+
const crudPro = new CrudPro();
|
|
25
|
+
|
|
26
|
+
// 设置事务管理器
|
|
27
|
+
const transaction = new Transaction();
|
|
28
|
+
crudPro.transaction = transaction;
|
|
29
|
+
|
|
30
|
+
// 设置日志器
|
|
31
|
+
const logger = {
|
|
32
|
+
info: (msg: any, ...args: any[]) => console.log('[INFO]', msg, ...args),
|
|
33
|
+
debug: (msg: any, ...args: any[]) => console.log('[DEBUG]', msg, ...args),
|
|
34
|
+
error: (msg: any, ...args: any[]) => console.error('[ERROR]', msg, ...args),
|
|
35
|
+
warn: (msg: any, ...args: any[]) => console.warn('[WARN]', msg, ...args),
|
|
36
|
+
};
|
|
37
|
+
crudPro.logger = logger;
|
|
38
|
+
|
|
39
|
+
// 设置访问者信息(用于权限校验)
|
|
40
|
+
const visitor = {
|
|
41
|
+
isLogin: true,
|
|
42
|
+
isSuperAdmin: false,
|
|
43
|
+
accountId: 'user123',
|
|
44
|
+
nickName: '张三',
|
|
45
|
+
roleCodes: ['admin', 'editor'],
|
|
46
|
+
functionCodes: ['user:create', 'user:read'],
|
|
47
|
+
};
|
|
48
|
+
crudPro.visitor = visitor;
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### 2. 执行第一个查询
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
import { IRequestModel, IRequestCfgModel } from './interfaces';
|
|
55
|
+
|
|
56
|
+
// 请求参数
|
|
57
|
+
const reqJson: IRequestModel = {
|
|
58
|
+
method: 'user.getList', // 非必须,executeCrudByCfg 会使用 cfgJson.method
|
|
59
|
+
columns: 'id,name,email',
|
|
60
|
+
condition: { status: 1 },
|
|
61
|
+
pageNo: 1,
|
|
62
|
+
pageSize: 10,
|
|
63
|
+
orderBy: 'created_at-',
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
// 配置(可以从数据库读取)
|
|
67
|
+
const cfgJson: IRequestCfgModel = {
|
|
68
|
+
method: 'user.getList',
|
|
69
|
+
sqlTable: 'sys_user',
|
|
70
|
+
sqlDatabase: 'default_db',
|
|
71
|
+
sqlSimpleName: KeysOfSimpleSQL.SIMPLE_QUERY_PAGE, // 使用简单分页查询
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
// 执行
|
|
75
|
+
const result = await crudPro.executeCrudByCfg(reqJson, cfgJson);
|
|
76
|
+
console.log(result.getResRows()); // 获取查询结果
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## 核心概念
|
|
80
|
+
|
|
81
|
+
### 执行流程
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
1. 接收请求 (RequestModel)
|
|
85
|
+
↓
|
|
86
|
+
2. 加载配置 (RequestCfgModel)
|
|
87
|
+
↓
|
|
88
|
+
3. 字段过滤 (filterDataByTableMeta) ← 根据表结构过滤不存在的字段
|
|
89
|
+
↓
|
|
90
|
+
4. 数据类型转换 (convertDataTypeByTableMeta) ← 根据表结构字段类型自动转换
|
|
91
|
+
↓
|
|
92
|
+
5. 数据校验 (validateByAllow/rejectCfg/validateCfg)
|
|
93
|
+
↓
|
|
94
|
+
6. 权限校验 (validateByAuthCfg)
|
|
95
|
+
↓
|
|
96
|
+
7. 默认值设置 (updateByCfg)
|
|
97
|
+
↓
|
|
98
|
+
8. 生成 SQL (generateSQLList)
|
|
99
|
+
↓
|
|
100
|
+
9. 执行 SQL (executeSQLList)
|
|
101
|
+
↓
|
|
102
|
+
10. 返回结果 (ExecuteContext)
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### 简单 SQL 类型 (sqlSimpleName)
|
|
106
|
+
|
|
107
|
+
| 类型 | 说明 | 适用场景 |
|
|
108
|
+
|------|------|----------|
|
|
109
|
+
| `SIMPLE_QUERY` | 简单查询 | 列表查询 |
|
|
110
|
+
| `SIMPLE_QUERY_ONE` | 查询单条 | 详情查询 |
|
|
111
|
+
| `SIMPLE_QUERY_PAGE` | 分页查询 | 分页列表 |
|
|
112
|
+
| `SIMPLE_QUERY_COUNT` | 查询数量 | 统计总数 |
|
|
113
|
+
| `SIMPLE_QUERY_EXIST` | 判断存在 | 存在性检查 |
|
|
114
|
+
| `SIMPLE_UPDATE` | 更新操作 | 修改数据 |
|
|
115
|
+
| `SIMPLE_INSERT` | 插入操作 | 新增单条 |
|
|
116
|
+
| `SIMPLE_BATCH_INSERT` | 批量插入 | 批量新增 |
|
|
117
|
+
| `SIMPLE_DELETE` | 删除操作 | 删除数据 |
|
|
118
|
+
| `SIMPLE_INSERT_ON_DUPLICATE_UPDATE` | 插入或更新 | MySQL 特有 |
|
|
119
|
+
| `SIMPLE_INSERT_OR_UPDATE` | 插入或更新 | PostgreSQL/SQL Server |
|
|
120
|
+
| `CUSTOM` | 自定义 SQL | 复杂查询 |
|
|
121
|
+
|
|
122
|
+
### 查询条件操作符
|
|
123
|
+
|
|
124
|
+
支持 MongoDB 风格的查询条件:
|
|
125
|
+
|
|
126
|
+
```typescript
|
|
127
|
+
const condition = {
|
|
128
|
+
// 基础等于
|
|
129
|
+
status: 1,
|
|
130
|
+
|
|
131
|
+
// 比较操作
|
|
132
|
+
age: { $gt: 18 }, // 大于
|
|
133
|
+
score: { $gte: 60 }, // 大于等于
|
|
134
|
+
price: { $lt: 100 }, // 小于
|
|
135
|
+
count: { $lte: 10 }, // 小于等于
|
|
136
|
+
type: { $ne: 'deleted' }, // 不等于
|
|
137
|
+
|
|
138
|
+
// 范围查询
|
|
139
|
+
id: { $in: [1, 2, 3] }, // IN
|
|
140
|
+
code: { $nin: ['a', 'b'] }, // NOT IN
|
|
141
|
+
amount: { $range: [100, 200] }, // BETWEEN
|
|
142
|
+
|
|
143
|
+
// 模糊查询
|
|
144
|
+
name: { $like: '张' }, // 前缀匹配 (张%)
|
|
145
|
+
title: { $likeInclude: '文章' }, // 包含匹配 (%文章%)
|
|
146
|
+
|
|
147
|
+
// NULL 判断
|
|
148
|
+
deleted_at: { $null: true }, // IS NULL
|
|
149
|
+
updated_at: { $notNull: true }, // IS NOT NULL
|
|
150
|
+
|
|
151
|
+
// 逻辑组合
|
|
152
|
+
$or: [
|
|
153
|
+
{ name: { $like: '张' } },
|
|
154
|
+
{ name: { $like: '李' } },
|
|
155
|
+
],
|
|
156
|
+
};
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## 配置详解
|
|
160
|
+
|
|
161
|
+
### 请求配置 (IRequestCfgModel)
|
|
162
|
+
|
|
163
|
+
```typescript
|
|
164
|
+
interface IRequestCfgModel {
|
|
165
|
+
method: string; // 方法标识(必填)
|
|
166
|
+
sqlTable?: string; // 表名
|
|
167
|
+
sqlSchema?: string; // Schema(PostgreSQL/SQL Server)
|
|
168
|
+
sqlDatabase?: string; // 数据库名
|
|
169
|
+
sqlDbType?: 'mysql' | 'postgres' | 'sqlserver';
|
|
170
|
+
|
|
171
|
+
// 执行模式(二选一,sqlCfgList 优先级更高)
|
|
172
|
+
sqlSimpleName?: KeysOfSimpleSQL; // 简单 SQL 类型
|
|
173
|
+
sqlCfgList?: ISqlCfgModel[]; // 自定义 SQL 列表
|
|
174
|
+
|
|
175
|
+
// 事务控制
|
|
176
|
+
transactionEnable?: boolean; // 是否开启事务
|
|
177
|
+
transactionIsolation?: number; // 事务隔离级别
|
|
178
|
+
|
|
179
|
+
// 数据操作配置
|
|
180
|
+
uniqueColumn?: string[]; // 唯一键列(用于 UPSERT)
|
|
181
|
+
updateCfg?: Record<string, IFuncCfgModel>; // 字段默认值配置
|
|
182
|
+
allowCfg?: Record<string, string[]>; // 允许修改的字段
|
|
183
|
+
rejectCfg?: Record<string, string[]>; // 拒绝修改的字段
|
|
184
|
+
validateCfg?: Record<string, IValidatorCfgItem[]>; // 字段校验规则
|
|
185
|
+
|
|
186
|
+
// 权限配置
|
|
187
|
+
authType?: 'free' | 'login' | 'byRoleCode' | 'byFuncCode';
|
|
188
|
+
authConfig?: string | string[]; // 角色码或功能点码
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### 自定义 SQL 配置 (ISqlCfgModel)
|
|
193
|
+
|
|
194
|
+
```typescript
|
|
195
|
+
interface ISqlCfgModel {
|
|
196
|
+
resName?: string; // 结果名称
|
|
197
|
+
resPicker?: string; // 结果提取器
|
|
198
|
+
|
|
199
|
+
// 表配置
|
|
200
|
+
sqlTable?: string;
|
|
201
|
+
sqlSchema?: string;
|
|
202
|
+
sqlDatabase?: string;
|
|
203
|
+
sqlDbType?: SqlDbType;
|
|
204
|
+
columns?: string | string[];
|
|
205
|
+
columnsRelation?: ColumnRelation[];
|
|
206
|
+
|
|
207
|
+
// SQL 配置
|
|
208
|
+
originSql?: string; // 原始 SQL(含占位符)
|
|
209
|
+
executeSql?: string; // 可执行 SQL
|
|
210
|
+
executeSqlArgs?: any[]; // SQL 参数
|
|
211
|
+
isNativeSQL?: boolean; // 是否原生 SQL
|
|
212
|
+
|
|
213
|
+
// 执行控制
|
|
214
|
+
validate?: IFuncCfgModel; // 前置校验
|
|
215
|
+
executeWhen?: IFuncCfgModel; // 执行条件
|
|
216
|
+
}
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### SQL 占位符
|
|
220
|
+
|
|
221
|
+
```sql
|
|
222
|
+
-- 表名占位符
|
|
223
|
+
SELECT * FROM @@table WHERE id = 1
|
|
224
|
+
|
|
225
|
+
-- 列名占位符
|
|
226
|
+
SELECT @@columns FROM @@table
|
|
227
|
+
|
|
228
|
+
-- 条件占位符
|
|
229
|
+
SELECT * FROM @@table WHERE @@asWhere:condition
|
|
230
|
+
|
|
231
|
+
-- 更新占位符
|
|
232
|
+
UPDATE @@table SET @@asUpdate:data WHERE id = @@condition.id
|
|
233
|
+
|
|
234
|
+
-- 插入占位符
|
|
235
|
+
INSERT INTO @@table (@@asInsertKeys:data) VALUES (@@asInsertValues:data)
|
|
236
|
+
|
|
237
|
+
-- 批量插入
|
|
238
|
+
INSERT INTO @@table (@@asBatchInsertKeys:data) VALUES @@asBatchInsertValues:data
|
|
239
|
+
|
|
240
|
+
-- 分页和排序
|
|
241
|
+
SELECT * FROM @@table @@asWhere:condition @@orderBys @@offsetLimit
|
|
242
|
+
|
|
243
|
+
-- 从请求中取单个值
|
|
244
|
+
SELECT * FROM @@table WHERE id = @@data.id
|
|
245
|
+
SELECT * FROM @@table WHERE status = @@condition.status
|
|
246
|
+
|
|
247
|
+
-- 从结果中提取值(多 SQL 场景)
|
|
248
|
+
SELECT * FROM @@table WHERE id = @@pickResAsNumber:rows[0].id
|
|
249
|
+
SELECT * FROM @@table WHERE name = @@pickResAsString:row.name
|
|
250
|
+
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
## @@function 说明
|
|
254
|
+
|
|
255
|
+
@@function 不是执行数据库的内置函数,而是执行CrudProExecuteFuncService提供的内置函数。完整的内置函数列表和用法请参考 [README_FUNC.md](./README_FUNC.md)。
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
## 使用示例
|
|
259
|
+
|
|
260
|
+
### 示例 1:简单分页查询
|
|
261
|
+
|
|
262
|
+
```typescript
|
|
263
|
+
// 配置
|
|
264
|
+
const cfgJson: IRequestCfgModel = {
|
|
265
|
+
method: 'article.list',
|
|
266
|
+
sqlTable: 'article',
|
|
267
|
+
sqlSimpleName: KeysOfSimpleSQL.SIMPLE_QUERY_PAGE,
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
// 请求
|
|
271
|
+
const reqJson: IRequestModel = {
|
|
272
|
+
method: 'article.list', // 非必须,executeCrudByCfg 会使用 cfgJson.method
|
|
273
|
+
columns: 'id,title,content,author_id,created_at',
|
|
274
|
+
condition: {
|
|
275
|
+
status: 1,
|
|
276
|
+
category_id: { $in: [1, 2, 3] },
|
|
277
|
+
created_at: { $gte: '2024-01-01' },
|
|
278
|
+
},
|
|
279
|
+
pageNo: 1,
|
|
280
|
+
pageSize: 20,
|
|
281
|
+
orderBy: 'created_at-',
|
|
282
|
+
};
|
|
283
|
+
|
|
284
|
+
const ctx = await crudPro.executeCrudByCfg(reqJson, cfgJson);
|
|
285
|
+
const { rows, total_count } = ctx.getResModelForQueryPage();
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### 示例 2:单条数据插入
|
|
289
|
+
|
|
290
|
+
```typescript
|
|
291
|
+
// 配置:带默认值和字段白名单
|
|
292
|
+
const cfgJson: IRequestCfgModel = {
|
|
293
|
+
method: 'user.create', // 非必须,此处仅用于打印日志或调试跟踪记录
|
|
294
|
+
sqlTable: 'sys_user',
|
|
295
|
+
sqlSimpleName: KeysOfSimpleSQL.SIMPLE_INSERT,
|
|
296
|
+
sqlDatabase: 'default_db',
|
|
297
|
+
allowCfg: {
|
|
298
|
+
data: ['name', 'email', 'phone', 'status'], // 只允许这些字段
|
|
299
|
+
},
|
|
300
|
+
updateCfg: {
|
|
301
|
+
'data.created_at': { functionName: 'getCurrentTimeString' }, // 设置创建时间
|
|
302
|
+
'data.created_by': { context: 'visitor.accountId' }, // 设置创建人
|
|
303
|
+
},
|
|
304
|
+
validateCfg: {
|
|
305
|
+
'data.name': ['required', 'string', 'length:2,50'],
|
|
306
|
+
'data.email': ['required', 'email'],
|
|
307
|
+
'data.phone': ['phone:cn'],
|
|
308
|
+
},
|
|
309
|
+
};
|
|
310
|
+
|
|
311
|
+
// 请求
|
|
312
|
+
const reqJson: IRequestModel = {
|
|
313
|
+
method: 'user.create', // 非必须,executeCrudByCfg 会使用 cfgJson.method
|
|
314
|
+
data: {
|
|
315
|
+
name: '张三',
|
|
316
|
+
email: 'zhangsan@example.com',
|
|
317
|
+
phone: '13800138000',
|
|
318
|
+
status: 1,
|
|
319
|
+
},
|
|
320
|
+
};
|
|
321
|
+
|
|
322
|
+
const ctx = await crudPro.executeCrudByCfg(reqJson, cfgJson);
|
|
323
|
+
console.log('插入结果:', ctx.getResModel().affected);
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
### 示例 3:批量插入
|
|
327
|
+
|
|
328
|
+
```typescript
|
|
329
|
+
const cfgJson: IRequestCfgModel = {
|
|
330
|
+
method: 'log.batchCreate',
|
|
331
|
+
sqlTable: 'operation_log',
|
|
332
|
+
sqlSimpleName: KeysOfSimpleSQL.SIMPLE_BATCH_INSERT,
|
|
333
|
+
};
|
|
334
|
+
|
|
335
|
+
const reqJson: IRequestModel = {
|
|
336
|
+
method: 'log.batchCreate', // 非必须,executeCrudByCfg 会使用 cfgJson.method
|
|
337
|
+
data: [
|
|
338
|
+
{ action: 'login', user_id: '1', created_at: new Date() },
|
|
339
|
+
{ action: 'logout', user_id: '1', created_at: new Date() },
|
|
340
|
+
{ action: 'login', user_id: '2', created_at: new Date() },
|
|
341
|
+
],
|
|
342
|
+
};
|
|
343
|
+
|
|
344
|
+
const ctx = await crudPro.executeCrudByCfg(reqJson, cfgJson);
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
### 示例 4:带事务的多 SQL 操作
|
|
348
|
+
|
|
349
|
+
```typescript
|
|
350
|
+
const cfgJson: IRequestCfgModel = {
|
|
351
|
+
method: 'order.create',
|
|
352
|
+
sqlTable: 'orders',
|
|
353
|
+
transactionEnable: true, // 开启事务
|
|
354
|
+
functionCfg: {
|
|
355
|
+
uuid: { functionName: 'uuid' }
|
|
356
|
+
},
|
|
357
|
+
sqlCfgList: [
|
|
358
|
+
// 第一步:插入订单
|
|
359
|
+
{
|
|
360
|
+
resName: 'order',
|
|
361
|
+
resPicker: KeysOfSqlResPicker.UPDATE_RESULT,
|
|
362
|
+
sqlTable: 'orders',
|
|
363
|
+
originSql: `INSERT INTO @@table (order_no, user_id, amount, status)
|
|
364
|
+
VALUES (@@function:uuid(), @@data.user_id, @@data.amount, 0)`,
|
|
365
|
+
},
|
|
366
|
+
// 第二步:插入订单明细
|
|
367
|
+
{
|
|
368
|
+
resName: 'items',
|
|
369
|
+
sqlTable: 'order_items',
|
|
370
|
+
resPicker: null, // INSERT、UPDATE语句自动使用:KeysOfSqlResPicker.UPDATE_RESULT
|
|
371
|
+
originSql: `INSERT INTO @@table (order_id, product_id, quantity, price)
|
|
372
|
+
VALUES (@@pickResAsString:order.insertId, @@data.product_id, @@data.quantity, @@data.price)`,
|
|
373
|
+
},
|
|
374
|
+
// 第三步:扣减库存
|
|
375
|
+
{
|
|
376
|
+
resName: 'stockResult',
|
|
377
|
+
sqlTable: 'product_stock',
|
|
378
|
+
originSql: `UPDATE @@table
|
|
379
|
+
SET stock = stock - @@data.quantity
|
|
380
|
+
WHERE product_id = @@data.product_id`,
|
|
381
|
+
},
|
|
382
|
+
],
|
|
383
|
+
};
|
|
384
|
+
|
|
385
|
+
const reqJson: IRequestModel = {
|
|
386
|
+
method: 'order.create', // 非必须,executeCrudByCfg 会使用 cfgJson.method
|
|
387
|
+
data: {
|
|
388
|
+
user_id: 'user123',
|
|
389
|
+
amount: 199.99,
|
|
390
|
+
product_id: 'prod456',
|
|
391
|
+
quantity: 2,
|
|
392
|
+
price: 99.99,
|
|
393
|
+
},
|
|
394
|
+
};
|
|
395
|
+
|
|
396
|
+
const ctx = await crudPro.executeCrudByCfg(reqJson, cfgJson);
|
|
397
|
+
console.log('订单创建成功:', ctx.getResModelItem('order'));
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
### 示例 5:权限控制
|
|
401
|
+
|
|
402
|
+
```typescript
|
|
403
|
+
// 登录即可访问
|
|
404
|
+
const cfg1: IRequestCfgModel = {
|
|
405
|
+
method: 'user.profile',
|
|
406
|
+
sqlTable: 'sys_user',
|
|
407
|
+
sqlSimpleName: KeysOfSimpleSQL.SIMPLE_QUERY_ONE,
|
|
408
|
+
authType: 'login',
|
|
409
|
+
};
|
|
410
|
+
|
|
411
|
+
// 需要特定角色
|
|
412
|
+
const cfg2: IRequestCfgModel = {
|
|
413
|
+
method: 'admin.userList',
|
|
414
|
+
sqlTable: 'sys_user',
|
|
415
|
+
sqlSimpleName: KeysOfSimpleSQL.SIMPLE_QUERY_PAGE,
|
|
416
|
+
authType: 'byRoleCode',
|
|
417
|
+
authConfig: 'admin', // 或 ['admin', 'super_admin']
|
|
418
|
+
};
|
|
419
|
+
|
|
420
|
+
// 需要特定功能点
|
|
421
|
+
const cfg3: IRequestCfgModel = {
|
|
422
|
+
method: 'user.delete',
|
|
423
|
+
sqlTable: 'sys_user',
|
|
424
|
+
sqlSimpleName: KeysOfSimpleSQL.SIMPLE_DELETE,
|
|
425
|
+
authType: 'byFuncCode',
|
|
426
|
+
authConfig: 'user:delete',
|
|
427
|
+
};
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
### 示例 6:直接执行 SQL
|
|
431
|
+
|
|
432
|
+
```typescript
|
|
433
|
+
import { ISqlCfgModel } from './interfaces';
|
|
434
|
+
|
|
435
|
+
// 框架自动转换占位符(? → $1/$2 或 @fatcms_ms1/@fatcms_ms2)
|
|
436
|
+
// 自动转换虽然方便,但当 SQL 中包含非参数绑定的问号(如正则表达式、字符串常量中的 ?)时会被误替换,
|
|
437
|
+
// 此时需使用 isNativeSQL: true 并手写数据库原生占位符,详见示例 6b
|
|
438
|
+
const sqlCfg: ISqlCfgModel = {
|
|
439
|
+
sqlTable: 'sys_user',
|
|
440
|
+
sqlDatabase: 'default_db',
|
|
441
|
+
executeSql: 'SELECT * FROM sys_user WHERE status = ? AND created_at > ?',
|
|
442
|
+
executeSqlArgs: [1, '2024-01-01'],
|
|
443
|
+
};
|
|
444
|
+
|
|
445
|
+
const result = await crudPro.executeSQL(sqlCfg);
|
|
446
|
+
console.log(result);
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
### 示例 6b:原生 SQL 模式(isNativeSQL)
|
|
450
|
+
|
|
451
|
+
当 `isNativeSQL: true` 时,框架不转换占位符,SQL 按原样发送到数据库驱动。
|
|
452
|
+
|
|
453
|
+
```typescript
|
|
454
|
+
// PostgreSQL:直接使用 $1、$2 占位符
|
|
455
|
+
const pgSqlCfg: ISqlCfgModel = {
|
|
456
|
+
isNativeSQL: true,
|
|
457
|
+
sqlDatabase: 'default_db',
|
|
458
|
+
executeSql: 'SELECT * FROM sys_user WHERE status = $1 AND created_at > $2',
|
|
459
|
+
executeSqlArgs: [1, '2024-01-01'],
|
|
460
|
+
};
|
|
461
|
+
|
|
462
|
+
// SQL Server:直接使用 @param 占位符
|
|
463
|
+
const mssqlSqlCfg: ISqlCfgModel = {
|
|
464
|
+
isNativeSQL: true,
|
|
465
|
+
sqlDatabase: 'default_db',
|
|
466
|
+
executeSql: 'SELECT * FROM sys_user WHERE status = @p1 AND created_at > @p2',
|
|
467
|
+
executeSqlArgs: [1, '2024-01-01'],
|
|
468
|
+
};
|
|
469
|
+
|
|
470
|
+
const result = await crudPro.executeSQL(pgSqlCfg);
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
### 示例 7:从数据库加载配置
|
|
474
|
+
|
|
475
|
+
```typescript
|
|
476
|
+
// 假设数据库中已存储了配置
|
|
477
|
+
const reqJson: IRequestModel = {
|
|
478
|
+
method: 'article.list', // 通过 method 查找配置
|
|
479
|
+
condition: { status: 1 },
|
|
480
|
+
pageNo: 1,
|
|
481
|
+
pageSize: 10,
|
|
482
|
+
};
|
|
483
|
+
|
|
484
|
+
// 从数据库加载配置并执行(启用缓存)
|
|
485
|
+
const ctx = await crudPro.executeCrud(reqJson, true);
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
## 高级特性
|
|
489
|
+
|
|
490
|
+
### 1. 字段校验规则
|
|
491
|
+
|
|
492
|
+
```typescript
|
|
493
|
+
const validateCfg = {
|
|
494
|
+
'data.name': [
|
|
495
|
+
'required', // 必填
|
|
496
|
+
'string', // 字符串类型
|
|
497
|
+
'length:2,50', // 长度 2-50
|
|
498
|
+
'name', // 必须是合法标识符
|
|
499
|
+
],
|
|
500
|
+
'data.email': [
|
|
501
|
+
'required',
|
|
502
|
+
'email', // 邮箱格式
|
|
503
|
+
],
|
|
504
|
+
'data.age': [
|
|
505
|
+
'integer', // 整数
|
|
506
|
+
'scale:[0,150]', // 范围 0-150
|
|
507
|
+
],
|
|
508
|
+
'data.status': [
|
|
509
|
+
'enum:0,1,2', // 枚举值
|
|
510
|
+
],
|
|
511
|
+
'data.phone': [
|
|
512
|
+
'phone:cn', // 中国手机号
|
|
513
|
+
],
|
|
514
|
+
'data.birthday': [
|
|
515
|
+
'moment:YYYY-MM-DD', // 日期格式
|
|
516
|
+
],
|
|
517
|
+
'data.remark': [
|
|
518
|
+
(value: string) => { // 自定义校验函数
|
|
519
|
+
if (value && value.length > 500) {
|
|
520
|
+
throw { code: 'REMARK_TOO_LONG', message: '备注不能超过500字' };
|
|
521
|
+
}
|
|
522
|
+
},
|
|
523
|
+
],
|
|
524
|
+
};
|
|
525
|
+
```
|
|
526
|
+
|
|
527
|
+
### 2. 字段默认值设置(强制使用更新后的值,避免非法数据)
|
|
528
|
+
|
|
529
|
+
```typescript
|
|
530
|
+
const updateCfg = {
|
|
531
|
+
// 常量值
|
|
532
|
+
'data.status': { const: 1 },
|
|
533
|
+
'data.version': { constNumber: 1 },
|
|
534
|
+
'data.is_deleted': { constBool: false },
|
|
535
|
+
|
|
536
|
+
// 从上下文取值
|
|
537
|
+
'data.created_by': { context: 'visitor.accountId' },
|
|
538
|
+
'data.updated_by': { context: 'visitor.nickName' },
|
|
539
|
+
|
|
540
|
+
// 函数调用(uuid 为内置函数,generateOrderNo 需自定义注册, 参考README_FUNC.md)
|
|
541
|
+
'data.id': { functionName: 'uuid' },
|
|
542
|
+
'data.order_no': { functionName: 'generateOrderNo', functionParams: ['PRE'] },
|
|
543
|
+
|
|
544
|
+
// 表达式执行(使用 EJS 模板语法,上下文变量为 reqModel / resModel / currentValue)
|
|
545
|
+
'data.full_name': { executeExpressReturnString: '<%= reqModel.data.first_name %> <%= reqModel.data.last_name %>' },
|
|
546
|
+
};
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
### 3. 关联查询(columnsRelation)
|
|
550
|
+
|
|
551
|
+
> `columnsRelation` 的关联数据填充在应用服务层实现(`src/service/curd/`),不在 crud-pro 库内。
|
|
552
|
+
> 完整文档请参考 [src/service/curd/README.md](../../service/curd/README.md)。
|
|
553
|
+
|
|
554
|
+
|
|
555
|
+
### 4. 排序语法
|
|
556
|
+
|
|
557
|
+
```typescript
|
|
558
|
+
// 标准 SQL 格式
|
|
559
|
+
orderBy: 'created_at DESC, amount ASC'
|
|
560
|
+
|
|
561
|
+
// 简写格式(+ 升序,- 降序)
|
|
562
|
+
orderBy: 'created_at-, amount+'
|
|
563
|
+
orderBy: 'name, age-' // 默认升序
|
|
564
|
+
|
|
565
|
+
// 数组格式(字符串 + 对象混合)
|
|
566
|
+
orderBy: [
|
|
567
|
+
'order_id',
|
|
568
|
+
{ fieldName: 'created_at', orderType: 'desc' },
|
|
569
|
+
'amount+',
|
|
570
|
+
]
|
|
571
|
+
```
|
|
572
|
+
|
|
573
|
+
### 5. 分页方式
|
|
574
|
+
|
|
575
|
+
```typescript
|
|
576
|
+
// 方式 1:使用 pageNo/pageSize
|
|
577
|
+
const req1: IRequestModel = {
|
|
578
|
+
pageNo: 2, // 第 2 页
|
|
579
|
+
pageSize: 20, // 每页 20 条
|
|
580
|
+
};
|
|
581
|
+
|
|
582
|
+
// 方式 2:使用 limit/offset
|
|
583
|
+
const req2: IRequestModel = {
|
|
584
|
+
limit: 20,
|
|
585
|
+
offset: 20, // 跳过 20 条
|
|
586
|
+
};
|
|
587
|
+
```
|
|
588
|
+
|
|
589
|
+
### 6. 数据类型自动转换
|
|
590
|
+
|
|
591
|
+
CrudPro 在执行 INSERT/UPDATE 操作前,会根据表结构字段类型自动转换数据格式,确保数据与数据库方言兼容。
|
|
592
|
+
|
|
593
|
+
#### PostgreSQL ARRAY 类型
|
|
594
|
+
|
|
595
|
+
PostgreSQL 的 ARRAY 字段要求使用数组字面量语法 `{"a","b","c"}`,而前端/Node.js 层通常传递 JSON 格式 `["a","b","c"]`。CrudPro 会自动完成转换:
|
|
596
|
+
|
|
597
|
+
```typescript
|
|
598
|
+
// 无需手动处理,CrudPro 自动转换
|
|
599
|
+
const cfgJson: IRequestCfgModel = {
|
|
600
|
+
method: 'article.create',
|
|
601
|
+
sqlTable: 'article',
|
|
602
|
+
sqlDatabase: 'my_pg_db',
|
|
603
|
+
sqlDbType: SqlDbType.postgres,
|
|
604
|
+
sqlSimpleName: KeysOfSimpleSQL.SIMPLE_INSERT,
|
|
605
|
+
};
|
|
606
|
+
|
|
607
|
+
// 前端传入 JSON 数组
|
|
608
|
+
const reqJson: IRequestModel = {
|
|
609
|
+
data: {
|
|
610
|
+
title: '文章标题',
|
|
611
|
+
tags: ['技术', '前端', 'React'], // JSON 数组 → 自动转为 {"技术","前端","React"}
|
|
612
|
+
categories: '[1,2,3]', // JSON 字符串 → 自动转为 {"1","2","3"}
|
|
613
|
+
},
|
|
614
|
+
};
|
|
615
|
+
|
|
616
|
+
// 执行后,tags 和 categories 字段会自动转为 PG 数组字面量格式
|
|
617
|
+
```
|
|
618
|
+
|
|
619
|
+
**支持的转换:**
|
|
620
|
+
|
|
621
|
+
| 源数据格式 | 转换结果 | 说明 |
|
|
622
|
+
|-----------|---------|------|
|
|
623
|
+
| `["a","b","c"]` | `{"a","b","c"}` | 字符串数组:双引号包裹 |
|
|
624
|
+
| `[1,2,3]` | `{1,2,3}` | 数字数组:不加引号 |
|
|
625
|
+
| `[true,false]` | `{t,f}` | 布尔数组:转为 t/f |
|
|
626
|
+
| `[1,null,3]` | `{1,NULL,3}` | 含 null:输出 NULL |
|
|
627
|
+
| `[]` | `{}` | 空数组 |
|
|
628
|
+
| `['he"llo']` | `{"he\"llo"}` | 特殊字符自动转义 |
|
|
629
|
+
| `'[1,2,3]'` | `{1,2,3}` | JSON 字符串自动解析后转换 |
|
|
630
|
+
|
|
631
|
+
**适用操作:**
|
|
632
|
+
|
|
633
|
+
- `SIMPLE_INSERT`
|
|
634
|
+
- `SIMPLE_UPDATE`
|
|
635
|
+
- `SIMPLE_INSERT_ON_DUPLICATE_UPDATE`
|
|
636
|
+
- `SIMPLE_INSERT_OR_UPDATE`
|
|
637
|
+
- `SIMPLE_BATCH_INSERT`(批量插入时逐行转换)
|
|
638
|
+
|
|
639
|
+
> 此功能仅对 PostgreSQL 生效,MySQL 和 SQL Server 不需要此转换。
|
|
640
|
+
> 转换依赖 `getTableMeta()` 获取表字段类型信息,已复用缓存机制,不会产生额外查询开销。
|
|
641
|
+
|
|
642
|
+
## API 参考
|
|
643
|
+
|
|
644
|
+
### CrudPro 类
|
|
645
|
+
|
|
646
|
+
#### 属性设置
|
|
647
|
+
|
|
648
|
+
| 属性 | 类型 | 必填 | 说明 |
|
|
649
|
+
|------|------|------|------|
|
|
650
|
+
| `transaction` | `Transaction` | 是 | 事务管理器 |
|
|
651
|
+
| `logger` | `ILogger` | 是 | 日志器 |
|
|
652
|
+
| `visitor` | `IVisitor` | 是 | 访问者信息 |
|
|
653
|
+
| `contextFunc` | `IExecuteContextFunc` | 否 | 上下文函数扩展 |
|
|
654
|
+
| `contextCfg` | `ICrudProCfg` | 否 | 全局配置 |
|
|
655
|
+
|
|
656
|
+
#### 核心方法
|
|
657
|
+
|
|
658
|
+
##### `executeCrudByCfg(reqJson, cfgJson)`
|
|
659
|
+
|
|
660
|
+
核心执行方法,通过配置执行 CRUD 操作。
|
|
661
|
+
|
|
662
|
+
```typescript
|
|
663
|
+
public async executeCrudByCfg(
|
|
664
|
+
reqJson: IRequestModel,
|
|
665
|
+
cfgJson: IRequestCfgModel
|
|
666
|
+
): Promise<ExecuteContext>
|
|
667
|
+
```
|
|
668
|
+
|
|
669
|
+
**参数:**
|
|
670
|
+
- `reqJson`: 请求参数
|
|
671
|
+
- `cfgJson`: 执行配置
|
|
672
|
+
|
|
673
|
+
**返回:** `ExecuteContext` - 执行上下文,包含结果数据
|
|
674
|
+
|
|
675
|
+
---
|
|
676
|
+
|
|
677
|
+
##### `executeCrud(reqJson, isEnableCache)`
|
|
678
|
+
|
|
679
|
+
从数据库加载配置并执行。
|
|
680
|
+
|
|
681
|
+
```typescript
|
|
682
|
+
public async executeCrud(
|
|
683
|
+
reqJson: IRequestModel,
|
|
684
|
+
isEnableCache: boolean
|
|
685
|
+
): Promise<ExecuteContext>
|
|
686
|
+
```
|
|
687
|
+
|
|
688
|
+
**参数:**
|
|
689
|
+
- `reqJson`: 请求参数(必须包含 `method`)
|
|
690
|
+
- `isEnableCache`: 是否启用配置缓存
|
|
691
|
+
|
|
692
|
+
---
|
|
693
|
+
|
|
694
|
+
##### `executeSQL(sqlCfgModel)`
|
|
695
|
+
|
|
696
|
+
直接执行 SQL。
|
|
697
|
+
|
|
698
|
+
```typescript
|
|
699
|
+
public async executeSQL(sqlCfgModel: ISqlCfgModel): Promise<any>
|
|
700
|
+
```
|
|
701
|
+
|
|
702
|
+
---
|
|
703
|
+
|
|
704
|
+
##### `getCachedCfgByMethod(method, isEnableCache)`
|
|
705
|
+
|
|
706
|
+
从缓存或数据库获取配置。
|
|
707
|
+
|
|
708
|
+
```typescript
|
|
709
|
+
public async getCachedCfgByMethod(
|
|
710
|
+
method: string,
|
|
711
|
+
isEnableCache: boolean
|
|
712
|
+
): Promise<IRequestCfgModel>
|
|
713
|
+
```
|
|
714
|
+
|
|
715
|
+
---
|
|
716
|
+
|
|
717
|
+
##### `getAllTableInfos(query, options?)`
|
|
718
|
+
|
|
719
|
+
获取数据库中的所有表信息。
|
|
720
|
+
|
|
721
|
+
```typescript
|
|
722
|
+
public async getAllTableInfos(
|
|
723
|
+
query: ITableNamesQuery,
|
|
724
|
+
options?: ITableNamesOptions
|
|
725
|
+
): Promise<ITableListResult>
|
|
726
|
+
```
|
|
727
|
+
|
|
728
|
+
### ExecuteContext 结果处理
|
|
729
|
+
|
|
730
|
+
| 方法 | 说明 |
|
|
731
|
+
|------|------|
|
|
732
|
+
| `getResRows()` | 获取查询结果数组 |
|
|
733
|
+
| `getOneObj()` | 获取单条结果(key 为 'row') |
|
|
734
|
+
| `getResModelItem(name)` | 获取指定名称的结果 |
|
|
735
|
+
| `getResModelItemLodash(name)` | 支持路径获取(如 'rows[0].id') |
|
|
736
|
+
| `getResModelForQueryPage()` | 获取分页查询结果(含 total_count) |
|
|
737
|
+
| `getResMessage()` | 获取执行消息 |
|
|
738
|
+
|
|
739
|
+
### 全局配置 (ICrudProCfg)
|
|
740
|
+
|
|
741
|
+
```typescript
|
|
742
|
+
interface ICrudProCfg {
|
|
743
|
+
sysDatabaseName?: string; // 默认:fatcms
|
|
744
|
+
sysDatabaseDbType?: SqlDbType; // 默认:mysql
|
|
745
|
+
methodsTableName?: string; // 默认:sys_crud_methods
|
|
746
|
+
methodsCacheTime?: number; // 默认:60000 (毫秒)
|
|
747
|
+
dictItemTableName?: string; // 默认:sys_data_dict_item
|
|
748
|
+
sysConfigTableName?: string; // 默认:sys_configs
|
|
749
|
+
tableMetaCacheTime?: number; // 表结构缓存时间
|
|
750
|
+
}
|
|
751
|
+
```
|
|
752
|
+
|
|
753
|
+
## 异常处理
|
|
754
|
+
|
|
755
|
+
CrudPro 使用 `CommonException` 抛出异常,可通过 `code` 字段识别错误类型:
|
|
756
|
+
|
|
757
|
+
```typescript
|
|
758
|
+
try {
|
|
759
|
+
await crudPro.executeCrudByCfg(reqJson, cfgJson);
|
|
760
|
+
} catch (e) {
|
|
761
|
+
if (e instanceof CommonException) {
|
|
762
|
+
console.log('错误码:', e.code);
|
|
763
|
+
console.log('错误消息:', e.message);
|
|
764
|
+
|
|
765
|
+
// 常见错误码处理
|
|
766
|
+
switch (e.code) {
|
|
767
|
+
case 'NO_AUTH':
|
|
768
|
+
// 权限不足
|
|
769
|
+
break;
|
|
770
|
+
case 'NOT_LOGIN':
|
|
771
|
+
// 未登录
|
|
772
|
+
break;
|
|
773
|
+
case 'CFG_NOT_FOUND':
|
|
774
|
+
// 配置不存在
|
|
775
|
+
break;
|
|
776
|
+
case 'VALIDATE_EXCEPTION':
|
|
777
|
+
// 数据校验失败
|
|
778
|
+
break;
|
|
779
|
+
case 'RUN_SQL_EXCEPTION_ER_DUP_ENTRY':
|
|
780
|
+
// 数据重复
|
|
781
|
+
break;
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
```
|
|
786
|
+
|
|
787
|
+
### 常见错误码
|
|
788
|
+
|
|
789
|
+
| 错误码 | 说明 |
|
|
790
|
+
|--------|------|
|
|
791
|
+
| `NO_AUTH` | 没有权限 |
|
|
792
|
+
| `NOT_LOGIN` | 未登录 |
|
|
793
|
+
| `CFG_NOT_FOUND` | 配置不存在 |
|
|
794
|
+
| `CFG_METHOD_EMPTY` | 方法名为空 |
|
|
795
|
+
| `VALIDATE_EXCEPTION` | 数据校验失败 |
|
|
796
|
+
| `VALIDATE_ALLOW_ERR` | 包含不允许的字段 |
|
|
797
|
+
| `VALIDATE_REJECT_ERR` | 包含被拒绝的字段 |
|
|
798
|
+
| `RUN_SQL_EXCEPTION_ER_DUP_ENTRY` | 数据重复 |
|
|
799
|
+
| `RUN_SQL_EXCEPTION_ER_NO_SUCH_TABLE` | 表不存在 |
|
|
800
|
+
|
|
801
|
+
## 最佳实践
|
|
802
|
+
|
|
803
|
+
1. **配置管理**:将常用配置存储到数据库,通过 `method` 动态加载
|
|
804
|
+
2. **缓存策略**:生产环境启用配置缓存,减少数据库查询
|
|
805
|
+
3. **权限控制**:合理使用 `authType` 和 `authConfig` 保护接口
|
|
806
|
+
4. **字段过滤**:使用 `allowCfg` 和 `rejectCfg` 控制可操作的字段
|
|
807
|
+
5. **数据校验**:配置 `validateCfg` 确保数据有效性
|
|
808
|
+
6. **事务管理**:多 SQL 操作开启 `transactionEnable` 保证数据一致性
|
|
809
|
+
7. **日志记录**:实现 `ILogger` 接口记录执行日志
|