user-goods.schema.ts 11 KB

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