goods.schema.ts 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. import { z } from '@hono/zod-openapi';
  2. import { GoodsCategorySchema } from './goods-category.schema';
  3. import { SupplierSchema } from '@/server/modules/supplier/supplier.schema';
  4. import { FileSchema } from '@/server/modules/files/file.schema';
  5. export const GoodsSchema = z.object({
  6. id: z.number().int().positive().openapi({ description: '商品ID' }),
  7. name: z.string().min(1, '商品名称不能为空').max(255, '商品名称最多255个字符').openapi({
  8. description: '商品名称',
  9. example: 'iPhone 15'
  10. }),
  11. price: z.coerce.number().multipleOf(0.01, '价格最多保留两位小数').min(0, '价格不能为负数').default(0).openapi({
  12. description: '售卖价',
  13. example: 5999.99
  14. }),
  15. costPrice: z.coerce.number().multipleOf(0.01, '成本价最多保留两位小数').min(0, '成本价不能为负数').default(0).openapi({
  16. description: '成本价',
  17. example: 4999.99
  18. }),
  19. salesNum: z.coerce.number().int().nonnegative('销售数量必须为非负数').default(0).openapi({
  20. description: '销售数量',
  21. example: 100
  22. }),
  23. clickNum: z.coerce.number().int().nonnegative('点击次数必须为非负数').default(0).openapi({
  24. description: '点击次数',
  25. example: 1000
  26. }),
  27. categoryId1: z.number().int().nonnegative('一级类别ID必须为非负数').default(0).openapi({
  28. description: '一级类别id',
  29. example: 1
  30. }),
  31. categoryId2: z.number().int().nonnegative('二级类别ID必须为非负数').default(0).openapi({
  32. description: '二级类别id',
  33. example: 2
  34. }),
  35. categoryId3: z.number().int().nonnegative('三级类别ID必须为非负数').default(0).openapi({
  36. description: '三级类别id',
  37. example: 3
  38. }),
  39. goodsType: z.number().int().min(1).max(2).default(1).openapi({
  40. description: '订单类型 1实物产品 2虚拟产品',
  41. example: 1
  42. }),
  43. supplierId: z.number().int().positive().nullable().openapi({
  44. description: '所属供应商id',
  45. example: 1
  46. }),
  47. imageFileId: z.number().int().positive().nullable().openapi({
  48. description: '商品主图文件ID',
  49. example: 1
  50. }),
  51. slideImages: z.array(FileSchema).nullable().optional().openapi({
  52. description: '商品轮播图文件列表',
  53. example: [{
  54. id: 1,
  55. name: 'image1.jpg',
  56. fullUrl: 'https://example.com/image1.jpg',
  57. type: 'image/jpeg',
  58. size: 102400
  59. }]
  60. }),
  61. detail: z.string().nullable().optional().openapi({
  62. description: '商品详情',
  63. example: '这是商品详情内容'
  64. }),
  65. instructions: z.string().max(255, '简介最多255个字符').nullable().optional().openapi({
  66. description: '简介',
  67. example: '高品质智能手机'
  68. }),
  69. sort: z.number().int().nonnegative('排序值必须为非负数').default(0).openapi({
  70. description: '排序',
  71. example: 0
  72. }),
  73. state: z.number().int().min(1).max(2).default(1).openapi({
  74. description: '状态 1可用 2不可用',
  75. example: 1
  76. }),
  77. stock: z.coerce.number().int().nonnegative('库存必须为非负数').default(0).openapi({
  78. description: '库存',
  79. example: 100
  80. }),
  81. spuId: z.number().int().nonnegative('主商品ID必须为非负数').default(0).openapi({
  82. description: '主商品ID',
  83. example: 0
  84. }),
  85. spuName: z.string().max(255, '主商品名称最多255个字符').nullable().optional().openapi({
  86. description: '主商品名称',
  87. example: 'iPhone系列'
  88. }),
  89. lowestBuy: z.number().int().positive('最小起购量必须为正整数').default(1).openapi({
  90. description: '最小起购量',
  91. example: 1
  92. }),
  93. category1: GoodsCategorySchema.nullable().optional().openapi({
  94. description: '一级分类信息'
  95. }),
  96. category2: GoodsCategorySchema.nullable().optional().openapi({
  97. description: '二级分类信息'
  98. }),
  99. category3: GoodsCategorySchema.nullable().optional().openapi({
  100. description: '三级分类信息'
  101. }),
  102. supplier: SupplierSchema.nullable().optional().openapi({
  103. description: '供应商信息'
  104. }),
  105. imageFile: FileSchema.nullable().optional().openapi({
  106. description: '商品主图信息'
  107. }),
  108. createdAt: z.coerce.date().openapi({
  109. description: '创建时间',
  110. example: '2024-01-01T12:00:00Z'
  111. }),
  112. updatedAt: z.coerce.date().openapi({
  113. description: '更新时间',
  114. example: '2024-01-01T12:00:00Z'
  115. }),
  116. createdBy: z.number().int().positive().nullable().openapi({
  117. description: '创建用户ID',
  118. example: 1
  119. }),
  120. updatedBy: z.number().int().positive().nullable().openapi({
  121. description: '更新用户ID',
  122. example: 1
  123. }),
  124. });
  125. export const CreateGoodsDto = z.object({
  126. name: z.string().min(1, '商品名称不能为空').max(255, '商品名称最多255个字符').openapi({
  127. description: '商品名称',
  128. example: 'iPhone 15'
  129. }),
  130. price: z.coerce.number().multipleOf(0.01, '价格最多保留两位小数').min(0, '价格不能为负数').default(0).openapi({
  131. description: '售卖价',
  132. example: 5999.99
  133. }),
  134. costPrice: z.coerce.number().multipleOf(0.01, '成本价最多保留两位小数').min(0, '成本价不能为负数').default(0).openapi({
  135. description: '成本价',
  136. example: 4999.99
  137. }),
  138. categoryId1: z.number().int().nonnegative('一级类别ID必须为非负数').default(0).openapi({
  139. description: '一级类别id',
  140. example: 1
  141. }),
  142. categoryId2: z.number().int().nonnegative('二级类别ID必须为非负数').default(0).openapi({
  143. description: '二级类别id',
  144. example: 2
  145. }),
  146. categoryId3: z.number().int().nonnegative('三级类别ID必须为非负数').default(0).openapi({
  147. description: '三级类别id',
  148. example: 3
  149. }),
  150. goodsType: z.number().int().min(1).max(2).default(1).openapi({
  151. description: '订单类型 1实物产品 2虚拟产品',
  152. example: 1
  153. }),
  154. supplierId: z.number().int().positive().nullable().optional().openapi({
  155. description: '所属供应商id',
  156. example: 1
  157. }),
  158. imageFileId: z.number().int().positive().nullable().optional().openapi({
  159. description: '商品主图文件ID',
  160. example: 1
  161. }),
  162. slideImageIds: z.array(z.number().int().positive()).nullable().optional().openapi({
  163. description: '商品轮播图文件ID数组',
  164. example: [1, 2, 3]
  165. }),
  166. detail: z.string().nullable().optional().openapi({
  167. description: '商品详情',
  168. example: '这是商品详情内容'
  169. }),
  170. instructions: z.string().max(255, '简介最多255个字符').nullable().optional().openapi({
  171. description: '简介',
  172. example: '高品质智能手机'
  173. }),
  174. sort: z.number().int().nonnegative('排序值必须为非负数').default(0).openapi({
  175. description: '排序',
  176. example: 0
  177. }),
  178. state: z.number().int().min(1).max(2).default(1).openapi({
  179. description: '状态 1可用 2不可用',
  180. example: 1
  181. }),
  182. stock: z.coerce.number().int().nonnegative('库存必须为非负数').default(0).openapi({
  183. description: '库存',
  184. example: 100
  185. }),
  186. spuId: z.number().int().nonnegative('主商品ID必须为非负数').default(0).openapi({
  187. description: '主商品ID',
  188. example: 0
  189. }),
  190. spuName: z.string().max(255, '主商品名称最多255个字符').nullable().optional().openapi({
  191. description: '主商品名称',
  192. example: 'iPhone系列'
  193. }),
  194. lowestBuy: z.number().int().positive('最小起购量必须为正整数').default(1).openapi({
  195. description: '最小起购量',
  196. example: 1
  197. })
  198. });
  199. export const UpdateGoodsDto = z.object({
  200. name: z.string().min(1, '商品名称不能为空').max(255, '商品名称最多255个字符').optional().openapi({
  201. description: '商品名称',
  202. example: 'iPhone 15'
  203. }),
  204. price: z.coerce.number().multipleOf(0.01, '价格最多保留两位小数').min(0, '价格不能为负数').optional().openapi({
  205. description: '售卖价',
  206. example: 5999.99
  207. }),
  208. costPrice: z.coerce.number().multipleOf(0.01, '成本价最多保留两位小数').min(0, '成本价不能为负数').optional().openapi({
  209. description: '成本价',
  210. example: 4999.99
  211. }),
  212. categoryId1: z.number().int().nonnegative('一级类别ID必须为非负数').optional().openapi({
  213. description: '一级类别id',
  214. example: 1
  215. }),
  216. categoryId2: z.number().int().nonnegative('二级类别ID必须为非负数').optional().openapi({
  217. description: '二级类别id',
  218. example: 2
  219. }),
  220. categoryId3: z.number().int().nonnegative('三级类别ID必须为非负数').optional().openapi({
  221. description: '三级类别id',
  222. example: 3
  223. }),
  224. goodsType: z.number().int().min(1).max(2).optional().openapi({
  225. description: '订单类型 1实物产品 2虚拟产品',
  226. example: 1
  227. }),
  228. supplierId: z.number().int().positive().nullable().optional().openapi({
  229. description: '所属供应商id',
  230. example: 1
  231. }),
  232. imageFileId: z.number().int().positive().nullable().optional().openapi({
  233. description: '商品主图文件ID',
  234. example: 1
  235. }),
  236. slideImageIds: z.array(z.number().int().positive()).nullable().optional().openapi({
  237. description: '商品轮播图文件ID数组',
  238. example: [1, 2, 3]
  239. }),
  240. detail: z.string().nullable().optional().openapi({
  241. description: '商品详情',
  242. example: '这是商品详情内容'
  243. }),
  244. instructions: z.string().max(255, '简介最多255个字符').nullable().optional().openapi({
  245. description: '简介',
  246. example: '高品质智能手机'
  247. }),
  248. sort: z.number().int().nonnegative('排序值必须为非负数').optional().openapi({
  249. description: '排序',
  250. example: 0
  251. }),
  252. state: z.number().int().min(1).max(2).optional().openapi({
  253. description: '状态 1可用 2不可用',
  254. example: 1
  255. }),
  256. stock: z.coerce.number().int().nonnegative('库存必须为非负数').optional().openapi({
  257. description: '库存',
  258. example: 100
  259. }),
  260. spuId: z.number().int().nonnegative('主商品ID必须为非负数').optional().openapi({
  261. description: '主商品ID',
  262. example: 0
  263. }),
  264. spuName: z.string().max(255, '主商品名称最多255个字符').nullable().optional().openapi({
  265. description: '主商品名称',
  266. example: 'iPhone系列'
  267. }),
  268. lowestBuy: z.number().int().positive('最小起购量必须为正整数').optional().openapi({
  269. description: '最小起购量',
  270. example: 1
  271. })
  272. });