Goods.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. <?php
  2. namespace app\admin\validate\shop;
  3. use think\Validate;
  4. class Goods extends Validate
  5. {
  6. /**
  7. * 验证规则
  8. */
  9. protected $rule = [
  10. // 基础信息
  11. 'type' => 'require|in:1,2,3,4',
  12. 'goods_sn' => 'require|max:50|unique:shop_goods,goods_sn',
  13. 'title' => 'require|max:200',
  14. 'subtitle' => 'max:200',
  15. 'category_id' => 'require|integer|gt:0',
  16. 'category_ids' => 'require',
  17. 'brand_id' => 'integer|egt:0',
  18. 'image' => 'require',
  19. 'images' => 'require',
  20. 'weigh' => 'integer|egt:0',
  21. // 价格库存
  22. 'spec_type' => 'require|in:0,1',
  23. 'price' => 'requireIf:spec_type,0|float|gt:0',
  24. 'lineation_price' => 'float|egt:0',
  25. 'cost_price' => 'float|egt:0',
  26. 'stocks' => 'requireIf:spec_type,0|integer|gt:0',
  27. 'weight' => 'float|egt:0',
  28. 'volume' => 'float|egt:0',
  29. 'sku_sn' => 'max:100',
  30. 'single_image' => '',
  31. // 配送设置
  32. 'delivery_type' => 'require|in:EXPRESS,PICKUP,VIRTUAL',
  33. 'express_type' => 'requireIf:delivery_type,EXPRESS|in:1,2,3',
  34. 'express_price' => 'requireIf:express_type,2|float|egt:0',
  35. 'express_template_id' => 'requireIf:express_type,3|integer|gt:0',
  36. // 销售设置
  37. 'online_type' => 'require|in:1,2,3',
  38. 'stock_show_type' => 'require|in:1,2',
  39. 'sales_show_type' => 'require|in:1,2',
  40. 'scheduled_online_time' => 'requireIf:online_type,3',
  41. 'scheduled_offline_time' => 'requireIf:is_auto_offline,1',
  42. 'is_auto_offline' => 'in:0,1',
  43. 'keywords' => 'max:255',
  44. 'description' => 'max:500',
  45. // 多规格相关
  46. 'spec_data' => 'checkMultiSpec',
  47. 'sku_data' => 'checkSkuData',
  48. ];
  49. /**
  50. * 提示消息
  51. */
  52. protected $message = [
  53. // 基础信息
  54. 'type.require' => '请选择商品类型',
  55. 'type.in' => '商品类型值不正确',
  56. 'goods_sn.require' => '商品编码不能为空',
  57. 'goods_sn.max' => '商品编码不能超过50个字符',
  58. 'goods_sn.unique' => '商品编码已存在',
  59. 'title.require' => '商品标题不能为空',
  60. 'title.max' => '商品标题不能超过200个字符',
  61. 'subtitle.max' => '商品副标题不能超过200个字符',
  62. 'category_id.require' => '请选择商品分类',
  63. 'category_id.integer' => '商品分类ID必须是整数',
  64. 'category_id.gt' => '请选择有效的商品分类',
  65. 'category_ids.require' => '请选择商品分类',
  66. 'brand_id.integer' => '品牌ID必须是整数',
  67. 'brand_id.egt' => '品牌ID必须大于等于0',
  68. 'image.require' => '请上传商品主图',
  69. 'images.require' => '请上传商品轮播图',
  70. 'weigh.integer' => '排序值必须是整数',
  71. 'weigh.egt' => '排序值必须大于等于0',
  72. // 价格库存
  73. 'spec_type.require' => '请选择规格类型',
  74. 'spec_type.in' => '规格类型值不正确',
  75. 'price.requireIf' => '单规格商品必须设置销售价',
  76. 'price.float' => '销售价必须是数字',
  77. 'price.gt' => '销售价必须大于0',
  78. 'lineation_price.float' => '划线价必须是数字',
  79. 'lineation_price.egt' => '划线价必须大于等于0',
  80. 'cost_price.float' => '成本价必须是数字',
  81. 'cost_price.egt' => '成本价必须大于等于0',
  82. 'stocks.requireIf' => '单规格商品必须设置库存',
  83. 'stocks.integer' => '库存必须是整数',
  84. 'stocks.gt' => '库存必须大于0',
  85. 'weight.float' => '重量必须是数字',
  86. 'weight.egt' => '重量必须大于等于0',
  87. 'volume.float' => '体积必须是数字',
  88. 'volume.egt' => '体积必须大于等于0',
  89. 'sku_sn.max' => 'SKU编码不能超过100个字符',
  90. // 配送设置
  91. 'delivery_type.require' => '请选择配送方式',
  92. 'delivery_type.in' => '配送方式值不正确',
  93. 'express_type.requireIf' => '选择快递配送时必须设置运费方式',
  94. 'express_type.in' => '运费方式值不正确',
  95. 'express_price.requireIf' => '选择统一运费时必须设置运费金额',
  96. 'express_price.float' => '运费金额必须是数字',
  97. 'express_price.egt' => '运费金额必须大于等于0',
  98. 'express_template_id.requireIf' => '选择运费模板时必须选择模板',
  99. 'express_template_id.integer' => '运费模板ID必须是整数',
  100. 'express_template_id.gt' => '运费模板ID必须大于0',
  101. // 销售设置
  102. 'online_type.require' => '请选择上架方式',
  103. 'online_type.in' => '上架方式值不正确',
  104. 'stock_show_type.require' => '请选择库存显示方式',
  105. 'stock_show_type.in' => '库存显示方式值不正确',
  106. 'sales_show_type.require' => '请选择销量显示方式',
  107. 'sales_show_type.in' => '销量显示方式值不正确',
  108. 'scheduled_online_time.requireIf' => '定时上架必须设置上架时间',
  109. 'scheduled_offline_time.requireIf' => '自动下架必须设置下架时间',
  110. 'is_auto_offline.in' => '自动下架设置值不正确',
  111. 'keywords.max' => '关键词不能超过255个字符',
  112. 'description.max' => '描述不能超过500个字符',
  113. ];
  114. /**
  115. * 验证场景
  116. */
  117. protected $scene = [
  118. 'add' => [
  119. 'type', 'goods_sn', 'title', 'subtitle', 'category_id', 'category_ids', 'brand_id',
  120. 'image', 'images', 'weigh', 'spec_type', 'price', 'lineation_price', 'cost_price',
  121. 'stocks', 'weight', 'volume', 'sku_sn', 'single_image', 'delivery_type',
  122. 'express_type', 'express_price', 'express_template_id', 'online_type',
  123. 'stock_show_type', 'sales_show_type', 'scheduled_online_time', 'scheduled_offline_time',
  124. 'is_auto_offline', 'keywords', 'description', 'spec_data', 'sku_data'
  125. ],
  126. 'edit' => [
  127. 'type', 'goods_sn', 'title', 'subtitle', 'category_id', 'category_ids', 'brand_id',
  128. 'image', 'images', 'weigh', 'spec_type', 'price', 'lineation_price', 'cost_price',
  129. 'stocks', 'weight', 'volume', 'sku_sn', 'single_image', 'delivery_type',
  130. 'express_type', 'express_price', 'express_template_id', 'online_type',
  131. 'stock_show_type', 'sales_show_type', 'scheduled_online_time', 'scheduled_offline_time',
  132. 'is_auto_offline', 'keywords', 'description', 'spec_data', 'sku_data'
  133. ],
  134. ];
  135. /**
  136. * 字段描述
  137. */
  138. protected $field = [
  139. 'type' => '商品类型',
  140. 'goods_sn' => '商品编码',
  141. 'title' => '商品标题',
  142. 'subtitle' => '商品副标题',
  143. 'category_id' => '商品分类',
  144. 'category_ids' => '商品分类',
  145. 'brand_id' => '品牌',
  146. 'image' => '商品主图',
  147. 'images' => '商品轮播图',
  148. 'spec_type' => '规格类型',
  149. 'price' => '销售价',
  150. 'lineation_price' => '划线价',
  151. 'cost_price' => '成本价',
  152. 'stocks' => '库存',
  153. 'weight' => '重量',
  154. 'volume' => '体积',
  155. 'delivery_type' => '配送方式',
  156. 'express_type' => '运费方式',
  157. 'express_price' => '运费金额',
  158. 'express_template_id' => '运费模板',
  159. 'online_type' => '上架方式',
  160. 'stock_show_type' => '库存显示方式',
  161. 'sales_show_type' => '销量显示方式',
  162. 'scheduled_online_time' => '定时上架时间',
  163. 'scheduled_offline_time' => '定时下架时间',
  164. 'keywords' => '关键词',
  165. 'description' => '描述',
  166. ];
  167. /**
  168. * 自定义验证规则:多规格商品验证
  169. */
  170. protected function checkMultiSpec($value, $rule, $data)
  171. {
  172. if (isset($data['spec_type']) && $data['spec_type'] == '1') {
  173. // 多规格商品需要验证规格数据
  174. if (empty($data['spec_data']) || !is_array($data['spec_data'])) {
  175. return '多规格商品必须设置规格信息';
  176. }
  177. // 验证规格名称不能为空
  178. foreach ($data['spec_data'] as $key => $spec) {
  179. if (empty($spec['name'])) {
  180. return "规格#{$key}名称不能为空";
  181. }
  182. if (empty($spec['value']) || !is_array($spec['value'])) {
  183. return "规格「{$spec['name']}」的规格值不能为空";
  184. }
  185. foreach ($spec['value'] as $idx => $specValue) {
  186. if (empty($specValue['name'])) {
  187. return "规格「{$spec['name']}」的第" . ($idx + 1) . "个规格值名称不能为空";
  188. }
  189. // 检查定制规格是否上传了图片
  190. if (isset($spec['type']) && $spec['type'] === 'custom') {
  191. if (empty($specValue['image'])) {
  192. return "定制规格「{$spec['name']}」的规格值「{$specValue['name']}」必须上传图片";
  193. }
  194. }
  195. }
  196. }
  197. }
  198. return true;
  199. }
  200. /**
  201. * 自定义验证规则:SKU数据验证
  202. */
  203. protected function checkSkuData($value, $rule, $data)
  204. {
  205. if (isset($data['spec_type']) && $data['spec_type'] == '1') {
  206. // 多规格商品需要验证SKU数据
  207. if (empty($data['sku_data']) || !is_array($data['sku_data'])) {
  208. return '多规格商品必须设置SKU信息';
  209. }
  210. $hasValidSku = false;
  211. // 验证SKU数据
  212. foreach ($data['sku_data'] as $index => $sku) {
  213. // 检查显示状态的SKU
  214. if (isset($sku['status']) && ($sku['status'] == 1 || $sku['status'] === '1' || $sku['status'] === true)) {
  215. $hasValidSku = true;
  216. if (empty($sku['skus']) || !is_array($sku['skus'])) {
  217. return "第" . ($index + 1) . "个SKU的规格属性不能为空";
  218. }
  219. if (!isset($sku['price']) || floatval($sku['price']) <= 0) {
  220. return "第" . ($index + 1) . "个SKU的销售价必须大于0";
  221. }
  222. if (!isset($sku['stocks']) || intval($sku['stocks']) <= 0) {
  223. return "第" . ($index + 1) . "个SKU的库存必须大于0";
  224. }
  225. }
  226. }
  227. if (!$hasValidSku) {
  228. return '多规格商品至少需要一个有效的SKU';
  229. }
  230. }
  231. return true;
  232. }
  233. }