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
|
@@ -1,1100 +0,0 @@
|
|
|
1
|
-
# Curd 服务层
|
|
2
|
-
|
|
3
|
-
Curd 服务层在 CrudPro 库之上封装了**自动上下文注入、标准字段填充、软删除、快捷 CRUD、分表入口和关联数据填充**能力,是业务代码操作数据库的唯一入口。
|
|
4
|
-
|
|
5
|
-
> CrudPro 库本身的使用指南见 [libs/crud-pro/README.md](../../libs/crud-pro/README.md),分表路由逻辑见 [libs/crud-sharding/ROUTING_LOGIC.md](../../libs/crud-sharding/ROUTING_LOGIC.md)。
|
|
6
|
-
|
|
7
|
-
## 架构总览
|
|
8
|
-
|
|
9
|
-
```
|
|
10
|
-
业务代码
|
|
11
|
-
│
|
|
12
|
-
├── CurdMixService(协调入口,CurdProService + 关联数据填充)
|
|
13
|
-
│ ├── CurdMixByDictService → relatedType: 'dict'
|
|
14
|
-
│ ├── CurdMixBySysConfigService → relatedType: 'sysCfgEnum'
|
|
15
|
-
│ ├── CurdMixByAccountService → relatedType: 'accountBasic'
|
|
16
|
-
│ ├── CurdMixByWorkbenchService → relatedType: 'workbenchBasic'
|
|
17
|
-
│ └── CurdMixByLinkToCustomService → relatedType: 'linkToCustom'
|
|
18
|
-
│
|
|
19
|
-
└── CurdProService(核心封装层)
|
|
20
|
-
├── CrudProQuick → 快捷 CRUD(链式调用)
|
|
21
|
-
├── ShardingCrudPro → 分表 CRUD
|
|
22
|
-
├── fixCfgModel() → 标准字段自动填充
|
|
23
|
-
└── fixSoftDelete() → 软删除处理
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
核心工具:`CurdMixUtils` 提供 `copyColumnRelationToRow`、`forEachRowAndColumnsRelation` 等通用方法。
|
|
27
|
-
|
|
28
|
-
## 服务层 vs CrudPro 库
|
|
29
|
-
|
|
30
|
-
| 能力 | CrudPro 库 | Curd 服务层 |
|
|
31
|
-
|------|-----------|------------|
|
|
32
|
-
| SQL 生成与执行 | ✅ | 透传 |
|
|
33
|
-
| 事务 / 连接管理 | 需手动注入 | 自动从 Midway Context 注入 |
|
|
34
|
-
| visitor(当前用户)| 需手动设置 | 自动从 userSession 转换 |
|
|
35
|
-
| 标准字段自动填充 | 需手动配置 updateCfg | `fixCfgModel` 自动注入 |
|
|
36
|
-
| 软删除 | 无 | `fixSoftDelete` 自动处理 |
|
|
37
|
-
| 快捷 CRUD | 无 | `CrudProQuick` |
|
|
38
|
-
| 分表 CRUD | `ShardingCrudPro` 类 | `getShardingCrud()` 工厂方法 |
|
|
39
|
-
| 关联数据填充 | columnsRelation 定义 | `CurdMixService` 自动执行 |
|
|
40
|
-
| 自定义 SQL 执行 | `executeSQL` | 透传 |
|
|
41
|
-
|
|
42
|
-
## CurdProService
|
|
43
|
-
|
|
44
|
-
Midway `@Provide()` 服务,自动注入 `ctx`、数据库配置和全局配置。
|
|
45
|
-
|
|
46
|
-
### 自动上下文注入
|
|
47
|
-
|
|
48
|
-
每次调用 `getCrudPro()` 创建实例时,自动完成:
|
|
49
|
-
|
|
50
|
-
- **visitor**:从 `ctx.userSession` 提取用户信息(accountId、nickName、roleCodes、functionCodes、workbenchCode 等)
|
|
51
|
-
- **transaction**:从 `ctx.transaction` 获取事务管理器(需配合 `tx.middleware`)
|
|
52
|
-
- **logger**:使用 `BaseService.getContextLogger()`
|
|
53
|
-
- **contextCfg**:从全局配置注入系统数据库名/类型
|
|
54
|
-
- **contextFunc**:`MyContextFunc` 根据数据库名从 Midway Config 中获取连接池
|
|
55
|
-
|
|
56
|
-
### 核心方法
|
|
57
|
-
|
|
58
|
-
| 方法 | 说明 |
|
|
59
|
-
|------|------|
|
|
60
|
-
| `executeCrudByCfg(reqJson, cfgModel)` | 带标准字段填充 + 软删除的 CRUD 执行 |
|
|
61
|
-
| `executeCrud(reqJson)` | 从数据库加载配置并执行(method 必填) |
|
|
62
|
-
| `executeSQL(sqlCfgModel)` | 直接执行 SQL |
|
|
63
|
-
| `getQuickCrud(db, dbType, table?)` | 获取 CrudProQuick 实例 |
|
|
64
|
-
| `getShardingCrud(db, dbType, config)` | 获取 ShardingCrudPro 实例 |
|
|
65
|
-
| `getCachedCfgByMethod(method)` | 从缓存加载配置 |
|
|
66
|
-
| `getAllTableInfos(query, options?)` | 获取表结构信息 |
|
|
67
|
-
|
|
68
|
-
## CrudProQuick
|
|
69
|
-
|
|
70
|
-
面向业务代码的快捷 CRUD 工具,省去手动组装 `cfgModel` 的步骤。所有方法自动继承 `CurdProService` 的上下文(visitor、事务、软删除、标准字段填充等)。
|
|
71
|
-
|
|
72
|
-
### 获取实例
|
|
73
|
-
|
|
74
|
-
```typescript
|
|
75
|
-
import { SqlDbType } from '@/libs/crud-pro/models/keys';
|
|
76
|
-
|
|
77
|
-
// 方式1:通过 CurdProService(推荐)
|
|
78
|
-
const quick = curdProService.getQuickCrud('mydb', SqlDbType.mysql, 't_user');
|
|
79
|
-
|
|
80
|
-
// 方式2:通过 CurdMixService(兼容旧版本)
|
|
81
|
-
const quick = curdMixService.getBbUtil('mydb', SqlDbType.mysql, 't_user');
|
|
82
|
-
|
|
83
|
-
// sqlTable 可在构造时指定,也可在每次调用时覆盖
|
|
84
|
-
const quick2 = curdProService.getQuickCrud('mydb', SqlDbType.mysql);
|
|
85
|
-
const users = await quick2.getList({ condition: { status: 1 } }, 't_user');
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
### 基础配置
|
|
89
|
-
|
|
90
|
-
#### setBaseCfgModel
|
|
91
|
-
|
|
92
|
-
通过 `setBaseCfgModel` 可设置公共配置,后续所有操作自动携带:
|
|
93
|
-
|
|
94
|
-
```typescript
|
|
95
|
-
const quick = curdProService.getQuickCrud('mydb', SqlDbType.mysql, 't_order');
|
|
96
|
-
|
|
97
|
-
// 设置公共配置
|
|
98
|
-
quick.setBaseCfgModel({
|
|
99
|
-
maxLimit: 50000, // 最大查询限制
|
|
100
|
-
enableStandardUpdateCfg: true, // 启用标准字段自动填充
|
|
101
|
-
enableSoftDelete: true, // 启用软删除
|
|
102
|
-
enableStandardUpdateCfgCondition: true, // 查询条件自动注入 created_by
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
// 后续所有操作都会自动携带这些配置
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
### API 分类一览
|
|
109
|
-
|
|
110
|
-
#### 查询类方法
|
|
111
|
-
|
|
112
|
-
| 方法 | 返回类型 | 说明 |
|
|
113
|
-
|------|----------|------|
|
|
114
|
-
| `getList(reqJson, sqlTable?)` | `any[]` | 列表查询 |
|
|
115
|
-
| `getListPage(reqJson, sqlTable?)` | `ResModelPageQuery` | 分页查询(含 total_count) |
|
|
116
|
-
| `getUniqueOne(reqJson, sqlTable?)` | `any \| null` | 期望唯一一条,0条返回null,多条报错 |
|
|
117
|
-
| `getOne(reqJson, sqlTable?)` | `any` | 获取第一条(已废弃,建议用 getUniqueOne) |
|
|
118
|
-
| `isExist(reqJson, sqlTable?)` | `boolean` | 存在性判断(比 COUNT 高效) |
|
|
119
|
-
| `getTotalCount(reqJson, sqlTable?)` | `number` | 统计总数 |
|
|
120
|
-
|
|
121
|
-
#### 写入类方法
|
|
122
|
-
|
|
123
|
-
| 方法 | 返回类型 | 说明 |
|
|
124
|
-
|------|----------|------|
|
|
125
|
-
| `insertObject(reqJson, sqlTable?)` | `ResModelAffected` | 插入单条 |
|
|
126
|
-
| `batchInsert(reqJson, sqlTable?)` | `ResModelAffected` | 批量插入(推荐大数据量使用) |
|
|
127
|
-
| `updateObject(reqJson, sqlTable?)` | `ResModelAffected` | 更新 |
|
|
128
|
-
| `insertOrUpdate(reqJson, sqlTable?)` | `ResModelStandard` | 先查询存在性,再决定插入或更新 |
|
|
129
|
-
| `insertOnDuplicate(reqJson, uniqueColumn?, sqlTable?)` | `ResModelAffected` | 原生 upsert(效率更高) |
|
|
130
|
-
| `deleteObject(reqJson, sqlTable?)` | `ResModelAffected` | 删除(受软删除配置影响) |
|
|
131
|
-
|
|
132
|
-
#### 原生 SQL 方法
|
|
133
|
-
|
|
134
|
-
| 方法 | 返回类型 | 说明 |
|
|
135
|
-
|------|----------|------|
|
|
136
|
-
| `executeSQL(sql, args?)` | `any` | 框架封装的 SQL 执行(参数绑定) |
|
|
137
|
-
| `executeNativeSQL<T>(sql, args?)` | `T` | 原生 SQL 执行,不做额外处理 |
|
|
138
|
-
|
|
139
|
-
### 请求参数结构
|
|
140
|
-
|
|
141
|
-
所有查询/写入方法都接受 `IRequestModel` 作为参数:
|
|
142
|
-
|
|
143
|
-
```typescript
|
|
144
|
-
interface IRequestModel {
|
|
145
|
-
condition?: Record<string, any>; // 查询/更新/删除条件
|
|
146
|
-
data?: Record<string, any> | Record<string, any>[]; // 插入/更新数据
|
|
147
|
-
pageNo?: number; // 页码(从1开始)
|
|
148
|
-
pageSize?: number; // 每页条数
|
|
149
|
-
orderBy?: string | OrderByItem[]; // 排序规则
|
|
150
|
-
columns?: string[]; // 指定返回列(默认全返回)
|
|
151
|
-
}
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
### 条件查询详解
|
|
155
|
-
|
|
156
|
-
#### 基础条件(自动转 $eq)
|
|
157
|
-
|
|
158
|
-
```typescript
|
|
159
|
-
// 简单等值条件 - 自动转换为 $eq
|
|
160
|
-
const users = await quick.getList({
|
|
161
|
-
condition: { status: 'active', age: 18 }
|
|
162
|
-
});
|
|
163
|
-
// 等价于: WHERE status = 'active' AND age = 18
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
#### 操作符条件
|
|
167
|
-
|
|
168
|
-
```typescript
|
|
169
|
-
// 比较操作符
|
|
170
|
-
const users = await quick.getList({
|
|
171
|
-
condition: {
|
|
172
|
-
age: { $gt: 18, $lt: 60 }, // 大于且小于
|
|
173
|
-
score: { $gte: 60 }, // 大于等于
|
|
174
|
-
level: { $lte: 10 }, // 小于等于
|
|
175
|
-
status: { $ne: 'deleted' }, // 不等于
|
|
176
|
-
}
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
// 范围操作符
|
|
180
|
-
const orders = await quick.getList({
|
|
181
|
-
condition: {
|
|
182
|
-
id: { $in: [1, 2, 3, 4, 5] }, // IN 查询
|
|
183
|
-
type: { $nin: ['test', 'draft'] }, // NOT IN 查询
|
|
184
|
-
amount: { $between: [100, 500] }, // BETWEEN 查询
|
|
185
|
-
name: { $like: '%张三%' }, // LIKE 模糊查询
|
|
186
|
-
}
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
// NULL 判断
|
|
190
|
-
const users = await quick.getList({
|
|
191
|
-
condition: {
|
|
192
|
-
deleted_at: { $isNull: true }, // IS NULL
|
|
193
|
-
phone: { $isNotNull: true }, // IS NOT NULL
|
|
194
|
-
}
|
|
195
|
-
});
|
|
196
|
-
```
|
|
197
|
-
|
|
198
|
-
#### 组合条件
|
|
199
|
-
|
|
200
|
-
```typescript
|
|
201
|
-
// AND 条件(默认)
|
|
202
|
-
const users = await quick.getList({
|
|
203
|
-
condition: {
|
|
204
|
-
$and: [
|
|
205
|
-
{ status: 'active' },
|
|
206
|
-
{ age: { $gte: 18 } },
|
|
207
|
-
]
|
|
208
|
-
}
|
|
209
|
-
});
|
|
210
|
-
|
|
211
|
-
// OR 条件
|
|
212
|
-
const users = await quick.getList({
|
|
213
|
-
condition: {
|
|
214
|
-
$or: [
|
|
215
|
-
{ status: 'pending' },
|
|
216
|
-
{ status: 'processing' },
|
|
217
|
-
]
|
|
218
|
-
}
|
|
219
|
-
});
|
|
220
|
-
|
|
221
|
-
// AND + OR 组合
|
|
222
|
-
const users = await quick.getList({
|
|
223
|
-
condition: {
|
|
224
|
-
$and: [
|
|
225
|
-
{ department: 'tech' },
|
|
226
|
-
{
|
|
227
|
-
$or: [
|
|
228
|
-
{ level: 'senior' },
|
|
229
|
-
{ years: { $gte: 5 } },
|
|
230
|
-
]
|
|
231
|
-
}
|
|
232
|
-
]
|
|
233
|
-
}
|
|
234
|
-
});
|
|
235
|
-
// 等价于: WHERE department = 'tech' AND (level = 'senior' OR years >= 5)
|
|
236
|
-
```
|
|
237
|
-
|
|
238
|
-
### 排序规则
|
|
239
|
-
|
|
240
|
-
```typescript
|
|
241
|
-
// 字符串语法(推荐)
|
|
242
|
-
const users = await quick.getList({
|
|
243
|
-
condition: { status: 'active' },
|
|
244
|
-
orderBy: 'created_at-', // 降序(后缀 - 表示 DESC)
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
const users2 = await quick.getList({
|
|
248
|
-
condition: { status: 'active' },
|
|
249
|
-
orderBy: 'age+', // 升序(后缀 + 表示 ASC,可省略)
|
|
250
|
-
});
|
|
251
|
-
|
|
252
|
-
// 多字段排序
|
|
253
|
-
const users3 = await quick.getList({
|
|
254
|
-
condition: { status: 'active' },
|
|
255
|
-
orderBy: 'department+,age-,created_at-',
|
|
256
|
-
// 等价于: ORDER BY department ASC, age DESC, created_at DESC
|
|
257
|
-
});
|
|
258
|
-
|
|
259
|
-
// 对象数组语法
|
|
260
|
-
const users4 = await quick.getList({
|
|
261
|
-
condition: { status: 'active' },
|
|
262
|
-
orderBy: [
|
|
263
|
-
{ fieldName: 'department', orderType: 'ASC' },
|
|
264
|
-
{ fieldName: 'created_at', orderType: 'DESC' },
|
|
265
|
-
]
|
|
266
|
-
});
|
|
267
|
-
```
|
|
268
|
-
|
|
269
|
-
### 完整使用示例
|
|
270
|
-
|
|
271
|
-
#### 1. 查询操作
|
|
272
|
-
|
|
273
|
-
```typescript
|
|
274
|
-
const quick = curdProService.getQuickCrud('mydb', SqlDbType.mysql, 't_user');
|
|
275
|
-
|
|
276
|
-
// 基础查询
|
|
277
|
-
const users = await quick.getList({
|
|
278
|
-
condition: { status: 'active' }
|
|
279
|
-
});
|
|
280
|
-
|
|
281
|
-
// 条件 + 排序 + 指定字段
|
|
282
|
-
const users = await quick.getList({
|
|
283
|
-
condition: {
|
|
284
|
-
status: 'active',
|
|
285
|
-
age: { $gte: 18, $lte: 60 },
|
|
286
|
-
},
|
|
287
|
-
orderBy: 'created_at-',
|
|
288
|
-
columns: ['id', 'name', 'email'], // 只返回指定字段
|
|
289
|
-
});
|
|
290
|
-
|
|
291
|
-
// 分页查询
|
|
292
|
-
const page = await quick.getListPage({
|
|
293
|
-
condition: { status: 'active' },
|
|
294
|
-
pageNo: 1,
|
|
295
|
-
pageSize: 20,
|
|
296
|
-
orderBy: 'created_at-',
|
|
297
|
-
});
|
|
298
|
-
console.log(page.rows); // 当前页数据
|
|
299
|
-
console.log(page.total_count); // 总记录数
|
|
300
|
-
|
|
301
|
-
// 唯一查询(期望结果只有0或1条)
|
|
302
|
-
const user = await quick.getUniqueOne({
|
|
303
|
-
condition: { email: 'user@example.com' }
|
|
304
|
-
});
|
|
305
|
-
// 0条返回 null,多条抛出异常
|
|
306
|
-
|
|
307
|
-
// 存在性判断(比 COUNT 查询更高效)
|
|
308
|
-
const exists = await quick.isExist({
|
|
309
|
-
condition: { phone: '13800138000' }
|
|
310
|
-
});
|
|
311
|
-
|
|
312
|
-
// 统计总数
|
|
313
|
-
const count = await quick.getTotalCount({
|
|
314
|
-
condition: { status: 'active' }
|
|
315
|
-
});
|
|
316
|
-
```
|
|
317
|
-
|
|
318
|
-
#### 2. 写入操作
|
|
319
|
-
|
|
320
|
-
```typescript
|
|
321
|
-
// 插入单条
|
|
322
|
-
const result = await quick.insertObject({
|
|
323
|
-
data: {
|
|
324
|
-
name: '张三',
|
|
325
|
-
email: 'zhangsan@example.com',
|
|
326
|
-
status: 'active',
|
|
327
|
-
// 如果启用 enableStandardUpdateCfg,会自动填充 created_by 等字段
|
|
328
|
-
}
|
|
329
|
-
});
|
|
330
|
-
console.log(result.affectedRows); // 1
|
|
331
|
-
console.log(result.insertId); // 自增ID
|
|
332
|
-
|
|
333
|
-
// 批量插入(效率远高于循环单条插入)
|
|
334
|
-
const result = await quick.batchInsert({
|
|
335
|
-
data: [
|
|
336
|
-
{ name: '张三', email: 'zs@example.com' },
|
|
337
|
-
{ name: '李四', email: 'ls@example.com' },
|
|
338
|
-
{ name: '王五', email: 'ww@example.com' },
|
|
339
|
-
]
|
|
340
|
-
});
|
|
341
|
-
console.log(result.affectedRows); // 3
|
|
342
|
-
|
|
343
|
-
// 更新(注意:必须带 condition,否则可能全表更新)
|
|
344
|
-
const result = await quick.updateObject({
|
|
345
|
-
condition: { id: 1 }, // WHERE id = 1
|
|
346
|
-
data: {
|
|
347
|
-
name: '张三丰',
|
|
348
|
-
updated_at: new Date(),
|
|
349
|
-
// 如果启用 enableStandardUpdateCfg,会自动填充 modified_by 等字段
|
|
350
|
-
}
|
|
351
|
-
});
|
|
352
|
-
console.log(result.affectedRows); // 1
|
|
353
|
-
|
|
354
|
-
// 插入或更新(先查询存在性)
|
|
355
|
-
const result = await quick.insertOrUpdate({
|
|
356
|
-
condition: { email: 'zhangsan@example.com' }, // 查询条件
|
|
357
|
-
data: {
|
|
358
|
-
name: '张三',
|
|
359
|
-
email: 'zhangsan@example.com',
|
|
360
|
-
age: 25,
|
|
361
|
-
}
|
|
362
|
-
});
|
|
363
|
-
// 如果不存在:执行 INSERT
|
|
364
|
-
// 如果存在:执行 UPDATE(用 data 更新匹配的记录)
|
|
365
|
-
|
|
366
|
-
// 原生 upsert(MySQL: ON DUPLICATE KEY UPDATE)
|
|
367
|
-
const result = await quick.insertOnDuplicate(
|
|
368
|
-
{
|
|
369
|
-
data: {
|
|
370
|
-
id: 1,
|
|
371
|
-
name: '张三',
|
|
372
|
-
count: 1,
|
|
373
|
-
}
|
|
374
|
-
},
|
|
375
|
-
['id'], // 唯一列(PostgreSQL/SQL Server 必需)
|
|
376
|
-
);
|
|
377
|
-
// 如果唯一键冲突,执行 UPDATE,否则执行 INSERT
|
|
378
|
-
// MySQL 可省略 uniqueColumn,依赖表的唯一索引
|
|
379
|
-
|
|
380
|
-
// 删除(受软删除配置影响)
|
|
381
|
-
const result = await quick.deleteObject({
|
|
382
|
-
condition: { id: 1 }
|
|
383
|
-
});
|
|
384
|
-
// 如果 enableSoftDelete = true,实际执行 UPDATE 设置 deleted_at
|
|
385
|
-
// 如果 enableSoftDelete = false,执行物理 DELETE
|
|
386
|
-
```
|
|
387
|
-
|
|
388
|
-
#### 3. 原生 SQL 执行
|
|
389
|
-
|
|
390
|
-
```typescript
|
|
391
|
-
import { NativeSqlSelectResult, NativeSqlResultMySQL } from '@/libs/crud-pro/models/ResModel';
|
|
392
|
-
|
|
393
|
-
// 执行框架封装的 SQL(带参数绑定、日志等)
|
|
394
|
-
const rows = await quick.executeSQL(
|
|
395
|
-
'SELECT * FROM t_user WHERE status = ? AND created_at > ?',
|
|
396
|
-
['active', '2024-01-01']
|
|
397
|
-
);
|
|
398
|
-
|
|
399
|
-
// 执行原生 SQL(最小封装,返回数据库驱动原始结果)
|
|
400
|
-
|
|
401
|
-
// SELECT 查询
|
|
402
|
-
const users = await quick.executeNativeSQL<{id: number; name: string}[]>(
|
|
403
|
-
'SELECT id, name FROM t_user WHERE age > ? ORDER BY id DESC LIMIT 10',
|
|
404
|
-
[18]
|
|
405
|
-
);
|
|
406
|
-
|
|
407
|
-
// MySQL INSERT/UPDATE/DELETE
|
|
408
|
-
const result = await quick.executeNativeSQL<NativeSqlResultMySQL>(
|
|
409
|
-
'INSERT INTO t_user (name, age) VALUES (?, ?)',
|
|
410
|
-
['张三', 20]
|
|
411
|
-
);
|
|
412
|
-
console.log(result.insertId); // 自增ID
|
|
413
|
-
console.log(result.affectedRows); // 影响行数
|
|
414
|
-
console.log(result.changedRows); // 实际修改行数(MySQL特有)
|
|
415
|
-
```
|
|
416
|
-
|
|
417
|
-
#### 4. 动态表名切换
|
|
418
|
-
|
|
419
|
-
```typescript
|
|
420
|
-
// 构造时不指定表名
|
|
421
|
-
const quick = curdProService.getQuickCrud('mydb', SqlDbType.mysql);
|
|
422
|
-
|
|
423
|
-
// 每次调用时指定表名
|
|
424
|
-
const users = await quick.getList(
|
|
425
|
-
{ condition: { status: 'active' } },
|
|
426
|
-
't_user' // 第二个参数为表名
|
|
427
|
-
);
|
|
428
|
-
|
|
429
|
-
const orders = await quick.getList(
|
|
430
|
-
{ condition: { status: 'paid' } },
|
|
431
|
-
't_order'
|
|
432
|
-
);
|
|
433
|
-
```
|
|
434
|
-
|
|
435
|
-
### 高级配置组合示例
|
|
436
|
-
|
|
437
|
-
```typescript
|
|
438
|
-
const quick = curdProService.getQuickCrud('mydb', SqlDbType.mysql, 't_article');
|
|
439
|
-
|
|
440
|
-
// 组合配置:软删除 + 标准字段填充 + 数据权限
|
|
441
|
-
quick.setBaseCfgModel({
|
|
442
|
-
maxLimit: 10000,
|
|
443
|
-
enableSoftDelete: true, // 软删除
|
|
444
|
-
enableStandardUpdateCfg: true, // 自动填充 created_by/modified_by
|
|
445
|
-
enableStandardUpdateCfgCondition: ['by'], // 查询条件自动注入 created_by = 当前用户ID
|
|
446
|
-
});
|
|
447
|
-
|
|
448
|
-
// 此时:
|
|
449
|
-
// - insert: 自动填充 created_by 和 deleted_at = 0
|
|
450
|
-
// - update: 自动填充 modified_by,条件自动加 created_by = 当前用户ID
|
|
451
|
-
// - delete: 实际执行 UPDATE 设置 deleted_at 和 deleted_by
|
|
452
|
-
// - query: 自动追加 condition.deleted_at = 0
|
|
453
|
-
// - 查询条件: 自动追加 created_by = 当前用户ID(只能查自己的数据)
|
|
454
|
-
```
|
|
455
|
-
|
|
456
|
-
## IRequestCfgModel2 扩展配置
|
|
457
|
-
|
|
458
|
-
服务层在 CrudPro 的 `IRequestCfgModel` 基础上扩展了 `IRequestCfgModel2`:
|
|
459
|
-
|
|
460
|
-
```typescript
|
|
461
|
-
interface IRequestCfgModel2 extends IRequestCfgModel {
|
|
462
|
-
enableStandardUpdateCfg?: boolean | string[]; // 标准字段自动填充
|
|
463
|
-
enableStandardUpdateCfgCondition?: boolean | string[]; // condition 中的标准字段填充
|
|
464
|
-
enableSoftDelete?: boolean; // 启用软删除
|
|
465
|
-
}
|
|
466
|
-
```
|
|
467
|
-
|
|
468
|
-
### enableStandardUpdateCfg
|
|
469
|
-
|
|
470
|
-
控制 `fixCfgModel` 是否自动向 `updateCfg` 注入标准字段。
|
|
471
|
-
|
|
472
|
-
| 值 | 行为 |
|
|
473
|
-
|----|------|
|
|
474
|
-
| `undefined` / `true` | 默认行为:insert/update 自动填充 `created_by`、`modified_by` 等 |
|
|
475
|
-
| `false` | 完全关闭标准字段自动填充 |
|
|
476
|
-
| `string[]` | 指定要填充的字段后缀,如 `['by']` 只填充 `created_by`/`modified_by` |
|
|
477
|
-
| `['null']` | 等同于空数组,不填充任何字段 |
|
|
478
|
-
|
|
479
|
-
### enableStandardUpdateCfgCondition
|
|
480
|
-
|
|
481
|
-
控制查询/删除条件中是否自动注入 `created_by` 等字段,实现"只能查自己数据"的效果。
|
|
482
|
-
|
|
483
|
-
| 值 | 行为 |
|
|
484
|
-
|----|------|
|
|
485
|
-
| `undefined` / `false` | 不在 condition 中注入 |
|
|
486
|
-
| `string[]` | 指定字段后缀,如 `['by']` 自动注入 `condition.created_by = 当前用户ID` |
|
|
487
|
-
| `['null']` | 不注入 |
|
|
488
|
-
|
|
489
|
-
### 各操作类型自动填充规则
|
|
490
|
-
|
|
491
|
-
| 操作类型 | data 字段 | condition 字段 |
|
|
492
|
-
|---------|-----------|---------------|
|
|
493
|
-
| INSERT | `created_by`, `created_avatar`, `created_nickname`, `created_account_type` | — |
|
|
494
|
-
| UPDATE | `modified_by`, `modified_avatar`, `modified_nickname`, `modified_account_type` | `created_by`, `created_account_type`(限制只改自己的) |
|
|
495
|
-
| DELETE | — | `created_by`, `created_account_type`(限制只删自己的) |
|
|
496
|
-
| INSERT_OR_UPDATE / INSERT_ON_DUPLICATE_UPDATE | `created_*` + `modified_*` | `created_by`, `created_account_type` |
|
|
497
|
-
| QUERY / QUERY_PAGE / QUERY_ONE | — | 由 `enableStandardUpdateCfgCondition` 控制 |
|
|
498
|
-
|
|
499
|
-
> 上述 `created_by` / `modified_by` 取自 `visitor.accountId`,其余字段取自 visitor 对应属性。
|
|
500
|
-
|
|
501
|
-
## 软删除
|
|
502
|
-
|
|
503
|
-
当 `cfgModel.enableSoftDelete = true` 时,`fixSoftDelete` 自动改写操作行为:
|
|
504
|
-
|
|
505
|
-
| 操作 | 原始行为 | 软删除行为 |
|
|
506
|
-
|------|---------|-----------|
|
|
507
|
-
| INSERT | 正常插入 | 自动设置 `data.deleted_at = 0` |
|
|
508
|
-
| DELETE | 物理删除 | 改为 UPDATE:设置 `deleted_at = 当前时间戳`、`deleted_by = 当前用户ID` |
|
|
509
|
-
| QUERY / QUERY_ONE / QUERY_PAGE | 正常查询 | 自动追加 `condition.deleted_at = 0` |
|
|
510
|
-
|
|
511
|
-
**前提**:表必须包含 `deleted_at`(number 类型)和 `deleted_by`(string 类型)字段。
|
|
512
|
-
|
|
513
|
-
```typescript
|
|
514
|
-
// 启用软删除
|
|
515
|
-
const cfgModel: IRequestCfgModel2 = {
|
|
516
|
-
method: 'article.delete',
|
|
517
|
-
sqlTable: 'article',
|
|
518
|
-
sqlSimpleName: KeysOfSimpleSQL.SIMPLE_DELETE,
|
|
519
|
-
enableSoftDelete: true,
|
|
520
|
-
};
|
|
521
|
-
|
|
522
|
-
// 实际执行:UPDATE article SET deleted_at=1712851200000, deleted_by='user123' WHERE id=1
|
|
523
|
-
```
|
|
524
|
-
|
|
525
|
-
## 分表 CRUD 入口
|
|
526
|
-
|
|
527
|
-
通过 `CurdProService.getShardingCrud()` 获取分表操作器:
|
|
528
|
-
|
|
529
|
-
```typescript
|
|
530
|
-
import { ShardingType } from '@/libs/crud-sharding';
|
|
531
|
-
|
|
532
|
-
const sharding = curdProService.getShardingCrud('mydb', SqlDbType.mysql, {
|
|
533
|
-
type: ShardingType.MONTH,
|
|
534
|
-
baseTable: 't_order',
|
|
535
|
-
timeColumn: 'created_at',
|
|
536
|
-
countCache: { ttlSeconds: 300 },
|
|
537
|
-
});
|
|
538
|
-
|
|
539
|
-
// 后续调用 sharding.insert / query / queryPage 等
|
|
540
|
-
// 路由逻辑详见 libs/crud-sharding/ROUTING_LOGIC.md
|
|
541
|
-
```
|
|
542
|
-
|
|
543
|
-
### ShardingCrudPro 完整使用指南
|
|
544
|
-
|
|
545
|
-
#### 获取实例
|
|
546
|
-
|
|
547
|
-
```typescript
|
|
548
|
-
import { ShardingType } from '@/libs/crud-sharding';
|
|
549
|
-
|
|
550
|
-
// 方式1:通过 CurdProService 获取(推荐)
|
|
551
|
-
const sharding = curdProService.getShardingCrud('mydb', SqlDbType.mysql, {
|
|
552
|
-
type: ShardingType.MONTH, // 按月分表
|
|
553
|
-
baseTable: 't_order', // 基础表名
|
|
554
|
-
timeColumn: 'created_at', // 时间字段(时间分表必填)
|
|
555
|
-
autoCreateTable: true, // 自动创建分表(可选)
|
|
556
|
-
countCache: { // COUNT 查询缓存(可选)
|
|
557
|
-
ttlSeconds: 300,
|
|
558
|
-
maxSize: 1000,
|
|
559
|
-
},
|
|
560
|
-
});
|
|
561
|
-
|
|
562
|
-
// 方式2:通过 CurdMixService 获取
|
|
563
|
-
const sharding = curdMixService.getShardingCrud('mydb', SqlDbType.mysql, {
|
|
564
|
-
type: ShardingType.HASH,
|
|
565
|
-
baseTable: 't_user',
|
|
566
|
-
shardingColumn: 'user_id', // 分表字段(HASH/RANGE 必填)
|
|
567
|
-
tableCount: 16, // 分表数量
|
|
568
|
-
});
|
|
569
|
-
```
|
|
570
|
-
|
|
571
|
-
#### 支持的分表策略
|
|
572
|
-
|
|
573
|
-
| 策略 | 枚举值 | 说明 | 示例 |
|
|
574
|
-
|------|--------|------|------|
|
|
575
|
-
| 按年分表 | `ShardingType.YEAR` | 按年份分表 | `order_2024`, `order_2025` |
|
|
576
|
-
| 按月分表 | `ShardingType.MONTH` | 按月份分表 | `order_202401`, `order_202402` |
|
|
577
|
-
| 按日分表 | `ShardingType.DAY` | 按日期分表 | `order_20240101` |
|
|
578
|
-
| 按范围分表 | `ShardingType.RANGE` | 按数值范围分表 | `user_0` ~ `user_99` |
|
|
579
|
-
| 按哈希分表 | `ShardingType.HASH` | 按哈希值分表 | `order_01` ~ `order_16` |
|
|
580
|
-
| 自定义分表 | `ShardingType.CUSTOM` | 自定义路由规则 | 自定义函数决定 |
|
|
581
|
-
|
|
582
|
-
#### 配置选项详解
|
|
583
|
-
|
|
584
|
-
```typescript
|
|
585
|
-
interface IShardingConfig {
|
|
586
|
-
type: ShardingType; // 分表类型(必填)
|
|
587
|
-
baseTable: string; // 基础表名(必填)
|
|
588
|
-
timeColumn?: string; // 时间字段(时间分表必填)
|
|
589
|
-
shardingColumn?: string; // 分表字段(HASH/RANGE 必填)
|
|
590
|
-
tableCount?: number; // 分表数量(HASH/RANGE,默认 16/10)
|
|
591
|
-
autoCreateTable?: boolean; // 自动创建分表(默认 false)
|
|
592
|
-
tableCreateOptions?: { // 分表创建选项
|
|
593
|
-
copyIndexes?: boolean; // 是否复制索引(默认 false)
|
|
594
|
-
ignoreForeignKeys?: boolean; // 是否忽略外键(默认 true)
|
|
595
|
-
tableOptions?: string; // 表选项(如 MySQL 引擎配置)
|
|
596
|
-
};
|
|
597
|
-
countCache?: { // COUNT 查询缓存(时间分表)
|
|
598
|
-
ttlSeconds?: number; // 缓存有效期(默认 300 秒)
|
|
599
|
-
maxSize?: number; // 最大缓存条目(默认 1000)
|
|
600
|
-
};
|
|
601
|
-
recentTableCount?: number; // 查询无时间范围时返回最近 N 个分表
|
|
602
|
-
customRouter?: (ctx) => string | string[]; // 自定义路由函数(CUSTOM 类型)
|
|
603
|
-
suffixFormatter?: (suffix) => string; // 自定义后缀格式化
|
|
604
|
-
}
|
|
605
|
-
```
|
|
606
|
-
|
|
607
|
-
#### API 一览
|
|
608
|
-
|
|
609
|
-
| 方法 | 返回类型 | 说明 |
|
|
610
|
-
|------|----------|------|
|
|
611
|
-
| `setBaseCfg(cfg)` | `this` | 设置基础配置,支持链式调用 |
|
|
612
|
-
| `getConfig()` | `IShardingConfig` | 获取分表配置 |
|
|
613
|
-
| `insert(reqJson)` | `ExecuteContext` | 插入单条数据(自动路由) |
|
|
614
|
-
| `batchInsert(reqJson)` | `IShardingSmartBatchInsertResult` | 批量插入(支持跨分表) |
|
|
615
|
-
| `update(reqJson)` | `ExecuteContext` | 更新数据 |
|
|
616
|
-
| `delete(reqJson)` | `ExecuteContext` | 删除数据 |
|
|
617
|
-
| `insertOrUpdate(reqJson)` | `ExecuteContext` | 插入或更新 |
|
|
618
|
-
| `insertOnDuplicateUpdate(reqJson)` | `ExecuteContext` | 原生 upsert |
|
|
619
|
-
| `queryOne(reqJson)` | `any \| null` | 查询单条 |
|
|
620
|
-
| `query(reqJson)` | `any[]` | 列表查询(多表自动合并) |
|
|
621
|
-
| `queryPage(reqJson)` | `IShardingPageQueryResult` | 分页查询(跨分表分页) |
|
|
622
|
-
| `queryCount(reqJson)` | `number` | 统计总数 |
|
|
623
|
-
| `isExist(reqJson)` | `boolean` | 存在性判断 |
|
|
624
|
-
|
|
625
|
-
#### 使用示例
|
|
626
|
-
|
|
627
|
-
##### 1. 时间分表(按月)
|
|
628
|
-
|
|
629
|
-
```typescript
|
|
630
|
-
const sharding = curdProService.getShardingCrud('mydb', SqlDbType.mysql, {
|
|
631
|
-
type: ShardingType.MONTH,
|
|
632
|
-
baseTable: 't_order',
|
|
633
|
-
timeColumn: 'created_at',
|
|
634
|
-
autoCreateTable: true,
|
|
635
|
-
});
|
|
636
|
-
|
|
637
|
-
// 插入数据 - 自动路由到对应月份分表
|
|
638
|
-
await sharding.insert({
|
|
639
|
-
data: {
|
|
640
|
-
order_id: 'ORD001',
|
|
641
|
-
amount: 100,
|
|
642
|
-
created_at: '2024-03-15 10:00:00', // -> 路由到 t_order_202403
|
|
643
|
-
},
|
|
644
|
-
});
|
|
645
|
-
|
|
646
|
-
// 批量插入 - 自动分组并行插入
|
|
647
|
-
const result = await sharding.batchInsert({
|
|
648
|
-
data: [
|
|
649
|
-
{ order_id: '001', amount: 100, created_at: '2024-01-15' }, // -> t_order_202401
|
|
650
|
-
{ order_id: '002', amount: 200, created_at: '2024-01-20' }, // -> t_order_202401
|
|
651
|
-
{ order_id: '003', amount: 150, created_at: '2024-02-10' }, // -> t_order_202402
|
|
652
|
-
{ order_id: '004', amount: 300, created_at: '2024-03-05' }, // -> t_order_202403
|
|
653
|
-
],
|
|
654
|
-
});
|
|
655
|
-
console.log(result.totalAffected); // 4
|
|
656
|
-
console.log(result.tableCount); // 3(涉及3个分表)
|
|
657
|
-
console.log(result.tableResults); // 各分表插入详情
|
|
658
|
-
|
|
659
|
-
// 更新数据 - 需要包含时间字段用于路由
|
|
660
|
-
await sharding.update({
|
|
661
|
-
condition: { order_id: 'ORD001', created_at: '2024-03-15' },
|
|
662
|
-
data: { amount: 200 },
|
|
663
|
-
});
|
|
664
|
-
|
|
665
|
-
// 列表查询 - 自动合并多表结果(必须传 orderBy)
|
|
666
|
-
const orders = await sharding.query({
|
|
667
|
-
condition: {
|
|
668
|
-
status: 'paid',
|
|
669
|
-
created_at: { $gte: '2024-01-01', $lte: '2024-03-31' }, // 时间范围自动路由
|
|
670
|
-
},
|
|
671
|
-
orderBy: 'created_at DESC', // 必须传,且格式固定为 timeColumn DESC
|
|
672
|
-
});
|
|
673
|
-
|
|
674
|
-
// 分页查询 - 跨分表分页自动处理
|
|
675
|
-
const page = await sharding.queryPage({
|
|
676
|
-
condition: { status: 'paid' },
|
|
677
|
-
pageNo: 1,
|
|
678
|
-
pageSize: 10,
|
|
679
|
-
orderBy: 'created_at DESC', // 必须传
|
|
680
|
-
});
|
|
681
|
-
console.log(page.rows, page.total_count);
|
|
682
|
-
|
|
683
|
-
// 查询总数 - 并行查询各分表后汇总
|
|
684
|
-
const count = await sharding.queryCount({
|
|
685
|
-
condition: { status: 'paid' },
|
|
686
|
-
});
|
|
687
|
-
|
|
688
|
-
// 查询单条 - 按顺序查询各分表,找到即返回
|
|
689
|
-
const order = await sharding.queryOne({
|
|
690
|
-
condition: { order_id: 'ORD001' },
|
|
691
|
-
});
|
|
692
|
-
|
|
693
|
-
// 存在性判断 - 并行查询各分表
|
|
694
|
-
const exists = await sharding.isExist({
|
|
695
|
-
condition: { order_id: 'ORD001' },
|
|
696
|
-
});
|
|
697
|
-
```
|
|
698
|
-
|
|
699
|
-
##### 2. 哈希分表
|
|
700
|
-
|
|
701
|
-
```typescript
|
|
702
|
-
const sharding = curdProService.getShardingCrud('mydb', SqlDbType.mysql, {
|
|
703
|
-
type: ShardingType.HASH,
|
|
704
|
-
baseTable: 't_user',
|
|
705
|
-
shardingColumn: 'user_id',
|
|
706
|
-
tableCount: 16,
|
|
707
|
-
autoCreateTable: true,
|
|
708
|
-
});
|
|
709
|
-
|
|
710
|
-
// 插入 - 根据 user_id 哈希值路由
|
|
711
|
-
await sharding.insert({
|
|
712
|
-
data: { user_id: 10001, name: '张三' }, // -> 路由到 t_user_05
|
|
713
|
-
});
|
|
714
|
-
|
|
715
|
-
// 查询 - 需要提供分表字段用于路由
|
|
716
|
-
const user = await sharding.queryOne({
|
|
717
|
-
condition: { user_id: 10001 }, // 根据 user_id 确定分表
|
|
718
|
-
});
|
|
719
|
-
|
|
720
|
-
// 查询多表 - 不带分表字段时可能查询多个分表
|
|
721
|
-
const users = await sharding.query({
|
|
722
|
-
condition: { status: 'active' }, // 无 user_id,可能扫描多个分表
|
|
723
|
-
orderBy: 'created_at DESC',
|
|
724
|
-
});
|
|
725
|
-
```
|
|
726
|
-
|
|
727
|
-
##### 3. 范围分表
|
|
728
|
-
|
|
729
|
-
```typescript
|
|
730
|
-
const sharding = curdProService.getShardingCrud('mydb', SqlDbType.mysql, {
|
|
731
|
-
type: ShardingType.RANGE,
|
|
732
|
-
baseTable: 't_log',
|
|
733
|
-
shardingColumn: 'log_id',
|
|
734
|
-
tableCount: 100,
|
|
735
|
-
});
|
|
736
|
-
|
|
737
|
-
// log_id 1-9999 路由到 t_log_0,10000-19999 路由到 t_log_1,以此类推
|
|
738
|
-
await sharding.insert({
|
|
739
|
-
data: { log_id: 15000, content: 'xxx' }, // -> 路由到 t_log_1
|
|
740
|
-
});
|
|
741
|
-
```
|
|
742
|
-
|
|
743
|
-
##### 4. 自定义分表规则
|
|
744
|
-
|
|
745
|
-
```typescript
|
|
746
|
-
const sharding = curdProService.getShardingCrud('mydb', SqlDbType.mysql, {
|
|
747
|
-
type: ShardingType.CUSTOM,
|
|
748
|
-
baseTable: 't_data',
|
|
749
|
-
customRouter: (context) => {
|
|
750
|
-
const { data, condition, config } = context;
|
|
751
|
-
// 自定义路由逻辑
|
|
752
|
-
const tenantId = data?.tenant_id || condition?.tenant_id;
|
|
753
|
-
return `t_data_${tenantId}`; // 按租户ID分表
|
|
754
|
-
},
|
|
755
|
-
});
|
|
756
|
-
```
|
|
757
|
-
|
|
758
|
-
##### 5. 链式配置
|
|
759
|
-
|
|
760
|
-
```typescript
|
|
761
|
-
const sharding = curdProService
|
|
762
|
-
.getShardingCrud('mydb', SqlDbType.mysql, {
|
|
763
|
-
type: ShardingType.MONTH,
|
|
764
|
-
baseTable: 't_order',
|
|
765
|
-
timeColumn: 'created_at',
|
|
766
|
-
})
|
|
767
|
-
.setBaseCfg({
|
|
768
|
-
enableStandardUpdateCfg: true,
|
|
769
|
-
enableSoftDelete: true,
|
|
770
|
-
});
|
|
771
|
-
```
|
|
772
|
-
|
|
773
|
-
#### 重要约束
|
|
774
|
-
|
|
775
|
-
**时间分表查询约束:**
|
|
776
|
-
- 列表查询 (`query`) 和分页查询 (`queryPage`) 必须传 `orderBy` 参数
|
|
777
|
-
- `orderBy` 格式必须固定为 `'{timeColumn} DESC'`,如 `'created_at DESC'`
|
|
778
|
-
- 这是分表合并算法的要求:按时间倒序的表顺序 + 倒序排序的数据 = 无需内存排序直接合并
|
|
779
|
-
|
|
780
|
-
```typescript
|
|
781
|
-
// 正确
|
|
782
|
-
await sharding.query({
|
|
783
|
-
condition: { status: 'paid' },
|
|
784
|
-
orderBy: 'created_at DESC', // 符合约束
|
|
785
|
-
});
|
|
786
|
-
|
|
787
|
-
// 错误 - 缺少 orderBy
|
|
788
|
-
await sharding.query({
|
|
789
|
-
condition: { status: 'paid' },
|
|
790
|
-
});
|
|
791
|
-
|
|
792
|
-
// 错误 - 排序方向错误
|
|
793
|
-
await sharding.query({
|
|
794
|
-
condition: { status: 'paid' },
|
|
795
|
-
orderBy: 'created_at ASC',
|
|
796
|
-
});
|
|
797
|
-
```
|
|
798
|
-
|
|
799
|
-
**写操作路由约束:**
|
|
800
|
-
- `insert` 必须在 `data` 中包含 `timeColumn`(时间分表)或 `shardingColumn`(HASH/RANGE)
|
|
801
|
-
- `update`/`delete` 必须在 `condition` 中包含分表字段,或提供足够的时间范围确定单一分表
|
|
802
|
-
|
|
803
|
-
```typescript
|
|
804
|
-
// 正确 - 数据包含时间字段
|
|
805
|
-
await sharding.insert({
|
|
806
|
-
data: { order_id: '001', created_at: '2024-03-15' },
|
|
807
|
-
});
|
|
808
|
-
|
|
809
|
-
// 错误 - 缺少时间字段,无法路由
|
|
810
|
-
await sharding.insert({
|
|
811
|
-
data: { order_id: '001' }, // 报错:无法确定目标分表
|
|
812
|
-
});
|
|
813
|
-
```
|
|
814
|
-
|
|
815
|
-
## CurdMixService
|
|
816
|
-
|
|
817
|
-
### 关联数据填充执行流程
|
|
818
|
-
|
|
819
|
-
1. `CurdMixService.executeCrudByCfg()` → 调用 `prepare()` 注册 5 个处理器
|
|
820
|
-
2. CrudPro 执行 SQL,返回 `ExecuteContext`
|
|
821
|
-
3. `MyContextFunc.afterExecuteSQLList()` 遍历所有处理器:
|
|
822
|
-
- `handleExecuteContextPrepare()` — 预加载关联数据
|
|
823
|
-
- `handleExecuteContext()` — 遍历每行,按 `sourceColumn` 取值查关联数据,通过 `targetColumns` 映射写回
|
|
824
|
-
|
|
825
|
-
### linkColumnRelationDatas
|
|
826
|
-
|
|
827
|
-
独立于 CRUD 操作,直接对已有数据行执行关联填充。适用于数据来自缓存、外部接口或其他非 CurdMixService 渠道,但仍需要字典翻译、用户信息等关联数据的场景。
|
|
828
|
-
|
|
829
|
-
> ⚠️ 该方法会**原地修改** `rows` 数组中的对象,不会返回新数组。
|
|
830
|
-
|
|
831
|
-
#### 方法签名
|
|
832
|
-
|
|
833
|
-
```typescript
|
|
834
|
-
linkColumnRelationDatas(rows: any[], param: ILinkColumnRelationParam): Promise<void>
|
|
835
|
-
```
|
|
836
|
-
|
|
837
|
-
#### 参数接口
|
|
838
|
-
|
|
839
|
-
```typescript
|
|
840
|
-
interface ILinkColumnRelationParam {
|
|
841
|
-
columnsRelations: ColumnRelation[]; // 关联配置数组
|
|
842
|
-
}
|
|
843
|
-
```
|
|
844
|
-
|
|
845
|
-
| 参数 | 类型 | 说明 |
|
|
846
|
-
|------|------|------|
|
|
847
|
-
| `rows` | `any[]` | 待填充的数据行数组;为空或非数组时直接返回 |
|
|
848
|
-
| `param.columnsRelations` | `ColumnRelation[]` | 关联规则配置,与 CRUD 配置中的 `columnsRelation` 格式一致 |
|
|
849
|
-
|
|
850
|
-
#### 基础用法
|
|
851
|
-
|
|
852
|
-
```typescript
|
|
853
|
-
// 场景:从缓存或其他来源获取了数据行,仍需要关联填充
|
|
854
|
-
const rows = [...]; // 任意来源的数据行
|
|
855
|
-
|
|
856
|
-
await curdMixService.linkColumnRelationDatas(rows, {
|
|
857
|
-
columnsRelations: [
|
|
858
|
-
{
|
|
859
|
-
relatedType: 'dict',
|
|
860
|
-
relatedCode: 'SexEnum',
|
|
861
|
-
sourceColumn: 'sex',
|
|
862
|
-
targetColumns: [{ from: 'label', to: 'sex_text' }],
|
|
863
|
-
},
|
|
864
|
-
],
|
|
865
|
-
});
|
|
866
|
-
// rows 中的每行会原地追加 sex_text 字段
|
|
867
|
-
```
|
|
868
|
-
|
|
869
|
-
#### 多关联类型组合
|
|
870
|
-
|
|
871
|
-
```typescript
|
|
872
|
-
const rows = await redisCache.get('order_list');
|
|
873
|
-
|
|
874
|
-
await curdMixService.linkColumnRelationDatas(rows, {
|
|
875
|
-
columnsRelations: [
|
|
876
|
-
// 字典翻译
|
|
877
|
-
{
|
|
878
|
-
relatedType: 'dict',
|
|
879
|
-
relatedCode: 'OrderStatus',
|
|
880
|
-
sourceColumn: 'status',
|
|
881
|
-
targetColumns: [
|
|
882
|
-
{ from: 'label', to: 'status_text' },
|
|
883
|
-
{ from: 'color', to: 'status_color' },
|
|
884
|
-
],
|
|
885
|
-
},
|
|
886
|
-
// 系统配置枚举
|
|
887
|
-
{
|
|
888
|
-
relatedType: 'sysCfgEnum',
|
|
889
|
-
relatedCode: 'PayMethod',
|
|
890
|
-
sourceColumn: 'pay_method',
|
|
891
|
-
targetColumns: [
|
|
892
|
-
{ from: 'label', to: 'pay_method_info.label' },
|
|
893
|
-
{ from: 'style', to: 'pay_method_info.style' },
|
|
894
|
-
],
|
|
895
|
-
},
|
|
896
|
-
// 用户信息填充
|
|
897
|
-
{
|
|
898
|
-
relatedType: 'accountBasic',
|
|
899
|
-
sourceColumn: 'created_by',
|
|
900
|
-
targetColumns: [], // 空 = 使用默认映射
|
|
901
|
-
},
|
|
902
|
-
// 工作台信息
|
|
903
|
-
{
|
|
904
|
-
relatedType: 'workbenchBasic',
|
|
905
|
-
sourceColumn: 'workbench_code',
|
|
906
|
-
targetColumns: [
|
|
907
|
-
{ from: 'workbench_domain', to: 'workbench_info.workbench_domain' },
|
|
908
|
-
{ from: 'workbench_name', to: 'workbench_info.workbench_name' },
|
|
909
|
-
],
|
|
910
|
-
},
|
|
911
|
-
],
|
|
912
|
-
});
|
|
913
|
-
```
|
|
914
|
-
|
|
915
|
-
#### 与 CrudProQuick 配合使用
|
|
916
|
-
|
|
917
|
-
```typescript
|
|
918
|
-
const quick = curdProService.getQuickCrud('mydb', SqlDbType.mysql, 't_order');
|
|
919
|
-
|
|
920
|
-
// 先用 CrudProQuick 获取原始数据(不带关联)
|
|
921
|
-
const rows = await quick.getList({
|
|
922
|
-
condition: { status: 'paid' },
|
|
923
|
-
});
|
|
924
|
-
|
|
925
|
-
// 再用 linkColumnRelationDatas 补充关联数据
|
|
926
|
-
await curdMixService.linkColumnRelationDatas(rows, {
|
|
927
|
-
columnsRelations: [
|
|
928
|
-
{
|
|
929
|
-
relatedType: 'dict',
|
|
930
|
-
relatedCode: 'OrderStatus',
|
|
931
|
-
sourceColumn: 'status',
|
|
932
|
-
targetColumns: [{ from: 'label', to: 'status_text' }],
|
|
933
|
-
},
|
|
934
|
-
{
|
|
935
|
-
relatedType: 'accountBasic',
|
|
936
|
-
sourceColumn: 'created_by',
|
|
937
|
-
targetColumns: [],
|
|
938
|
-
},
|
|
939
|
-
],
|
|
940
|
-
});
|
|
941
|
-
```
|
|
942
|
-
|
|
943
|
-
> **提示**:如果 CRUD 操作本身就需要关联填充,建议直接使用 `CurdMixService.executeCrudByCfg()` 配置 `columnsRelation`,一步完成查询和填充。`linkColumnRelationDatas` 适用于数据已存在的二次填充场景。
|
|
944
|
-
|
|
945
|
-
## ColumnRelation 配置
|
|
946
|
-
|
|
947
|
-
```typescript
|
|
948
|
-
interface ColumnRelation {
|
|
949
|
-
relatedType: any; // 关联类型
|
|
950
|
-
relatedCode?: string; // 关联编码(dict/sysCfgEnum/linkToCustom 时必填)
|
|
951
|
-
sourceColumn: string; // 从结果行中取值的字段名
|
|
952
|
-
targetColumns?: CopyAttr[]; // 映射规则,[{ from: 'label', to: 'sex_text' }]
|
|
953
|
-
}
|
|
954
|
-
|
|
955
|
-
interface CopyAttr {
|
|
956
|
-
from: string; // 关联数据中的字段名,支持 '*' 表示整体赋值
|
|
957
|
-
to: string; // 写入结果行的目标路径(支持嵌套,如 'user_info.name')
|
|
958
|
-
}
|
|
959
|
-
```
|
|
960
|
-
|
|
961
|
-
## 关联类型
|
|
962
|
-
|
|
963
|
-
### dict — 数据字典
|
|
964
|
-
|
|
965
|
-
从 `sys_data_dict_item` 表查询字典数据,按 `dict_code` + `value` 匹配。
|
|
966
|
-
|
|
967
|
-
```typescript
|
|
968
|
-
const cfgJson: IRequestCfgModel = {
|
|
969
|
-
method: 'user.list',
|
|
970
|
-
sqlTable: 'sys_user',
|
|
971
|
-
sqlSimpleName: KeysOfSimpleSQL.SIMPLE_QUERY,
|
|
972
|
-
columnsRelation: [
|
|
973
|
-
{
|
|
974
|
-
relatedType: 'dict',
|
|
975
|
-
relatedCode: 'SexEnum', // 字典编码
|
|
976
|
-
sourceColumn: 'sex', // 结果行中的 sex 字段值作为字典 value
|
|
977
|
-
targetColumns: [
|
|
978
|
-
{ from: 'label', to: 'sex_text' }, // 字典 label → sex_text
|
|
979
|
-
],
|
|
980
|
-
},
|
|
981
|
-
{
|
|
982
|
-
relatedType: 'dict',
|
|
983
|
-
relatedCode: 'StatusEnum',
|
|
984
|
-
sourceColumn: 'status',
|
|
985
|
-
targetColumns: [
|
|
986
|
-
{ from: 'label', to: 'status_text' },
|
|
987
|
-
{ from: 'color', to: 'status_color' },
|
|
988
|
-
],
|
|
989
|
-
},
|
|
990
|
-
],
|
|
991
|
-
};
|
|
992
|
-
```
|
|
993
|
-
|
|
994
|
-
### sysCfgEnum — 系统配置枚举
|
|
995
|
-
|
|
996
|
-
从 `sys_configs` 表查询配置,按 `code` 列作为唯一键匹配。
|
|
997
|
-
|
|
998
|
-
```typescript
|
|
999
|
-
columnsRelation: [
|
|
1000
|
-
{
|
|
1001
|
-
relatedType: 'sysCfgEnum',
|
|
1002
|
-
relatedCode: 'OrderStatus',
|
|
1003
|
-
sourceColumn: 'order_status',
|
|
1004
|
-
targetColumns: [
|
|
1005
|
-
{ from: 'label', to: 'order_status_info.label' },
|
|
1006
|
-
{ from: 'style', to: 'order_status_info.style' },
|
|
1007
|
-
],
|
|
1008
|
-
},
|
|
1009
|
-
]
|
|
1010
|
-
```
|
|
1011
|
-
|
|
1012
|
-
### accountBasic — 用户账号信息
|
|
1013
|
-
|
|
1014
|
-
根据 `sourceColumn` 中的用户 ID,查询用户基本信息(昵称、头像等)。
|
|
1015
|
-
|
|
1016
|
-
```typescript
|
|
1017
|
-
columnsRelation: [
|
|
1018
|
-
{
|
|
1019
|
-
relatedType: 'accountBasic',
|
|
1020
|
-
sourceColumn: 'created_by', // 用户 ID 字段
|
|
1021
|
-
targetColumns: [], // 空 = 使用默认映射
|
|
1022
|
-
},
|
|
1023
|
-
]
|
|
1024
|
-
```
|
|
1025
|
-
|
|
1026
|
-
**用户 ID 适配**:支持数字、字符串、JSON 数组等多种 ID 格式,自动通过 `toFatcmsUserAccountId` 转换。
|
|
1027
|
-
|
|
1028
|
-
### workbenchBasic — 工作台站点信息
|
|
1029
|
-
|
|
1030
|
-
根据 `workbench_code` 查询站点信息。
|
|
1031
|
-
|
|
1032
|
-
```typescript
|
|
1033
|
-
columnsRelation: [
|
|
1034
|
-
{
|
|
1035
|
-
relatedType: 'workbenchBasic',
|
|
1036
|
-
sourceColumn: 'workbench_code',
|
|
1037
|
-
targetColumns: [
|
|
1038
|
-
{ from: 'workbench_domain', to: 'workbench_info.workbench_domain' },
|
|
1039
|
-
{ from: 'workbench_name', to: 'workbench_info.workbench_name' },
|
|
1040
|
-
],
|
|
1041
|
-
},
|
|
1042
|
-
]
|
|
1043
|
-
```
|
|
1044
|
-
|
|
1045
|
-
支持数组字段(如 `workbench_code_array`),目标路径使用 `$ARRAY_INDEX` 占位符:
|
|
1046
|
-
|
|
1047
|
-
```typescript
|
|
1048
|
-
columnsRelation: [
|
|
1049
|
-
{
|
|
1050
|
-
relatedType: 'workbenchBasic',
|
|
1051
|
-
sourceColumn: 'workbench_code_array',
|
|
1052
|
-
targetColumns: [
|
|
1053
|
-
{ from: 'workbench_domain', to: 'workbench_info_array[$ARRAY_INDEX].workbench_domain' },
|
|
1054
|
-
{ from: 'workbench_name', to: 'workbench_info_array[$ARRAY_INDEX].workbench_name' },
|
|
1055
|
-
],
|
|
1056
|
-
},
|
|
1057
|
-
]
|
|
1058
|
-
```
|
|
1059
|
-
|
|
1060
|
-
### linkToCustom — 自定义表关联
|
|
1061
|
-
|
|
1062
|
-
关联任意自定义表,需在 `sys_configs` 中配置关联规则。
|
|
1063
|
-
|
|
1064
|
-
```typescript
|
|
1065
|
-
columnsRelation: [
|
|
1066
|
-
{
|
|
1067
|
-
relatedType: 'linkToCustom',
|
|
1068
|
-
relatedCode: 'categoryLinkConfig', // 关联配置编码
|
|
1069
|
-
sourceColumn: 'category_id',
|
|
1070
|
-
targetColumns: [], // 使用配置中的默认映射
|
|
1071
|
-
},
|
|
1072
|
-
]
|
|
1073
|
-
```
|
|
1074
|
-
|
|
1075
|
-
## 标准表字段
|
|
1076
|
-
|
|
1077
|
-
推荐业务表包含以下标准字段,以配合服务层的自动填充和软删除机制:
|
|
1078
|
-
|
|
1079
|
-
**常用字段(6 个)**:`deleted_at`、`deleted_by`、`created_by`、`created_at`、`modified_by`、`modified_at`
|
|
1080
|
-
|
|
1081
|
-
**完整字段(12 个)**:在常用字段基础上增加 `created_account_type`、`created_avatar`、`created_nickname`、`modified_account_type`、`modified_avatar`、`modified_nickname`
|
|
1082
|
-
|
|
1083
|
-
类型定义位于 `@/models/StandardColumns`:
|
|
1084
|
-
|
|
1085
|
-
```typescript
|
|
1086
|
-
import { StandardDataModel, FullStandardDataModel, NotDeletedCondition } from '@/models/StandardColumns';
|
|
1087
|
-
|
|
1088
|
-
// 定义业务表数据类型
|
|
1089
|
-
interface OrderEntity {
|
|
1090
|
-
id: number;
|
|
1091
|
-
order_no: string;
|
|
1092
|
-
amount: number;
|
|
1093
|
-
}
|
|
1094
|
-
type Order = StandardDataModel<OrderEntity>; // 自动包含 6 个标准字段
|
|
1095
|
-
type OrderFull = FullStandardDataModel<OrderEntity>; // 自动包含 12 个标准字段
|
|
1096
|
-
|
|
1097
|
-
// 未删除查询条件
|
|
1098
|
-
const condition = { ...NotDeletedCondition, status: 1 };
|
|
1099
|
-
// 等价于 { deleted_at: 0, status: 1 }
|
|
1100
|
-
```
|