You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

GetStockData.php 22 KiB

3 年之前
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505
  1. <?php
  2. /**
  3. *
  4. * ============================================================================
  5. * * 版权所有 蜘蛛出行 * *
  6. * 网站地址: http://www.zhizhuchuxing.com
  7. * ----------------------------------------------------------------------------
  8. * 这不是一个自由软件!您只能在不用于商业目的的前提下对程序代码进行修改和
  9. * 使用;不允许对程序代码以任何形式任何目的的再发布。
  10. * ============================================================================
  11. * Author By: 温依莅
  12. * PhpStorm GetStockData.php 获取巴士,酒店,门票的库存和成本价信息
  13. * Create By 2017/6/23 9:44 $
  14. */
  15. namespace backend\modules\api\logic;
  16. use backend\modules\api\models\OperaProduct;
  17. use backend\modules\api\models\OperaProductRun;
  18. use backend\modules\api\models\OperaTickets;
  19. use backend\modules\api\models\RunMain;
  20. use backend\modules\api\models\RunProd;
  21. use backend\modules\api\models\OperaLine;
  22. use backend\modules\api\models\RunStation;
  23. use backend\modules\api\logic\SubmitBusAgentOrder;
  24. use yii\db\Query;
  25. use yii\base\Exception;
  26. use yii\db\Expression;
  27. use Yii;
  28. /**
  29. * 产品成本库存数据
  30. */
  31. class GetStockData extends Query
  32. {
  33. /**
  34. * Function Description:根据 班次run_id,票种prod_id得到 车资源库存
  35. * Function Name: getBusBasicStock
  36. * @param int $run_id 班次
  37. * @param int $prod_id 车次
  38. *
  39. * @return array
  40. *
  41. * @author 温依莅
  42. */
  43. public function getBusBasicStock($run_id, $prod_id)
  44. {
  45. //1,获取班次票种相关信息
  46. $res = RunProd::find()
  47. ->select([
  48. 'run_id' => 'rm.run_id',//班次id
  49. 'run_date' => 'rm.run_date',//出发日期
  50. 'run_time' => 'rm.run_time',//出发时间
  51. 'run_minutes' => 'rm.run_minutes',//出发分钟数
  52. 'prod_id' => 'rp.prod_id',//票种id
  53. 'prod_name' => 't.ticket_name',//票种名称
  54. 'seat_type' => 't.seat_type',//座位类型
  55. 'human_type' => 't.human_type',//人群属性
  56. 'line_id' => 't.line_id',//线路id
  57. 'line_name' => 'l.line_name',//线路名称
  58. 'start_res_id' => 't.start_station_res_id',//上车站id
  59. 'start_area_id' => 't.start_station_area_id',//出发地id
  60. 'start_seq_id' => 's1.station_order_id',//开始站顺序号
  61. 'start_time' => 's1.start_time',//开始时间
  62. 'start_minutes' => 's1.start_minutes',//开始分钟数
  63. 'end_res_id' => 't.end_station_res_id',//下车站id
  64. 'end_area_id' => 't.end_station_area_id',//目的地id
  65. 'end_seq_id' => 's2.station_order_id',//结束站顺序号
  66. 'end_time' => 's2.start_time',//结束时间
  67. 'end_minutes' => 's2.start_minutes',//结束分钟数
  68. ])
  69. ->from(RunProd::tableName() . ' as rp')
  70. ->leftJoin(RunMain::tableName() . ' as rm', 'rp.run_id = rm.run_id')
  71. ->leftJoin(OperaTickets::tableName() . ' as t', 'rp.prod_id = t.ticket_id')
  72. ->leftJoin(OperaLine::tableName() . ' as l', 't.line_id = l.line_id')
  73. ->leftJoin(RunStation::tableName() . ' as s1', 'rm.run_id = s1.run_id and l.line_id = s1.prod_id and t.start_station_res_id = s1.station_res_id')
  74. ->leftJoin(RunStation::tableName() . ' as s2', 'rm.run_id = s2.run_id and l.line_id = s2.prod_id and t.end_station_res_id = s2.station_res_id')
  75. ->where([
  76. 'and',
  77. ['=', 'rp.run_id', $run_id],
  78. ['=', 'rp.prod_id', $prod_id],
  79. ['=', 'rp.cancel_flag', 0],
  80. ['=', 'l.cancel_flag', 0],
  81. ['=', 'l.is_onsale', 1],
  82. ['=', 't.cancel_flag', 0],
  83. ['=', 't.is_onsale', 1],
  84. ]);
  85. $res_sql = $res->createCommand()->getRawSql();
  86. $result = array();
  87. $prod_info = $res->asArray()->one();
  88. if (!$prod_info) {
  89. $result['code'] = '2';
  90. $result['info'] = "班次-$run_id 票种-$prod_id 不可售";
  91. return $result;
  92. }
  93. $run_x_name = 'run_' . date('Ym', strtotime($prod_info['run_date']));
  94. //2,初步获取run_x表相关座位信息
  95. $res2 = (new Query())
  96. ->select('group_concat(id) as run_x_id,run_id,bus_order_id,seat_x,seat_y,seat_type,seat_seq_id,seat_name,count(id) as seat_count')
  97. ->from($run_x_name)
  98. ->where([
  99. 'and',
  100. ['=', 'run_id', $prod_info['run_id']],
  101. ['>=', 'order_id', $prod_info['start_seq_id']],
  102. ['<', 'order_id', $prod_info['end_seq_id']],
  103. ['=', 'seat_type', $prod_info['seat_type']],
  104. ['=', 'cancel_flag', 0],
  105. ['=', 'seat_status', 0],
  106. ])->groupBy(['run_id', 'bus_order_id', 'seat_type', 'seat_seq_id'])
  107. ->orderBy('seat_seq_id ASC')->all();
  108. if (!$res2) {
  109. $bus_arr = (new Query())->select('bus_order_id')->from('run_bus')->where(['run_id' => $run_id, 'cancel_flag' => 0])->all();//获取车次信息
  110. $stock_list = array('run_id' => $run_id, 'prod_id' => $prod_id, 'total_stock' => 0, 'single_max_stock' => 0);
  111. foreach ($bus_arr as $k => $v) {
  112. $stock_list['sub_list'][$v['bus_order_id']]['bus_order_id'] = $v['bus_order_id'];
  113. $stock_list['sub_list'][$v['bus_order_id']]['sub_stock'] = 0;
  114. }
  115. $result['code'] = '0';
  116. $result['info'] = '获取库存成功';
  117. $result['list'] = $stock_list;
  118. return $result;
  119. }
  120. //3,进一步筛选符合条件座位数
  121. $seat_arr = array();
  122. foreach ($res2 as $k => $v) {
  123. if ($v['seat_count'] == ($prod_info['end_seq_id'] - $prod_info['start_seq_id'])) {
  124. $seat_arr[$v['bus_order_id']][$v['seat_seq_id']] = $v;
  125. }
  126. }
  127. //4,处理得到库存数组
  128. $stock_list = array('run_id' => $run_id, 'prod_id' => $prod_id, 'total_stock' => 0, 'single_max_stock' => 0);
  129. foreach ($seat_arr as $ak => $av) {
  130. $add = count($av);
  131. $stock_list['single_max_stock'] = max($add, $stock_list['single_max_stock']); //单次最大购买数量
  132. $stock_list['total_stock'] += $add; //可购买总数量
  133. $stock_list['sub_list'][$ak]['bus_order_id'] = $ak;
  134. $stock_list['sub_list'][$ak]['sub_stock'] = $add;
  135. }
  136. $result['code'] = '0';
  137. $result['info'] = '获取巴士库存成功';
  138. $result['list'] = $stock_list;
  139. return $result;
  140. }
  141. /**
  142. * Function Description:得到巴士票种 在特定渠道和运营主体的 成本
  143. * Function Name: getBusBasicCost
  144. * @param int $prod_id 票种id
  145. * @param int $org_id 渠道id
  146. * @param int $user_id 下单用户id
  147. * @param int $main_corp_id 下单运营主体id
  148. *
  149. * @return array
  150. *
  151. * @author 温依莅
  152. */
  153. public function getBusBasicCost($prod_id, $org_id, $user_id, $main_corp_id = -1)
  154. {
  155. $agentObj = new SubmitBusAgentOrder();
  156. $result = array();
  157. //1,获取巴士票种在该渠道的成本(包含代售情形)
  158. $prod_info = $agentObj->getTicketAgentInfo($prod_id, $org_id, $user_id, $main_corp_id);
  159. if (!isset($prod_info['code']) || $prod_info['code'] != '0') {
  160. $result['code'] = '1';
  161. $result['info'] = $prod_info['info'];
  162. return json_encode($result);
  163. }
  164. $detail = $prod_info['list']['ticket_agent_list'][1];
  165. //2,获取巴士票种在该渠道的售价(包含代售情形)
  166. #1.1,判断是否是代售
  167. $is_agent = $prod_info['list']['is_agent'];
  168. $main_corp_id = $detail['main_corp_id']; //运营主体
  169. $opera_ticket_name = $is_agent ? 'opera_tickets_agent' : 'opera_tickets';
  170. $agent_condition = $is_agent ? ['and', ['=', 'ot.authority_status', 1], ['=', 'ot.to_main_corp_id', $main_corp_id]] : '';
  171. #1.2,获取巴士票种渠道数据
  172. $ticket_info = (new Query())
  173. ->select([
  174. 'ot.ticket_id',//票种id
  175. 'ot.cus_price',//零售价
  176. 'ot.prod_price',//分销价
  177. 'pub_sale_type' => 'bs.sale_type',//公有销售方式-->177 分销,277 代理,312 直营
  178. 'pri_sale_type' => 'otd.sale_type',//销售方式-->177 分销,277 代理,312 直营
  179. 'ticket_price' => 'otd.prod_price',//销售价格-->分销价格?
  180. //'otd.authority_status' //该渠道该票种是否授权
  181. ])
  182. ->from($opera_ticket_name . ' as ot')
  183. ->leftJoin('opera_tickets_distrib as otd', 'ot.ticket_id = otd.ticket_id and otd.cancel_flag = 0 and otd.supplier_id = ' . $org_id)
  184. ->leftJoin('base_supplier_sale as bs', 'bs.supplier_id = ' . $org_id . ' and bs.parent_type = 310')
  185. ->where([
  186. 'and',
  187. ['=', 'ot.ticket_id', $prod_id],
  188. ['=', 'ot.cancel_flag', 0],
  189. ['=', 'ot.is_onsale', 1],
  190. ['=', 'ot.ticket_type', 1],
  191. $agent_condition,
  192. ['=', 'bs.cancel_flag', 0],
  193. ['or', 'otd.authority_status=1', 'otd.authority_status is null'],
  194. ])->one();
  195. #1.3 根据规则获取巴士产品在该渠道的售价
  196. $sale_price = $this->getTicketPrice($ticket_info);
  197. //2,获取巴士票种在该渠道的成本(包含代售情形)
  198. $list['prod_id'] = $prod_id;
  199. $list['org_id'] = $detail['outside_sale_org_id'];//渠道id
  200. $list['main_corp_id'] = $detail['main_corp_id'];//下单运营主体id
  201. $list['source_main_corp_id'] = $detail['source_main_corp_id'] + 0;//票种所属运营主体id
  202. $list['base_price'] = $detail['base_price'];//票种成本
  203. $list['sale_price'] = $sale_price;//票种在该渠道的售价
  204. $result['code'] = '0';
  205. $result['info'] = '获取巴士成本成功';
  206. $result['list'] = $list;
  207. return $result;
  208. }
  209. /**
  210. * Function Description:获取票种销售价格
  211. * Function Name: getTicketPrice
  212. * @param mixed $ticket_info 票种信息
  213. *
  214. * @return mixed
  215. *
  216. * @author 张帅
  217. */
  218. public function getTicketPrice($ticket_info)
  219. {
  220. $sale_type = empty($ticket_info['pri_sale_type']) ? $ticket_info['pub_sale_type'] : $ticket_info['pri_sale_type'];
  221. #region 获取票种价格 判断销售规则是否设定价格
  222. if (empty($ticket_info['ticket_price'])) {
  223. #region 判断销售类型
  224. if ($sale_type == 177) {
  225. $result = $ticket_info['prod_price'];
  226. } else {
  227. $result = $ticket_info['cus_price'];
  228. }
  229. #endregion
  230. } else {
  231. $result = $ticket_info['ticket_price'];
  232. }
  233. #endregion
  234. return $result;
  235. }
  236. /**
  237. * Function Description:获取门票的成本和库存
  238. * Function Name: getTicketBasicStock
  239. * @param int $main_prod_id 门票父票种id
  240. * @param int $sub_prod_id 门票子票种id
  241. * @param string $run_date
  242. *
  243. * @return array
  244. *
  245. * @author 温依莅
  246. */
  247. public function getTicketBasicStock($main_prod_id, $sub_prod_id, $run_date, $to_org_id)
  248. {
  249. $model = new OperaProductRun();
  250. $res = $model->getProdInfo($main_prod_id, $sub_prod_id, $run_date, $to_org_id);
  251. // $res = (new Query())->select([
  252. // 'b.parent_id as main_prod_id',
  253. // 'a.prod_id as sub_prod_id',
  254. // 'a.run_date',
  255. // 'a.prod_price',
  256. // 'a.cus_price as base_price',
  257. // 'a.total_count',
  258. // 'a.saled_count',
  259. // '(a.total_count-a.saled_count) as stock',
  260. // 'a.is_onsale',
  261. // ])
  262. // ->from('opera_product_run a')
  263. // ->leftJoin('opera_product b', 'a.prod_id=b.prod_id')
  264. // ->where([
  265. // 'a.prod_id' => $sub_prod_id,
  266. // 'b.parent_id' => $main_prod_id,
  267. // 'a.run_date' => $run_date,
  268. // 'a.is_onsale' => 1,
  269. // 'a.cancel_flag' => 0,
  270. // 'b.is_onsale' => 1,
  271. // 'b.cancel_flag' => 0,
  272. // ])->one();
  273. $result = array();
  274. if (!$res) {
  275. $result['code'] = '1';
  276. $result['info'] = "($main_prod_id-$sub_prod_id-$run_date)该门票票种不可售";
  277. return $result;
  278. }
  279. //票种日期参数
  280. $list['main_prod_id'] = $res['main_prod_id'];
  281. $list['sub_prod_id'] = $res['sub_prod_id'];
  282. $list['run_date'] = $res['run_date'];
  283. $list['base_price'] = $res['base_price'];
  284. $list['total_stock'] = $res['stock'];
  285. $result['code'] = '0';
  286. $result['info'] = '获取门票成本库存成功';
  287. $result['list'] = $list;
  288. return $result;
  289. }
  290. /**
  291. * Function Description:获取酒店库存和成本
  292. * Function Name: getHotelProInfo
  293. * @param int $hotel_id 酒店id
  294. * @param int $base_room_type 基础房型
  295. * @param int $room_type 房型类型
  296. * @param string $run_date 入住日期
  297. * @param int $org_id 渠道id
  298. *
  299. * @return array
  300. *
  301. * @author 温依莅
  302. */
  303. public function getHotelBasicStock($hotel_id, $base_room_type, $room_type, $run_date, $org_id)
  304. {
  305. //1,获取每日房间属性
  306. $hotel_info = (new Query())
  307. ->select([
  308. 'rhd.run_date',//入住日期
  309. 'remaining_count' => new Expression("case rhd.run_status when 326 then rhd.remaining_count when 329 then -1 else 0 end"),//库存剩余数量
  310. 'rhd.oversell_flag',//允许超卖标志 1:允许超卖 0:不允许超卖
  311. 'rhd.consume_stock_type',//下单时消耗的库存类型顺序
  312. 'price' => new Expression("case when bss.sale_type = 177 then rhd.prod_price else rhd.cus_price end"),//价格
  313. 'bss.sale_type',//销售类型
  314. 'bss.commision_flag',
  315. 'bss.commision_type',
  316. 'bss.back_commision_type',
  317. 'bss.back_commision_method',
  318. 'bss.back_percent',
  319. 'bss.back_value',
  320. ])
  321. ->from('run_hotel_distrib as rhd')
  322. ->leftJoin('base_supplier_sale as bss', 'rhd.distrib_id = bss.supplier_id')
  323. ->leftJoin('opera_hotel as oh', 'oh.hotel_id=rhd.hotel_id')
  324. ->leftJoin('opera_hotel_base_room as ohbr', 'ohbr.hotel_id=rhd.hotel_id and ohbr.base_room_type = rhd.base_room_type')
  325. ->leftJoin('opera_hotel_room as ohr', 'ohr.hotel_id=rhd.hotel_id and ohr.parent_room_type = rhd.base_room_type and ohr.room_type = rhd.room_type')
  326. ->leftJoin('run_hotel_sub_room as rhsr', 'rhsr.hotel_id = rhd.hotel_id and rhsr.base_room_type = rhd.base_room_type and rhsr.room_type=rhd.room_type')
  327. ->where([
  328. 'and',
  329. ['=', 'rhd.distrib_id', $org_id],
  330. ['=', 'rhd.hotel_id', $hotel_id],
  331. ['=', 'rhd.room_type', $room_type],
  332. ['=', 'rhd.base_room_type', $base_room_type],
  333. ['=', 'rhd.run_date', $run_date],
  334. ['=', 'bss.parent_type', 25],
  335. ['=', 'bss.cancel_flag', 0],
  336. ['=', 'rhd.authority_status', 1],//run_hotel_distrib 授权
  337. ['=', 'rhd.run_status', 326],
  338. ['=', 'oh.hotel_status', 1],
  339. ['=', 'ohbr.cancel_flag', 0],
  340. ['=', 'ohr.is_onsale', 1],
  341. ['=', 'rhsr.run_status', 1],
  342. ])->one();
  343. if (!$hotel_info) {
  344. $result['code'] = '1';
  345. $result['info'] = "($hotel_id-$base_room_type-$room_type-$run_date-$org_id)该酒店房型不可售";
  346. return $result;
  347. }
  348. //2, 获取不同库存类型
  349. $stock_type_arr = explode(',', $hotel_info['consume_stock_type']);//下单时消耗的库存类型顺序
  350. $stock_type_arr = array_unique($stock_type_arr);
  351. $hotel_info['stock_type_arr'] = $stock_type_arr;//下单时消耗的库存类型顺序
  352. //3, 获取不同库存类型的库存及成本
  353. $stock_list = (new Query())
  354. ->select([
  355. 'rh.run_date',//入住日期
  356. 'rh.stock_type',//库存类型
  357. 'rh.remaining_count',//库存剩余数量
  358. 'cost_price' => new Expression("case rh.stock_type when 228 then rhs.base_price_buyout when 230 then rhs.base_price_reserve when 229 then rhs.base_price_inquiry else 0 end"),//价格
  359. ])
  360. ->from('run_hotel as rh')
  361. ->leftJoin('run_hotel_sub_room as rhs', 'rh.hotel_id = rhs.hotel_id and rh.base_room_type = rhs.base_room_type and rh.run_date = rhs.run_date')
  362. ->where([
  363. 'and',
  364. ['=', 'rh.hotel_id', $hotel_id],
  365. ['=', 'rhs.room_type', $room_type],
  366. ['=', 'rh.base_room_type', $base_room_type],
  367. ['=', 'rh.run_date', $hotel_info['run_date']],
  368. ['in', 'rh.stock_type', $hotel_info['stock_type_arr']],
  369. ['=', 'rhs.run_status', 1],
  370. ['=', 'rh.is_onsale', 1],//run_hotel上线
  371. ['=', 'rhs.is_onsale', 1],//run_hotel_sub_room 上线
  372. ])->all();
  373. if (!$stock_list) {
  374. $result['code'] = '1';
  375. $result['info'] = '该酒店房型不可售';
  376. return $result;
  377. }
  378. $stock_list_arr = [];
  379. foreach ($stock_list as $key => $vel) {
  380. $stock_list_arr[$vel['run_date'] . '-' . $vel['stock_type']] = $vel;
  381. }
  382. $hotel_info['limit_total_num'] = 0;//库存
  383. //4,获取总库存:max((买断228+保留230),现询229) ---$hotel_info['max_total_num']
  384. $sure_reserve = (int)$stock_list_arr[$hotel_info['run_date'] . '-' . 228]['remaining_count'] + (int)$stock_list_arr[$hotel_info['run_date'] . '-' . 230]['remaining_count'];
  385. $inquiry = (int)$stock_list_arr[$hotel_info['run_date'] . '-' . 229]['remaining_count'];
  386. #$max_total_num = max($sure_reserve, $inquiry); modify by nizf 现改为 获取总库存:(228+229+230)
  387. $max_total_num = $sure_reserve + $inquiry;
  388. $hotel_info['max_total_num'] = $max_total_num;
  389. //5,根据渠道超卖判断渠道最大可售库存 ---$hotel_info['limit_total_num']
  390. if ($hotel_info['oversell_flag'] == 1) {
  391. $hotel_info['limit_total_num'] = $max_total_num;
  392. } else {
  393. $hotel_info['limit_total_num'] = min($hotel_info['remaining_count'], $max_total_num) + 0;
  394. }
  395. //6,各类型子房型(买断228,保留230,现询229)详细信息(成本,库存)
  396. foreach ($hotel_info['stock_type_arr'] as $stock_key => $stock_vel) {
  397. if (isset($stock_list_arr[$hotel_info['run_date'] . '-' . $stock_vel])) {
  398. $hotel_info['stock_type_arr'][$stock_key] = $stock_list_arr[$hotel_info['run_date'] . '-' . $stock_vel];
  399. } else {
  400. unset($hotel_info['stock_type_arr'][$stock_key]);
  401. }
  402. }
  403. $result['code'] = '0';
  404. $result['info'] = '获取酒店房型成本库存成功';
  405. $result['list'] = $hotel_info;
  406. return $result;
  407. }
  408. /**
  409. * Function Description:获取特定日期产品价格和库存
  410. * Function Name: getProdPrice
  411. * @param $run_date
  412. * @param $to_org_id
  413. * @param $sub_prod_id
  414. *
  415. * @return array
  416. *
  417. * @author 冒炎
  418. */
  419. public function getProdPrice($run_date, $to_org_id, $sub_prod_id)
  420. {
  421. $prod = new OperaProduct();
  422. $product = $prod->getProdInfo($run_date, $to_org_id, $sub_prod_id, true);
  423. if (!$product) {
  424. return [
  425. 'code' => '2',
  426. 'info' => '产品不存在!'
  427. ];
  428. } else {
  429. //如果产品下架,返回库存为0
  430. if ($product['prod_is_onsale'] == 0 || $product['run_is_onsale'] == 0) {
  431. $data['cus_price'] = $product['cus_price'];
  432. $data['prod_price'] = $product['prod_price'];
  433. $data['total_count'] = '0';
  434. return [
  435. 'code' => '0',
  436. 'info' => '获取产品数据成功!',
  437. 'list' => $data
  438. ];
  439. } else {//如果没有价格,返回通用渠道的价格和库存
  440. if (!$product['cus_price']) {
  441. $ac_product = $prod->getProdInfo($run_date, $to_org_id, $sub_prod_id, false);
  442. //如果通用渠道的产品也没有价格,返回000
  443. if (!$ac_product['cus_price']) {
  444. $data['cus_price'] = '0';
  445. $data['prod_price'] = '0';
  446. $data['total_count'] = '0';
  447. return [
  448. 'code' => '0',
  449. 'info' => '获取产品数据成功!',
  450. 'list' => $data
  451. ];
  452. } else {
  453. return [
  454. 'code' => '0',
  455. 'info' => '获取产品数据成功!',
  456. 'list' => $ac_product
  457. ];
  458. }
  459. } else {
  460. return [
  461. 'code' => '0',
  462. 'info' => '获取产品数据成功!',
  463. 'list' => $product
  464. ];
  465. }
  466. }
  467. }
  468. }
  469. }