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.
Files changed (159) hide show
  1. package/.qoder/skills/midway-fatcms/01-quick-start.md +231 -0
  2. package/.qoder/skills/midway-fatcms/02-crud-quick.md +375 -0
  3. package/.qoder/skills/midway-fatcms/03-crud-sharding.md +489 -0
  4. package/.qoder/skills/midway-fatcms/04-condition-operators.md +93 -0
  5. package/.qoder/skills/midway-fatcms/05-configuration.md +290 -0
  6. package/.qoder/skills/midway-fatcms/06-builtin-functions.md +241 -0
  7. package/.qoder/skills/midway-fatcms/07-examples.md +504 -0
  8. package/.qoder/skills/midway-fatcms/SKILL.md +96 -0
  9. package/README.md +9 -9
  10. package/dist/configuration.d.ts +10 -0
  11. package/dist/configuration.js +26 -0
  12. package/dist/controller/base/BaseApiController.d.ts +1 -2
  13. package/dist/controller/base/BaseApiController.js +0 -4
  14. package/dist/controller/gateway/DocGatewayController.js +1 -1
  15. package/dist/controller/helpers.controller.d.ts +6 -0
  16. package/dist/controller/helpers.controller.js +19 -0
  17. package/dist/controller/manage/FlowConfigManageApi.js +4 -2
  18. package/dist/controller/manage/SysConfigMangeApi.js +6 -1
  19. package/dist/controller/manage/UserAccountManageApi.js +7 -2
  20. package/dist/index.d.ts +2 -2
  21. package/dist/index.js +2 -2
  22. package/dist/libs/crud-pro/CrudPro.d.ts +51 -3
  23. package/dist/libs/crud-pro/CrudPro.js +111 -4
  24. package/dist/libs/crud-pro/exceptions.d.ts +7 -0
  25. package/dist/libs/crud-pro/exceptions.js +7 -0
  26. package/dist/libs/crud-pro/interfaces.d.ts +83 -12
  27. package/dist/libs/crud-pro/models/CrudResult.d.ts +116 -0
  28. package/dist/libs/crud-pro/models/CrudResult.js +126 -0
  29. package/dist/libs/crud-pro/models/RequestModel.d.ts +2 -2
  30. package/dist/libs/crud-pro/models/ServiceHub.d.ts +2 -0
  31. package/dist/libs/crud-pro/services/CrudProDataTypeConvertService.d.ts +70 -2
  32. package/dist/libs/crud-pro/services/CrudProDataTypeConvertService.js +205 -13
  33. package/dist/libs/crud-pro/services/CrudProExecuteSqlService.js +36 -2
  34. package/dist/libs/crud-pro/services/CrudProGenSqlCondition.js +8 -4
  35. package/dist/libs/crud-pro/services/CrudProTableMetaService.d.ts +36 -0
  36. package/dist/libs/crud-pro/services/CrudProTableMetaService.js +97 -4
  37. package/dist/libs/crud-pro/services/CurdProServiceHub.d.ts +2 -0
  38. package/dist/libs/crud-pro/services/CurdProServiceHub.js +6 -0
  39. package/dist/libs/crud-pro-quick/CrudProQuick.d.ts +382 -0
  40. package/dist/libs/crud-pro-quick/CrudProQuick.js +689 -0
  41. package/dist/libs/crud-pro-quick/fixSoftDelete.d.ts +30 -0
  42. package/dist/{service/curd → libs/crud-pro-quick}/fixSoftDelete.js +3 -6
  43. package/dist/libs/crud-pro-quick/index.d.ts +36 -0
  44. package/dist/libs/crud-pro-quick/index.js +49 -0
  45. package/dist/libs/crud-pro-quick/models.d.ts +33 -0
  46. package/dist/libs/crud-pro-quick/models.js +2 -0
  47. package/dist/libs/crud-sharding/ShardingBase.d.ts +78 -0
  48. package/dist/libs/crud-sharding/ShardingBase.js +179 -0
  49. package/dist/libs/crud-sharding/ShardingByCustomCrud.d.ts +35 -0
  50. package/dist/libs/crud-sharding/ShardingByCustomCrud.js +297 -0
  51. package/dist/libs/crud-sharding/ShardingByHashCrud.d.ts +38 -0
  52. package/dist/libs/crud-sharding/ShardingByHashCrud.js +86 -0
  53. package/dist/libs/crud-sharding/ShardingByKeyCrud.d.ts +39 -0
  54. package/dist/libs/crud-sharding/ShardingByKeyCrud.js +74 -0
  55. package/dist/libs/crud-sharding/ShardingByTimeCrud.d.ts +66 -0
  56. package/dist/libs/crud-sharding/ShardingByTimeCrud.js +524 -0
  57. package/dist/libs/crud-sharding/ShardingConfig.d.ts +25 -10
  58. package/dist/libs/crud-sharding/ShardingConfig.js +5 -5
  59. package/dist/libs/crud-sharding/ShardingMerger.d.ts +10 -18
  60. package/dist/libs/crud-sharding/ShardingMerger.js +27 -44
  61. package/dist/libs/crud-sharding/ShardingResult.d.ts +33 -0
  62. package/dist/libs/crud-sharding/ShardingResult.js +16 -0
  63. package/dist/libs/crud-sharding/ShardingTableCreator.d.ts +21 -4
  64. package/dist/libs/crud-sharding/ShardingTableCreator.js +193 -59
  65. package/dist/libs/crud-sharding/ShardingUtils.d.ts +48 -0
  66. package/dist/libs/crud-sharding/ShardingUtils.js +122 -1
  67. package/dist/libs/crud-sharding/TIME_COLUMN_CLEAN_SPEC.md +488 -0
  68. package/dist/libs/crud-sharding/index.d.ts +13 -15
  69. package/dist/libs/crud-sharding/index.js +33 -17
  70. package/dist/models/RedisKeys.d.ts +1 -0
  71. package/dist/models/RedisKeys.js +1 -0
  72. package/dist/models/bizmodels.d.ts +2 -6
  73. package/dist/service/SysAppService.d.ts +2 -2
  74. package/dist/service/SysAppService.js +16 -5
  75. package/dist/service/SysConfigService.d.ts +1 -1
  76. package/dist/service/SysConfigService.js +7 -2
  77. package/dist/service/SysDictDataService.js +14 -4
  78. package/dist/service/SysMenuService.js +7 -2
  79. package/dist/service/TableMetaCacheRedisSubscriber.d.ts +31 -0
  80. package/dist/service/TableMetaCacheRedisSubscriber.js +98 -0
  81. package/dist/service/curd/CurdMixService.d.ts +6 -4
  82. package/dist/service/curd/CurdMixService.js +16 -2
  83. package/dist/service/curd/CurdProService.d.ts +149 -29
  84. package/dist/service/curd/CurdProService.js +157 -38
  85. package/dist/service/flow/FlowConfigService.js +7 -2
  86. package/dist/service/flow/FlowInstanceCrudService.js +22 -19
  87. package/package.json +1 -1
  88. package/src/configuration.ts +27 -0
  89. package/src/controller/base/BaseApiController.ts +0 -5
  90. package/src/controller/gateway/DocGatewayController.ts +1 -1
  91. package/src/controller/helpers.controller.ts +15 -0
  92. package/src/controller/manage/CrudStandardDesignApi.ts +4 -3
  93. package/src/controller/manage/FlowConfigManageApi.ts +4 -2
  94. package/src/controller/manage/SysConfigMangeApi.ts +6 -1
  95. package/src/controller/manage/UserAccountManageApi.ts +7 -2
  96. package/src/index.ts +2 -2
  97. package/src/libs/crud-pro/CrudPro.ts +134 -7
  98. package/src/libs/crud-pro/exceptions.ts +8 -0
  99. package/src/libs/crud-pro/interfaces.ts +111 -15
  100. package/src/libs/crud-pro/models/CrudResult.ts +178 -0
  101. package/src/libs/crud-pro/models/RequestModel.ts +2 -2
  102. package/src/libs/crud-pro/models/ServiceHub.ts +4 -0
  103. package/src/libs/crud-pro/services/CrudProDataTypeConvertService.ts +238 -15
  104. package/src/libs/crud-pro/services/CrudProExecuteSqlService.ts +41 -2
  105. package/src/libs/crud-pro/services/CrudProGenSqlCondition.ts +11 -7
  106. package/src/libs/crud-pro/services/CrudProTableMetaService.ts +110 -3
  107. package/src/libs/crud-pro/services/CurdProServiceHub.ts +8 -0
  108. package/src/libs/crud-pro-quick/CrudProQuick.ts +782 -0
  109. package/src/{service/curd → libs/crud-pro-quick}/fixSoftDelete.ts +23 -13
  110. package/src/libs/crud-pro-quick/index.ts +52 -0
  111. package/src/libs/crud-pro-quick/models.ts +35 -0
  112. package/src/libs/crud-sharding/ShardingBase.ts +256 -0
  113. package/src/libs/crud-sharding/ShardingByCustomCrud.ts +329 -0
  114. package/src/libs/crud-sharding/ShardingByHashCrud.ts +111 -0
  115. package/src/libs/crud-sharding/ShardingByKeyCrud.ts +97 -0
  116. package/src/libs/crud-sharding/ShardingByTimeCrud.ts +628 -0
  117. package/src/libs/crud-sharding/ShardingConfig.ts +28 -10
  118. package/src/libs/crud-sharding/ShardingMerger.ts +35 -63
  119. package/src/libs/crud-sharding/ShardingResult.ts +29 -0
  120. package/src/libs/crud-sharding/ShardingTableCreator.ts +214 -71
  121. package/src/libs/crud-sharding/ShardingUtils.ts +137 -0
  122. package/src/libs/crud-sharding/TIME_COLUMN_CLEAN_SPEC.md +488 -0
  123. package/src/libs/crud-sharding/index.ts +30 -16
  124. package/src/models/RedisKeys.ts +1 -0
  125. package/src/models/bizmodels.ts +4 -7
  126. package/src/service/SysAppService.ts +18 -7
  127. package/src/service/SysConfigService.ts +8 -3
  128. package/src/service/SysDictDataService.ts +14 -4
  129. package/src/service/SysMenuService.ts +7 -2
  130. package/src/service/TableMetaCacheRedisSubscriber.ts +105 -0
  131. package/src/service/crudstd/CrudStdService.ts +2 -2
  132. package/src/service/curd/CurdMixService.ts +26 -5
  133. package/src/service/curd/CurdProService.ts +186 -45
  134. package/src/service/flow/FlowConfigService.ts +7 -2
  135. package/src/service/flow/FlowInstanceCrudService.ts +23 -20
  136. package/.qoder/skills/midway-fatcms-crud/SKILL.md +0 -375
  137. package/.qoder/skills/midway-fatcms-crud/examples.md +0 -990
  138. package/.qoder/skills/midway-fatcms-crud/reference.md +0 -568
  139. package/dist/libs/crud-pro/README.md +0 -809
  140. package/dist/libs/crud-pro/README_FUNC.md +0 -193
  141. package/dist/libs/crud-sharding/ROUTING_LOGIC.md +0 -944
  142. package/dist/libs/crud-sharding/ShardingCrudPro.d.ts +0 -363
  143. package/dist/libs/crud-sharding/ShardingCrudPro.js +0 -675
  144. package/dist/libs/crud-sharding/ShardingRouter.d.ts +0 -69
  145. package/dist/libs/crud-sharding/ShardingRouter.js +0 -377
  146. package/dist/models/StandardColumns.d.ts +0 -71
  147. package/dist/models/StandardColumns.js +0 -28
  148. package/dist/service/curd/CrudProQuick.d.ts +0 -190
  149. package/dist/service/curd/CrudProQuick.js +0 -319
  150. package/dist/service/curd/README.md +0 -1100
  151. package/dist/service/curd/fixSoftDelete.d.ts +0 -20
  152. package/src/libs/crud-pro/README.md +0 -809
  153. package/src/libs/crud-pro/README_FUNC.md +0 -193
  154. package/src/libs/crud-sharding/ROUTING_LOGIC.md +0 -944
  155. package/src/libs/crud-sharding/ShardingCrudPro.ts +0 -835
  156. package/src/libs/crud-sharding/ShardingRouter.ts +0 -512
  157. package/src/models/StandardColumns.ts +0 -76
  158. package/src/service/curd/CrudProQuick.ts +0 -360
  159. package/src/service/curd/README.md +0 -1100
