create-dp-koa 1.0.0 → 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.
- package/package.json +2 -2
- package/template/.cursor/commands/cheatsheet-backend-controller.md +45 -0
- package/template/.cursor/commands/implement-backend-api-controller.md +60 -0
- package/template/.cursor/commands/plan-backend.md +97 -0
- package/template/.cursor/rules/00-backend-core.skill.md +61 -0
- package/template/.cursor/rules/01-backend-skill-router.skill.md +57 -0
- package/template/.cursor/rules/10-backend-api.skill.md +55 -0
- package/template/.cursor/rules/11-backend-controller-recipes.skill.md +188 -0
- package/template/.cursor/rules/20-backend-repository.skill.md +25 -0
- package/template/.cursor/rules/21-backend-service.skill.md +137 -0
- package/template/.cursor/rules/25-backend-comments-and-doc.skill.md +98 -0
- package/template/.cursor/rules/30-backend-validation.skill.md +342 -0
- package/template/.cursor/rules/40-backend-error-logging.skill.md +21 -0
- package/template/.cursor/rules/50-backend-bootstrap-lifecycle.skill.md +105 -0
- package/template/.cursor/rules/60-backend-router-registration.skill.md +73 -0
- package/template/.cursor/rules/70-backend-middleware.skill.md +100 -0
- package/template/.cursor/rules/80-backend-utils-and-libs.skill.md +108 -0
- package/template/.cursor/rules/85-backend-plugins.rule.md +65 -0
- package/template/.cursor/rules/90-backend-testing.skill.md +29 -0
- package/template/.cursor/rules/README.md +49 -0
- package/template/.trae/skills/11-backend-controller-recipes.skill.md +91 -10
- package/template/scripts/sync-template.mjs +0 -1
- package/template/src/controllers/example/ExampleController.ts +14 -0
- package/template/src/entity/index.ts +1 -15
- package/template/src/framework/decorator/processor/AnnotationProcessor.ts +5 -1
- package/template/src/routers/index.ts +0 -35
- package/template/src/utils/testDataInitializer.ts +2 -269
- package/template/test/controllers/example/ExampleController.test.ts +29 -31
- package/template/test/framework/annotation/AnnotationDecorators.test.ts +15 -15
- package/template/test/framework/annotation/AnnotationExecutor.test.ts +27 -32
- package/template/test/framework/annotation/AnnotationProcessor.test.ts +25 -24
- package/template/test/framework/annotation/CustomProcessors.test.ts +15 -25
- package/template/test/framework/annotation/NewRouter.test.ts +9 -7
- package/template/test/framework/annotation/ProcessorManager.test.ts +14 -27
- package/template/test/framework/databaseConfig.test.ts +2 -2
- package/template/test/integration/integration.test.ts +15 -72
- package/template/src/controllers/cacheManagement.controller.ts +0 -131
- package/template/src/controllers/captcha.controller.ts +0 -57
- package/template/src/controllers/example/NewAnnotationExampleController.ts +0 -159
- package/template/src/controllers/example/SwaggerExampleController.ts +0 -205
- package/template/src/controllers/example/TransactionExample.controller.ts +0 -336
- package/template/src/controllers/health.controller.ts +0 -235
- package/template/src/controllers/home/register.controller.ts +0 -58
- package/template/src/controllers/home/ytGoods.controller.ts +0 -92
- package/template/src/controllers/home/ytShop.controller.ts +0 -135
- package/template/src/controllers/home/ytUser.controller.ts +0 -89
- package/template/src/controllers/logManagement.controller.ts +0 -396
- package/template/src/controllers/public/emailSend.controller.ts +0 -65
- package/template/src/controllers/public/ytUserAuth.controller.ts +0 -174
- package/template/src/controllers/testData.controller.ts +0 -253
- package/template/src/dto/controller/example/NewAnnotationExampleController.dto.ts +0 -73
- package/template/src/dto/controller/home/emailSend.controller.dto.ts +0 -40
- package/template/src/dto/controller/home/register.controller.dto.ts +0 -45
- package/template/src/dto/controller/home/ytGoods.controller.dto.ts +0 -55
- package/template/src/dto/controller/home/ytShop.controller.dto.ts +0 -69
- package/template/src/dto/controller/home/ytUser.controller.dto.ts +0 -44
- package/template/src/dto/controller/public/ytUserAuth.controller.dto.ts +0 -63
- package/template/src/dto/goods.dto.ts +0 -212
- package/template/src/dto/service/ytService.dto.ts +0 -13
- package/template/src/dto/user.dto.ts +0 -177
- package/template/src/entity/columnTypes.ts +0 -13
- package/template/src/entity/goodsImagesUnlockKey.entity.ts +0 -33
- package/template/src/entity/goodsUnlocker.entity.ts +0 -34
- package/template/src/entity/shop.entity.ts +0 -52
- package/template/src/entity/shopUser.entity.ts +0 -41
- package/template/src/entity/ytGoods.entity.ts +0 -94
- package/template/src/entity/ytUser.entity.ts +0 -96
- package/template/src/examples/SwaggerProcessorExample.ts +0 -169
- package/template/src/examples/TransactionManagerDemo.ts +0 -377
- package/template/src/framework/utils/dynamicSwagger.ts +0 -410
- package/template/src/repository/UserRepository.ts +0 -122
- package/template/src/service/paramValidateTest.service.ts +0 -139
- package/template/src/service/ytGoods.service.ts +0 -42
- package/template/src/service/ytShop.service.ts +0 -90
- package/template/src/service/ytUser.service.ts +0 -451
- package/template/src/test/swaggerParameterTest.ts +0 -90
- package/template/test/controllers/controllers.test.ts +0 -173
- package/template/test/controllers/example/NewAnnotationExampleController.test.ts +0 -200
- package/template/test/framework/TransactionManagerDemo.test.ts +0 -363
- package/template/test/service/business.test.ts +0 -87
- package/template/test/service/paramValidateTest.service.test.ts +0 -184
- package/template/test/service/ytUser.service.test.ts +0 -566
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
import { Get, Post } from '@src/framework/decorator/controller';
|
|
2
|
-
import { Body } from '@src/framework/decorator/controller';
|
|
3
|
-
import { BaseController } from '@src/controllers/base.controller';
|
|
4
|
-
import { getCache, deleteCache, getCacheStats, getCacheMemoryUsage, clearAllCaches } from '@src/framework/utils/cache';
|
|
5
|
-
import { logger } from '@src/framework/utils/logger';
|
|
6
|
-
|
|
7
|
-
export class CacheManagementController extends BaseController {
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* 获取所有缓存统计信息
|
|
11
|
-
*/
|
|
12
|
-
@Get('/cache/stats')
|
|
13
|
-
async getCacheStats() {
|
|
14
|
-
const stats = getCacheStats();
|
|
15
|
-
const memory = getCacheMemoryUsage();
|
|
16
|
-
|
|
17
|
-
return this.success({
|
|
18
|
-
stats,
|
|
19
|
-
memory,
|
|
20
|
-
timestamp: new Date().toISOString()
|
|
21
|
-
});
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* 清理指定缓存
|
|
26
|
-
*/
|
|
27
|
-
@Post('/cache/clear')
|
|
28
|
-
async clearCache(@Body() body: { cacheName: string }) {
|
|
29
|
-
const { cacheName } = body;
|
|
30
|
-
|
|
31
|
-
if (!cacheName) {
|
|
32
|
-
return this.fail(400, '缓存名称不能为空');
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
try {
|
|
36
|
-
const cache = getCache(cacheName);
|
|
37
|
-
if (!cache) {
|
|
38
|
-
return this.fail(404, `缓存 ${cacheName} 不存在`);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// 清空缓存内容
|
|
42
|
-
cache.flushAll();
|
|
43
|
-
logger.info(`手动清理缓存: ${cacheName}`);
|
|
44
|
-
|
|
45
|
-
return this.success({
|
|
46
|
-
message: `缓存 ${cacheName} 已清理`,
|
|
47
|
-
cacheName,
|
|
48
|
-
timestamp: new Date().toISOString()
|
|
49
|
-
});
|
|
50
|
-
} catch (error) {
|
|
51
|
-
logger.error(`清理缓存 ${cacheName} 失败:`, error as Error);
|
|
52
|
-
return this.fail(500, `清理缓存失败: ${error instanceof Error ? error.message : '未知错误'}`);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* 删除指定缓存实例
|
|
58
|
-
*/
|
|
59
|
-
@Post('/cache/delete')
|
|
60
|
-
async deleteCache(@Body() body: { cacheName: string }) {
|
|
61
|
-
const { cacheName } = body;
|
|
62
|
-
|
|
63
|
-
if (!cacheName) {
|
|
64
|
-
return this.fail(400, '缓存名称不能为空');
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
try {
|
|
68
|
-
deleteCache(cacheName);
|
|
69
|
-
logger.info(`删除缓存实例: ${cacheName}`);
|
|
70
|
-
|
|
71
|
-
return this.success({
|
|
72
|
-
message: `缓存实例 ${cacheName} 已删除`,
|
|
73
|
-
cacheName,
|
|
74
|
-
timestamp: new Date().toISOString()
|
|
75
|
-
});
|
|
76
|
-
} catch (error) {
|
|
77
|
-
logger.error(`删除缓存实例 ${cacheName} 失败:`, error as Error);
|
|
78
|
-
return this.fail(500, `删除缓存实例失败: ${error instanceof Error ? error.message : '未知错误'}`);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* 清理所有缓存
|
|
84
|
-
*/
|
|
85
|
-
@Post('/cache/clear-all')
|
|
86
|
-
async clearAllCache() {
|
|
87
|
-
try {
|
|
88
|
-
clearAllCaches();
|
|
89
|
-
logger.info('手动清理所有缓存');
|
|
90
|
-
|
|
91
|
-
return this.success({
|
|
92
|
-
message: '所有缓存已清理',
|
|
93
|
-
timestamp: new Date().toISOString()
|
|
94
|
-
});
|
|
95
|
-
} catch (error) {
|
|
96
|
-
logger.error('清理所有缓存失败:', error as Error);
|
|
97
|
-
return this.fail(500, `清理所有缓存失败: ${error instanceof Error ? error.message : '未知错误'}`);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* 获取特定缓存的详细信息
|
|
103
|
-
*/
|
|
104
|
-
@Get('/cache/info')
|
|
105
|
-
async getCacheInfo(@Body() body: { cacheName: string }) {
|
|
106
|
-
const { cacheName } = body;
|
|
107
|
-
|
|
108
|
-
if (!cacheName) {
|
|
109
|
-
return this.fail(400, '缓存名称不能为空');
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
const cache = getCache(cacheName);
|
|
113
|
-
if (!cache) {
|
|
114
|
-
return this.fail(404, `缓存 ${cacheName} 不存在`);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
const keys = cache.keys();
|
|
118
|
-
const stats = getCacheStats();
|
|
119
|
-
const memory = getCacheMemoryUsage();
|
|
120
|
-
|
|
121
|
-
return this.success({
|
|
122
|
-
cacheName,
|
|
123
|
-
keys: keys.slice(0, 10), // 只显示前10个键
|
|
124
|
-
totalKeys: keys.length,
|
|
125
|
-
stats: stats[cacheName] || null,
|
|
126
|
-
memory: memory[cacheName] || null,
|
|
127
|
-
config: cache.options,
|
|
128
|
-
timestamp: new Date().toISOString()
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
|
-
}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import { Get, Post } from '@src/framework/decorator/controller';
|
|
3
|
-
import { Body } from '@src/framework/decorator/controller';
|
|
4
|
-
import { CaptchaGenerator } from '@src/libs/captcha';
|
|
5
|
-
import { Inject } from 'dp-ioc2';
|
|
6
|
-
import { createCache, CacheType } from '@src/framework/utils/cache';
|
|
7
|
-
|
|
8
|
-
// 创建验证码缓存实例
|
|
9
|
-
const captchaCache = createCache('captcha-controller', CacheType.CAPTCHA, {
|
|
10
|
-
stdTTL: 300, // 5分钟过期
|
|
11
|
-
maxKeys: 100 // 最多100个验证码
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
export class CaptchaController {
|
|
15
|
-
|
|
16
|
-
// @Inject(CaptchaGenerator)
|
|
17
|
-
// captchaGenerator: CaptchaGenerator;
|
|
18
|
-
|
|
19
|
-
@Get('/captcha')
|
|
20
|
-
async getCaptcha() {
|
|
21
|
-
const { image, token } = CaptchaGenerator.generate();
|
|
22
|
-
return {
|
|
23
|
-
image,
|
|
24
|
-
token,
|
|
25
|
-
contentType: 'image/svg+xml'
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
@Post('/captcha/verify')
|
|
30
|
-
async verifyCaptcha(
|
|
31
|
-
@Body() body: { captcha: string, token: string }
|
|
32
|
-
) {
|
|
33
|
-
const { captcha, token } = body;
|
|
34
|
-
if (!token) {
|
|
35
|
-
return {
|
|
36
|
-
status: 400,
|
|
37
|
-
body: { success: false, message: 'Missing captcha token' }
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// 检查是否已经验证过(防止重复验证)
|
|
42
|
-
const verifyKey = `verify_${token}`;
|
|
43
|
-
if (captchaCache.get(verifyKey)) {
|
|
44
|
-
return { success: false, message: '验证码已使用' };
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const isValid = CaptchaGenerator.verify(token, captcha);
|
|
48
|
-
|
|
49
|
-
if (isValid) {
|
|
50
|
-
// 验证成功后标记为已使用,防止重复验证
|
|
51
|
-
captchaCache.set(verifyKey, true, 300); // 5分钟内不能重复验证
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
return { success: isValid };
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
}
|
|
@@ -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
|
-
|