Goods.php 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469
  1. <?php
  2. namespace app\admin\controller\commission;
  3. use app\common\controller\Backend;
  4. use app\common\model\commission\CommissionGoods as CommissionGoodsModel;
  5. use app\common\model\Goods as GoodsModel;
  6. use app\common\model\commission\Level as LevelModel;
  7. use app\common\Enum\CommissionGoodsEnum;
  8. use app\common\Enum\GoodsEnum;
  9. use app\common\Service\ShopConfigService;
  10. use think\Db;
  11. class Goods extends Backend
  12. {
  13. protected $model = null;
  14. protected $goodsModel;
  15. /**
  16. * 无需登录的方法,同时也就无需鉴权了
  17. */
  18. protected $noNeedLogin = [];
  19. /**
  20. * 无需鉴权的方法,但需要登录
  21. */
  22. protected $noNeedRight = ['commission', 'detail'];
  23. /**
  24. * 快速搜索时执行查找的字段
  25. */
  26. protected $searchFields = 'id,title,subtitle';
  27. /**
  28. * 是否是关联查询
  29. */
  30. protected $relationSearch = false;
  31. public function _initialize()
  32. {
  33. parent::_initialize();
  34. $this->model = new GoodsModel(); // 使用商品模型作为主模型,以便使用FastAdmin的标准功能
  35. $this->goodsModel = new GoodsModel();
  36. // 传递枚举配置给前端
  37. $this->assignconfig('commission_goods_participate_list', CommissionGoodsEnum::$participateList);
  38. $this->assignconfig('commission_goods_order_status_list', CommissionGoodsEnum::$orderStatusList);
  39. $this->assignconfig('commission_goods_rule_type_list', CommissionGoodsEnum::$ruleTypeList);
  40. $this->assignconfig('commission_goods_level_list', CommissionGoodsEnum::$levelList);
  41. $this->assignconfig('commission_goods_self_buy_list', CommissionGoodsEnum::$selfBuyList);
  42. $this->assignconfig('commission_goods_settlement_list', CommissionGoodsEnum::$settlementList);
  43. $this->assignconfig('commission_goods_commission_settlement_list', CommissionGoodsEnum::$commissionSettlementList);
  44. $this->assignconfig('commission_goods_commission_type_list', CommissionGoodsEnum::$commissionTypeList);
  45. // 传递商品枚举配置给前端
  46. $this->assignconfig('goods_status_map', GoodsEnum::getGoodsStatusMap());
  47. $this->assignconfig('goods_spec_type_map', GoodsEnum::getSpecTypeMap());
  48. $this->assignconfig('goods_type_map', GoodsEnum::getGoodsTypeMap());
  49. $this->assignconfig('goods_delivery_type_map', GoodsEnum::getDeliveryTypeMap());
  50. $this->assignconfig('goods_express_type_map', GoodsEnum::getExpressTypeMap());
  51. }
  52. public function index()
  53. {
  54. if (!$this->request->isAjax()) {
  55. return $this->view->fetch();
  56. }
  57. //如果发送的来源是 Selectpage,则转发到 Selectpage
  58. if ($this->request->request('keyField')) {
  59. return $this->selectpage();
  60. }
  61. [$where, $sort, $order, $offset, $limit] = $this->buildparams();
  62. $list = $this->model
  63. ->with('commission_goods')
  64. ->where($where)
  65. ->order($sort, $order)
  66. ->paginate($limit);
  67. // 为列表项添加文本表示
  68. $items = collection($list->items())->each(function ($goods) {
  69. return $this->formatGoodsData($goods);
  70. });
  71. $result = ['total' => $list->total(), 'rows' => $items];
  72. return json($result);
  73. }
  74. /**
  75. * 详情
  76. *
  77. * @param $id
  78. */
  79. public function detail($id)
  80. {
  81. $goodsList = collection(GoodsModel::with(['commission_goods'])->whereIn('id', $id)->select())->each(function ($goods) {
  82. $goods->skus = $goods->skus;
  83. $goods->sku_prices = $goods->sku_prices;
  84. // 使用统一的格式化方法
  85. return $this->formatGoodsData($goods);
  86. });
  87. // 获取分销配置
  88. $config = [
  89. 'participate_list' => CommissionGoodsEnum::$participateList,
  90. 'rule_type_list' => CommissionGoodsEnum::$ruleTypeList,
  91. 'level_list' => CommissionGoodsEnum::$levelList,
  92. // 商品枚举配置
  93. 'goods_status_map' => GoodsEnum::getGoodsStatusMap(),
  94. 'goods_spec_type_map' => GoodsEnum::getSpecTypeMap(),
  95. 'goods_type_map' => GoodsEnum::getGoodsTypeMap(),
  96. 'goods_delivery_type_map' => GoodsEnum::getDeliveryTypeMap(),
  97. 'goods_express_type_map' => GoodsEnum::getExpressTypeMap()
  98. ];
  99. $this->success('分销商品详情', null, [
  100. 'goods' => $goodsList,
  101. 'config' => $config
  102. ]);
  103. }
  104. /**
  105. * 设置佣金
  106. *
  107. * @param $ids
  108. */
  109. public function commission($ids = null)
  110. {
  111. if (!$this->request->isPost()) {
  112. // GET请求,显示设置页面
  113. $goodsIds = explode(',', $ids);
  114. $goodsList = GoodsModel::whereIn('id', $goodsIds)
  115. ->with(['commission_goods'])
  116. ->select();
  117. // 获取分销商等级列表及其佣金规则
  118. $levelList = LevelModel::order('level asc')
  119. ->select();
  120. // 获取分销配置(用于显示默认佣金比例)
  121. $commissionConfig = ShopConfigService::getConfigs('shop.commission');
  122. // 提取默认佣金规则用于前端显示
  123. $defaultCommissionRules = [];
  124. foreach ($levelList as $level) {
  125. if (isset($level->commission_rules) && is_array($level->commission_rules)) {
  126. $defaultCommissionRules[$level->level] = $level->commission_rules;
  127. }
  128. }
  129. // 获取第一个商品的分销数据(如果存在)
  130. $commissionData = null;
  131. if (isset($goodsList[0]) && $goodsList[0]->commission_goods) {
  132. $commissionData = $goodsList[0]->commission_goods->toArray();
  133. // 如果是默认规则,从系统配置中读取默认值用于前端显示
  134. if ($commissionData['rule_type'] == CommissionGoodsEnum::RULE_TYPE_DEFAULT) {
  135. // 从分销配置中读取默认值
  136. $commissionData['config'] = [
  137. 'self_buy' => $commissionConfig['self_buy'] ?? 1,
  138. 'level' => $commissionConfig['level'] ?? 3,
  139. 'reward_type' => $commissionConfig['reward_type'] ?? 'pay_price',
  140. 'reward_event' => $commissionConfig['reward_event'] ?? 'paid'
  141. ];
  142. }
  143. } else {
  144. // 如果没有分销数据,创建默认数据,从系统配置中读取
  145. $commissionData = [
  146. 'rule_type' => CommissionGoodsEnum::RULE_TYPE_DEFAULT,
  147. 'status' => CommissionGoodsEnum::PARTICIPATE_NO,
  148. 'order_status' => CommissionGoodsEnum::ORDER_STATUS_YES,
  149. 'config' => [
  150. 'self_buy' => $commissionConfig['self_buy'] ?? 1,
  151. 'level' => $commissionConfig['level'] ?? 3,
  152. 'reward_type' => $commissionConfig['reward_type'] ?? 'pay_price',
  153. 'reward_event' => $commissionConfig['reward_event'] ?? 'paid'
  154. ]
  155. ];
  156. }
  157. // 传递数据给前端
  158. $this->assignconfig('commission_data', $commissionData);
  159. $this->assignconfig('commission_config', $commissionConfig);
  160. $this->assignconfig('default_commission_rules', $defaultCommissionRules);
  161. $this->view->assign([
  162. 'goods_list' => $goodsList,
  163. 'level_list' => $levelList,
  164. 'goods_ids' => $ids,
  165. 'commission_data' => $commissionData, // 传递佣金数据用于数据初始化
  166. 'commission_config' => $commissionConfig, // 传递分销配置
  167. 'default_commission_rules' => $defaultCommissionRules, // 传递默认佣金规则
  168. // 商品枚举配置
  169. 'goods_status_map' => GoodsEnum::getGoodsStatusMap(),
  170. 'goods_spec_type_map' => GoodsEnum::getSpecTypeMap(),
  171. 'goods_type_map' => GoodsEnum::getGoodsTypeMap(),
  172. 'goods_delivery_type_map' => GoodsEnum::getDeliveryTypeMap(),
  173. 'goods_express_type_map' => GoodsEnum::getExpressTypeMap(),
  174. // 分销商品枚举配置
  175. 'commission_participate_list' => CommissionGoodsEnum::$participateList,
  176. 'commission_order_status_list' => CommissionGoodsEnum::$orderStatusList,
  177. 'commission_rule_type_list' => CommissionGoodsEnum::$ruleTypeList,
  178. 'commission_level_list' => CommissionGoodsEnum::$levelList,
  179. 'commission_self_buy_list' => CommissionGoodsEnum::$selfBuyList,
  180. 'commission_settlement_list' => CommissionGoodsEnum::$settlementList,
  181. 'commission_settlement_event_list' => CommissionGoodsEnum::$commissionSettlementList,
  182. 'commission_type_list' => CommissionGoodsEnum::$commissionTypeList
  183. ]);
  184. return $this->view->fetch();
  185. }
  186. // POST请求,保存设置
  187. $this->token();
  188. $params = $this->request->post();
  189. // 验证必需参数
  190. if (empty($ids)) {
  191. $this->error('商品ID不能为空');
  192. }
  193. $result = Db::transaction(function () use ($ids, $params) {
  194. $goodsIds = explode(',', $ids);
  195. $count = 0;
  196. $ruleType = intval($params['rule_type'] ?? CommissionGoodsEnum::RULE_TYPE_DEFAULT);
  197. foreach ($goodsIds as $goods_id) {
  198. $goods_id = intval($goods_id);
  199. if ($goods_id <= 0) continue;
  200. // 查找或创建分销商品记录
  201. $commissionGoods = CommissionGoodsModel::where('goods_id', $goods_id)->find();
  202. if (!$commissionGoods) {
  203. $commissionGoods = new CommissionGoodsModel();
  204. $commissionGoods->goods_id = $goods_id;
  205. }
  206. // 保存规则类型(所有情况都需要)
  207. $commissionGoods->rule_type = $ruleType;
  208. // 根据不同规则类型处理
  209. if ($ruleType == CommissionGoodsEnum::RULE_TYPE_DEFAULT) {
  210. // 默认规则:保存"是否参与"和"分销商业绩"设置,但不保存其他自定义配置
  211. $commissionGoods->status = intval($params['status'] ?? CommissionGoodsEnum::PARTICIPATE_NO);
  212. $commissionGoods->order_status = intval($params['order_status'] ?? CommissionGoodsEnum::ORDER_STATUS_YES);
  213. $commissionGoods->config = []; // 不保存其他自定义配置
  214. // 删除可能存在的自定义佣金规则
  215. Db::name('shop_commission_rules')
  216. ->where('goods_id', $goods_id)
  217. ->delete();
  218. } else if (in_array($ruleType, [CommissionGoodsEnum::RULE_TYPE_CUSTOM, CommissionGoodsEnum::RULE_TYPE_BATCH])) {
  219. // 独立规则或批量规则
  220. $distributionStatus = intval($params['status'] ?? CommissionGoodsEnum::PARTICIPATE_NO);
  221. $commissionGoods->status = $distributionStatus;
  222. // 只有在分销设置开启时才保存其他配置
  223. if ($distributionStatus == CommissionGoodsEnum::PARTICIPATE_YES) {
  224. // 保存分销商业绩设置
  225. $commissionGoods->order_status = intval($params['order_status'] ?? CommissionGoodsEnum::ORDER_STATUS_YES);
  226. // 保存扩展配置到JSON字段中
  227. $config = $commissionGoods->config ?? [];
  228. // 保存自购配置
  229. if (isset($params['self_buy'])) {
  230. $config['self_buy'] = intval($params['self_buy']);
  231. }
  232. // 保存分销层级
  233. if (isset($params['level'])) {
  234. $config['level'] = intval($params['level']);
  235. }
  236. // 保存商品结算方式
  237. if (isset($params['reward_type'])) {
  238. $config['reward_type'] = $params['reward_type'];
  239. }
  240. // 保存佣金结算时机
  241. if (isset($params['reward_event'])) {
  242. $config['reward_event'] = $params['reward_event'];
  243. }
  244. // 如果有其他自定义配置
  245. if (!empty($params['config']) && is_array($params['config'])) {
  246. $config = array_merge($config, $params['config']);
  247. }
  248. $commissionGoods->config = $config;
  249. // 保存佣金规则
  250. if (!empty($params['commission_rules'])) {
  251. $this->saveCommissionRules($goods_id, $params['commission_rules'], $ruleType);
  252. }
  253. } else {
  254. // 分销设置关闭时,清空相关配置但保留rule_type
  255. $commissionGoods->order_status = CommissionGoodsEnum::ORDER_STATUS_YES; // 保持默认值
  256. $commissionGoods->config = []; // 清空配置
  257. // 删除佣金规则
  258. Db::name('shop_commission_rules')
  259. ->where('goods_id', $goods_id)
  260. ->delete();
  261. }
  262. }
  263. $commissionGoods->save();
  264. $count++;
  265. }
  266. return $count;
  267. });
  268. if ($result) {
  269. $this->success('设置成功', '', $result);
  270. } else {
  271. $this->error('设置失败');
  272. }
  273. }
  274. /**
  275. * 保存佣金规则
  276. */
  277. private function saveCommissionRules($goodsId, $rulesData, $ruleType)
  278. {
  279. // 删除现有规则
  280. Db::name('shop_commission_rules')
  281. ->where('goods_id', $goodsId)
  282. ->delete();
  283. if (empty($rulesData) || !is_array($rulesData)) {
  284. return true;
  285. }
  286. $insertData = [];
  287. foreach ($rulesData as $agentLevel => $levelRules) {
  288. if (!is_array($levelRules)) continue;
  289. foreach ($levelRules as $commissionLevel => $rule) {
  290. if (empty($rule['value']) || bccomp($rule['value'], '0', 4) <= 0) {
  291. continue;
  292. }
  293. $insertData[] = [
  294. 'goods_id' => $goodsId,
  295. 'sku_id' => 0, // 批量规则统一为0,独立规则需要具体SKU ID
  296. 'agent_level' => intval($agentLevel),
  297. 'level' => intval($commissionLevel), // 新表字段名为level
  298. 'type' => $rule['type'] ?? 'rate',
  299. 'value' => floatval($rule['value']),
  300. 'status' => 1,
  301. 'created_at' => date('Y-m-d H:i:s'),
  302. 'updated_at' => date('Y-m-d H:i:s')
  303. ];
  304. }
  305. }
  306. if (!empty($insertData)) {
  307. return Db::name('shop_commission_rules')->insertAll($insertData);
  308. }
  309. return true;
  310. }
  311. /**
  312. * 格式化商品数据,添加文本表示
  313. *
  314. * @param object $goods 商品对象
  315. * @return object
  316. */
  317. private function formatGoodsData($goods)
  318. {
  319. // 添加商品状态和规格类型的文本表示
  320. $goods->status_text = GoodsEnum::getGoodsStatusText($goods->status);
  321. $goods->spec_type_text = GoodsEnum::getSpecTypeText($goods->spec_type);
  322. $goods->goods_type_text = GoodsEnum::getGoodsTypeText($goods->type);
  323. $goods->delivery_type_text = GoodsEnum::getDeliveryTypeText($goods->delivery_type ?? '');
  324. $goods->express_type_text = GoodsEnum::getExpressTypeText($goods->express_type ?? '');
  325. // 如果有分销商品信息,添加分销状态文本
  326. if ($goods->commission_goods) {
  327. $goods->commission_goods->participate_text = CommissionGoodsEnum::getParticipateText($goods->commission_goods->status);
  328. $goods->commission_goods->order_status_text = CommissionGoodsEnum::getOrderStatusText($goods->commission_goods->order_status);
  329. $goods->commission_goods->rule_type_text = CommissionGoodsEnum::getRuleTypeText($goods->commission_goods->rule_type);
  330. // 从config JSON中获取self_buy配置
  331. $config = $goods->commission_goods->config ?? [];
  332. $selfBuy = $config['self_buy'] ?? 0;
  333. $goods->commission_goods->self_buy = $selfBuy;
  334. $goods->commission_goods->self_buy_text = CommissionGoodsEnum::getSelfBuyText($selfBuy);
  335. // 添加颜色标识
  336. $goods->commission_goods->participate_color = CommissionGoodsEnum::getParticipateColor($goods->commission_goods->status);
  337. $goods->commission_goods->order_status_color = CommissionGoodsEnum::getOrderStatusColor($goods->commission_goods->order_status);
  338. $goods->commission_goods->self_buy_color = CommissionGoodsEnum::getSelfBuyColor($selfBuy);
  339. // 从config中获取其他配置
  340. $goods->commission_goods->level = $config['level'] ?? 0;
  341. $goods->commission_goods->reward_type = $config['reward_type'] ?? 'pay_price';
  342. $goods->commission_goods->reward_event = $config['reward_event'] ?? 'paid';
  343. }
  344. return $goods;
  345. }
  346. /**
  347. * 获取商品状态筛选选项
  348. *
  349. * @return array
  350. */
  351. public function getStatusFilterOptions()
  352. {
  353. return [
  354. 'goods_status' => GoodsEnum::getGoodsStatusMap(),
  355. 'spec_type' => GoodsEnum::getSpecTypeMap(),
  356. 'goods_type' => GoodsEnum::getGoodsTypeMap(),
  357. 'commission_participate' => CommissionGoodsEnum::$participateList,
  358. 'commission_rule_type' => CommissionGoodsEnum::$ruleTypeList
  359. ];
  360. }
  361. /**
  362. * 批量设置商品分销状态
  363. *
  364. * @param string $ids 商品ID,多个用逗号分隔
  365. * @param int $status 分销状态
  366. * @return void
  367. */
  368. public function batchSetStatus($ids, $status)
  369. {
  370. if (!$this->request->isPost()) {
  371. $this->error('请求方式错误');
  372. }
  373. $goodsIds = explode(',', $ids);
  374. $status = intval($status);
  375. if (!CommissionGoodsEnum::isValidParticipate($status)) {
  376. $this->error('无效的分销状态');
  377. }
  378. $count = 0;
  379. foreach ($goodsIds as $goodsId) {
  380. $goodsId = intval($goodsId);
  381. if ($goodsId <= 0) continue;
  382. // 查找或创建分销商品记录
  383. $commissionGoods = CommissionGoodsModel::where('goods_id', $goodsId)->find();
  384. if (!$commissionGoods) {
  385. $commissionGoods = new CommissionGoodsModel();
  386. $commissionGoods->goods_id = $goodsId;
  387. $commissionGoods->order_status = 1; // 默认计入业绩
  388. $commissionGoods->rule_type = 0; // 默认使用默认规则
  389. }
  390. $commissionGoods->status = $status;
  391. $commissionGoods->save();
  392. $count++;
  393. }
  394. $this->success("已更新 {$count} 个商品的分销状态");
  395. }
  396. }