@@ -0,0 +1,231 @@
1
+ # 快速入门
2
+
3
+ ## 安装
4
+
5
+ ```bash
6
+ npm install midway-fatcms
7
+ ```
8
+
9
+ ## 服务注入
10
+
11
+ midway-fatcms 提供两个核心服务:
12
+
13
+ ```typescript
14
+ import { Provide, Inject } from '@midwayjs/core';
15
+ import { CurdMixService, CurdProService } from 'midway-fatcms';
16
+
17
+ @Provide()
18
+ export class MyService {
19
+ @Inject()
20
+ curdMixService: CurdMixService; // 协调层(带关联填充)
21
+
22
+ @Inject()
23
+ curdProService: CurdProService; // 核心层
24
+ }
25
+ ```
26
+
27
+ ## 数据库类型
28
+
29
+ ```typescript
30
+ import { SqlDbType } from 'midway-fatcms';
31
+
32
+ // 支持三种数据库
33
+ SqlDbType.mysql // MySQL
34
+ SqlDbType.postgres // PostgreSQL
35
+ SqlDbType.sqlserver // SQL Server
36
+ ```
37
+
38
+ ## 三种使用方式
39
+
40
+ ### 方式一:CrudProQuick(推荐入门)
41
+
42
+ 适用于单表 CRUD 操作:
43
+
44
+ ```typescript
45
+ const quick = this.curdProService.getQuickCrud({
46
+ sqlDatabase: 'mydb',
47
+ sqlDbType: SqlDbType.mysql,
48
+ sqlTable: 't_user',
49
+ });
50
+
51
+ // 查询列表
52
+ const result = await quick.findList({ condition: { status: 1 } });
53
+ console.log(result.rows, result.count);
54
+
55
+ // 分页查询
56
+ const page = await quick.findPage({
57
+ condition: { status: 1 },
58
+ pageNo: 1,
59
+ pageSize: 10,
60
+ orderBy: 'created_at DESC',
61
+ });
62
+ console.log(page.rows, page.totalCount);
63
+
64
+ // 插入
65
+ const insertResult = await quick.insert({
66
+ data: { name: '张三', age: 20 },
67
+ });
68
+ console.log(insertResult.insertId);
69
+
70
+ // 更新
71
+ await quick.update({
72
+ condition: { id: 1 },
73
+ data: { age: 21 },
74
+ });
75
+
76
+ // 删除
77
+ await quick.delete({ condition: { id: 1 } });
78
+ ```
79
+
80
+ ### 方式二:ShardingCrudPro(分表场景)
81
+
82
+ 适用于按时间、哈希分表的场景:
83
+
84
+ ```typescript
85
+ import { ShardingType } from 'midway-fatcms';
86
+
87
+ const sharding = this.curdProService.getShardingCrud({
88
+ sqlDatabase: 'mydb',
89
+ sqlDbType: SqlDbType.mysql,
90
+ shardingConfig: {
91
+ type: ShardingType.MONTH, // 按月分表
92
+ baseTable: 't_order', // 基础表名
93
+ timeColumn: 'created_at', // 时间字段
94
+ },
95
+ });
96
+
97
+ // 插入(自动路由到 t_order_202401)
98
+ await sharding.insert({
99
+ data: { order_id: '001', created_at: '2024-01-15' },
100
+ });
101
+
102
+ // 分页查询(自动合并多表结果)
103
+ const page = await sharding.findPage({
104
+ condition: { status: 'paid' },
105
+ pageNo: 1,
106
+ pageSize: 10,
107
+ orderBy: 'created_at DESC', // 时间分表必须传
108
+ });
109
+ ```
110
+
111
+ ### 方式三:CurdMixService(关联填充)
112
+
113
+ 适用于需要字典翻译、用户信息填充的场景:
114
+
115
+ ```typescript
116
+ const cfgModel = {
117
+ method: 'order.list',
118
+ sqlTable: 't_order',
119
+ sqlSimpleName: 'SIMPLE_QUERY_PAGE',
120
+ columnsRelation: [
121
+ // 订单状态字典翻译
122
+ {
123
+ relatedType: 'dict',
124
+ relatedCode: 'OrderStatusEnum',
125
+ sourceColumn: 'status',
126
+ targetColumns: [{ from: 'label', to: 'status_text' }],
127
+ },
128
+ // 创建者信息填充
129
+ {
130
+ relatedType: 'accountBasic',
131
+ sourceColumn: 'created_by',
132
+ targetColumns: [], // 使用默认映射
133
+ },
134
+ ],
135
+ };
136
+
137
+ const ctx = await this.curdMixService.executeCrudByCfg(
138
+ { condition: {}, pageNo: 1, pageSize: 10, orderBy: 'created_at DESC' },
139
+ cfgModel
140
+ );
141
+
142
+ const { rows } = ctx.getResModelForQueryPage();
143
+ // rows 自动包含 status_text、created_by_nickname 等字段
144
+ ```
145
+
146
+ ## 常用配置
147
+
148
+ ### 软删除
149
+
150
+ 启用后,DELETE 操作会转为 UPDATE:
151
+
152
+ ```typescript
153
+ quick.setBaseCfgModel({
154
+ enableSoftDelete: true,
155
+ });
156
+
157
+ // 实际执行:UPDATE t_user SET deleted_at=?, deleted_by=? WHERE id=1
158
+ await quick.delete({ condition: { id: 1 } });
159
+
160
+ // 查询时自动追加 deleted_at = 0
161
+ const users = await quick.findList({ condition: { status: 1 } });
162
+ ```
163
+
164
+ ### 标准字段自动填充
165
+
166
+ ```typescript
167
+ quick.setBaseCfgModel({
168
+ enableStandardUpdateCfg: true,
169
+ });
170
+
171
+ // INSERT 自动填充:created_by, created_at, created_nickname 等
172
+ await quick.insert({ data: { name: '张三' } });
173
+
174
+ // UPDATE 自动填充:modified_by, modified_at 等
175
+ await quick.update({ condition: { id: 1 }, data: { age: 21 } });
176
+ ```
177
+
178
+ ## 条件查询示例
179
+
180
+ ```typescript
181
+ // 简单条件
182
+ { status: 'active' }
183
+
184
+ // 比较操作
185
+ { age: { $gt: 18, $lt: 60 } }
186
+ { score: { $gte: 60 } }
187
+
188
+ // 范围操作
189
+ { id: { $in: [1, 2, 3] } }
190
+ { amount: { $range: [100, 500] } }
191
+
192
+ // 模糊查询
193
+ { name: { $like: '张%' } } // 前缀匹配
194
+ { name: { $likeInclude: '张三' } } // 包含匹配
195
+
196
+ // NULL 判断
197
+ { deleted_at: { $null: true } }
198
+ { phone: { $notNull: true } }
199
+
200
+ // 逻辑组合
201
+ {
202
+ $and: [
203
+ { status: 'active' },
204
+ { $or: [{ level: 'vip' }, { amount: { $gte: 1000 } }] }
205
+ ]
206
+ }
207
+ ```
208
+
209
+ ## 排序语法
210
+
211
+ ```typescript
212
+ // 字符串格式
213
+ orderBy: 'created_at DESC'
214
+ orderBy: 'created_at DESC, amount ASC'
215
+
216
+ // 简写格式(+ 升序,- 降序)
217
+ orderBy: 'created_at-'
218
+ orderBy: 'age+,created_at-'
219
+
220
+ // 数组格式
221
+ orderBy: [
222
+ { fieldName: 'created_at', orderType: 'DESC' },
223
+ { fieldName: 'amount', orderType: 'ASC' },
224
+ ]
225
+ ```
226
+
227
+ ## 下一步
228
+
229
+ - [CrudProQuick 单表操作](./02-crud-quick.md) - 完整 API 参考
230
+ - [ShardingCrudPro 分表操作](./03-crud-sharding.md) - 分表路由详解
231
+ - [条件操作符大全](./04-condition-operators.md) - 所有支持的查询条件
@@ -0,0 +1,375 @@
1
+ # CrudProQuick 单表操作
2
+
3
+ CrudProQuick 是在 CrudPro 之上封装的便捷操作层,提供简洁的 API 进行单表 CRUD 操作。
4
+
5
+ ## 获取实例
6
+
7
+ ```typescript
8
+ const quick = this.curdProService.getQuickCrud({
9
+ sqlDatabase: 'mydb', // 数据库名(必填)
10
+ sqlDbType: SqlDbType.mysql, // 数据库类型(必填)
11
+ sqlTable: 't_user', // 表名(可选,调用时传入)
12
+ });
13
+ ```
14
+
15
+ ## API 总览
16
+
17
+ ### 查询方法
18
+
19
+ | 方法 | 返回类型 | 说明 |
20
+ |------|----------|------|
21
+ | `findOne(req, table?)` | `CrudQueryOneResult<T>` | 查询单条(无顺序保证) |
22
+ | `findUniqueOne(req, table?)` | `CrudQueryOneResult<T>` | 唯一查询(多条报错) |
23
+ | `findList(req, table?)` | `CrudQueryListResult<T>` | 列表查询 |
24
+ | `findPage(req, table?)` | `CrudQueryPageResult<T>` | 分页查询 |
25
+ | `isExist(req, table?)` | `CrudExistResult` | 存在性判断 |
26
+ | `findCount(req, table?)` | `CrudCountResult` | 统计总数 |
27
+ | `findOneById(id, table?)` | `CrudQueryOneResult<T>` | 根据主键 ID 查询单条(多条报错) |
28
+ | `findListByIds(ids, table?)` | `CrudQueryListResult<T>` | 根据主键 ID 列表查询多条 |
29
+
30
+ ### 写入方法
31
+
32
+ | 方法 | 返回类型 | 说明 |
33
+ |------|----------|------|
34
+ | `insert(req, table?)` | `CrudWriteResult` | 插入单条 |
35
+ | `batchInsert(req, table?)` | `CrudWriteResult` | 批量插入 |
36
+ | `update(req, table?)` | `CrudWriteResult` | 更新 |
37
+ | `delete(req, table?)` | `CrudWriteResult` | 删除 |
38
+ | `restore(req, table?)` | `CrudWriteResult` | 恢复软删除记录(重置 deleted_at/deleted_by) |
39
+ | `insertOrUpdate(req, table?)` | `CrudUpsertResult` | 先查再插/更 |
40
+ | `insertOnDuplicateUpdate(req, uniqueCols?, table?)` | `CrudWriteResult` | 原生 upsert |
41
+ | `save(req, table?)` | `CrudUpsertResult` | 自动判断 INSERT/UPDATE |
42
+
43
+ ### SQL 方法
44
+
45
+ | 方法 | 返回类型 | 说明 |
46
+ |------|----------|------|
47
+ | `executeSQL(sql, args?)` | `ExecuteSQLResult` | 框架封装 SQL |
48
+ | `executeNativeSQL<T>(sql, args?)` | `ExecuteSQLResult<T>` | 原生 SQL |
49
+
50
+ ---
51
+
52
+ ## 查询方法详解
53
+
54
+ ### findOne - 查询单条
55
+
56
+ 返回第一条匹配记录,不保证顺序:
57
+
58
+ ```typescript
59
+ const result = await quick.findOne({
60
+ condition: { status: 'active' },
61
+ orderBy: 'created_at DESC',
62
+ });
63
+
64
+ if (result.found) {
65
+ console.log(result.row);
66
+ }
67
+ ```
68
+
69
+ ### findUniqueOne - 唯一查询
70
+
71
+ 期望结果为 0 条或 1 条,多条时报错:
72
+
73
+ ```typescript
74
+ const result = await quick.findUniqueOne({
75
+ condition: { email: 'user@example.com' },
76
+ });
77
+
78
+ if (result.found) {
79
+ console.log(result.row);
80
+ }
81
+ // 多条时抛出异常
82
+ ```
83
+
84
+ ### findList - 列表查询
85
+
86
+ ```typescript
87
+ const result = await quick.findList({
88
+ condition: { status: 'active' },
89
+ orderBy: 'created_at DESC',
90
+ columns: ['id', 'name', 'email'],
91
+ });
92
+
93
+ console.log(result.rows, result.count);
94
+ ```
95
+
96
+ ### findPage - 分页查询
97
+
98
+ ```typescript
99
+ const page = await quick.findPage({
100
+ condition: { status: 'active' },
101
+ pageNo: 1,
102
+ pageSize: 20,
103
+ orderBy: 'created_at DESC',
104
+ });
105
+
106
+ console.log(page.rows, page.totalCount);
107
+ ```
108
+
109
+ ### isExist - 存在性判断
110
+
111
+ ```typescript
112
+ const result = await quick.isExist({
113
+ condition: { email: 'user@example.com' },
114
+ });
115
+ console.log(result.exists); // true / false
116
+ ```
117
+
118
+ ### findCount - 统计总数
119
+
120
+ ```typescript
121
+ const result = await quick.findCount({
122
+ condition: { status: 'active' },
123
+ });
124
+ console.log(result.count);
125
+ ```
126
+
127
+ ### findOneById - 根据主键 ID 查询单条
128
+
129
+ 等价于 `findUniqueOne({ condition: { id } })`,但更简洁。如果查询到多条记录会抛出异常。
130
+
131
+ ```typescript
132
+ // 根据 ID 查询单条
133
+ const result = await quick.findOneById(1);
134
+ if (result.found) {
135
+ console.log(result.row);
136
+ }
137
+
138
+ // 字符串 ID
139
+ const result = await quick.findOneById('ORD001', 't_order');
140
+ ```
141
+
142
+ ### findListByIds - 根据主键 ID 列表查询多条
143
+
144
+ 等价于 `findList({ condition: { id: { $in: ids } } })`,但更简洁。
145
+
146
+ ```typescript
147
+ // 根据 ID 列表查询
148
+ const result = await quick.findListByIds([1, 2, 3]);
149
+ console.log(result.rows, result.count);
150
+
151
+ // 字符串 ID 列表
152
+ const result = await quick.findListByIds(['ORD001', 'ORD002'], 't_order');
153
+ ```
154
+
155
+ ---
156
+
157
+ ## 写入方法详解
158
+
159
+ ### insert - 插入单条
160
+
161
+ ```typescript
162
+ const result = await quick.insert({
163
+ data: { name: '张三', email: 'test@example.com', age: 25 },
164
+ });
165
+ console.log(result.insertId, result.affectedRows);
166
+ ```
167
+
168
+ ### batchInsert - 批量插入
169
+
170
+ ```typescript
171
+ const result = await quick.batchInsert({
172
+ data: [
173
+ { name: '张三', age: 25 },
174
+ { name: '李四', age: 30 },
175
+ ],
176
+ });
177
+ console.log(result.affectedRows);
178
+ ```
179
+
180
+ ### update - 更新
181
+
182
+ ```typescript
183
+ const result = await quick.update({
184
+ condition: { id: 1 },
185
+ data: { name: '张三更新', age: 26 },
186
+ });
187
+ ```
188
+
189
+ ### delete - 删除
190
+
191
+ ```typescript
192
+ const result = await quick.delete({
193
+ condition: { id: 1 },
194
+ });
195
+ ```
196
+
197
+ ### restore - 恢复软删除
198
+
199
+ 恢复已软删除的记录,将 `deleted_at` 重置为 0,`deleted_by` 重置为空字符串。需要启用软删除(`setBaseCfgModel({ enableSoftDelete: true })`)。
200
+
201
+ ```typescript
202
+ // 恢复指定 ID 的记录
203
+ await quick.restore({ condition: { id: 1 } });
204
+
205
+ // 恢复多条记录(使用 $in 操作符)
206
+ await quick.restore({ condition: { id: { $in: [1, 2, 3] } } });
207
+
208
+ // 按条件批量恢复记录
209
+ await quick.restore({ condition: { status: 'deleted' } });
210
+ ```
211
+
212
+ ### insertOrUpdate - 先查再插/更
213
+
214
+ ```typescript
215
+ const result = await quick.insertOrUpdate({
216
+ condition: { email: 'test@example.com' },
217
+ data: { email: 'test@example.com', name: '用户' },
218
+ });
219
+ console.log(result.isExist ? '更新' : '插入');
220
+ ```
221
+
222
+ ### insertOnDuplicateUpdate - 原生 Upsert
223
+
224
+ > **前置条件**:目标表必须拥有 UNIQUE 索引(除自增主键外)。
225
+ >
226
+ > `INSERT ON DUPLICATE KEY UPDATE` 只在 UNIQUE 索引或 PRIMARY KEY 冲突时触发 UPDATE。
227
+ > 如果表只有普通索引(KEY/INDEX),MySQL 不会报错,但**永远走 INSERT 路径,不会触发 UPDATE**,且每次调用都会插入新行。
228
+ >
229
+ > ```sql
230
+ > -- 检查表是否有 UNIQUE 索引
231
+ > SELECT DISTINCT INDEX_NAME FROM information_schema.STATISTICS
232
+ > WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'your_table'
233
+ > AND NON_UNIQUE = 0 AND INDEX_NAME != 'PRIMARY';
234
+ >
235
+ > -- 添加 UNIQUE 索引
236
+ > ALTER TABLE your_table ADD UNIQUE KEY uk_xxx (column_name);
237
+ > ```
238
+
239
+ ```typescript
240
+ const result = await quick.insertOnDuplicateUpdate(
241
+ { data: { id: 1, name: '用户' } },
242
+ ['id'] // 唯一列,PostgreSQL/SQL Server 必填
243
+ );
244
+ ```
245
+
246
+ ### save - 自动判断 INSERT/UPDATE
247
+
248
+ 只需传入 `data`,无需手动指定 `condition`。方法会自动查询表的主键列,根据 `data` 中是否包含主键值来决定操作:
249
+
250
+ - **data 包含主键且值不为 null/undefined** → 调用 `insertOrUpdate`(先查后写,存在则更新,不存在则插入)
251
+ - **data 不包含主键或主键值为 null/undefined** → 调用 `insert`(直接插入)
252
+
253
+ ```typescript
254
+ // 有主键 → 先查后写
255
+ await quick.save({ data: { id: 1, name: '张三' } });
256
+
257
+ // 无主键 → 直接 INSERT
258
+ await quick.save({ data: { name: '李四' } });
259
+
260
+ // 主键值为 null → 视为无主键,直接 INSERT
261
+ await quick.save({ data: { id: null, name: '王五' } });
262
+ ```
263
+
264
+ > **与 insertOrUpdate 的区别**:`save` 不需要传 `condition`,自动从 `data` 中提取主键组成 `condition`。本质是 `insertOrUpdate` 的便捷版。
265
+ >
266
+ > **性能说明**:首次调用 `save` 时会查询表的主键列信息,结果缓存 24 小时,后续调用无额外开销。
267
+
268
+ ---
269
+
270
+ ## SQL 方法详解
271
+
272
+ ### executeNativeSQL - 原生 SQL
273
+
274
+ ```typescript
275
+ const users = await quick.executeNativeSQL<{ id: number; name: string }[]>(
276
+ 'SELECT id, name FROM t_user WHERE age > ?',
277
+ [18]
278
+ );
279
+ ```
280
+
281
+ ---
282
+
283
+ ## 配置方法
284
+
285
+ ### setBaseCfgModel
286
+
287
+ ```typescript
288
+ quick.setBaseCfgModel({
289
+ enableSoftDelete: true, // 启用软删除(delete 设置 deleted_at/deleted_by,而非物理删除)
290
+ enableStandardUpdateCfg: true,
291
+ maxLimit: 10000,
292
+ });
293
+ ```
294
+
295
+ 启用软删除后,`delete` 操作会设置 `deleted_at`(当前时间戳)和 `deleted_by`(当前用户 ID),查询时自动过滤已删除记录。可通过 `restore` 方法恢复。
296
+
297
+ ---
298
+
299
+ ## 软删除
300
+
301
+ 启用软删除后,数据不会被物理删除,而是标记删除状态:
302
+
303
+ ```typescript
304
+ const quick = this.curdProService.getQuickCrud({
305
+ sqlDatabase: 'mydb',
306
+ sqlDbType: SqlDbType.mysql,
307
+ sqlTable: 't_user',
308
+ });
309
+
310
+ // 启用软删除
311
+ quick.setBaseCfgModel({ enableSoftDelete: true });
312
+
313
+ // 软删除(设置 deleted_at 和 deleted_by)
314
+ await quick.delete({ condition: { id: 1 } });
315
+
316
+ // 恢复软删除记录
317
+ await quick.restore({ condition: { id: 1 } });
318
+
319
+ // 查询时自动过滤 deleted_at != 0 的记录
320
+ const result = await quick.findList({ condition: { status: 'active' } });
321
+ ```
322
+
323
+ ---
324
+
325
+ ## 返回类型
326
+
327
+ ```typescript
328
+ // 写操作结果
329
+ interface CrudWriteResult {
330
+ affectedRows: number;
331
+ insertId?: string | number;
332
+ }
333
+
334
+ // 单条查询结果
335
+ interface CrudQueryOneResult<T> {
336
+ row: T | null;
337
+ found: boolean;
338
+ }
339
+
340
+ // 列表查询结果
341
+ interface CrudQueryListResult<T> {
342
+ rows: T[];
343
+ count: number;
344
+ }
345
+
346
+ // 分页查询结果
347
+ interface CrudQueryPageResult<T> {
348
+ rows: T[];
349
+ totalCount: number;
350
+ count: number;
351
+ }
352
+
353
+ // 存在性结果
354
+ interface CrudExistResult {
355
+ exists: boolean;
356
+ }
357
+
358
+ // 计数结果
359
+ interface CrudCountResult {
360
+ count: number;
361
+ }
362
+ ```
363
+
364
+ ---
365
+
366
+ ## 实例复用
367
+
368
+ CrudProQuick **可以安全复用**:
369
+
370
+ ```typescript
371
+ const quick = this.curdProService.getQuickCrud({...});
372
+ await quick.findList({ condition: {...} });
373
+ await quick.insert({ data: {...} });
374
+ // 复用 OK!
375
+ ```