UpdateForm.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. <?php
  2. namespace hd\models\goods;
  3. use hd\models\BaseForm;
  4. /**
  5. * 商品更新表单模型
  6. */
  7. class UpdateForm extends BaseForm
  8. {
  9. /**
  10. * 商品ID
  11. * @var int
  12. */
  13. public $id;
  14. /**
  15. * 商品名称
  16. * @var string
  17. */
  18. public $name;
  19. /**
  20. * 商品价格
  21. * @var float
  22. */
  23. public $price;
  24. /**
  25. * 价格类型
  26. * @var int
  27. */
  28. public $priceType;
  29. /**
  30. * 已售数量
  31. * @var int
  32. */
  33. public $sold;
  34. /**
  35. * 花朵数量
  36. * @var int
  37. */
  38. public $flowerNum;
  39. /**
  40. * 重量
  41. * @var float
  42. */
  43. public $weight;
  44. /**
  45. * 自动涨价
  46. * @var int
  47. */
  48. public $autoRise;
  49. /**
  50. * 商品图片
  51. * @var array
  52. */
  53. public $shopImg;
  54. /**
  55. * 商品封面图
  56. * @var string
  57. */
  58. public $cover;
  59. /**
  60. * 库存状态
  61. * @var int
  62. */
  63. public $stockSet;
  64. /**
  65. * 商品库存
  66. * @var int
  67. */
  68. public $stock;
  69. /**
  70. * 商品分类ID列表
  71. * @var array
  72. */
  73. public $categoryIdList;
  74. /**
  75. * 商品状态
  76. * @var int
  77. */
  78. public $status;
  79. /**
  80. * 删除状态
  81. * @var int
  82. */
  83. public $delStatus;
  84. /**
  85. * 商品子项数量
  86. * @var int
  87. */
  88. public $setItemNum;
  89. /**
  90. * 是否需要发货
  91. * @var int
  92. */
  93. public $needSend;
  94. /**
  95. * 运费类型
  96. * @var int
  97. */
  98. public $freightType;
  99. public $useCaseIdList;
  100. public $specEnabled;
  101. public $specList;
  102. /**
  103. * 规格名称:多规格时把首规格名称回写到主记录,便于主记录可售
  104. * @var string
  105. */
  106. public $specName;
  107. /**
  108. * 商品规格形态:0 单规格,1 多规格(主记录承载第一个规格)
  109. * @var int
  110. */
  111. public $goodsStyle;
  112. /**
  113. * {@inheritdoc}
  114. */
  115. public function rules()
  116. {
  117. return [
  118. // 必填字段验证
  119. [['id'], 'required', 'message' => '商品ID不能为空'],
  120. [['name'], 'required', 'message' => '请填写商品名称'],
  121. [['categoryIdList'], 'required', 'message' => '请选择商品分类'],
  122. // 数据类型验证
  123. [['id', 'status', 'delStatus', 'setItemNum'], 'integer'],
  124. [['name', 'cover'], 'string'],
  125. [['price'], 'number', 'min' => 0, 'message' => '商品价格必须大于或等于0'],
  126. [['sold'], 'integer', 'min' => 0, 'message' => '已售数量必须大于或等于0'],
  127. ['flowerNum', 'integer', 'min' => 0, 'message' => '花朵数量必须大于或等于0'],
  128. ['weight', 'number', 'min' => 0, 'message' => '重量必须大于或等于0'],
  129. [['autoRise'], 'in', 'range' => [0, 1]],
  130. [['stockSet'], 'in', 'range' => [0, 1]],
  131. [['stock'], 'integer', 'min' => 0, 'message' => '库存不能小于0'],
  132. [['priceType'], 'in', 'range' => [0, 1]],
  133. [['delStatus'], 'in', 'range' => [0, 1]],
  134. [['needSend'], 'in', 'range' => [0, 1]],
  135. [['freightType'], 'in', 'range' => [0, 1]],
  136. [['status'], 'in', 'range' => [0, 1]],
  137. // 数组类型验证
  138. [['shopImg'], 'validateShopImg'],
  139. [['categoryIdList'], 'validateCategoryIdList'],
  140. // 默认值设置
  141. ['flowerNum', 'default', 'value' => 0],
  142. ['weight', 'default', 'value' => 1],//当没有重量时,默认给1千克
  143. ['setItemNum', 'default', 'value' => 0],// 在更新时,没传值,会为 NULL 而导致报错
  144. ['status', 'default', 'value' => 1],
  145. ['delStatus', 'default', 'value' => 0],
  146. ['categoryIdList', 'default', 'value' => []],
  147. ['stock', 'default', 'value' => 0],
  148. ['useCaseIdList', 'default', 'value' => []],
  149. ['specEnabled', 'default', 'value' => 0],
  150. ['specName', 'default', 'value' => ''],
  151. ['goodsStyle', 'default', 'value' => 0],
  152. [['specEnabled'], 'in', 'range' => [0, 1]],
  153. [['goodsStyle'], 'in', 'range' => [0, 1]],
  154. [['specName'], 'string'],
  155. [['useCaseIdList'], 'validateUseCaseIdList'],
  156. [['specList'], 'validateSpecList'],
  157. ];
  158. }
  159. /**
  160. * 验证商品图片
  161. * @param string $attribute 属性名
  162. * @param array $params 参数
  163. */
  164. public function validateShopImg($attribute, $params)
  165. {
  166. if (!empty($this->$attribute) && !is_array($this->$attribute)) {
  167. $this->addError($attribute, '商品图片格式不正确');
  168. }
  169. }
  170. /**
  171. * 验证分类ID列表
  172. * @param string $attribute 属性名
  173. * @param array $params 参数
  174. */
  175. public function validateCategoryIdList($attribute, $params)
  176. {
  177. if (!empty($this->$attribute) && !is_array($this->$attribute)) {
  178. $this->addError($attribute, '商品分类格式不正确');
  179. }
  180. }
  181. public function validateUseCaseIdList($attribute) {
  182. if (!is_array($this->$attribute)) $this->addError($attribute, '使用场景格式不正确');
  183. }
  184. /**
  185. * 校验多规格列表:关闭时清空规格并标记单规格;开启时把首规格价库/名称回写主记录字段
  186. * @param string $attribute 属性名
  187. */
  188. public function validateSpecList($attribute)
  189. {
  190. if ((int)$this->specEnabled !== 1) {
  191. $this->$attribute = [];
  192. // 关闭多规格:清空主记录规格名,标记为单规格
  193. $this->specName = '';
  194. $this->goodsStyle = 0;
  195. return;
  196. }
  197. $list = $this->$attribute;
  198. if (is_string($list)) {
  199. $list = json_decode($list, true);
  200. }
  201. if (!is_array($list) || empty($list)) {
  202. $this->addError($attribute, '请至少填写一个规格');
  203. return;
  204. }
  205. $formatList = [];
  206. foreach ($list as $index => $spec) {
  207. $name = '规格' . ($index + 1);
  208. if (!is_array($spec)) {
  209. $this->addError($attribute, $name . '格式错误');
  210. return;
  211. }
  212. $specName = trim($spec['specName'] ?? '');
  213. if ($specName === '') {
  214. $this->addError($attribute, '请填写' . $name . '名称');
  215. return;
  216. }
  217. $priceType = $spec['priceType'] ?? null;
  218. if ($priceType === null || !in_array((int)$priceType, [0, 1], true)) {
  219. $this->addError($attribute, $name . '价格类型错误');
  220. return;
  221. }
  222. $price = $spec['price'] ?? 0;
  223. if ((int)$priceType === 1 && (!is_numeric($price) || $price <= 0)) {
  224. $this->addError($attribute, '请填写' . $name . '价格');
  225. return;
  226. }
  227. $stockSet = $spec['stockSet'] ?? 0;
  228. if (!in_array((int)$stockSet, [0, 1], true)) {
  229. $this->addError($attribute, $name . '库存类型错误');
  230. return;
  231. }
  232. $stock = $spec['stock'] ?? 0;
  233. if ((int)$stockSet === 1 && (!is_numeric($stock) || (int)$stock < 0 || (int)$stock != $stock)) {
  234. $this->addError($attribute, $name . '库存数量错误');
  235. return;
  236. }
  237. $flowerNum = $spec['flowerNum'] ?? 0;
  238. if (!is_numeric($flowerNum) || (int)$flowerNum < 0 || (int)$flowerNum != $flowerNum) {
  239. $this->addError($attribute, $name . '花支数错误');
  240. return;
  241. }
  242. $weight = $spec['weight'] ?? 1;
  243. if (!is_numeric($weight) || $weight < 0) {
  244. $this->addError($attribute, $name . '重量错误');
  245. return;
  246. }
  247. $sold = $spec['sold'] ?? 0;
  248. if (!is_numeric($sold) || (int)$sold < 0 || (int)$sold != $sold) {
  249. $this->addError($attribute, $name . '已售数量错误');
  250. return;
  251. }
  252. $specImg = is_array($spec['shopImg'] ?? null) ? $spec['shopImg'] : [];
  253. $specCover = trim($spec['cover'] ?? '');
  254. // 封面必须落在该规格图片列表里,占位值「1」回落到第一张
  255. if (!empty($specImg) && ($specCover === '' || !in_array($specCover, $specImg, true))) {
  256. $specCover = $specImg[0];
  257. }
  258. $formatList[] = [
  259. 'id' => (int)($spec['id'] ?? 0),
  260. 'specName' => $specName,
  261. 'priceType' => (int)$priceType,
  262. 'price' => (int)$priceType === 1 ? (float)$price : 0,
  263. 'stockSet' => (int)$stockSet,
  264. 'stock' => (int)$stockSet === 1 ? (int)$stock : 9999,
  265. 'flowerNum' => (int)$flowerNum,
  266. 'weight' => (float)$weight,
  267. 'sold' => (int)$sold,
  268. 'shopImg' => $specImg,
  269. 'cover' => $specCover,
  270. ];
  271. }
  272. $this->$attribute = $formatList;
  273. // 多规格:主记录承载首规格的价库与规格名,goodsStyle=1 供列表/下单判断
  274. $firstSpec = $formatList[0];
  275. $this->specName = $firstSpec['specName'];
  276. $this->goodsStyle = 1;
  277. $this->priceType = $firstSpec['priceType'];
  278. $this->price = $firstSpec['price'];
  279. $this->stockSet = $firstSpec['stockSet'];
  280. $this->stock = $firstSpec['stock'];
  281. $this->flowerNum = $firstSpec['flowerNum'];
  282. $this->weight = $firstSpec['weight'];
  283. $this->sold = $firstSpec['sold'];
  284. // 规格1即主记录:图片/封面回写主字段,避免把占位值「1」当封面入库
  285. if (!empty($firstSpec['shopImg'])) {
  286. $this->shopImg = $firstSpec['shopImg'];
  287. $this->cover = $firstSpec['cover'];
  288. }
  289. }
  290. /**
  291. * 获取属性标签
  292. * @return array
  293. */
  294. public function attributeLabels()
  295. {
  296. return [
  297. 'id' => '商品ID',
  298. 'name' => '商品名称',
  299. 'price' => '商品价格',
  300. 'priceType' => '价格类型',
  301. 'flowerNum' => '花朵数量',
  302. 'shopImg' => '商品图片',
  303. 'cover' => '商品封面图',
  304. 'stock' => '商品库存',
  305. 'categoryIdList' => '商品分类',
  306. 'status' => '商品状态',
  307. 'delStatus' => '删除状态',
  308. 'setItemNum' => '商品子项数量',
  309. 'itemList' => '商品子项列表',
  310. ];
  311. }
  312. }