midway-fatcms 0.0.7 → 0.0.9
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/01-quick-start.md +231 -0
- package/.qoder/skills/midway-fatcms/02-crud-quick.md +375 -0
- package/.qoder/skills/midway-fatcms/03-crud-sharding.md +489 -0
- package/.qoder/skills/midway-fatcms/04-condition-operators.md +93 -0
- package/.qoder/skills/midway-fatcms/05-configuration.md +290 -0
- package/.qoder/skills/midway-fatcms/06-builtin-functions.md +241 -0
- package/.qoder/skills/midway-fatcms/07-examples.md +504 -0
- package/.qoder/skills/midway-fatcms/SKILL.md +96 -0
- package/README.md +9 -9
- package/dist/configuration.d.ts +10 -0
- package/dist/configuration.js +26 -0
- package/dist/controller/base/BaseApiController.d.ts +1 -2
- package/dist/controller/base/BaseApiController.js +0 -4
- package/dist/controller/gateway/DocGatewayController.js +1 -1
- package/dist/controller/helpers.controller.d.ts +6 -0
- package/dist/controller/helpers.controller.js +19 -0
- package/dist/controller/manage/FlowConfigManageApi.js +4 -2
- package/dist/controller/manage/SysConfigMangeApi.js +6 -1
- package/dist/controller/manage/UserAccountManageApi.js +7 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/libs/crud-pro/CrudPro.d.ts +51 -3
- package/dist/libs/crud-pro/CrudPro.js +111 -4
- package/dist/libs/crud-pro/exceptions.d.ts +7 -0
- package/dist/libs/crud-pro/exceptions.js +7 -0
- package/dist/libs/crud-pro/interfaces.d.ts +83 -12
- package/dist/libs/crud-pro/models/CrudResult.d.ts +116 -0
- package/dist/libs/crud-pro/models/CrudResult.js +126 -0
- package/dist/libs/crud-pro/models/RequestModel.d.ts +2 -2
- package/dist/libs/crud-pro/models/ServiceHub.d.ts +2 -0
- package/dist/libs/crud-pro/services/CrudProDataTypeConvertService.d.ts +70 -2
- package/dist/libs/crud-pro/services/CrudProDataTypeConvertService.js +205 -13
- package/dist/libs/crud-pro/services/CrudProExecuteSqlService.js +36 -2
- package/dist/libs/crud-pro/services/CrudProGenSqlCondition.js +8 -4
- package/dist/libs/crud-pro/services/CrudProTableMetaService.d.ts +36 -0
- package/dist/libs/crud-pro/services/CrudProTableMetaService.js +97 -4
- package/dist/libs/crud-pro/services/CurdProServiceHub.d.ts +2 -0
- package/dist/libs/crud-pro/services/CurdProServiceHub.js +6 -0
- package/dist/libs/crud-pro-quick/CrudProQuick.d.ts +382 -0
- package/dist/libs/crud-pro-quick/CrudProQuick.js +689 -0
- package/dist/libs/crud-pro-quick/fixSoftDelete.d.ts +30 -0
- package/dist/{service/curd → libs/crud-pro-quick}/fixSoftDelete.js +3 -6
- package/dist/libs/crud-pro-quick/index.d.ts +36 -0
- package/dist/libs/crud-pro-quick/index.js +49 -0
- package/dist/libs/crud-pro-quick/models.d.ts +33 -0
- package/dist/libs/crud-pro-quick/models.js +2 -0
- package/dist/libs/crud-sharding/ShardingBase.d.ts +78 -0
- package/dist/libs/crud-sharding/ShardingBase.js +179 -0
- package/dist/libs/crud-sharding/ShardingByCustomCrud.d.ts +35 -0
- package/dist/libs/crud-sharding/ShardingByCustomCrud.js +297 -0
- package/dist/libs/crud-sharding/ShardingByHashCrud.d.ts +38 -0
- package/dist/libs/crud-sharding/ShardingByHashCrud.js +86 -0
- package/dist/libs/crud-sharding/ShardingByKeyCrud.d.ts +39 -0
- package/dist/libs/crud-sharding/ShardingByKeyCrud.js +74 -0
- package/dist/libs/crud-sharding/ShardingByTimeCrud.d.ts +66 -0
- package/dist/libs/crud-sharding/ShardingByTimeCrud.js +524 -0
- package/dist/libs/crud-sharding/ShardingConfig.d.ts +25 -10
- package/dist/libs/crud-sharding/ShardingConfig.js +5 -5
- package/dist/libs/crud-sharding/ShardingMerger.d.ts +10 -18
- package/dist/libs/crud-sharding/ShardingMerger.js +27 -44
- package/dist/libs/crud-sharding/ShardingResult.d.ts +33 -0
- package/dist/libs/crud-sharding/ShardingResult.js +16 -0
- package/dist/libs/crud-sharding/ShardingTableCreator.d.ts +21 -4
- package/dist/libs/crud-sharding/ShardingTableCreator.js +193 -59
- package/dist/libs/crud-sharding/ShardingUtils.d.ts +48 -0
- package/dist/libs/crud-sharding/ShardingUtils.js +122 -1
- package/dist/libs/crud-sharding/TIME_COLUMN_CLEAN_SPEC.md +488 -0
- package/dist/libs/crud-sharding/index.d.ts +13 -15
- package/dist/libs/crud-sharding/index.js +33 -17
- package/dist/models/RedisKeys.d.ts +1 -0
- package/dist/models/RedisKeys.js +1 -0
- package/dist/models/bizmodels.d.ts +2 -6
- package/dist/service/SysAppService.d.ts +2 -2
- package/dist/service/SysAppService.js +16 -5
- package/dist/service/SysConfigService.d.ts +1 -1
- package/dist/service/SysConfigService.js +7 -2
- package/dist/service/SysDictDataService.js +14 -4
- package/dist/service/SysMenuService.js +7 -2
- package/dist/service/TableMetaCacheRedisSubscriber.d.ts +31 -0
- package/dist/service/TableMetaCacheRedisSubscriber.js +98 -0
- package/dist/service/curd/CurdMixService.d.ts +6 -4
- package/dist/service/curd/CurdMixService.js +16 -2
- package/dist/service/curd/CurdProService.d.ts +149 -29
- package/dist/service/curd/CurdProService.js +157 -38
- package/dist/service/flow/FlowConfigService.js +7 -2
- package/dist/service/flow/FlowInstanceCrudService.js +22 -19
- package/package.json +1 -1
- package/src/configuration.ts +27 -0
- package/src/controller/base/BaseApiController.ts +0 -5
- package/src/controller/gateway/DocGatewayController.ts +1 -1
- package/src/controller/helpers.controller.ts +15 -0
- package/src/controller/manage/CrudStandardDesignApi.ts +4 -3
- package/src/controller/manage/FlowConfigManageApi.ts +4 -2
- package/src/controller/manage/SysConfigMangeApi.ts +6 -1
- package/src/controller/manage/UserAccountManageApi.ts +7 -2
- package/src/index.ts +2 -2
- package/src/libs/crud-pro/CrudPro.ts +134 -7
- package/src/libs/crud-pro/exceptions.ts +8 -0
- package/src/libs/crud-pro/interfaces.ts +111 -15
- package/src/libs/crud-pro/models/CrudResult.ts +178 -0
- package/src/libs/crud-pro/models/RequestModel.ts +2 -2
- package/src/libs/crud-pro/models/ServiceHub.ts +4 -0
- package/src/libs/crud-pro/services/CrudProDataTypeConvertService.ts +238 -15
- package/src/libs/crud-pro/services/CrudProExecuteSqlService.ts +41 -2
- package/src/libs/crud-pro/services/CrudProGenSqlCondition.ts +11 -7
- package/src/libs/crud-pro/services/CrudProTableMetaService.ts +110 -3
- package/src/libs/crud-pro/services/CurdProServiceHub.ts +8 -0
- package/src/libs/crud-pro-quick/CrudProQuick.ts +782 -0
- package/src/{service/curd → libs/crud-pro-quick}/fixSoftDelete.ts +23 -13
- package/src/libs/crud-pro-quick/index.ts +52 -0
- package/src/libs/crud-pro-quick/models.ts +35 -0
- package/src/libs/crud-sharding/ShardingBase.ts +256 -0
- package/src/libs/crud-sharding/ShardingByCustomCrud.ts +329 -0
- package/src/libs/crud-sharding/ShardingByHashCrud.ts +111 -0
- package/src/libs/crud-sharding/ShardingByKeyCrud.ts +97 -0
- package/src/libs/crud-sharding/ShardingByTimeCrud.ts +628 -0
- package/src/libs/crud-sharding/ShardingConfig.ts +28 -10
- package/src/libs/crud-sharding/ShardingMerger.ts +35 -63
- package/src/libs/crud-sharding/ShardingResult.ts +29 -0
- package/src/libs/crud-sharding/ShardingTableCreator.ts +214 -71
- package/src/libs/crud-sharding/ShardingUtils.ts +137 -0
- package/src/libs/crud-sharding/TIME_COLUMN_CLEAN_SPEC.md +488 -0
- package/src/libs/crud-sharding/index.ts +30 -16
- package/src/models/RedisKeys.ts +1 -0
- package/src/models/bizmodels.ts +4 -7
- package/src/service/SysAppService.ts +18 -7
- package/src/service/SysConfigService.ts +8 -3
- package/src/service/SysDictDataService.ts +14 -4
- package/src/service/SysMenuService.ts +7 -2
- package/src/service/TableMetaCacheRedisSubscriber.ts +105 -0
- package/src/service/crudstd/CrudStdService.ts +2 -2
- package/src/service/curd/CurdMixService.ts +26 -5
- package/src/service/curd/CurdProService.ts +186 -45
- package/src/service/flow/FlowConfigService.ts +7 -2
- package/src/service/flow/FlowInstanceCrudService.ts +23 -20
- package/.qoder/skills/midway-fatcms-crud/SKILL.md +0 -375
- package/.qoder/skills/midway-fatcms-crud/examples.md +0 -990
- package/.qoder/skills/midway-fatcms-crud/reference.md +0 -568
- package/dist/libs/crud-pro/README.md +0 -809
- package/dist/libs/crud-pro/README_FUNC.md +0 -193
- package/dist/libs/crud-sharding/ROUTING_LOGIC.md +0 -944
- package/dist/libs/crud-sharding/ShardingCrudPro.d.ts +0 -363
- package/dist/libs/crud-sharding/ShardingCrudPro.js +0 -675
- package/dist/libs/crud-sharding/ShardingRouter.d.ts +0 -69
- package/dist/libs/crud-sharding/ShardingRouter.js +0 -377
- package/dist/models/StandardColumns.d.ts +0 -71
- package/dist/models/StandardColumns.js +0 -28
- package/dist/service/curd/CrudProQuick.d.ts +0 -190
- package/dist/service/curd/CrudProQuick.js +0 -319
- package/dist/service/curd/README.md +0 -1100
- package/dist/service/curd/fixSoftDelete.d.ts +0 -20
- package/src/libs/crud-pro/README.md +0 -809
- package/src/libs/crud-pro/README_FUNC.md +0 -193
- package/src/libs/crud-sharding/ROUTING_LOGIC.md +0 -944
- package/src/libs/crud-sharding/ShardingCrudPro.ts +0 -835
- package/src/libs/crud-sharding/ShardingRouter.ts +0 -512
- package/src/models/StandardColumns.ts +0 -76
- package/src/service/curd/CrudProQuick.ts +0 -360
- package/src/service/curd/README.md +0 -1100
|
@@ -0,0 +1,504 @@
|
|
|
1
|
+
# 完整示例集
|
|
2
|
+
|
|
3
|
+
## 基础查询
|
|
4
|
+
|
|
5
|
+
```typescript
|
|
6
|
+
const quick = this.curdProService.getQuickCrud({
|
|
7
|
+
sqlDatabase: 'mydb',
|
|
8
|
+
sqlDbType: SqlDbType.mysql,
|
|
9
|
+
sqlTable: 't_order',
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
// 列表查询
|
|
13
|
+
const list = await quick.findList({
|
|
14
|
+
condition: { status: 'paid' },
|
|
15
|
+
orderBy: 'created_at DESC',
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
// 指定列查询
|
|
19
|
+
const list2 = await quick.findList({
|
|
20
|
+
condition: { status: 'paid' },
|
|
21
|
+
columns: ['id', 'order_no', 'amount'],
|
|
22
|
+
orderBy: 'created_at DESC',
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
// 分页查询
|
|
26
|
+
const page = await quick.findPage({
|
|
27
|
+
condition: { status: 'paid' },
|
|
28
|
+
pageNo: 1,
|
|
29
|
+
pageSize: 20,
|
|
30
|
+
orderBy: 'created_at DESC',
|
|
31
|
+
});
|
|
32
|
+
console.log(page.rows, page.totalCount);
|
|
33
|
+
|
|
34
|
+
// 查询单条(不保证唯一性)
|
|
35
|
+
const order = await quick.findOne({
|
|
36
|
+
condition: { order_no: 'ORD001' },
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
// 唯一查询(多条时报错,推荐用于唯一索引)
|
|
40
|
+
const order2 = await quick.findUniqueOne({
|
|
41
|
+
condition: { order_no: 'ORD001' },
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// 根据主键 ID 查询单条(内部使用 findUniqueOne)
|
|
45
|
+
const order3 = await quick.findOneById(1);
|
|
46
|
+
const order4 = await quick.findOneById('ORD001'); // 字符串 ID
|
|
47
|
+
|
|
48
|
+
// 根据主键 ID 列表查询多条
|
|
49
|
+
const orders = await quick.findListByIds([1, 2, 3]);
|
|
50
|
+
const orders2 = await quick.findListByIds(['ORD001', 'ORD002']);
|
|
51
|
+
|
|
52
|
+
// 存在性判断
|
|
53
|
+
const exists = await quick.isExist({
|
|
54
|
+
condition: { email: 'test@example.com' },
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// 统计总数
|
|
58
|
+
const count = await quick.findCount({
|
|
59
|
+
condition: { status: 'paid' },
|
|
60
|
+
});
|
|
61
|
+
console.log(count.count);
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## 条件查询
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
// 比较操作
|
|
68
|
+
const adults = await quick.findList({
|
|
69
|
+
condition: { age: { $gt: 18, $lt: 60 } },
|
|
70
|
+
orderBy: 'age ASC',
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
// 大于等于 / 小于等于
|
|
74
|
+
const recentOrders = await quick.findList({
|
|
75
|
+
condition: {
|
|
76
|
+
created_at: { $gte: '2024-01-01 00:00:00', $lte: '2024-12-31 23:59:59' },
|
|
77
|
+
},
|
|
78
|
+
orderBy: 'created_at DESC',
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
// 不等于
|
|
82
|
+
const activeUsers = await quick.findList({
|
|
83
|
+
condition: { status: { $ne: 'deleted' } },
|
|
84
|
+
orderBy: 'id ASC',
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
// IN 查询
|
|
88
|
+
const selectedOrders = await quick.findList({
|
|
89
|
+
condition: { id: { $in: [1, 2, 3, 4, 5] } },
|
|
90
|
+
orderBy: 'id ASC',
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// NOT IN 查询
|
|
94
|
+
const otherTypes = await quick.findList({
|
|
95
|
+
condition: { type: { $nin: ['test', 'demo'] } },
|
|
96
|
+
orderBy: 'id ASC',
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
// 范围查询(BETWEEN ... AND)
|
|
100
|
+
const midRange = await quick.findList({
|
|
101
|
+
condition: { amount: { $range: [100, 500] } },
|
|
102
|
+
orderBy: 'amount DESC',
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
// 前缀匹配(LIKE '张%')
|
|
106
|
+
const zhangUsers = await quick.findList({
|
|
107
|
+
condition: { name: { $like: '张' } },
|
|
108
|
+
orderBy: 'name ASC',
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
// 包含匹配(LIKE '%张三%')
|
|
112
|
+
const containsName = await quick.findList({
|
|
113
|
+
condition: { name: { $likeInclude: '张三' } },
|
|
114
|
+
orderBy: 'name ASC',
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
// NULL 判断
|
|
118
|
+
const noPhone = await quick.findList({
|
|
119
|
+
condition: { phone: { $null: true } },
|
|
120
|
+
orderBy: 'id ASC',
|
|
121
|
+
});
|
|
122
|
+
const hasPhone = await quick.findList({
|
|
123
|
+
condition: { phone: { $notNull: true } },
|
|
124
|
+
orderBy: 'id ASC',
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
// 逻辑或(OR)
|
|
128
|
+
const pendingOrPaid = await quick.findList({
|
|
129
|
+
condition: {
|
|
130
|
+
$or: [{ status: 'pending' }, { status: 'paid' }],
|
|
131
|
+
},
|
|
132
|
+
orderBy: 'created_at DESC',
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
// 逻辑与(AND)+ 嵌套 OR
|
|
136
|
+
const complexCondition = await quick.findList({
|
|
137
|
+
condition: {
|
|
138
|
+
$and: [
|
|
139
|
+
{ department: 'tech' },
|
|
140
|
+
{ $or: [{ level: 'senior' }, { years: { $gte: 5 } }] },
|
|
141
|
+
],
|
|
142
|
+
},
|
|
143
|
+
orderBy: 'years DESC',
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
// 多条件组合
|
|
147
|
+
const results = await quick.findList({
|
|
148
|
+
condition: {
|
|
149
|
+
status: 'active',
|
|
150
|
+
age: { $gte: 18 },
|
|
151
|
+
city: { $in: ['北京', '上海', '深圳'] },
|
|
152
|
+
phone: { $notNull: true },
|
|
153
|
+
},
|
|
154
|
+
orderBy: 'created_at DESC',
|
|
155
|
+
columns: ['id', 'name', 'age', 'city'],
|
|
156
|
+
});
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## 写入操作
|
|
160
|
+
|
|
161
|
+
```typescript
|
|
162
|
+
// 插入单条
|
|
163
|
+
const result = await quick.insert({
|
|
164
|
+
data: { order_no: 'ORD001', amount: 199.99, status: 'pending' },
|
|
165
|
+
});
|
|
166
|
+
console.log(result.insertId, result.affectedRows);
|
|
167
|
+
|
|
168
|
+
// 批量插入
|
|
169
|
+
const batchResult = await quick.batchInsert({
|
|
170
|
+
data: [
|
|
171
|
+
{ order_no: '001', amount: 100 },
|
|
172
|
+
{ order_no: '002', amount: 200 },
|
|
173
|
+
{ order_no: '003', amount: 300 },
|
|
174
|
+
],
|
|
175
|
+
});
|
|
176
|
+
console.log(batchResult.affectedRows);
|
|
177
|
+
|
|
178
|
+
// 更新
|
|
179
|
+
await quick.update({
|
|
180
|
+
condition: { id: 1 },
|
|
181
|
+
data: { status: 'completed', amount: 299.99 },
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
// 删除
|
|
185
|
+
await quick.delete({ condition: { id: 1 } });
|
|
186
|
+
|
|
187
|
+
// 先查再插/更(insertOrUpdate)
|
|
188
|
+
const upsertResult = await quick.insertOrUpdate({
|
|
189
|
+
condition: { email: 'test@example.com' },
|
|
190
|
+
data: { email: 'test@example.com', name: '用户', age: 25 },
|
|
191
|
+
});
|
|
192
|
+
console.log(upsertResult.isExist ? '已更新' : '已插入');
|
|
193
|
+
|
|
194
|
+
// 原生 upsert(单条 SQL 完成)
|
|
195
|
+
await quick.insertOnDuplicateUpdate(
|
|
196
|
+
{ data: { id: 1, name: '用户', age: 25 } },
|
|
197
|
+
['id'] // 唯一列,PostgreSQL/SQL Server 必填
|
|
198
|
+
);
|
|
199
|
+
|
|
200
|
+
// save - 自动判断 INSERT/UPDATE(只需 data)
|
|
201
|
+
await quick.save({ data: { id: 1, name: '用户', age: 25 } }); // 有主键 → 先查后写
|
|
202
|
+
await quick.save({ data: { name: '新用户', age: 20 } }); // 无主键 → 直接插入
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
## 软删除与恢复
|
|
206
|
+
|
|
207
|
+
```typescript
|
|
208
|
+
quick.setBaseCfgModel({
|
|
209
|
+
enableSoftDelete: true,
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
// 软删除(实际执行 UPDATE ... SET deleted_at=时间戳, deleted_by=用户ID)
|
|
213
|
+
await quick.delete({ condition: { id: 1 } });
|
|
214
|
+
|
|
215
|
+
// 查询时自动过滤 deleted_at != 0 的记录
|
|
216
|
+
const activeUsers = await quick.findList({
|
|
217
|
+
condition: { status: 'active' },
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
// 恢复软删除的记录(重置 deleted_at=0, deleted_by='')
|
|
221
|
+
await quick.restore({ condition: { id: 1 } });
|
|
222
|
+
|
|
223
|
+
// 批量恢复
|
|
224
|
+
await quick.restore({ condition: { id: { $in: [1, 2, 3] } } });
|
|
225
|
+
|
|
226
|
+
// 按条件批量恢复
|
|
227
|
+
await quick.restore({ condition: { status: 'deleted' } });
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
## 标准字段自动填充
|
|
231
|
+
|
|
232
|
+
```typescript
|
|
233
|
+
quick.setBaseCfgModel({
|
|
234
|
+
enableStandardUpdateCfg: true,
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
// INSERT 自动填充:created_by, created_at, created_nickname 等
|
|
238
|
+
await quick.insert({ data: { name: '张三', age: 20 } });
|
|
239
|
+
|
|
240
|
+
// UPDATE 自动填充:modified_by, modified_at 等
|
|
241
|
+
await quick.update({
|
|
242
|
+
condition: { id: 1 },
|
|
243
|
+
data: { age: 21 },
|
|
244
|
+
});
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
## 分表操作 - 时间分表
|
|
248
|
+
|
|
249
|
+
```typescript
|
|
250
|
+
import { ShardingType } from 'midway-fatcms';
|
|
251
|
+
|
|
252
|
+
// ============ 按月分表 ============
|
|
253
|
+
const sharding = this.curdProService.getShardingCrud({
|
|
254
|
+
sqlDatabase: 'mydb',
|
|
255
|
+
sqlDbType: SqlDbType.mysql,
|
|
256
|
+
shardingConfig: {
|
|
257
|
+
type: ShardingType.MONTH,
|
|
258
|
+
baseTable: 't_order',
|
|
259
|
+
timeColumn: 'created_at',
|
|
260
|
+
autoCreateTable: true,
|
|
261
|
+
},
|
|
262
|
+
});
|
|
263
|
+
sharding.setBaseCfg({
|
|
264
|
+
sqlDatabase: 'mydb',
|
|
265
|
+
sqlDbType: SqlDbType.mysql,
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
// 插入(自动路由到 t_order_202401)
|
|
269
|
+
await sharding.insert({
|
|
270
|
+
data: { order_id: '001', amount: 100, created_at: '2024-01-15' },
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
// 批量插入(自动按月分组并行写入)
|
|
274
|
+
const batchResult = await sharding.batchInsert({
|
|
275
|
+
data: [
|
|
276
|
+
{ order_id: '001', created_at: '2024-01-15' },
|
|
277
|
+
{ order_id: '002', created_at: '2024-02-10' },
|
|
278
|
+
{ order_id: '003', created_at: '2024-03-05' },
|
|
279
|
+
],
|
|
280
|
+
});
|
|
281
|
+
console.log(batchResult.totalAffected, batchResult.tableCount);
|
|
282
|
+
|
|
283
|
+
// 更新(condition 必须包含 timeColumn)
|
|
284
|
+
await sharding.update({
|
|
285
|
+
condition: { order_id: '001', created_at: '2024-01-15' },
|
|
286
|
+
data: { status: 'shipped' },
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
// 删除(condition 必须包含 timeColumn)
|
|
290
|
+
await sharding.delete({
|
|
291
|
+
condition: { order_id: '001', created_at: '2024-01-15' },
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
// 分页查询(必须传 orderBy,时间分表必须是 timeColumn DESC/ASC)
|
|
295
|
+
const page = await sharding.findPage({
|
|
296
|
+
condition: {
|
|
297
|
+
status: 'paid',
|
|
298
|
+
created_at: { $gte: '2024-01-01 00:00:00', $lte: '2024-03-31 23:59:59' },
|
|
299
|
+
},
|
|
300
|
+
pageNo: 1,
|
|
301
|
+
pageSize: 10,
|
|
302
|
+
orderBy: 'created_at DESC',
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
// 列表查询(跨分表自动合并)
|
|
306
|
+
const list = await sharding.findList({
|
|
307
|
+
condition: {
|
|
308
|
+
created_at: { $gte: '2024-01-01 00:00:00', $lte: '2024-06-30 23:59:59' },
|
|
309
|
+
},
|
|
310
|
+
orderBy: 'created_at DESC',
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
// 无时间条件查询(自动查最近 N 张表,默认 MONTH=3)
|
|
314
|
+
const recentOrders = await sharding.findList({
|
|
315
|
+
condition: { status: 'paid' },
|
|
316
|
+
orderBy: 'created_at DESC',
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
// ============ 按年分表 ============
|
|
320
|
+
const yearlySharding = this.curdProService.getShardingCrud({
|
|
321
|
+
sqlDatabase: 'mydb',
|
|
322
|
+
sqlDbType: SqlDbType.mysql,
|
|
323
|
+
shardingConfig: {
|
|
324
|
+
type: ShardingType.YEAR,
|
|
325
|
+
baseTable: 't_log',
|
|
326
|
+
timeColumn: 'log_date',
|
|
327
|
+
recentTableCount: 5, // 查询最近5年
|
|
328
|
+
},
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
// ============ 按日分表 ============
|
|
332
|
+
const dailySharding = this.curdProService.getShardingCrud({
|
|
333
|
+
sqlDatabase: 'mydb',
|
|
334
|
+
sqlDbType: SqlDbType.mysql,
|
|
335
|
+
shardingConfig: {
|
|
336
|
+
type: ShardingType.DAY,
|
|
337
|
+
baseTable: 't_access_log',
|
|
338
|
+
timeColumn: 'access_time',
|
|
339
|
+
recentTableCount: 30, // 查询最近30天
|
|
340
|
+
},
|
|
341
|
+
});
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
## 分表操作 - 哈希分表
|
|
345
|
+
|
|
346
|
+
```typescript
|
|
347
|
+
const hashSharding = this.curdProService.getShardingCrud({
|
|
348
|
+
sqlDatabase: 'mydb',
|
|
349
|
+
sqlDbType: SqlDbType.mysql,
|
|
350
|
+
shardingConfig: {
|
|
351
|
+
type: ShardingType.HASH,
|
|
352
|
+
baseTable: 't_user',
|
|
353
|
+
shardingColumn: 'user_id',
|
|
354
|
+
tableCount: 16, // t_user_01 ~ t_user_16
|
|
355
|
+
},
|
|
356
|
+
});
|
|
357
|
+
hashSharding.setBaseCfg({
|
|
358
|
+
sqlDatabase: 'mydb',
|
|
359
|
+
sqlDbType: SqlDbType.mysql,
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
// 插入(根据 user_id 哈希路由到对应分表)
|
|
363
|
+
await hashSharding.insert({
|
|
364
|
+
data: { user_id: 10001, name: '张三' },
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
// 查询单个用户(根据 user_id 确定分表)
|
|
368
|
+
const user = await hashSharding.findOne({
|
|
369
|
+
condition: { user_id: 10001 },
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
// 全表扫描(无 user_id 时扫描所有分表,必须传 orderBy)
|
|
373
|
+
const allActiveUsers = await hashSharding.findList({
|
|
374
|
+
condition: { status: 'active' },
|
|
375
|
+
orderBy: 'user_id ASC',
|
|
376
|
+
});
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
## 分表 + 软删除
|
|
380
|
+
|
|
381
|
+
```typescript
|
|
382
|
+
const sharding = this.curdProService
|
|
383
|
+
.getShardingCrud({
|
|
384
|
+
sqlDatabase: 'mydb',
|
|
385
|
+
sqlDbType: SqlDbType.mysql,
|
|
386
|
+
shardingConfig: {
|
|
387
|
+
type: ShardingType.MONTH,
|
|
388
|
+
baseTable: 't_order',
|
|
389
|
+
timeColumn: 'created_at',
|
|
390
|
+
},
|
|
391
|
+
})
|
|
392
|
+
.setBaseCfg({
|
|
393
|
+
sqlDatabase: 'mydb',
|
|
394
|
+
sqlDbType: SqlDbType.mysql,
|
|
395
|
+
enableSoftDelete: true,
|
|
396
|
+
});
|
|
397
|
+
|
|
398
|
+
// 软删除
|
|
399
|
+
await sharding.delete({
|
|
400
|
+
condition: { order_id: '001', created_at: '2024-03-15' },
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
// 恢复软删除
|
|
404
|
+
await sharding.restore({
|
|
405
|
+
condition: { order_id: '001', created_at: '2024-03-15' },
|
|
406
|
+
});
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
## 原生 SQL
|
|
410
|
+
|
|
411
|
+
```typescript
|
|
412
|
+
const quick = this.curdProService.getQuickCrud({
|
|
413
|
+
sqlDatabase: 'mydb',
|
|
414
|
+
sqlDbType: SqlDbType.mysql,
|
|
415
|
+
sqlTable: 't_order',
|
|
416
|
+
});
|
|
417
|
+
|
|
418
|
+
// 框架封装 SQL(参数绑定,更安全)
|
|
419
|
+
const result = await quick.executeSQL(
|
|
420
|
+
'SELECT COUNT(*) as cnt FROM t_order WHERE status = ?',
|
|
421
|
+
['completed']
|
|
422
|
+
);
|
|
423
|
+
|
|
424
|
+
// 原生 SQL(直接执行,支持泛型)
|
|
425
|
+
const stats = await quick.executeNativeSQL<{ cnt: number }>(
|
|
426
|
+
'SELECT COUNT(*) as cnt FROM t_order WHERE status = ?',
|
|
427
|
+
['completed']
|
|
428
|
+
);
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
## 链式配置
|
|
432
|
+
|
|
433
|
+
```typescript
|
|
434
|
+
// CrudProQuick 链式配置
|
|
435
|
+
const quick = this.curdProService.getQuickCrud({
|
|
436
|
+
sqlDatabase: 'mydb',
|
|
437
|
+
sqlDbType: SqlDbType.mysql,
|
|
438
|
+
sqlTable: 't_user',
|
|
439
|
+
});
|
|
440
|
+
quick.setBaseCfgModel({
|
|
441
|
+
enableSoftDelete: true,
|
|
442
|
+
enableStandardUpdateCfg: true,
|
|
443
|
+
maxLimit: 5000,
|
|
444
|
+
});
|
|
445
|
+
|
|
446
|
+
// ShardingCrudPro 链式配置
|
|
447
|
+
const sharding = this.curdProService
|
|
448
|
+
.getShardingCrud({
|
|
449
|
+
sqlDatabase: 'mydb',
|
|
450
|
+
sqlDbType: SqlDbType.mysql,
|
|
451
|
+
shardingConfig: {
|
|
452
|
+
type: ShardingType.MONTH,
|
|
453
|
+
baseTable: 't_order',
|
|
454
|
+
timeColumn: 'created_at',
|
|
455
|
+
autoCreateTable: true,
|
|
456
|
+
recentTableCount: 6,
|
|
457
|
+
},
|
|
458
|
+
})
|
|
459
|
+
.setBaseCfg({
|
|
460
|
+
sqlDatabase: 'mydb',
|
|
461
|
+
sqlDbType: SqlDbType.mysql,
|
|
462
|
+
enableSoftDelete: true,
|
|
463
|
+
});
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
## 关联数据填充
|
|
467
|
+
|
|
468
|
+
```typescript
|
|
469
|
+
const cfgModel = {
|
|
470
|
+
method: 'order.list',
|
|
471
|
+
sqlTable: 't_order',
|
|
472
|
+
sqlSimpleName: 'SIMPLE_QUERY_PAGE',
|
|
473
|
+
columnsRelation: [
|
|
474
|
+
// 字典翻译
|
|
475
|
+
{
|
|
476
|
+
relatedType: 'dict',
|
|
477
|
+
relatedCode: 'OrderStatusEnum',
|
|
478
|
+
sourceColumn: 'status',
|
|
479
|
+
targetColumns: [{ from: 'label', to: 'status_text' }],
|
|
480
|
+
},
|
|
481
|
+
// 用户信息填充
|
|
482
|
+
{
|
|
483
|
+
relatedType: 'accountBasic',
|
|
484
|
+
sourceColumn: 'created_by',
|
|
485
|
+
targetColumns: [],
|
|
486
|
+
},
|
|
487
|
+
// 站点信息填充
|
|
488
|
+
{
|
|
489
|
+
relatedType: 'workbenchBasic',
|
|
490
|
+
sourceColumn: 'workbench_code',
|
|
491
|
+
targetColumns: [
|
|
492
|
+
{ from: 'workbench_name', to: 'site_name' },
|
|
493
|
+
],
|
|
494
|
+
},
|
|
495
|
+
],
|
|
496
|
+
};
|
|
497
|
+
|
|
498
|
+
const ctx = await this.curdMixService.executeCrudByCfg(
|
|
499
|
+
{ condition: {}, pageNo: 1, pageSize: 10, orderBy: 'created_at DESC' },
|
|
500
|
+
cfgModel
|
|
501
|
+
);
|
|
502
|
+
const { rows } = ctx.getResModelForQueryPage();
|
|
503
|
+
// rows 自动包含 status_text、created_by_nickname、site_name 等字段
|
|
504
|
+
```
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: midway-fatcms
|
|
3
|
+
description: >-
|
|
4
|
+
midway-fatcms 是一个功能完善的 CMS 服务端框架,提供数据库 CRUD 操作、分表查询、
|
|
5
|
+
数据关联填充、权限验证等能力。支持 MySQL、PostgreSQL、SQL Server。
|
|
6
|
+
当用户需要执行数据库操作、分表查询、字典翻译、用户信息填充时使用本 Skill。
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# midway-fatcms SDK 使用指南
|
|
10
|
+
|
|
11
|
+
## 简介
|
|
12
|
+
|
|
13
|
+
midway-fatcms 提供三个层次的 CRUD 操作能力:
|
|
14
|
+
|
|
15
|
+
| 层次 | 类名 | 用途 | 获取方式 |
|
|
16
|
+
|------|------|------|---------|
|
|
17
|
+
| **便捷层** | `CrudProQuick` | 单表快速操作 | `curdProService.getQuickCrud()` |
|
|
18
|
+
| **分表层** | `ShardingCrudPro` | 自动路由分表 | `curdProService.getShardingCrud()` |
|
|
19
|
+
| **协调层** | `CurdMixService` | 带关联数据填充 | `curdMixService.executeCrud()` |
|
|
20
|
+
|
|
21
|
+
## 章节导航
|
|
22
|
+
|
|
23
|
+
| 章节 | 内容 | 适用场景 |
|
|
24
|
+
|------|------|---------|
|
|
25
|
+
| [01-quick-start](./01-quick-start.md) | 快速入门、安装配置 | 首次使用 |
|
|
26
|
+
| [02-crud-quick](./02-crud-quick.md) | CrudProQuick 单表操作 | 基础增删改查 |
|
|
27
|
+
| [03-crud-sharding](./03-crud-sharding.md) | ShardingCrudPro 分表操作 | 分库分表场景 |
|
|
28
|
+
| [04-condition-operators](./04-condition-operators.md) | 条件操作符大全 | 复杂查询条件 |
|
|
29
|
+
| [05-configuration](./05-configuration.md) | 配置模型、返回类型 | 高级配置 |
|
|
30
|
+
| [06-builtin-functions](./06-builtin-functions.md) | 内置函数参考 | 自动字段填充 |
|
|
31
|
+
| [07-examples](./07-examples.md) | 完整示例集 | 参考实现 |
|
|
32
|
+
|
|
33
|
+
## 快速开始
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
import { Provide, Inject } from '@midwayjs/core';
|
|
37
|
+
import { CurdProService, SqlDbType } from 'midway-fatcms';
|
|
38
|
+
|
|
39
|
+
@Provide()
|
|
40
|
+
export class OrderService {
|
|
41
|
+
@Inject()
|
|
42
|
+
curdProService: CurdProService;
|
|
43
|
+
|
|
44
|
+
async getOrders() {
|
|
45
|
+
// 1. 获取 CrudProQuick 实例
|
|
46
|
+
const quick = this.curdProService.getQuickCrud({
|
|
47
|
+
sqlDatabase: 'mydb',
|
|
48
|
+
sqlDbType: SqlDbType.mysql,
|
|
49
|
+
sqlTable: 't_order',
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
// 2. 分页查询
|
|
53
|
+
const page = await quick.findPage({
|
|
54
|
+
condition: { status: 'paid' },
|
|
55
|
+
pageNo: 1,
|
|
56
|
+
pageSize: 20,
|
|
57
|
+
orderBy: 'created_at DESC',
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
return {
|
|
61
|
+
list: page.rows,
|
|
62
|
+
total: page.totalCount,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## 核心特性
|
|
69
|
+
|
|
70
|
+
- ✅ **三种数据库**:MySQL、PostgreSQL、SQL Server
|
|
71
|
+
- ✅ **类型安全**:完整的 TypeScript 类型支持
|
|
72
|
+
- ✅ **软删除**:自动将 DELETE 转为 UPDATE
|
|
73
|
+
- ✅ **标准字段填充**:自动填充 created_by、modified_by 等
|
|
74
|
+
- ✅ **分表路由**:时间分表、哈希分表、范围分表
|
|
75
|
+
- ✅ **数据关联**:字典翻译、用户信息填充
|
|
76
|
+
- ✅ **原生 SQL**:支持执行自定义 SQL 语句
|
|
77
|
+
|
|
78
|
+
## 实例复用规则
|
|
79
|
+
|
|
80
|
+
| 类 | 是否可复用 | 原因 |
|
|
81
|
+
|----|-----------|------|
|
|
82
|
+
| `CrudPro` | ❌ 禁止复用 | 有状态执行器,内部 Context 会累积 |
|
|
83
|
+
| `CrudProQuick` | ✅ 可复用 | 内部每次获取新 CrudPro |
|
|
84
|
+
| `ShardingCrudPro` | ✅ 可复用 | 内部每次获取新 CrudPro |
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
// ✅ CrudProQuick 可复用
|
|
88
|
+
const quick = this.curdProService.getQuickCrud({...});
|
|
89
|
+
await quick.findList({ condition: {...} });
|
|
90
|
+
await quick.insert({ data: {...} }); // 复用 OK
|
|
91
|
+
|
|
92
|
+
// ❌ CrudPro 禁止复用
|
|
93
|
+
const crudPro = new CrudPro();
|
|
94
|
+
await crudPro.executeCrudByCfg(req1, cfg1);
|
|
95
|
+
// 禁止再次使用同一个 crudPro 实例!
|
|
96
|
+
```
|
package/README.md
CHANGED
|
@@ -102,7 +102,7 @@ const ctx = await crudPro.executeCrudByCfg(reqJson, cfgJson);
|
|
|
102
102
|
const { rows, total_count } = ctx.getResModelForQueryPage();
|
|
103
103
|
```
|
|
104
104
|
|
|
105
|
-
> Full CRUD-Pro documentation: [src/libs/crud-pro/README.md](
|
|
105
|
+
> Full CRUD-Pro documentation: [src/libs/crud-pro/README.md](doc/skills/CrudPro使用指南.md) · Built-in Functions: [src/libs/crud-pro/README_FUNC.md](doc/skills/CrudPro内置函数参考.md)
|
|
106
106
|
|
|
107
107
|
---
|
|
108
108
|
|
|
@@ -155,7 +155,7 @@ const page = await sharding.queryPage({
|
|
|
155
155
|
});
|
|
156
156
|
```
|
|
157
157
|
|
|
158
|
-
> Full Sharding documentation: [src/libs/crud-sharding/ROUTING_LOGIC.md](
|
|
158
|
+
> Full Sharding documentation: [src/libs/crud-sharding/ROUTING_LOGIC.md](doc/skills/分表CRUD使用指南.md)
|
|
159
159
|
|
|
160
160
|
---
|
|
161
161
|
|
|
@@ -408,7 +408,7 @@ Business Code
|
|
|
408
408
|
└── fixSoftDelete() → Soft delete handling
|
|
409
409
|
```
|
|
410
410
|
|
|
411
|
-
> Full service layer documentation: [src/service/curd/README.md](
|
|
411
|
+
> Full service layer documentation: [src/service/curd/README.md](doc/skills/Curd服务层.md)
|
|
412
412
|
|
|
413
413
|
---
|
|
414
414
|
|
|
@@ -433,7 +433,7 @@ const result = await quick.insertObject({ data: { name: 'Alice', email: 'a@b.com
|
|
|
433
433
|
const batch = await quick.batchInsert({ data: [{ name: 'A' }, { name: 'B' }] });
|
|
434
434
|
const updated = await quick.updateObject({ condition: { id: 1 }, data: { name: 'Bob' } });
|
|
435
435
|
const deleted = await quick.deleteObject({ condition: { id: 1 } });
|
|
436
|
-
const upserted = await quick.
|
|
436
|
+
const upserted = await quick.insertOnDuplicateUpdate({ data: { id: 1, name: 'A' } }, ['id']);
|
|
437
437
|
|
|
438
438
|
// Raw SQL
|
|
439
439
|
const rows = await quick.executeSQL('SELECT * FROM t_user WHERE status = ?', ['active']);
|
|
@@ -499,7 +499,7 @@ CrudPro provides 30+ built-in functions for `updateCfg`, `validateCfg`, `execute
|
|
|
499
499
|
|
|
500
500
|
**Type Check:** `isBasicType`, `isBoolean`, `isString`, `isInteger`, `isNumber`, `isNumeric`, `isValidName`, `isChinesePhone`, `isEmailStrValid`, `pickNumber`
|
|
501
501
|
|
|
502
|
-
> Full function reference: [src/libs/crud-pro/README_FUNC.md](
|
|
502
|
+
> Full function reference: [src/libs/crud-pro/README_FUNC.md](doc/skills/CrudPro内置函数参考.md)
|
|
503
503
|
|
|
504
504
|
### Soft Delete
|
|
505
505
|
|
|
@@ -656,10 +656,10 @@ http://127.0.0.1:7002/ns/api/helpers/cryptoAes128CBC?input=123
|
|
|
656
656
|
|
|
657
657
|
| Document | Description |
|
|
658
658
|
|----------|-------------|
|
|
659
|
-
| [CRUD-Pro Guide](
|
|
660
|
-
| [Built-in Functions](
|
|
661
|
-
| [Service Layer Guide](
|
|
662
|
-
| [Sharding Routing Logic](
|
|
659
|
+
| [CRUD-Pro Guide](doc/skills/CrudPro使用指南.md) | Configuration-driven CRUD operations, validation, permissions |
|
|
660
|
+
| [Built-in Functions](doc/skills/CrudPro内置函数参考.md) | 30+ functions: date, compare, utility, type check |
|
|
661
|
+
| [Service Layer Guide](doc/skills/Curd服务层.md) | Context injection, soft delete, quick CRUD, sharding, relations |
|
|
662
|
+
| [Sharding Routing Logic](doc/skills/分表CRUD使用指南.md) | Shard strategies, cross-shard pagination, COUNT cache |
|
|
663
663
|
|
|
664
664
|
---
|
|
665
665
|
|
package/dist/configuration.d.ts
CHANGED
|
@@ -3,5 +3,15 @@ export declare class ContainerLifeCycle {
|
|
|
3
3
|
app: koa.Application;
|
|
4
4
|
onConfigLoad(): Promise<any>;
|
|
5
5
|
onReady(): Promise<void>;
|
|
6
|
+
/**
|
|
7
|
+
* 初始化表元数据缓存的 Redis Pub/Sub 广播
|
|
8
|
+
*
|
|
9
|
+
* - 发布客户端:复用已有的 RedisService 实例
|
|
10
|
+
* - 订阅客户端:通过 duplicate() 创建独立连接
|
|
11
|
+
*
|
|
12
|
+
* 集群部署时,任意节点调用 clearTableMetaCacheWithBroadcast()
|
|
13
|
+
* 会通过 Redis 广播通知所有节点清空本地缓存。
|
|
14
|
+
*/
|
|
15
|
+
private initTableMetaCacheRedis;
|
|
6
16
|
private startScheduleOnReady;
|
|
7
17
|
}
|