midway-fatcms 0.0.5 → 0.0.7
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/.qoder/skills/midway-fatcms-crud/SKILL.md +375 -0
- package/.qoder/skills/midway-fatcms-crud/examples.md +990 -0
- package/.qoder/skills/midway-fatcms-crud/reference.md +568 -0
- package/README.md +377 -134
- 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 +6 -2
- package/dist/libs/crud-pro/models/RequestModel.js +20 -53
- 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/OrderByUtils.d.ts +70 -0
- package/dist/libs/crud-pro/utils/OrderByUtils.js +158 -0
- 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 +675 -0
- package/dist/libs/crud-sharding/ShardingMerger.d.ts +130 -0
- package/dist/libs/crud-sharding/ShardingMerger.js +282 -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 +1100 -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 +4 -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 +23 -65
- 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/OrderByUtils.ts +169 -0
- 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 +835 -0
- package/src/libs/crud-sharding/ShardingMerger.ts +384 -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 +1100 -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,990 @@
|
|
|
1
|
+
# midway-fatcms CRUD 使用示例大全
|
|
2
|
+
|
|
3
|
+
## 基础查询示例
|
|
4
|
+
|
|
5
|
+
### 简单列表查询
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
import { Provide, Inject } from '@midwayjs/core';
|
|
9
|
+
import { CurdMixService } from 'midway-fatcms';
|
|
10
|
+
import { SqlDbType } from 'midway-fatcms';
|
|
11
|
+
|
|
12
|
+
@Provide()
|
|
13
|
+
export class OrderService {
|
|
14
|
+
@Inject()
|
|
15
|
+
curdMixService: CurdMixService;
|
|
16
|
+
|
|
17
|
+
async getOrderList() {
|
|
18
|
+
const quick = this.curdMixService.getBbUtil('mydb', SqlDbType.mysql, 't_order');
|
|
19
|
+
|
|
20
|
+
// 基础查询
|
|
21
|
+
const orders = await quick.getList({
|
|
22
|
+
condition: { status: 'paid' },
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
return orders;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### 条件 + 排序 + 指定字段
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
async getFilteredOrders() {
|
|
34
|
+
const quick = this.curdMixService.getBbUtil('mydb', SqlDbType.mysql, 't_order');
|
|
35
|
+
|
|
36
|
+
const orders = await quick.getList({
|
|
37
|
+
condition: {
|
|
38
|
+
status: 'paid',
|
|
39
|
+
amount: { $gte: 100, $lte: 1000 },
|
|
40
|
+
created_at: { $gte: '2024-01-01' },
|
|
41
|
+
},
|
|
42
|
+
orderBy: 'created_at DESC', // 降序
|
|
43
|
+
columns: ['id', 'order_no', 'amount', 'status', 'created_at'],
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
return orders;
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### 分页查询
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
async getOrderPage(pageNo: number, pageSize: number) {
|
|
54
|
+
const quick = this.curdMixService.getBbUtil('mydb', SqlDbType.mysql, 't_order');
|
|
55
|
+
|
|
56
|
+
const page = await quick.getListPage({
|
|
57
|
+
condition: { status: 'paid' },
|
|
58
|
+
pageNo,
|
|
59
|
+
pageSize,
|
|
60
|
+
orderBy: 'created_at DESC',
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
return {
|
|
64
|
+
list: page.rows,
|
|
65
|
+
total: page.total_count,
|
|
66
|
+
pageNo,
|
|
67
|
+
pageSize,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### 唯一查询
|
|
73
|
+
|
|
74
|
+
```typescript
|
|
75
|
+
async getOrderByNo(orderNo: string) {
|
|
76
|
+
const quick = this.curdMixService.getBbUtil('mydb', SqlDbType.mysql, 't_order');
|
|
77
|
+
|
|
78
|
+
// 0条返回 null,多条抛出异常
|
|
79
|
+
const order = await quick.getUniqueOne({
|
|
80
|
+
condition: { order_no: orderNo },
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
return order; // null 或对象
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### 存在性判断
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
async checkOrderExists(orderNo: string) {
|
|
91
|
+
const quick = this.curdMixService.getBbUtil('mydb', SqlDbType.mysql, 't_order');
|
|
92
|
+
|
|
93
|
+
const exists = await quick.isExist({
|
|
94
|
+
condition: { order_no: orderNo },
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
return exists; // true / false
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### 复杂条件查询
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
async getComplexOrders() {
|
|
105
|
+
const quick = this.curdMixService.getBbUtil('mydb', SqlDbType.mysql, 't_order');
|
|
106
|
+
|
|
107
|
+
// AND + OR 组合
|
|
108
|
+
const orders = await quick.getList({
|
|
109
|
+
condition: {
|
|
110
|
+
$and: [
|
|
111
|
+
{ status: 'active' },
|
|
112
|
+
{
|
|
113
|
+
$or: [
|
|
114
|
+
{ type: 'normal' },
|
|
115
|
+
{ type: 'vip', amount: { $gte: 500 } },
|
|
116
|
+
],
|
|
117
|
+
},
|
|
118
|
+
],
|
|
119
|
+
},
|
|
120
|
+
orderBy: 'created_at DESC',
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
return orders;
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### 包含匹配查询
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
async searchOrdersByKeyword(keyword: string) {
|
|
131
|
+
const quick = this.curdMixService.getBbUtil('mydb', SqlDbType.mysql, 't_order');
|
|
132
|
+
|
|
133
|
+
const orders = await quick.getList({
|
|
134
|
+
condition: {
|
|
135
|
+
status: 'active',
|
|
136
|
+
order_name: { $likeInclude: keyword }, // LIKE '%keyword%'
|
|
137
|
+
},
|
|
138
|
+
orderBy: 'created_at DESC',
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
return orders;
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### IN 查询
|
|
146
|
+
|
|
147
|
+
```typescript
|
|
148
|
+
async getOrdersByStatuses(statuses: string[]) {
|
|
149
|
+
const quick = this.curdMixService.getBbUtil('mydb', SqlDbType.mysql, 't_order');
|
|
150
|
+
return await quick.getList({
|
|
151
|
+
condition: { status: { $in: statuses } },
|
|
152
|
+
orderBy: 'id DESC',
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
## 写入操作示例
|
|
158
|
+
|
|
159
|
+
### 插入单条
|
|
160
|
+
|
|
161
|
+
```typescript
|
|
162
|
+
async createOrder(orderData: any) {
|
|
163
|
+
const quick = this.curdMixService.getBbUtil('mydb', SqlDbType.mysql, 't_order');
|
|
164
|
+
|
|
165
|
+
// 启用标准字段自动填充
|
|
166
|
+
quick.setBaseCfgModel({
|
|
167
|
+
enableStandardUpdateCfg: true,
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
const result = await quick.insertObject({
|
|
171
|
+
data: {
|
|
172
|
+
order_no: orderData.orderNo,
|
|
173
|
+
amount: orderData.amount,
|
|
174
|
+
status: 'pending',
|
|
175
|
+
user_id: orderData.userId,
|
|
176
|
+
},
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
return {
|
|
180
|
+
id: result.insertId,
|
|
181
|
+
affectedRows: result.affectedRows,
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### 批量插入
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
async batchCreateOrders(orders: any[]) {
|
|
190
|
+
const quick = this.curdMixService.getBbUtil('mydb', SqlDbType.mysql, 't_order');
|
|
191
|
+
|
|
192
|
+
const result = await quick.batchInsert({
|
|
193
|
+
data: orders.map(order => ({
|
|
194
|
+
order_no: order.orderNo,
|
|
195
|
+
amount: order.amount,
|
|
196
|
+
status: order.status,
|
|
197
|
+
user_id: order.userId,
|
|
198
|
+
})),
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
return {
|
|
202
|
+
affectedRows: result.affectedRows,
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### 更新数据
|
|
208
|
+
|
|
209
|
+
```typescript
|
|
210
|
+
async updateOrderStatus(orderId: number, status: string) {
|
|
211
|
+
const quick = this.curdMixService.getBbUtil('mydb', SqlDbType.mysql, 't_order');
|
|
212
|
+
|
|
213
|
+
// 注意:必须带 condition,否则可能全表更新
|
|
214
|
+
const result = await quick.updateObject({
|
|
215
|
+
condition: { id: orderId },
|
|
216
|
+
data: {
|
|
217
|
+
status,
|
|
218
|
+
updated_at: new Date(),
|
|
219
|
+
},
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
return {
|
|
223
|
+
affectedRows: result.affectedRows,
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### 插入或更新
|
|
229
|
+
|
|
230
|
+
```typescript
|
|
231
|
+
async saveOrUpdateOrder(orderData: any) {
|
|
232
|
+
const quick = this.curdMixService.getBbUtil('mydb', SqlDbType.mysql, 't_order');
|
|
233
|
+
|
|
234
|
+
// 先查询存在性,再决定插入或更新(2条 SQL)
|
|
235
|
+
const result = await quick.insertOrUpdate({
|
|
236
|
+
condition: { order_no: orderData.orderNo }, // 查询条件
|
|
237
|
+
data: {
|
|
238
|
+
order_no: orderData.orderNo,
|
|
239
|
+
amount: orderData.amount,
|
|
240
|
+
status: orderData.status,
|
|
241
|
+
user_id: orderData.userId,
|
|
242
|
+
},
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
return result;
|
|
246
|
+
}
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
### 原生 Upsert(更高效)
|
|
250
|
+
|
|
251
|
+
```typescript
|
|
252
|
+
async upsertOrder(orderData: any) {
|
|
253
|
+
const quick = this.curdMixService.getBbUtil('mydb', SqlDbType.mysql, 't_order');
|
|
254
|
+
|
|
255
|
+
// MySQL: ON DUPLICATE KEY UPDATE(1条 SQL)
|
|
256
|
+
const result = await quick.insertOnDuplicate(
|
|
257
|
+
{
|
|
258
|
+
data: {
|
|
259
|
+
id: orderData.id,
|
|
260
|
+
order_no: orderData.orderNo,
|
|
261
|
+
amount: orderData.amount,
|
|
262
|
+
count: orderData.count,
|
|
263
|
+
},
|
|
264
|
+
},
|
|
265
|
+
['id'], // 唯一列,PostgreSQL/SQL Server 必填
|
|
266
|
+
);
|
|
267
|
+
|
|
268
|
+
return result;
|
|
269
|
+
}
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### 删除操作
|
|
273
|
+
|
|
274
|
+
```typescript
|
|
275
|
+
async deleteOrder(orderId: number) {
|
|
276
|
+
const quick = this.curdMixService.getBbUtil('mydb', SqlDbType.mysql, 't_order');
|
|
277
|
+
|
|
278
|
+
// 启用软删除
|
|
279
|
+
quick.setBaseCfgModel({
|
|
280
|
+
enableSoftDelete: true,
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
// 如果启用软删除,实际执行 UPDATE 设置 deleted_at
|
|
284
|
+
// 如果未启用,执行物理 DELETE
|
|
285
|
+
const result = await quick.deleteObject({
|
|
286
|
+
condition: { id: orderId },
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
return {
|
|
290
|
+
affectedRows: result.affectedRows,
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
## 分表操作示例
|
|
296
|
+
|
|
297
|
+
### 按月分表(订单表)
|
|
298
|
+
|
|
299
|
+
```typescript
|
|
300
|
+
import { ShardingType } from 'midway-fatcms';
|
|
301
|
+
import { CurdProService } from 'midway-fatcms';
|
|
302
|
+
|
|
303
|
+
@Provide()
|
|
304
|
+
export class OrderShardingService {
|
|
305
|
+
@Inject()
|
|
306
|
+
curdProService: CurdProService;
|
|
307
|
+
|
|
308
|
+
// 获取按月分表实例
|
|
309
|
+
private getOrderSharding() {
|
|
310
|
+
return this.curdProService.getShardingCrud('mydb', SqlDbType.mysql, {
|
|
311
|
+
type: ShardingType.MONTH,
|
|
312
|
+
baseTable: 't_order',
|
|
313
|
+
timeColumn: 'created_at',
|
|
314
|
+
autoCreateTable: true,
|
|
315
|
+
tableCreateOptions: {
|
|
316
|
+
copyIndexes: true,
|
|
317
|
+
tableOptions: 'ENGINE=InnoDB DEFAULT CHARSET=utf8mb4',
|
|
318
|
+
},
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// 插入订单(自动路由到对应月份表)
|
|
323
|
+
async createOrder(orderData: any) {
|
|
324
|
+
const sharding = this.getOrderSharding();
|
|
325
|
+
|
|
326
|
+
await sharding.insert({
|
|
327
|
+
data: {
|
|
328
|
+
order_id: orderData.orderId,
|
|
329
|
+
amount: orderData.amount,
|
|
330
|
+
created_at: orderData.createdAt, // 用于路由到对应分表
|
|
331
|
+
},
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
// 批量插入(自动分组并行写入)
|
|
336
|
+
async batchCreateOrders(orders: any[]) {
|
|
337
|
+
const sharding = this.getOrderSharding();
|
|
338
|
+
|
|
339
|
+
const result = await sharding.batchInsert({
|
|
340
|
+
data: orders.map(o => ({
|
|
341
|
+
order_id: o.orderId,
|
|
342
|
+
amount: o.amount,
|
|
343
|
+
created_at: o.createdAt,
|
|
344
|
+
})),
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
console.log(`涉及 ${result.tableCount} 个分表,共插入 ${result.totalAffected} 条`);
|
|
348
|
+
return result;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// 列表查询(自动合并多表结果)
|
|
352
|
+
async getOrdersByMonth(startDate: string, endDate: string) {
|
|
353
|
+
const sharding = this.getOrderSharding();
|
|
354
|
+
|
|
355
|
+
const orders = await sharding.query({
|
|
356
|
+
condition: {
|
|
357
|
+
status: 'paid',
|
|
358
|
+
created_at: { $gte: startDate, $lte: endDate },
|
|
359
|
+
},
|
|
360
|
+
orderBy: 'created_at DESC', // 时间分表必须传此格式
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
return orders;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// 分页查询(跨分表自动处理)
|
|
367
|
+
async getOrderPage(pageNo: number, pageSize: number) {
|
|
368
|
+
const sharding = this.getOrderSharding();
|
|
369
|
+
|
|
370
|
+
const page = await sharding.queryPage({
|
|
371
|
+
condition: { status: 'paid' },
|
|
372
|
+
pageNo,
|
|
373
|
+
pageSize,
|
|
374
|
+
orderBy: 'created_at DESC',
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
return {
|
|
378
|
+
list: page.rows,
|
|
379
|
+
total: page.total_count,
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
// 统计总数
|
|
384
|
+
async countOrders() {
|
|
385
|
+
const sharding = this.getOrderSharding();
|
|
386
|
+
|
|
387
|
+
return await sharding.queryCount({
|
|
388
|
+
condition: { status: 'paid' },
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
### 哈希分表(用户表)
|
|
395
|
+
|
|
396
|
+
```typescript
|
|
397
|
+
@Provide()
|
|
398
|
+
export class UserShardingService {
|
|
399
|
+
@Inject()
|
|
400
|
+
curdProService: CurdProService;
|
|
401
|
+
|
|
402
|
+
// 获取哈希分表实例
|
|
403
|
+
private getUserSharding() {
|
|
404
|
+
return this.curdProService.getShardingCrud('mydb', SqlDbType.mysql, {
|
|
405
|
+
type: ShardingType.HASH,
|
|
406
|
+
baseTable: 't_user',
|
|
407
|
+
shardingColumn: 'user_id',
|
|
408
|
+
tableCount: 16, // t_user_01 ~ t_user_16
|
|
409
|
+
});
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
// 插入用户
|
|
413
|
+
async createUser(userData: any) {
|
|
414
|
+
const sharding = this.getUserSharding();
|
|
415
|
+
|
|
416
|
+
await sharding.insert({
|
|
417
|
+
data: {
|
|
418
|
+
user_id: userData.userId, // 用于哈希路由
|
|
419
|
+
name: userData.name,
|
|
420
|
+
email: userData.email,
|
|
421
|
+
},
|
|
422
|
+
});
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
// 查询用户(需要提供 user_id 用于路由)
|
|
426
|
+
async getUserById(userId: string) {
|
|
427
|
+
const sharding = this.getUserSharding();
|
|
428
|
+
|
|
429
|
+
return await sharding.queryOne({
|
|
430
|
+
condition: { user_id: userId },
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
// 查询多用户(无 user_id 时扫描多个分表)
|
|
435
|
+
async getUsersByStatus(status: string) {
|
|
436
|
+
const sharding = this.getUserSharding();
|
|
437
|
+
|
|
438
|
+
return await sharding.query({
|
|
439
|
+
condition: { status },
|
|
440
|
+
orderBy: 'created_at DESC',
|
|
441
|
+
});
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
### 分表 + 软删除 + 标准字段
|
|
447
|
+
|
|
448
|
+
```typescript
|
|
449
|
+
async createOrderWithFullConfig(orderData: any) {
|
|
450
|
+
const sharding = this.curdProService
|
|
451
|
+
.getShardingCrud('mydb', SqlDbType.mysql, {
|
|
452
|
+
type: ShardingType.MONTH,
|
|
453
|
+
baseTable: 't_order',
|
|
454
|
+
timeColumn: 'created_at',
|
|
455
|
+
})
|
|
456
|
+
.setBaseCfg({
|
|
457
|
+
enableSoftDelete: true,
|
|
458
|
+
enableStandardUpdateCfg: true,
|
|
459
|
+
});
|
|
460
|
+
|
|
461
|
+
await sharding.insert({
|
|
462
|
+
data: {
|
|
463
|
+
order_id: orderData.orderId,
|
|
464
|
+
amount: orderData.amount,
|
|
465
|
+
created_at: orderData.createdAt,
|
|
466
|
+
},
|
|
467
|
+
});
|
|
468
|
+
// 自动填充:created_by, deleted_at = 0
|
|
469
|
+
}
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
## 关联数据填充示例
|
|
473
|
+
|
|
474
|
+
### 字典翻译
|
|
475
|
+
|
|
476
|
+
```typescript
|
|
477
|
+
import { Provide, Inject } from '@midwayjs/core';
|
|
478
|
+
import { CurdMixService } from 'midway-fatcms';
|
|
479
|
+
|
|
480
|
+
@Provide()
|
|
481
|
+
export class OrderWithDictService {
|
|
482
|
+
@Inject()
|
|
483
|
+
curdMixService: CurdMixService;
|
|
484
|
+
|
|
485
|
+
async getOrdersWithDict() {
|
|
486
|
+
const cfgModel = {
|
|
487
|
+
method: 'order.list.withDict',
|
|
488
|
+
sqlTable: 't_order',
|
|
489
|
+
sqlSimpleName: 'SIMPLE_QUERY_PAGE',
|
|
490
|
+
columnsRelation: [
|
|
491
|
+
// 订单状态翻译
|
|
492
|
+
{
|
|
493
|
+
relatedType: 'dict',
|
|
494
|
+
relatedCode: 'OrderStatusEnum',
|
|
495
|
+
sourceColumn: 'status',
|
|
496
|
+
targetColumns: [
|
|
497
|
+
{ from: 'label', to: 'status_text' },
|
|
498
|
+
{ from: 'color', to: 'status_color' },
|
|
499
|
+
],
|
|
500
|
+
},
|
|
501
|
+
// 支付类型翻译
|
|
502
|
+
{
|
|
503
|
+
relatedType: 'dict',
|
|
504
|
+
relatedCode: 'PayTypeEnum',
|
|
505
|
+
sourceColumn: 'pay_type',
|
|
506
|
+
targetColumns: [{ from: 'label', to: 'pay_type_text' }],
|
|
507
|
+
},
|
|
508
|
+
],
|
|
509
|
+
};
|
|
510
|
+
|
|
511
|
+
const ctx = await this.curdMixService.executeCrudByCfg(
|
|
512
|
+
{
|
|
513
|
+
condition: {},
|
|
514
|
+
pageNo: 1,
|
|
515
|
+
pageSize: 10,
|
|
516
|
+
orderBy: 'created_at DESC',
|
|
517
|
+
},
|
|
518
|
+
cfgModel
|
|
519
|
+
);
|
|
520
|
+
|
|
521
|
+
const { rows } = ctx.getResModelForQueryPage();
|
|
522
|
+
// rows 自动包含 status_text, status_color, pay_type_text
|
|
523
|
+
return rows;
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
```
|
|
527
|
+
|
|
528
|
+
### 用户信息填充
|
|
529
|
+
|
|
530
|
+
```typescript
|
|
531
|
+
async getOrdersWithUserInfo() {
|
|
532
|
+
const cfgModel = {
|
|
533
|
+
method: 'order.list.withUser',
|
|
534
|
+
sqlTable: 't_order',
|
|
535
|
+
sqlSimpleName: 'SIMPLE_QUERY_PAGE',
|
|
536
|
+
columnsRelation: [
|
|
537
|
+
// 创建者信息填充
|
|
538
|
+
{
|
|
539
|
+
relatedType: 'accountBasic',
|
|
540
|
+
sourceColumn: 'created_by',
|
|
541
|
+
targetColumns: [], // 空数组使用默认映射
|
|
542
|
+
},
|
|
543
|
+
],
|
|
544
|
+
};
|
|
545
|
+
|
|
546
|
+
const ctx = await this.curdMixService.executeCrudByCfg(
|
|
547
|
+
{
|
|
548
|
+
condition: {},
|
|
549
|
+
pageNo: 1,
|
|
550
|
+
pageSize: 10,
|
|
551
|
+
orderBy: 'created_at DESC',
|
|
552
|
+
},
|
|
553
|
+
cfgModel
|
|
554
|
+
);
|
|
555
|
+
|
|
556
|
+
const { rows } = ctx.getResModelForQueryPage();
|
|
557
|
+
// rows 自动包含:
|
|
558
|
+
// - created_by_nickname
|
|
559
|
+
// - created_by_avatar
|
|
560
|
+
// - created_by_account_type
|
|
561
|
+
return rows;
|
|
562
|
+
}
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
### 多级关联填充
|
|
566
|
+
|
|
567
|
+
```typescript
|
|
568
|
+
async getOrdersWithMultiRelation() {
|
|
569
|
+
const cfgModel = {
|
|
570
|
+
method: 'order.list.full',
|
|
571
|
+
sqlTable: 't_order',
|
|
572
|
+
sqlSimpleName: 'SIMPLE_QUERY_PAGE',
|
|
573
|
+
columnsRelation: [
|
|
574
|
+
// 订单状态字典
|
|
575
|
+
{
|
|
576
|
+
relatedType: 'dict',
|
|
577
|
+
relatedCode: 'OrderStatusEnum',
|
|
578
|
+
sourceColumn: 'status',
|
|
579
|
+
targetColumns: [{ from: 'label', to: 'status_text' }],
|
|
580
|
+
},
|
|
581
|
+
// 创建者信息
|
|
582
|
+
{
|
|
583
|
+
relatedType: 'accountBasic',
|
|
584
|
+
sourceColumn: 'created_by',
|
|
585
|
+
targetColumns: [
|
|
586
|
+
{ from: 'nickName', to: 'creator_name' },
|
|
587
|
+
{ from: 'avatar', to: 'creator_avatar' },
|
|
588
|
+
],
|
|
589
|
+
},
|
|
590
|
+
// 更新者信息
|
|
591
|
+
{
|
|
592
|
+
relatedType: 'accountBasic',
|
|
593
|
+
sourceColumn: 'modified_by',
|
|
594
|
+
targetColumns: [
|
|
595
|
+
{ from: 'nickName', to: 'modifier_name' },
|
|
596
|
+
],
|
|
597
|
+
},
|
|
598
|
+
// 所属站点信息
|
|
599
|
+
{
|
|
600
|
+
relatedType: 'workbenchBasic',
|
|
601
|
+
sourceColumn: 'workbench_code',
|
|
602
|
+
targetColumns: [
|
|
603
|
+
{ from: 'workbench_name', to: 'site_name' },
|
|
604
|
+
{ from: 'workbench_domain', to: 'site_domain' },
|
|
605
|
+
],
|
|
606
|
+
},
|
|
607
|
+
],
|
|
608
|
+
};
|
|
609
|
+
|
|
610
|
+
const ctx = await this.curdMixService.executeCrudByCfg(
|
|
611
|
+
{ condition: {}, pageNo: 1, pageSize: 10, orderBy: 'created_at DESC' },
|
|
612
|
+
cfgModel
|
|
613
|
+
);
|
|
614
|
+
|
|
615
|
+
return ctx.getResModelForQueryPage();
|
|
616
|
+
}
|
|
617
|
+
```
|
|
618
|
+
|
|
619
|
+
### 独立关联填充(已有数据)
|
|
620
|
+
|
|
621
|
+
```typescript
|
|
622
|
+
async linkRelationToExistingData(rows: any[]) {
|
|
623
|
+
// 对已有数据(如从缓存获取的)执行关联填充
|
|
624
|
+
await this.curdMixService.linkColumnRelationDatas(rows, {
|
|
625
|
+
columnsRelations: [
|
|
626
|
+
{
|
|
627
|
+
relatedType: 'dict',
|
|
628
|
+
relatedCode: 'OrderStatusEnum',
|
|
629
|
+
sourceColumn: 'status',
|
|
630
|
+
targetColumns: [{ from: 'label', to: 'status_text' }],
|
|
631
|
+
},
|
|
632
|
+
{
|
|
633
|
+
relatedType: 'accountBasic',
|
|
634
|
+
relatedCode: 'SexEnum',
|
|
635
|
+
sourceColumn: 'sex',
|
|
636
|
+
targetColumns: [{ from: 'label', to: 'sex_text' }],
|
|
637
|
+
},
|
|
638
|
+
],
|
|
639
|
+
});
|
|
640
|
+
|
|
641
|
+
// rows 中的每行自动追加 status_text、sex_text 字段
|
|
642
|
+
return rows;
|
|
643
|
+
}
|
|
644
|
+
```
|
|
645
|
+
|
|
646
|
+
## 综合业务场景示例
|
|
647
|
+
|
|
648
|
+
### 场景1:订单管理(完整 CURD)
|
|
649
|
+
|
|
650
|
+
```typescript
|
|
651
|
+
@Provide()
|
|
652
|
+
export class OrderManagerService {
|
|
653
|
+
@Inject()
|
|
654
|
+
curdProService: CurdProService;
|
|
655
|
+
|
|
656
|
+
@Inject()
|
|
657
|
+
curdMixService: CurdMixService;
|
|
658
|
+
|
|
659
|
+
private getQuick() {
|
|
660
|
+
const quick = this.curdMixService.getBbUtil('mydb', SqlDbType.mysql, 't_order');
|
|
661
|
+
quick.setBaseCfgModel({
|
|
662
|
+
enableStandardUpdateCfg: true,
|
|
663
|
+
enableSoftDelete: true,
|
|
664
|
+
});
|
|
665
|
+
return quick;
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
// 创建订单
|
|
669
|
+
async create(orderData: any) {
|
|
670
|
+
const quick = this.getQuick();
|
|
671
|
+
|
|
672
|
+
const result = await quick.insertObject({
|
|
673
|
+
data: {
|
|
674
|
+
order_no: orderData.orderNo,
|
|
675
|
+
user_id: orderData.userId,
|
|
676
|
+
amount: orderData.amount,
|
|
677
|
+
status: 'pending',
|
|
678
|
+
},
|
|
679
|
+
});
|
|
680
|
+
|
|
681
|
+
return { id: result.insertId };
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
// 查询订单列表(带分页、字典翻译)
|
|
685
|
+
async list(params: any) {
|
|
686
|
+
const cfgModel = {
|
|
687
|
+
method: 'order.list',
|
|
688
|
+
sqlTable: 't_order',
|
|
689
|
+
sqlSimpleName: 'SIMPLE_QUERY_PAGE',
|
|
690
|
+
enableSoftDelete: true, // 自动过滤 deleted_at = 0
|
|
691
|
+
columnsRelation: [
|
|
692
|
+
{
|
|
693
|
+
relatedType: 'dict',
|
|
694
|
+
relatedCode: 'OrderStatusEnum',
|
|
695
|
+
sourceColumn: 'status',
|
|
696
|
+
targetColumns: [{ from: 'label', to: 'status_text' }],
|
|
697
|
+
},
|
|
698
|
+
{
|
|
699
|
+
relatedType: 'accountBasic',
|
|
700
|
+
sourceColumn: 'created_by',
|
|
701
|
+
targetColumns: [],
|
|
702
|
+
},
|
|
703
|
+
],
|
|
704
|
+
};
|
|
705
|
+
|
|
706
|
+
const ctx = await this.curdMixService.executeCrudByCfg(
|
|
707
|
+
{
|
|
708
|
+
condition: {
|
|
709
|
+
status: params.status,
|
|
710
|
+
user_id: params.userId,
|
|
711
|
+
},
|
|
712
|
+
pageNo: params.pageNo || 1,
|
|
713
|
+
pageSize: params.pageSize || 20,
|
|
714
|
+
orderBy: 'created_at DESC',
|
|
715
|
+
},
|
|
716
|
+
cfgModel
|
|
717
|
+
);
|
|
718
|
+
|
|
719
|
+
return ctx.getResModelForQueryPage();
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
// 更新订单
|
|
723
|
+
async update(orderId: number, updateData: any) {
|
|
724
|
+
const quick = this.getQuick();
|
|
725
|
+
|
|
726
|
+
await quick.updateObject({
|
|
727
|
+
condition: { id: orderId },
|
|
728
|
+
data: {
|
|
729
|
+
status: updateData.status,
|
|
730
|
+
amount: updateData.amount,
|
|
731
|
+
},
|
|
732
|
+
});
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
// 删除订单(软删除)
|
|
736
|
+
async delete(orderId: number) {
|
|
737
|
+
const quick = this.getQuick();
|
|
738
|
+
|
|
739
|
+
await quick.deleteObject({
|
|
740
|
+
condition: { id: orderId },
|
|
741
|
+
});
|
|
742
|
+
// 实际执行:UPDATE t_order SET deleted_at=xxx, deleted_by='user123' WHERE id=1
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
```
|
|
746
|
+
|
|
747
|
+
### 场景2:大数据量分表订单系统
|
|
748
|
+
|
|
749
|
+
```typescript
|
|
750
|
+
import * as dayjs from 'dayjs';
|
|
751
|
+
|
|
752
|
+
@Provide()
|
|
753
|
+
export class BigDataOrderService {
|
|
754
|
+
@Inject()
|
|
755
|
+
curdProService: CurdProService;
|
|
756
|
+
|
|
757
|
+
private getSharding() {
|
|
758
|
+
return this.curdProService
|
|
759
|
+
.getShardingCrud('bigdata_db', SqlDbType.mysql, {
|
|
760
|
+
type: ShardingType.MONTH,
|
|
761
|
+
baseTable: 't_order',
|
|
762
|
+
timeColumn: 'created_at',
|
|
763
|
+
countCache: {
|
|
764
|
+
ttlSeconds: 300,
|
|
765
|
+
maxSize: 1000,
|
|
766
|
+
},
|
|
767
|
+
})
|
|
768
|
+
.setBaseCfg({
|
|
769
|
+
enableStandardUpdateCfg: true,
|
|
770
|
+
enableSoftDelete: true,
|
|
771
|
+
});
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
// 接收订单数据(可能跨多月)
|
|
775
|
+
async receiveOrders(orders: any[]) {
|
|
776
|
+
const sharding = this.getSharding();
|
|
777
|
+
|
|
778
|
+
// 自动按月份分组,并行插入到不同分表
|
|
779
|
+
const result = await sharding.batchInsert({
|
|
780
|
+
data: orders.map(o => ({
|
|
781
|
+
order_no: o.orderNo,
|
|
782
|
+
user_id: o.userId,
|
|
783
|
+
amount: o.amount,
|
|
784
|
+
created_at: o.createdAt,
|
|
785
|
+
})),
|
|
786
|
+
});
|
|
787
|
+
|
|
788
|
+
return {
|
|
789
|
+
total: result.totalAffected,
|
|
790
|
+
tableCount: result.tableCount,
|
|
791
|
+
};
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
// 查询最近3个月的订单
|
|
795
|
+
async getRecentOrders(userId: string) {
|
|
796
|
+
const sharding = this.getSharding();
|
|
797
|
+
|
|
798
|
+
const threeMonthsAgo = dayjs().subtract(3, 'month').format('YYYY-MM-DD');
|
|
799
|
+
|
|
800
|
+
return await sharding.query({
|
|
801
|
+
condition: {
|
|
802
|
+
user_id: userId,
|
|
803
|
+
created_at: { $gte: threeMonthsAgo },
|
|
804
|
+
},
|
|
805
|
+
orderBy: 'created_at DESC',
|
|
806
|
+
});
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
// 分页查询历史订单(跨分表)
|
|
810
|
+
async getHistoryOrders(userId: string, pageNo: number) {
|
|
811
|
+
const sharding = this.getSharding();
|
|
812
|
+
|
|
813
|
+
return await sharding.queryPage({
|
|
814
|
+
condition: { user_id: userId },
|
|
815
|
+
pageNo,
|
|
816
|
+
pageSize: 20,
|
|
817
|
+
orderBy: 'created_at DESC',
|
|
818
|
+
});
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
```
|
|
822
|
+
|
|
823
|
+
### 场景3:使用原生 SQL
|
|
824
|
+
|
|
825
|
+
```typescript
|
|
826
|
+
@Provide()
|
|
827
|
+
export class ReportService {
|
|
828
|
+
@Inject()
|
|
829
|
+
curdMixService: CurdMixService;
|
|
830
|
+
|
|
831
|
+
async getReportBySQL() {
|
|
832
|
+
const quick = this.curdMixService.getBbUtil('mydb', SqlDbType.mysql);
|
|
833
|
+
|
|
834
|
+
// 执行框架封装的 SQL(带参数绑定)
|
|
835
|
+
const rows = await quick.executeSQL(
|
|
836
|
+
`SELECT
|
|
837
|
+
DATE_FORMAT(created_at, '%Y-%m') as month,
|
|
838
|
+
COUNT(*) as order_count,
|
|
839
|
+
SUM(amount) as total_amount
|
|
840
|
+
FROM t_order
|
|
841
|
+
WHERE status = ? AND created_at > ?
|
|
842
|
+
GROUP BY month
|
|
843
|
+
ORDER BY month DESC`,
|
|
844
|
+
['completed', '2024-01-01']
|
|
845
|
+
);
|
|
846
|
+
|
|
847
|
+
return rows;
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
async executeComplexQuery() {
|
|
851
|
+
const quick = this.curdMixService.getBbUtil('mydb', SqlDbType.mysql);
|
|
852
|
+
|
|
853
|
+
// 执行原生 SQL(最小封装,支持泛型)
|
|
854
|
+
const users = await quick.executeNativeSQL<
|
|
855
|
+
{ id: number; name: string; total_orders: number }[]
|
|
856
|
+
>(
|
|
857
|
+
`SELECT u.id, u.name, COUNT(o.id) as total_orders
|
|
858
|
+
FROM t_user u
|
|
859
|
+
LEFT JOIN t_order o ON u.id = o.user_id
|
|
860
|
+
WHERE u.status = ?
|
|
861
|
+
GROUP BY u.id
|
|
862
|
+
HAVING total_orders > ?`,
|
|
863
|
+
['active', 5]
|
|
864
|
+
);
|
|
865
|
+
|
|
866
|
+
return users;
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
async getRawTables() {
|
|
870
|
+
const quick = this.curdMixService.getBbUtil('mydb', SqlDbType.mysql);
|
|
871
|
+
|
|
872
|
+
// 原生 SQL 执行 SHOW TABLES
|
|
873
|
+
return await quick.executeNativeSQL('SHOW TABLES');
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
```
|
|
877
|
+
|
|
878
|
+
### 场景4:配置驱动 CURD
|
|
879
|
+
|
|
880
|
+
```typescript
|
|
881
|
+
@Provide()
|
|
882
|
+
export class ConfigDrivenService {
|
|
883
|
+
@Inject()
|
|
884
|
+
curdMixService: CurdMixService;
|
|
885
|
+
|
|
886
|
+
async executeByConfig() {
|
|
887
|
+
// 定义配置
|
|
888
|
+
const cfgJson = {
|
|
889
|
+
method: 'user.customQuery',
|
|
890
|
+
sqlTable: 'sys_user',
|
|
891
|
+
sqlSimpleName: 'SIMPLE_QUERY_PAGE',
|
|
892
|
+
allowCfg: {
|
|
893
|
+
data: ['name', 'email', 'phone'], // 只允许这些字段被修改
|
|
894
|
+
},
|
|
895
|
+
updateCfg: {
|
|
896
|
+
// 自动设置创建时间
|
|
897
|
+
'data.created_at': { functionName: 'getCurrentTimeString' },
|
|
898
|
+
// 自动设置创建人
|
|
899
|
+
'data.created_by': { context: 'visitor.accountId' },
|
|
900
|
+
},
|
|
901
|
+
validateCfg: {
|
|
902
|
+
// 字段校验
|
|
903
|
+
'data.name': ['required', 'string', 'length:2,50'],
|
|
904
|
+
'data.email': ['required', 'email'],
|
|
905
|
+
'data.phone': ['phone:cn'],
|
|
906
|
+
},
|
|
907
|
+
};
|
|
908
|
+
|
|
909
|
+
// 执行
|
|
910
|
+
const ctx = await this.curdMixService.executeCrudByCfg(
|
|
911
|
+
{
|
|
912
|
+
condition: { status: 1 },
|
|
913
|
+
pageNo: 1,
|
|
914
|
+
pageSize: 10,
|
|
915
|
+
orderBy: 'created_at DESC',
|
|
916
|
+
},
|
|
917
|
+
cfgJson
|
|
918
|
+
);
|
|
919
|
+
|
|
920
|
+
return ctx.getResModelForQueryPage();
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
// 执行数据库中存储的 method
|
|
924
|
+
async executeDbMethod(methodCode: string, params: any) {
|
|
925
|
+
const ctx = await this.curdMixService.executeCrud({
|
|
926
|
+
method: methodCode,
|
|
927
|
+
...params,
|
|
928
|
+
});
|
|
929
|
+
return ctx;
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
```
|
|
933
|
+
|
|
934
|
+
### 场景5:日志批量插入
|
|
935
|
+
|
|
936
|
+
```typescript
|
|
937
|
+
@Provide()
|
|
938
|
+
export class LogService {
|
|
939
|
+
@Inject()
|
|
940
|
+
curdMixService: CurdMixService;
|
|
941
|
+
|
|
942
|
+
async batchInsertLogs(logs: Array<{ action: string; user_id: number }>) {
|
|
943
|
+
const quick = this.curdMixService.getBbUtil('mydb', SqlDbType.mysql, 't_log');
|
|
944
|
+
const result = await quick.batchInsert({
|
|
945
|
+
data: logs.map(log => ({
|
|
946
|
+
...log,
|
|
947
|
+
created_at: new Date().toISOString(),
|
|
948
|
+
})),
|
|
949
|
+
});
|
|
950
|
+
return result; // { affectedRows }
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
```
|
|
954
|
+
|
|
955
|
+
### 场景6:事务中的多表操作
|
|
956
|
+
|
|
957
|
+
```typescript
|
|
958
|
+
@Provide()
|
|
959
|
+
export class TransferService {
|
|
960
|
+
@Inject()
|
|
961
|
+
curdMixService: CurdMixService;
|
|
962
|
+
|
|
963
|
+
async transfer(fromId: number, toId: number, amount: number) {
|
|
964
|
+
// 当使用事务中间件时,所有操作共享同一个事务
|
|
965
|
+
const quick = this.curdMixService.getBbUtil('mydb', SqlDbType.mysql);
|
|
966
|
+
|
|
967
|
+
// 扣减转出账户余额
|
|
968
|
+
await quick.updateObject({
|
|
969
|
+
condition: { id: fromId },
|
|
970
|
+
data: { balance: { $decr: amount } }, // 使用递减操作符
|
|
971
|
+
}, 't_account');
|
|
972
|
+
|
|
973
|
+
// 增加转入账户余额
|
|
974
|
+
await quick.updateObject({
|
|
975
|
+
condition: { id: toId },
|
|
976
|
+
data: { balance: { $incr: amount } }, // 使用递增操作符
|
|
977
|
+
}, 't_account');
|
|
978
|
+
|
|
979
|
+
// 记录转账日志
|
|
980
|
+
await quick.insertObject({
|
|
981
|
+
data: {
|
|
982
|
+
from_id: fromId,
|
|
983
|
+
to_id: toId,
|
|
984
|
+
amount,
|
|
985
|
+
created_at: new Date().toISOString(),
|
|
986
|
+
},
|
|
987
|
+
}, 't_transfer_log');
|
|
988
|
+
}
|
|
989
|
+
}
|
|
990
|
+
```
|