Skip to content

Commit 2593eeb

Browse files
authored
feat(@142vip/nest): 增加通用dtodecorator工具,支持分页等功能 (#731)
1 parent 48cf52d commit 2593eeb

File tree

7 files changed

+210
-0
lines changed

7 files changed

+210
-0
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './transform.decorator'
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
import { HttpException, HttpStatus } from '@nestjs/common'
2+
import { Transform } from 'class-transformer'
3+
4+
export function TransformToBoolean(): PropertyDecorator {
5+
return Transform(({ value }) => {
6+
switch (typeof value) {
7+
case 'string':
8+
return value === 'true' || value === '1'
9+
? true
10+
: value === 'false' || value === '0'
11+
? false
12+
: value
13+
case 'number':
14+
return Boolean(value)
15+
default:
16+
return value
17+
}
18+
})
19+
}
20+
21+
export function TransformToNumber(): PropertyDecorator {
22+
return Transform(({ value }) => Number(value))
23+
}
24+
25+
export function TransformToNumberArray(): PropertyDecorator {
26+
return Transform(({ value }) => {
27+
switch (typeof value) {
28+
case 'string':
29+
return value.split(',').map(i => Number(i.trim()))
30+
case 'object':
31+
return Array.isArray(value) ? value.map(i => Number(i)) : value
32+
default:
33+
return value
34+
}
35+
})
36+
}
37+
38+
export function TransformToStringArray(): PropertyDecorator {
39+
return Transform(({ value }) => {
40+
switch (typeof value) {
41+
case 'string':
42+
return value.split(',')
43+
case 'object':
44+
return Array.isArray(value) ? value.map(i => String(i)) : value
45+
default:
46+
return value
47+
}
48+
})
49+
}
50+
51+
export function TransformToStringAndNumberArray(): PropertyDecorator {
52+
return Transform(({ value }) => {
53+
switch (typeof value) {
54+
case 'string':
55+
return value.split(',').map((i) => {
56+
const num = Number(i.trim())
57+
return Number.isNaN(num) ? i.trim() : num
58+
})
59+
case 'object':
60+
return Array.isArray(value)
61+
? value.map((i) => {
62+
const num = Number(i)
63+
return Number.isNaN(num) ? i : num
64+
})
65+
: value
66+
default:
67+
return value
68+
}
69+
})
70+
}
71+
72+
/**
73+
* 自动转化开启使用
74+
*/
75+
export function Trim(): PropertyDecorator {
76+
return Transform(p => p.value?.trim())
77+
}
78+
79+
/**
80+
* 用于转换boolean类型的值
81+
*/
82+
export function DtoTransformToBoolean(): PropertyDecorator {
83+
return Transform(p =>
84+
p.obj[p.key] === 'true'
85+
? true
86+
: p.obj[p.key] === 'false'
87+
? false
88+
: undefined,
89+
)
90+
}
91+
92+
/**
93+
* Get请求
94+
* 用于前端传递的字符串参数解码
95+
*/
96+
export function DtoDecodeURI(): PropertyDecorator {
97+
return Transform((p) => {
98+
// 对解密失败的字段,抛错
99+
try {
100+
return p.value != null ? decodeURI(p.value) : p.value
101+
}
102+
catch {
103+
throw new HttpException('参数格式异常', HttpStatus.BAD_REQUEST)
104+
}
105+
})
106+
}
107+
108+
/**
109+
* 设置默认值(当值为null时生效)
110+
*/
111+
export function DefaultValue(value?: unknown): PropertyDecorator {
112+
return Transform(target => target.value ?? value)
113+
}
114+
115+
/**
116+
* 手机号、API key等数据脱敏
117+
*/
118+
export function StrDesensitize(): PropertyDecorator {
119+
return Transform(({ value }) => {
120+
if (typeof value !== 'string') {
121+
return value
122+
}
123+
124+
const length = value.length
125+
126+
if (length === 0) {
127+
return ''
128+
}
129+
else if (length <= 2) {
130+
return '*'.repeat(length)
131+
}
132+
else if (length === 3 || length === 4) {
133+
return `${value[0]}${'*'.repeat(length - 2)}${value[length - 1]}`
134+
}
135+
else {
136+
const start = value.slice(0, 2)
137+
const end = value.slice(-2)
138+
return `${start}${'*'.repeat(length - 4)}${end}`
139+
}
140+
})
141+
}

packages/nest/src/dtos/base.vo.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export class BaseVo<T> {
2+
constructor(obj: T) {
3+
Object.assign(this, obj)
4+
}
5+
}

packages/nest/src/dtos/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export * from './base.vo'
2+
export * from './pagination.dto'
3+
export * from './pagination.vo'
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { Exclude, Expose, Transform } from 'class-transformer'
2+
import { IsOptional, IsPositive } from 'class-validator'
3+
4+
/**
5+
* 默认分页参数
6+
*/
7+
@Exclude()
8+
export class PaginationDto {
9+
/**
10+
* 页号 默认1
11+
*/
12+
@Expose()
13+
@IsOptional()
14+
@Transform(({ value }) => Number(value) ?? 1)
15+
@IsPositive()
16+
pageNum!: number
17+
18+
/**
19+
* 单页大小,默认10
20+
*/
21+
@Expose()
22+
@IsOptional()
23+
@Transform(({ value }) => Number(value) ?? 10)
24+
@IsPositive()
25+
pageSize!: number
26+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { Exclude, Expose } from 'class-transformer'
2+
import { BaseVo } from './base.vo'
3+
4+
/**
5+
* 分页
6+
*/
7+
@Exclude()
8+
export class PaginationVo<T> extends BaseVo<PaginationVo<T>> {
9+
/**
10+
* 总数
11+
*/
12+
@Expose()
13+
total!: number
14+
15+
/**
16+
* 分页数据
17+
*/
18+
@Expose()
19+
data!: T[]
20+
21+
/**
22+
* 页码
23+
*/
24+
@Expose()
25+
pageNum!: number
26+
27+
/**
28+
* 每页数量
29+
*/
30+
@Expose()
31+
pageSize!: number
32+
}

packages/nest/src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
export * from './app.module'
2+
export * from './decorators'
3+
export * from './dtos'

0 commit comments

Comments
 (0)