StoreProductValidate.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2016~2024 https://www.crmeb.com All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
  8. // +----------------------------------------------------------------------
  9. // | Author: CRMEB Team <admin@crmeb.com>
  10. // +----------------------------------------------------------------------
  11. namespace app\validate\merchant;
  12. use think\Exception;
  13. use think\File;
  14. use think\Validate;
  15. use app\common\repositories\store\product\NewProductRepository;
  16. class StoreProductValidate extends Validate
  17. {
  18. protected $failException = true;
  19. protected $rule = [
  20. "image|主图" => 'require|max:128',
  21. "store_name|商品名称" => 'require|max:128',
  22. "cate_id|平台分类" => 'require',
  23. "mer_cate_id|商户分类" => 'array',
  24. "unit_name|单位名称" => 'max:4',
  25. "spec_type" => "in:0,1",
  26. "is_show|是否上架" => "require|in:0,1,2",
  27. "auto_on_time|定时上架时间" => "requireIf:is_show,2|date",
  28. "auto_off_time|定时下架时间" => "date",
  29. "extension_type|分销类型" => "in:0,1",
  30. 'type|商品类型' => 'require|in:0,1,2,3,4,5,6',
  31. 'delivery_way|发货方式' => 'requireIf:type,0|requireIf:type,1|requireIf:type,2|requireIf:type,3',
  32. 'once_min_count|最小限购' => 'min:0',
  33. 'pay_limit|是否限购' => 'require|in:0,1,2|payLimit',
  34. 'reservation_time_type|预约时段划分' => 'requireIf:type,4|in:1,2|integer',
  35. 'reservation_start_time|预约开始时段' =>'requireIf:reservation_time_type,1|date',
  36. 'reservation_end_time|预约结束时间' =>'requireIf:reservation_time_type,1|date',
  37. 'reservation_time_interval|时间跨度' =>'requireIf:reservation_time_type,1|integer|egt:10|elt:1440',
  38. 'time_period|时段信息' =>'requireIf:type,4|array|validateTimePeriods',
  39. 'reservation_type|服务模式' =>'requireIf:type,4|in:1,2,3|integer',
  40. 'sale_time_type|可售日期类型' =>'requireIf:type,4|in:1,2|integer',
  41. 'sale_time_start_day|可售日期自定义开始时间' =>'requireIf:sale_time_type,2|date',
  42. 'sale_time_end_day|可售日期自定义结束时间' =>'requireIf:sale_time_type,2|date',
  43. 'sale_time_week|可售日期星期数据' =>'requireIf:sale_time_type,2|array',
  44. 'show_reservation_days|预约展示天数' =>'requireIf:type,4|integer|egt:1|elt:999999',
  45. 'show_num_type|是否显示剩余可约数量' =>'requireIf:type,4|in:0,1',
  46. 'is_advance|是否提前预约' =>'requireIf:type,4|in:0,1',
  47. 'advance_time|提前预约时间' =>'requireIf:is_advance,1|integer|egt:1|elt:999999',
  48. 'is_cancel_reservation|是否可取消预约' =>'requireIf:type,4|in:0,1',
  49. 'cancel_reservation_time|取消预约时间' =>'requireIf:is_cancel_reservation,1|integer|egt:0|elt:999999',
  50. "attr|商品规格" => "requireIf:spec_type,1|Array|checkUnique|checkValueLength",
  51. "attrValue|商品属性" => "require|array|productAttrValue"
  52. ];
  53. protected $scene = [
  54. 'add' => ['image','auto_on_time','auto_off_time','store_name','cate_id','mer_cate_id','unit_name','spec_type','is_show','extension_type','attr','attrValue','type','delivery_way','once_min_count','pay_limit'],
  55. 'reservation' => [
  56. 'reservation_time_type',
  57. 'reservation_start_time',
  58. 'reservation_end_time',
  59. 'reservation_time_interval',
  60. 'time_period',
  61. 'reservation_type',
  62. 'sale_time_type',
  63. 'sale_time_start_day',
  64. 'sale_time_end_day',
  65. 'sale_time_week',
  66. 'show_reservation_days',
  67. 'show_num_type',
  68. 'is_advance',
  69. 'advance_time',
  70. 'is_cancel_reservation',
  71. 'cancel_reservation_time'
  72. ]
  73. ];
  74. protected function checkValueLength($array) {
  75. $maxLength = 30;
  76. foreach ($array as $item) {
  77. if (isset($item['value']) && (mb_strlen($item['value']) > $maxLength)) {
  78. return '规格长度不能超过30个字符'; // 发现超过 20 的值,返回 false
  79. }
  80. if (isset($item['detail']) && is_array($item['detail'])) {
  81. foreach ($item['detail'] as $detailItem) {
  82. if (isset($detailItem['value']) && mb_strlen($detailItem['value']) > $maxLength) {
  83. return '规格值长度不能超过30个字符';
  84. }
  85. }
  86. }
  87. }
  88. return true; // 所有值都符合长度限制
  89. }
  90. protected function payLimit($value,$rule,$data)
  91. {
  92. if ($value && ($data['once_max_count'] < $data['once_min_count']))
  93. return '限购数量不能小于最少购买件数';
  94. return true;
  95. }
  96. protected function productAttrValue($value,$rule,$data)
  97. {
  98. $arr = [];
  99. try{
  100. foreach ($value as $v){
  101. $sku = '';
  102. if(isset($v['detail']) && is_array($v['detail'])){
  103. sort($v['detail'],SORT_STRING);
  104. $sku = implode(',',$v['detail']);
  105. if(in_array($sku,$arr)) return '商品SKU重复';
  106. $arr[] = $sku;
  107. }
  108. if(isset($data['extension_type']) && $data['extension_type'] && systemConfig('extension_status')){
  109. if(!isset($v['extension_one']) || !isset($v['extension_two'])) return '奖金金额必须填写';
  110. if(($v['extension_one'] < 0) || ($v['extension_two'] < 0))
  111. return '奖金金额不可存在负数';
  112. if($v['price'] < bcadd($v['extension_one'],$v['extension_two'],2))
  113. return '自定义奖金总金额不能大于商品售价';
  114. }
  115. if ($data['product_type'] == 20 && !$v['ot_price']) {
  116. return '积分商品兑换积分必须大于0';
  117. }
  118. if($data['type'] == NewProductRepository::DEFINE_TYPE_RESERVATION) {
  119. if(!isset($v['reservation'])) {
  120. return '预约商品规格错误';
  121. }
  122. foreach ($v['reservation'] as $item) {
  123. if(!isset($item['start_time'])
  124. || !isset($item['end_time'])
  125. || !isset($item['stock'])
  126. ) {
  127. return '预约商品规格错误';
  128. }
  129. if($item['stock'] < 0) {
  130. return '预约库存不可小于0';
  131. }
  132. }
  133. }
  134. }
  135. } catch (\Exception $exception) {
  136. return '商品属性格式错误';
  137. }
  138. return true;
  139. }
  140. protected function checkUnique($value,$rule,$data)
  141. {
  142. if($data['type'] == NewProductRepository::DEFINE_TYPE_RESERVATION && count($value) > 1) {
  143. return '预约商品规格最多只能添加一个';
  144. }
  145. $arr = [];
  146. foreach ($value as $item){
  147. if(in_array($item['value'],$arr))return '规格重复';
  148. $arr[] = $item['value'];
  149. if ($data['product_type'] == 20) {
  150. $count = array_unique($item['detail']);
  151. } else {
  152. $count = array_unique(array_column($item['detail'],'value'));
  153. }
  154. if (count($item['detail']) != count($count))
  155. return '属性重复';
  156. }
  157. return true;
  158. }
  159. public function sceneCreate(array $data)
  160. {
  161. if (!$this->scene('add')->check($data)) {
  162. return false;
  163. }
  164. if (!$data['spec_type'] && count($data['attrValue']) > 1) {
  165. $this->error = '单规格商品属性错误';
  166. return false;
  167. }
  168. if($data['type'] == NewProductRepository::DEFINE_TYPE_RESERVATION) {
  169. if(!$this->scene('reservation')->check($data)) {
  170. return false;
  171. }
  172. }
  173. return true;
  174. }
  175. public function sceneUpdate(array $data)
  176. {
  177. if (!$this->scene('add')->check($data)) {
  178. return false;
  179. }
  180. if (!$data['spec_type'] && count($data['attrValue']) > 1) {
  181. $this->error = '单规格商品属性错误';
  182. return false;
  183. }
  184. if($data['type'] == NewProductRepository::DEFINE_TYPE_RESERVATION) {
  185. if(!$this->scene('reservation')->check($data)) {
  186. return false;
  187. }
  188. }
  189. return true;
  190. }
  191. public function sceneBatchProductStock(array $data)
  192. {
  193. if(!isset($data['stockValue'])) {
  194. $this->error = '预约商品规格错误';
  195. return false;
  196. }
  197. foreach ($data['stockValue'] as $item) {
  198. if(!isset($item['value_id'])) {
  199. $this->error = '预约商品规格传参错误';
  200. return false;
  201. }
  202. foreach ($item['reservation'] as $reservation) {
  203. if(!isset($reservation['stock']) || !isset($reservation['attr_reservation_id'])) {
  204. $this->error = '预约商品规格错误';
  205. return false;
  206. }
  207. if($reservation['stock'] < 0) {
  208. $this->error = '预约库存不可小于0';
  209. return false;
  210. }
  211. }
  212. }
  213. return true;
  214. }
  215. protected function validateTimePeriods($periods)
  216. {
  217. if (!is_array($periods) || empty($periods)) {
  218. return '时段不能为空';
  219. }
  220. $uniquePeriods = [];
  221. $lastEndTime = null;
  222. foreach ($periods as $period) {
  223. if (!isset($period['start']) || !isset($period['end']) || !isset($period['is_show'])) {
  224. return '时段传参错误';
  225. }
  226. $startTime = strtotime($period['start']);
  227. $endTime = strtotime($period['end']);
  228. if (!$startTime || !$endTime) {
  229. return '时间格式错误';
  230. }
  231. if ($startTime >= $endTime) {
  232. return '时段结束时间必须大于开始时间';
  233. }
  234. // 检查时间段是否递增且无交集
  235. if ($lastEndTime !== null && $startTime < $lastEndTime) {
  236. return '时段必须递增且无交集';
  237. }
  238. $lastEndTime = $endTime;
  239. // 检查重复时段
  240. $timeKey = $period['start'] . '-' . $period['end'];
  241. if (in_array($timeKey, $uniquePeriods)) {
  242. return '存在重复时段';
  243. }
  244. $uniquePeriods[] = $timeKey;
  245. }
  246. return true;
  247. }
  248. }