create-dp-koa 1.0.1 → 1.0.2

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 (65) hide show
  1. package/package.json +1 -1
  2. package/template/.cursor/commands/cheatsheet-backend-controller.md +2 -2
  3. package/template/.cursor/commands/implement-backend-api-controller.md +6 -4
  4. package/template/.cursor/rules/11-backend-controller-recipes.skill.md +89 -10
  5. package/template/.trae/skills/11-backend-controller-recipes.skill.md +91 -10
  6. package/template/src/controllers/example/ExampleController.ts +14 -0
  7. package/template/src/entity/index.ts +1 -15
  8. package/template/src/framework/decorator/processor/AnnotationProcessor.ts +5 -1
  9. package/template/src/routers/index.ts +0 -35
  10. package/template/src/utils/testDataInitializer.ts +2 -269
  11. package/template/test/controllers/example/ExampleController.test.ts +29 -31
  12. package/template/test/framework/annotation/AnnotationDecorators.test.ts +15 -15
  13. package/template/test/framework/annotation/AnnotationExecutor.test.ts +27 -32
  14. package/template/test/framework/annotation/AnnotationProcessor.test.ts +25 -24
  15. package/template/test/framework/annotation/CustomProcessors.test.ts +15 -25
  16. package/template/test/framework/annotation/NewRouter.test.ts +9 -7
  17. package/template/test/framework/annotation/ProcessorManager.test.ts +14 -27
  18. package/template/test/framework/databaseConfig.test.ts +2 -2
  19. package/template/test/integration/integration.test.ts +15 -72
  20. package/template/src/controllers/cacheManagement.controller.ts +0 -131
  21. package/template/src/controllers/captcha.controller.ts +0 -57
  22. package/template/src/controllers/example/NewAnnotationExampleController.ts +0 -159
  23. package/template/src/controllers/example/SwaggerExampleController.ts +0 -205
  24. package/template/src/controllers/example/TransactionExample.controller.ts +0 -336
  25. package/template/src/controllers/health.controller.ts +0 -235
  26. package/template/src/controllers/home/register.controller.ts +0 -58
  27. package/template/src/controllers/home/ytGoods.controller.ts +0 -92
  28. package/template/src/controllers/home/ytShop.controller.ts +0 -135
  29. package/template/src/controllers/home/ytUser.controller.ts +0 -89
  30. package/template/src/controllers/logManagement.controller.ts +0 -396
  31. package/template/src/controllers/public/emailSend.controller.ts +0 -65
  32. package/template/src/controllers/public/ytUserAuth.controller.ts +0 -174
  33. package/template/src/controllers/testData.controller.ts +0 -253
  34. package/template/src/dto/controller/example/NewAnnotationExampleController.dto.ts +0 -73
  35. package/template/src/dto/controller/home/emailSend.controller.dto.ts +0 -40
  36. package/template/src/dto/controller/home/register.controller.dto.ts +0 -45
  37. package/template/src/dto/controller/home/ytGoods.controller.dto.ts +0 -55
  38. package/template/src/dto/controller/home/ytShop.controller.dto.ts +0 -69
  39. package/template/src/dto/controller/home/ytUser.controller.dto.ts +0 -44
  40. package/template/src/dto/controller/public/ytUserAuth.controller.dto.ts +0 -63
  41. package/template/src/dto/goods.dto.ts +0 -212
  42. package/template/src/dto/service/ytService.dto.ts +0 -13
  43. package/template/src/dto/user.dto.ts +0 -177
  44. package/template/src/entity/columnTypes.ts +0 -13
  45. package/template/src/entity/goodsImagesUnlockKey.entity.ts +0 -33
  46. package/template/src/entity/goodsUnlocker.entity.ts +0 -34
  47. package/template/src/entity/shop.entity.ts +0 -52
  48. package/template/src/entity/shopUser.entity.ts +0 -41
  49. package/template/src/entity/ytGoods.entity.ts +0 -94
  50. package/template/src/entity/ytUser.entity.ts +0 -96
  51. package/template/src/examples/SwaggerProcessorExample.ts +0 -169
  52. package/template/src/examples/TransactionManagerDemo.ts +0 -377
  53. package/template/src/framework/utils/dynamicSwagger.ts +0 -410
  54. package/template/src/repository/UserRepository.ts +0 -122
  55. package/template/src/service/paramValidateTest.service.ts +0 -139
  56. package/template/src/service/ytGoods.service.ts +0 -42
  57. package/template/src/service/ytShop.service.ts +0 -90
  58. package/template/src/service/ytUser.service.ts +0 -451
  59. package/template/src/test/swaggerParameterTest.ts +0 -90
  60. package/template/test/controllers/controllers.test.ts +0 -173
  61. package/template/test/controllers/example/NewAnnotationExampleController.test.ts +0 -200
  62. package/template/test/framework/TransactionManagerDemo.test.ts +0 -363
  63. package/template/test/service/business.test.ts +0 -87
  64. package/template/test/service/paramValidateTest.service.test.ts +0 -184
  65. package/template/test/service/ytUser.service.test.ts +0 -566
@@ -1,159 +0,0 @@
1
- import { Get, Post, Query, Body, State, ResponseCode, ResponseHeader } from '@src/framework/decorator/controller';
2
- import { BaseController, ControllerResponse } from '@src/controllers/base.controller';
3
- import { Inject } from 'dp-ioc2';
4
- import { YtUserService } from '@src/service/ytUser.service';
5
- import { Logging, Permission, RateLimit } from '@src/framework/decorator/processor/AnnotationDecorators';
6
- import { ExampleBodyDto, ExampleQueryDto } from '@src/dto/controller/example/NewAnnotationExampleController.dto';
7
-
8
- /**
9
- * 新注解系统使用示例控制器
10
- * 展示如何在实际项目中使用新的注解处理器系统
11
- */
12
- export class NewAnnotationExampleController extends BaseController {
13
- @Inject(YtUserService)
14
- private ytUserService: YtUserService;
15
-
16
- /**
17
- * 示例1:基础的新注解使用
18
- * 使用 Logging 注解记录请求日志
19
- */
20
- @Get('/basic-example')
21
- @Logging()
22
- @ResponseCode(200)
23
- async basicExample(@Query() query: ExampleQueryDto): Promise<ControllerResponse<string>> {
24
- console.log('执行基础示例方法');
25
- return this.success('基础示例执行成功');
26
- }
27
-
28
- /**
29
- * 示例2:权限控制
30
- * 使用 Permission 注解进行权限检查
31
- */
32
- @Get('/protected-data')
33
- @Logging()
34
- @Permission({ requiredPermission: 'read:sensitive-data' })
35
- @ResponseCode(200)
36
- async getProtectedData(@State('user') user: any): Promise<ControllerResponse<any>> {
37
- console.log('获取受保护的数据');
38
- return this.success({
39
- message: '这是受保护的数据',
40
- user: user,
41
- timestamp: new Date().toISOString()
42
- });
43
- }
44
-
45
- /**
46
- * 示例3:请求限流
47
- * 使用 RateLimit 注解限制请求频率
48
- */
49
- @Post('/rate-limited-endpoint')
50
- @Logging()
51
- @RateLimit({ maxRequests: 5, windowMs: 60000 }) // 每分钟最多5次请求
52
- @ResponseCode(201)
53
- async rateLimitedEndpoint(@Body() body: ExampleBodyDto): Promise<ControllerResponse<any>> {
54
- console.log('处理限流端点请求');
55
- return this.success({
56
- message: '请求处理成功',
57
- data: body,
58
- timestamp: new Date().toISOString()
59
- });
60
- }
61
-
62
- /**
63
- * 示例4:复合注解使用
64
- * 同时使用多个新注解
65
- */
66
- @Get('/complex-example')
67
- @Logging()
68
- @Permission({ requiredPermission: 'read:complex-data' })
69
- @RateLimit({ maxRequests: 10, windowMs: 300000 }) // 5分钟内最多10次请求
70
- @ResponseCode(200)
71
- @ResponseHeader('X-Custom-Header', 'ComplexExample')
72
- async complexExample(
73
- @Query() query: ExampleQueryDto,
74
- @State('user') user: any
75
- ): Promise<ControllerResponse<any>> {
76
- console.log('执行复杂示例方法');
77
-
78
- // 模拟业务逻辑
79
- const usersResult = await this.ytUserService.getUsers({ page: 1, pageSize: 10 });
80
-
81
- return this.success({
82
- message: '复杂示例执行成功',
83
- query: query,
84
- user: user,
85
- usersCount: usersResult.data ? usersResult.data[1] : 0,
86
- timestamp: new Date().toISOString()
87
- });
88
- }
89
-
90
- /**
91
- * 示例5:新旧注解混合使用
92
- * 展示新旧注解系统的兼容性
93
- */
94
- @Post('/mixed-annotations')
95
- @Logging() // 新注解
96
- @ResponseCode(201) // 旧注解
97
- @ResponseHeader('X-Mixed-Example', 'true') // 旧注解
98
- async mixedAnnotations(@Body() body: ExampleBodyDto): Promise<ControllerResponse<any>> {
99
- console.log('执行混合注解示例');
100
- return this.success({
101
- message: '混合注解示例执行成功',
102
- data: body,
103
- note: '这个端点同时使用了新旧注解系统'
104
- });
105
- }
106
-
107
- /**
108
- * 示例6:错误处理
109
- * 展示注解处理器如何处理错误情况
110
- */
111
- @Get('/error-example')
112
- @Logging()
113
- @Permission({ requiredPermission: 'admin:access' })
114
- async errorExample(): Promise<ControllerResponse<any>> {
115
- console.log('执行错误示例');
116
-
117
- // 模拟权限不足的情况
118
- throw new Error('模拟权限不足错误');
119
- }
120
-
121
- /**
122
- * 示例7:异步处理
123
- * 展示注解处理器如何处理异步方法
124
- */
125
- @Get('/async-example')
126
- @Logging()
127
- @RateLimit({ maxRequests: 3, windowMs: 60000 })
128
- async asyncExample(): Promise<ControllerResponse<any>> {
129
- console.log('开始异步处理');
130
-
131
- // 模拟异步操作
132
- await new Promise(resolve => setTimeout(resolve, 1000));
133
-
134
- console.log('异步处理完成');
135
- return this.success({
136
- message: '异步处理完成',
137
- timestamp: new Date().toISOString()
138
- });
139
- }
140
-
141
- /**
142
- * 示例8:数据验证
143
- * 展示参数验证和响应验证
144
- */
145
- @Post('/validation-example')
146
- @Logging()
147
- async validationExample(@Body() body: ExampleBodyDto): Promise<ControllerResponse<any>> {
148
- console.log('执行验证示例');
149
-
150
- // 这里会进行参数验证(通过 @Body 注解)
151
- // 响应也会进行验证(通过 ControllerResponse 类型)
152
-
153
- return this.success({
154
- message: '验证通过',
155
- receivedData: body,
156
- validationTimestamp: new Date().toISOString()
157
- });
158
- }
159
- }
@@ -1,205 +0,0 @@
1
- import { Get, Post, Put, Del, Body, Query, Params } from '@src/framework/decorator/controller';
2
- import { BaseController } from '@src/controllers/base.controller';
3
- import { Api, ApiTags, ApiResponse, ApiBody, ApiParam } from '@src/framework/decorator/swagger';
4
- import { logger } from '@src/framework/utils/logger';
5
-
6
- /**
7
- * Swagger示例控制器 - 展示完整的Swagger注解用法
8
- */
9
- @ApiTags('Swagger示例', 'API文档完整示例')
10
- export class SwaggerExampleController extends BaseController {
11
-
12
- /**
13
- * GET请求 - 带查询参数
14
- */
15
- @Get('/user/list')
16
- @Api({
17
- tags: ['用户管理'],
18
- summary: '获取用户列表',
19
- description: '根据查询参数获取用户列表',
20
- operationId: 'getUserList',
21
- })
22
- @ApiResponse({
23
- status: 200,
24
- description: '成功返回用户列表',
25
- schema: {
26
- type: 'object',
27
- properties: {
28
- code: { type: 'number', example: 0 },
29
- data: {
30
- type: 'array',
31
- items: {
32
- type: 'object',
33
- properties: {
34
- id: { type: 'number' },
35
- name: { type: 'string' },
36
- email: { type: 'string' },
37
- },
38
- },
39
- },
40
- message: { type: 'string' },
41
- },
42
- },
43
- })
44
- async getUserList(@Query() query: { page: number; pageSize: number; keyword?: string }) {
45
- return this.success({
46
- users: [
47
- { id: 1, name: '张三', email: 'zhang@example.com' },
48
- { id: 2, name: '李四', email: 'li@example.com' },
49
- ],
50
- total: 2,
51
- page: query.page || 1,
52
- pageSize: query.pageSize || 10,
53
- }, '获取用户列表成功');
54
- }
55
-
56
- /**
57
- * GET请求 - 带路径参数
58
- */
59
- @Get('/user/:id')
60
- @Api({
61
- tags: ['用户管理'],
62
- summary: '获取用户详情',
63
- description: '根据用户ID获取用户详细信息',
64
- })
65
- @ApiResponse({
66
- status: 200,
67
- description: '成功返回用户详情',
68
- })
69
- @ApiResponse({
70
- status: 404,
71
- description: '用户不存在',
72
- })
73
- async getUserById(@Params() params: { id: number }) {
74
- return this.success({
75
- id: params.id,
76
- name: '张三',
77
- email: 'zhang@example.com',
78
- avatar: 'https://example.com/avatar.jpg',
79
- }, '获取用户详情成功');
80
- }
81
-
82
- /**
83
- * POST请求 - 带请求体
84
- */
85
- @Post('/user')
86
- @Api({
87
- tags: ['用户管理'],
88
- summary: '创建新用户',
89
- description: '创建新用户并返回用户信息',
90
- })
91
- @ApiBody({
92
- description: '用户信息',
93
- required: true,
94
- schema: {
95
- type: 'object',
96
- required: ['name', 'email'],
97
- properties: {
98
- name: { type: 'string', description: '用户名', example: '张三' },
99
- email: { type: 'string', format: 'email', description: '邮箱', example: 'zhang@example.com' },
100
- age: { type: 'number', description: '年龄', example: 25 },
101
- },
102
- },
103
- examples: {
104
- example1: {
105
- summary: '示例数据1',
106
- value: {
107
- name: '张三',
108
- email: 'zhang@example.com',
109
- age: 25,
110
- },
111
- },
112
- },
113
- })
114
- @ApiResponse({
115
- status: 200,
116
- description: '成功创建用户',
117
- schema: {
118
- type: 'object',
119
- properties: {
120
- code: { type: 'number' },
121
- data: {
122
- type: 'object',
123
- properties: {
124
- id: { type: 'number' },
125
- name: { type: 'string' },
126
- email: { type: 'string' },
127
- },
128
- },
129
- message: { type: 'string' },
130
- },
131
- },
132
- })
133
- @ApiResponse({
134
- status: 400,
135
- description: '参数验证失败',
136
- })
137
- async createUser(@Body() body: { name: string; email: string; age?: number }) {
138
- return this.success({
139
- id: Math.floor(Math.random() * 1000),
140
- name: body.name,
141
- email: body.email,
142
- age: body.age,
143
- }, '创建用户成功');
144
- }
145
-
146
- /**
147
- * PUT请求 - 更新资源
148
- */
149
- @Put('/user/:id')
150
- @Api({
151
- tags: ['用户管理'],
152
- summary: '更新用户信息',
153
- description: '根据用户ID更新用户信息',
154
- })
155
- @ApiBody({
156
- description: '更新的用户信息',
157
- required: true,
158
- schema: {
159
- type: 'object',
160
- properties: {
161
- name: { type: 'string', description: '用户名' },
162
- email: { type: 'string', format: 'email', description: '邮箱' },
163
- age: { type: 'number', description: '年龄' },
164
- },
165
- },
166
- })
167
- @ApiResponse({
168
- status: 200,
169
- description: '成功更新用户信息',
170
- })
171
- @ApiResponse({
172
- status: 404,
173
- description: '用户不存在',
174
- })
175
- async updateUser(@Params() params: { id: number }, @Body() body: { name?: string; email?: string; age?: number }) {
176
- return this.success({
177
- id: params.id,
178
- ...body,
179
- }, '更新用户成功');
180
- }
181
-
182
- /**
183
- * DELETE请求 - 删除资源
184
- */
185
- @Del('/user/:id')
186
- @Api({
187
- tags: ['用户管理'],
188
- summary: '删除用户',
189
- description: '根据用户ID删除用户',
190
- })
191
- @ApiResponse({
192
- status: 200,
193
- description: '成功删除用户',
194
- })
195
- @ApiResponse({
196
- status: 404,
197
- description: '用户不存在',
198
- })
199
- async deleteUser(@Params() params: { id: number }) {
200
- logger.debug('🔍 deleteUser 方法被调用');
201
- logger.debug('📋 参数:', params);
202
- return this.success(null, '删除用户成功');
203
- }
204
- }
205
-
@@ -1,336 +0,0 @@
1
- /**
2
- * 事务管理器使用示例控制器
3
- * 演示在实际 API 中如何使用 TransactionManager
4
- */
5
-
6
- import { Post, Get, Put, Del } from '@src/framework/decorator/controller';
7
- import { Context } from 'koa';
8
- import { transactionManager } from '@src/framework/utils/TransactionManager';
9
- import { YtUserEntity } from '@src/entity/ytUser.entity';
10
- import { logger } from '@src/framework/utils/logger';
11
- import * as bcrypt from 'bcryptjs';
12
-
13
- export class TransactionExampleController {
14
-
15
- /**
16
- * 示例 1: 基本事务 - 创建用户
17
- * POST /api/example/transaction/create-user
18
- */
19
- @Post('/create-user')
20
- async createUser(ctx: Context) {
21
- const { email, telnumber, password } = ctx.request.body;
22
-
23
- try {
24
- const result = await transactionManager.executeInTransaction(async (manager) => {
25
- // 检查用户是否已存在
26
- const existingUser = await manager.findOne(YtUserEntity, {
27
- where: [{ email }, { telnumber }] as any
28
- });
29
-
30
- if (existingUser) {
31
- throw new Error('用户已存在');
32
- }
33
-
34
- // 创建新用户
35
- const user = new YtUserEntity();
36
- user.email = email;
37
- user.telnumber = telnumber;
38
- user.password = await bcrypt.hash(password, 10);
39
- user.createDate = new Date();
40
- user.updateDate = new Date();
41
-
42
- return await manager.save(user);
43
- });
44
-
45
- ctx.body = {
46
- success: true,
47
- message: '用户创建成功',
48
- data: result
49
- };
50
- ctx.status = 200;
51
-
52
- } catch (error) {
53
- logger.error('创建用户失败:', error as Error);
54
- ctx.body = {
55
- success: false,
56
- message: error instanceof Error ? error.message : '创建用户失败',
57
- error: '事务已回滚'
58
- };
59
- ctx.status = 500;
60
- }
61
- }
62
-
63
- /**
64
- * 示例 2: 更新用户信息(使用隔离级别)
65
- * PUT /api/example/transaction/update-user/:id
66
- */
67
- @Put('/update-user/:id')
68
- async updateUser(ctx: Context) {
69
- const id = parseInt(ctx.params.id);
70
- const { email, telnumber } = ctx.request.body;
71
-
72
- try {
73
- const result = await transactionManager.executeInTransaction(
74
- async (manager) => {
75
- // 查找用户
76
- const user = await manager.findOne(YtUserEntity, {
77
- where: { id } as any
78
- });
79
-
80
- if (!user) {
81
- throw new Error('用户不存在');
82
- }
83
-
84
- // 更新用户信息
85
- if (email) {
86
- // 检查邮箱是否被其他用户使用
87
- const existingUser = await manager.findOne(YtUserEntity, {
88
- where: { email } as any
89
- });
90
- if (existingUser && existingUser.id !== id) {
91
- throw new Error('邮箱已被其他用户使用');
92
- }
93
- user.email = email;
94
- }
95
-
96
- if (telnumber) {
97
- // 检查手机号是否被其他用户使用
98
- const existingUser = await manager.findOne(YtUserEntity, {
99
- where: { telnumber } as any
100
- });
101
- if (existingUser && existingUser.id !== id) {
102
- throw new Error('手机号已被其他用户使用');
103
- }
104
- user.telnumber = telnumber;
105
- }
106
-
107
- user.updateDate = new Date();
108
- return await manager.save(user);
109
- },
110
- 'SERIALIZABLE' // 使用最高隔离级别,防止并发更新冲突
111
- );
112
-
113
- ctx.body = {
114
- success: true,
115
- message: '用户更新成功',
116
- data: result
117
- };
118
- ctx.status = 200;
119
-
120
- } catch (error) {
121
- logger.error('更新用户失败:', error as Error);
122
- ctx.body = {
123
- success: false,
124
- message: error instanceof Error ? error.message : '更新用户失败',
125
- error: '事务已回滚'
126
- };
127
- ctx.status = 500;
128
- }
129
- }
130
-
131
- /**
132
- * 示例 3: 批量创建用户
133
- * POST /api/example/transaction/batch-create
134
- */
135
- @Post('/batch-create')
136
- async batchCreateUsers(ctx: Context) {
137
- const { users } = ctx.request.body; // [{ email, telnumber, password }, ...]
138
-
139
- try {
140
- const operations = users.map((userData: any) => {
141
- return async (manager: any) => {
142
- // 验证数据
143
- if (!userData.email || !userData.password) {
144
- throw new Error('邮箱和密码不能为空');
145
- }
146
-
147
- // 加密密码
148
- const hashedPassword = await bcrypt.hash(userData.password, 10);
149
-
150
- // 创建用户
151
- const user = new YtUserEntity();
152
- user.email = userData.email;
153
- user.telnumber = userData.telnumber;
154
- user.password = hashedPassword;
155
- user.createDate = new Date();
156
- user.updateDate = new Date();
157
-
158
- return await manager.save(user);
159
- };
160
- });
161
-
162
- const results = await transactionManager.executeBatchTransaction(operations);
163
-
164
- ctx.body = {
165
- success: true,
166
- message: `成功创建 ${results.length} 个用户`,
167
- data: results
168
- };
169
- ctx.status = 200;
170
-
171
- } catch (error) {
172
- logger.error('批量创建用户失败:', error as Error);
173
- ctx.body = {
174
- success: false,
175
- message: '批量创建用户失败,所有更改已回滚',
176
- error: error instanceof Error ? error.message : '未知错误'
177
- };
178
- ctx.status = 500;
179
- }
180
- }
181
-
182
- /**
183
- * 示例 4: 删除用户(演示事务回滚)
184
- * DELETE /api/example/transaction/delete-user/:id
185
- */
186
- @Del('/delete-user/:id')
187
- async deleteUser(ctx: Context) {
188
- const id = parseInt(ctx.params.id);
189
-
190
- try {
191
- await transactionManager.executeInTransaction(async (manager) => {
192
- // 查找用户
193
- const user = await manager.findOne(YtUserEntity, {
194
- where: { id } as any
195
- });
196
-
197
- if (!user) {
198
- throw new Error('用户不存在');
199
- }
200
-
201
- // 模拟业务规则:不允许删除管理员用户
202
- if (user.userType && String(user.userType) === 'admin') {
203
- throw new Error('不能删除管理员用户');
204
- }
205
-
206
- // 删除用户
207
- await manager.remove(user);
208
-
209
- // 模拟额外操作(如果有的话)
210
- // await manager.save(DeleteLog, { userId: id });
211
- });
212
-
213
- ctx.body = {
214
- success: true,
215
- message: '用户删除成功'
216
- };
217
- ctx.status = 200;
218
-
219
- } catch (error) {
220
- logger.error('删除用户失败:', error as Error);
221
- ctx.body = {
222
- success: false,
223
- message: error instanceof Error ? error.message : '删除用户失败',
224
- error: '事务已回滚'
225
- };
226
- ctx.status = 500;
227
- }
228
- }
229
-
230
- /**
231
- * 示例 5: 查询统计(使用只读事务)
232
- * GET /api/example/transaction/stats
233
- */
234
- @Get('/stats')
235
- async getStats(ctx: Context) {
236
- try {
237
- const stats = await transactionManager.executeInReadOnlyTransaction(async (manager) => {
238
- // 只读事务,不会产生任何写操作
239
- const totalUsers = await manager.count(YtUserEntity);
240
- const activeUsers = await manager.count(YtUserEntity, {
241
- where: { status: 'normal' } as any
242
- });
243
-
244
- const users = await manager.find(YtUserEntity, {
245
- take: 10,
246
- order: { createDate: 'DESC' } as any
247
- });
248
-
249
- return {
250
- total: totalUsers,
251
- active: activeUsers,
252
- inactive: totalUsers - activeUsers,
253
- recentUsers: users
254
- };
255
- });
256
-
257
- ctx.body = {
258
- success: true,
259
- data: stats
260
- };
261
- ctx.status = 200;
262
-
263
- } catch (error) {
264
- logger.error('获取统计信息失败:', error as Error);
265
- ctx.body = {
266
- success: false,
267
- message: '获取统计信息失败'
268
- };
269
- ctx.status = 500;
270
- }
271
- }
272
-
273
- /**
274
- * 示例 6: 复杂业务场景 - 用户迁移
275
- * POST /api/example/transaction/migrate-user
276
- */
277
- @Post('/migrate-user')
278
- async migrateUser(ctx: Context) {
279
- const { fromUserId, toEmail } = ctx.request.body;
280
-
281
- try {
282
- const result = await transactionManager.executeInTransaction(async (manager) => {
283
- // 步骤 1: 查找原用户
284
- const fromUser = await manager.findOne(YtUserEntity, {
285
- where: { id: fromUserId } as any
286
- });
287
-
288
- if (!fromUser) {
289
- throw new Error('原用户不存在');
290
- }
291
-
292
- // 步骤 2: 检查新邮箱是否已使用
293
- const existingUser = await manager.findOne(YtUserEntity, {
294
- where: { email: toEmail } as any
295
- });
296
-
297
- if (existingUser) {
298
- throw new Error('新邮箱已被使用');
299
- }
300
-
301
- // 步骤 3: 创建新用户(复制数据)
302
- const newUser = new YtUserEntity();
303
- newUser.email = toEmail;
304
- newUser.telnumber = fromUser.telnumber;
305
- newUser.password = fromUser.password;
306
- newUser.createDate = new Date();
307
- newUser.updateDate = new Date();
308
- const savedNewUser = await manager.save(newUser);
309
-
310
- // 步骤 4: 删除原用户
311
- await manager.remove(fromUser);
312
-
313
- return {
314
- oldUser: fromUser,
315
- newUser: savedNewUser
316
- };
317
- });
318
-
319
- ctx.body = {
320
- success: true,
321
- message: '用户迁移成功',
322
- data: result
323
- };
324
- ctx.status = 200;
325
-
326
- } catch (error) {
327
- logger.error('用户迁移失败:', error as Error);
328
- ctx.body = {
329
- success: false,
330
- message: error instanceof Error ? error.message : '用户迁移失败',
331
- error: '所有操作已回滚'
332
- };
333
- ctx.status = 500;
334
- }
335
- }
336
- }