Product.php 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  1. <?php namespace App\Http\Controllers\Api;
  2. use App\Http\Controllers\Api\Api;
  3. use App\Http\Requests\Api\Product as Request;
  4. use App\Models\Business;
  5. use App\Models\Custom;
  6. use App\Models\Product as Model;
  7. use App\Models\Product\Attr as ProductAttr;
  8. use App\Models\Product\City as ProductCity;
  9. use App\Models\Product\Spec as ProductSpec;
  10. use App\Models\Product\Skus as ProductSkus;
  11. use App\Models\ProductPhoto;
  12. use App\Models\PromoProduct;
  13. use App\Models\PromoRebate;
  14. use App\Models\RegimentActive;
  15. use App\Models\PayCity;
  16. use App\Models\Regiment;
  17. use App\Models\WeiBan\Tags as WeiBanTags;
  18. use Illuminate\Support\Facades\DB;
  19. /**
  20. * 产品接口
  21. *
  22. * @author 刘相欣
  23. *
  24. * */
  25. class Product extends Api{
  26. /**
  27. * 获取产品列表 /api/product/get_list
  28. *
  29. * @param string $name 产品名称
  30. * @param int $page 页码,默认1
  31. * @param int $limit 每页条数,默认10条
  32. *
  33. * */
  34. public function get_list(Request $request,Model $Model,Custom $Custom,Business $Business,RegimentActive $RegimentActive,WeiBanTags $WeiBanTags){
  35. // 接口验签
  36. // $this->verify_sign();
  37. // 验证参数
  38. $request->scene('get_list')->validate();
  39. // 检查登录
  40. $uid = $this->getUid();
  41. // 获取客户信息
  42. $custom = $uid ? $Custom->getOne($uid) : [];
  43. // 接收参数
  44. $name = request('name','');
  45. $classId = request('class_id',0);
  46. $getTop = request('get_top',0);
  47. $limit = request('limit',10);
  48. $cityId = empty($custom['city_id']) ? 0 : $custom['city_id'];
  49. // 显示
  50. $map = [['product.status','=','0'],['product.stock','>',0]];
  51. // 分类ID
  52. if( $classId ) $map[] = ['product.class_id','=',$classId];
  53. // 分类ID
  54. if( $name ) $map[] = ['product.name','like','%'.$name.'%'];
  55. // 是否有城市
  56. $wherIn = empty($custom['city_id']) ? [1] : [1,$custom['city_id']];
  57. // 获取分页信息
  58. $Paginator = $Model->query()
  59. ->join('product_city','product_city.product_id','=','product.id')
  60. ->join('orders_product','orders_product.product_id','=','product.id')
  61. ->where($map)
  62. ->whereIn('product_city.city_id',$wherIn)
  63. ->groupBy('product.id')
  64. ->orderBy( $getTop ? 'top_total' : 'product.sort', $getTop ? 'desc':'asc')
  65. ->orderBy('product.id')
  66. ->select(['product.id','product.sort','product.business_id','product.name','product.tag_scope','product.tag_exclude','product.thumb','product.spec','product.price','product.market_price','product.stock',DB::raw("count('product.id') as top_total")])
  67. ->paginate($limit);
  68. // 获取数据
  69. $data['total'] = $Paginator->total();
  70. $data['current_page'] = $Paginator->currentPage();
  71. $data['per_page'] = $Paginator->perPage();
  72. $data['last_page'] = $Paginator->lastPage();
  73. $data['data'] = $Paginator->items();
  74. //产品促销活动
  75. $productIds = array_column($Paginator->items(),'id');
  76. $time = time();
  77. $where = [
  78. ['promo.status','=','0'],
  79. ['promo.start_time','<=',$time],
  80. ['promo.end_time','>=',$time],
  81. ['promo_product.status','=',0],
  82. ];
  83. // 查询促销活动
  84. $promoList = PromoProduct::query()
  85. ->join('promo','promo.id','=','promo_product.promo_id')
  86. ->where($where)
  87. ->whereIn('promo_product.product_id',$productIds)
  88. ->select('promo.*','promo_product.product_id','promo_product.id as promo_product_id')
  89. ->get()
  90. ->toArray();
  91. // 查询促销活动
  92. if ($promoList) $promoList = array_column($promoList,NULL,'product_id');
  93. // 查询用户标签
  94. $tags = $custom ? $WeiBanTags->getListByWeibanExtid($custom['weiban_extid']) : [];
  95. $tagsList = array_column($tags,'name');
  96. // 处理请求
  97. foreach ( $data['data'] as $key => $value ) {
  98. // 判断是不是可以参与
  99. if( $value['tag_scope'] ) {
  100. // 解析数组
  101. $value['tag_scope'] = explode(',',$value['tag_scope']);
  102. // 如果没有交集,不在参与范围内
  103. if( !array_intersect($value['tag_scope'],$tagsList) ) {
  104. unset($data['data'][$key]);
  105. continue;
  106. }
  107. }
  108. // 判断是不是可以参与
  109. if( $value['tag_exclude'] ) {
  110. // 解析数组
  111. $value['tag_exclude'] = explode(',',$value['tag_exclude']);
  112. // 如果有交集,在排除范围内
  113. if( array_intersect($value['tag_exclude'],$tagsList) ) {
  114. unset($data['data'][$key]);
  115. continue;
  116. }
  117. }
  118. // 处理数据
  119. $value['thumb'] = path_compat($value['thumb']);
  120. $value['regiment_active_id'] = null;
  121. $value['regiment_title'] = '';
  122. $value['business_name'] = $Business->getOne($value['business_id'],'name');
  123. // 查询产品拼团信息
  124. $regiment = $RegimentActive::query()->where([['status','=',1],['start_time','<=',$time],['end_time','>=',$time],['product_id','=',$value['id']]])->first(['id as active_id','number','automatic']);
  125. // 如果有拼团信息
  126. if ( $regiment ) {
  127. $value['regiment_active_id']= $regiment['id'];
  128. $value['regiment_title'] = $regiment['automatic'] == 1 ? '多人团' : $regiment['number'].'人团';
  129. }
  130. if ($promoList && $cityId){
  131. if (isset($promoList[$value['id']])){
  132. $promoInfo = $promoList[$value['id']];
  133. $promoTitle = '';
  134. if ($promoInfo['rebate_type'] == 1){
  135. $promoTitle = "满减";
  136. }elseif ($promoInfo['rebate_type'] == 2){
  137. $promoTitle .= "满折";
  138. }elseif ($promoInfo['rebate_type'] == 3){
  139. $promoTitle .= "满赠";
  140. }
  141. $promoInfoCity = [];
  142. if ($promoInfo['city_ids']){
  143. $promoInfoCity = explode(',',$promoInfo['city_ids']);
  144. }
  145. // 判断是不是可以参与
  146. if (!$promoInfoCity || in_array($cityId,$promoInfoCity)){
  147. if( $promoInfo['tag_scope']) {
  148. // 解析数组
  149. $promoInfo['tag_scope'] = explode(',',$promoInfo['tag_scope']);
  150. // 标签范围限定时,默认不能参与
  151. $allowJoin = 0;
  152. // 判断标签是不是存在
  153. if ($tags){
  154. foreach ($tags as $v) {
  155. // 标签范围内,允许参加
  156. if( in_array($v['name'],$promoInfo['tag_scope']) ) $allowJoin = 1;
  157. }
  158. // 在范围
  159. if( $allowJoin ) {
  160. $value['promo_title'] = $promoTitle;
  161. }
  162. }
  163. }else{
  164. $value['promo_title'] = $promoTitle;
  165. }
  166. }
  167. }
  168. }
  169. // 重组数据
  170. $data['data'][$key] = $value;
  171. }
  172. // 数据重组
  173. $data['data'] = array_values($data['data']);
  174. // 返回结果
  175. return json_send(['code'=>'success','msg'=>'获取成功','data'=>$data]);
  176. }
  177. /**
  178. * 获取产品列表 /api/product/get_detail
  179. *
  180. * @param int $id 产品id
  181. *
  182. * */
  183. public function get_detail(Request $request, Model $Model, ProductPhoto $ProductPhoto,ProductCity $ProductCity, Business $Business, ProductAttr $ProductAttr, ProductSpec $ProductSpec, ProductSkus $ProductSkus, RegimentActive $RegimentActive, Regiment $Regiment, Custom $Custom, WeiBanTags $WeiBanTags, PromoProduct $PromoProduct,PayCity $PayCity){
  184. // 接口验签
  185. // $this->verify_sign();
  186. // 验证参数
  187. $request->scene('get_detail')->validate();
  188. // 检查登录
  189. $uid = $this->getUid();
  190. // 获取客户信息
  191. $custom = $uid ? $Custom->getOne($uid) : [];
  192. $cityId = empty($custom['city_id']) ? 0 : $custom['city_id'];
  193. // 接收参数
  194. $id = request('id',0);
  195. // 显示
  196. $map[] = ['status','=','0'];
  197. // 查询
  198. $data = $Model->query()->where($map)->find($id,['id','hide_orderbtn','name','tag_scope','tag_exclude','thumb','stock','spec','poster','price','business_id','market_price']);
  199. // 如果没有数据
  200. if( !$data ) return json_send(['code'=>'error','msg'=>'产品已下架','data'=>['error'=>'产品已下架或不存在']]);
  201. // 允许城市
  202. $allowCity = $ProductCity->where([['product_id','=',$id]])->pluck('city_id')->toArray();
  203. // 如果不是全国城市 也不是服务城市范围
  204. if ( !in_array(1,$allowCity) && ( isset($cityId) && !in_array($cityId,$allowCity)) ) return json_send(['code'=>'error','msg'=>'您的城市不在该产品服务范围','data'=>['error'=>'您的城市不在该产品服务范围']]);
  205. //判断产品城市是否设置了支付
  206. $payCity = $PayCity->where([['status','=',0]])->first();
  207. $isPay = 0;
  208. if ($payCity && $payCity['city_ids'] && isset($cityId)) {
  209. $cityIds = explode(',',$payCity['city_ids']);
  210. foreach ($allowCity as $item) {
  211. if (($item == 1 || in_array($item,$cityIds)) && in_array($cityId,$cityIds)) $isPay = 1;
  212. }
  213. }
  214. // 转数组
  215. $data = $data->toArray();
  216. // 处理数据
  217. $data['is_pay'] = $isPay;
  218. $data['thumb'] = path_compat($data['thumb']);
  219. $data['poster'] = $data['poster'] ? path_compat($data['poster']) : '';
  220. $data['description'] = $Model->getDesc($id);
  221. $data['business_info'] = $Business->getOne($data['business_id']);
  222. $data['photo_list'] = $ProductPhoto->getListByProductId($id);
  223. // 缩略图处理
  224. foreach ($data['photo_list'] as $key => $value) {
  225. $value['thumb'] = path_compat($value['thumb']);
  226. $data['photo_list'][$key] = $value;
  227. }
  228. // 主图追加进去
  229. if( $data['photo_list'] ) array_unshift($data['photo_list'],['id'=>0,'sort'=>0,'thumb'=>$data['thumb']]);
  230. // 获取产品属性
  231. $attr = $ProductAttr->getListByProductId($id);
  232. // 规格属性
  233. $specAttr = [];
  234. // 获取数据
  235. foreach ($attr as $value) {
  236. // 默认未选中
  237. $value['active'] = 0;
  238. $specAttr[$value['spec_id']]['spec_id'] = $value['spec_id'];
  239. $specAttr[$value['spec_id']]['spec_name'] = $ProductSpec->getOne($value['spec_id'],'name');
  240. $specAttr[$value['spec_id']]['attr_list'][] = $value;
  241. }
  242. // 获取规格详情数据
  243. $data['product_attr'] = array_values($specAttr);
  244. // 获取SKU数据
  245. $data['product_sku'] = $ProductSkus->getListByProductId($id);
  246. // 获取数据
  247. foreach ($data['product_sku'] as $key=>$value) {
  248. // 默认未选中
  249. $value['sku_thumb'] = $value['sku_thumb'] ? path_compat($value['sku_thumb']) : '';
  250. $data['product_sku'][$key]= $value;
  251. }
  252. // 手机号
  253. if( isset($data['business_info']['phone']) ) unset($data['business_info']['phone']);
  254. if( isset($data['business_info']['logopic']) ) $data['business_info']['logopic'] = path_compat($data['business_info']['logopic']);
  255. //拼团数据
  256. $time = time();
  257. $regimentWhere = [
  258. ['status','=',1],
  259. ['start_time','<=',$time],
  260. ['end_time','>=',$time],
  261. ['product_id','=',$data['id']]
  262. ];
  263. $regimentActive = $RegimentActive::query()
  264. ->where($regimentWhere)
  265. ->first();
  266. $data['regiment_list'] = [];
  267. $data['automatic_info'] = [];
  268. if ( $regimentActive ){
  269. $data['regiment_number'] = $regimentActive['number'];
  270. $data['regiment_active_id'] = $regimentActive['id'];
  271. $data['regiment_price'] = $regimentActive['regiment_price'];
  272. $data['regiment_quota'] = $regimentActive['quota'];
  273. $data['regiment_active'] = $regimentActive;
  274. $data['automatic_info'] = [];
  275. if ($regimentActive['automatic'] == 1){
  276. $automaticInfo = $Regiment::query()->where([['status','=',0],['active_id','=',$regimentActive['id']],['start_time','<=',$time],['end_time','>=',$time]])->first();
  277. if ($automaticInfo){
  278. $data['automatic_info'] = $automaticInfo;
  279. $data['regiment_type'] = 1;
  280. }else{
  281. $data['regiment_type'] = 2;
  282. }
  283. $data['regiment_title'] = '多人团';
  284. }else{
  285. $data['regiment_title'] = $regimentActive['number'].'人团';
  286. $data['regiment_type'] = 2;
  287. $regiment = $Regiment::query()
  288. ->join('custom','custom.uid','=','regiment.custom_uid')
  289. ->where([['regiment.active_id','=',$data['regiment_active_id']],['regiment.product_id','=',$data['id']],['regiment.status','=',0],['regiment.start_time','<=',$time],['regiment.end_time','>=',$time]])
  290. ->select(['regiment.*','custom.username','custom.userpic'])
  291. ->get();
  292. if ($regiment){
  293. foreach ($regiment as &$value) {
  294. $value['userpic'] = $value['userpic'] ? path_compat($value['userpic']) : '';
  295. $surplusNumber = $data['regiment_number'] - $value['people_number'];
  296. if ($surplusNumber > 0){
  297. $value['surplus_number'] = $surplusNumber;
  298. }else{
  299. $value['surplus_number'] = 0;
  300. }
  301. }
  302. $data['regiment_list'] = $regiment;
  303. }
  304. }
  305. }else{
  306. $data['regiment_active_id'] = null;
  307. $data['regiment_type'] = 0;
  308. }
  309. // 查询用户标签
  310. $tags = [];
  311. if ($custom){
  312. $tags = $WeiBanTags->getListByWeibanExtid($custom['weiban_extid']);
  313. $tagsList = array_column($tags,'name');
  314. // 判断是不是可以参与
  315. if( $data['tag_scope'] ) {
  316. // 解析数组
  317. $data['tag_scope'] = explode(',',$data['tag_scope']);
  318. // 如果没有交集,不在参与范围内
  319. if( !array_intersect($data['tag_scope'],$tagsList) ) return json_send(['code'=>'error','msg'=>'账号不在标签范围','data'=>['error'=>'账号不在标签范围']]);
  320. }
  321. // 判断是不是可以参与
  322. if( $data['tag_exclude'] ) {
  323. // 解析数组
  324. $data['tag_exclude'] = explode(',',$data['tag_exclude']);
  325. // 如果有交集,在排除范围内
  326. if( array_intersect($data['tag_exclude'],$tagsList) ) return json_send(['code'=>'error','msg'=>'账号不在标签允许范围','data'=>['error'=>'账号不在标签允许范围']]);
  327. }
  328. }
  329. //促销活动信息
  330. $promoInfo = $PromoProduct->getListById($data['id']);
  331. if ($promoInfo && $cityId){
  332. $promoTitle = "满". $promoInfo['std_pay']. "元";
  333. if ($promoInfo['rebate_type'] == 1){
  334. $promoTitle .= "减". $promoInfo['rebate']. "元";
  335. }elseif ($promoInfo['rebate_type'] == 2){
  336. $promoTitle .= "打". $promoInfo['rebate']. "折";
  337. }elseif ($promoInfo['rebate_type'] == 3){
  338. $rebate = (string) PromoRebate::query()->join('product','promo_rebate.product_id','=','product.id')->where([['promo_id','=',$promoInfo['id']]])->value('product.name');
  339. $promoTitle .= "赠送". $rebate;
  340. }
  341. $promoInfoCity = [];
  342. if ($promoInfo['city_ids']){
  343. $promoInfoCity = explode(',',$promoInfo['city_ids']);
  344. }
  345. // 判断是不是可以参与
  346. if (!$promoInfoCity || in_array($cityId,$promoInfoCity)){
  347. if( $promoInfo['tag_scope']) {
  348. // 解析数组
  349. $promoInfo['tag_scope'] = explode(',',$promoInfo['tag_scope']);
  350. // 标签范围限定时,默认不能参与
  351. $allowJoin = 0;
  352. // 判断标签是不是存在
  353. if ($tags){
  354. foreach ($tags as $v) {
  355. // 标签范围内,允许参加
  356. if( in_array($v['name'],$promoInfo['tag_scope']) ) $allowJoin = 1;
  357. }
  358. // 在范围
  359. if( $allowJoin ) {
  360. $data['promo_title'] = $promoTitle;
  361. }
  362. }
  363. }else{
  364. $data['promo_title'] = $promoTitle;
  365. }
  366. }
  367. }
  368. // 返回结果
  369. return json_send(['code'=>'success','msg'=>'获取成功','data'=>$data]);
  370. }
  371. /**
  372. * 获取产品列表 /api/product/get_sku
  373. *
  374. * @param int $id 产品id
  375. *
  376. * */
  377. public function get_sku(Request $request,ProductAttr $ProductAttr,ProductSpec $ProductSpec,ProductSkus $ProductSkus ){
  378. // 接口验签
  379. // $this->verify_sign();
  380. // 验证参数
  381. $request->scene('get_sku')->validate();
  382. // 检查登录
  383. $uid = $this->checkLogin();
  384. // 接收参数
  385. $id = request('id',0);
  386. // 获取产品属性
  387. $attr = $ProductAttr->getListByProductId($id);
  388. // 规格属性
  389. $specAttr = [];
  390. // 获取数据
  391. foreach ($attr as $value) {
  392. // 默认未选中
  393. $value['active'] = 0;
  394. $specAttr[$value['spec_id']]['spec_id'] = $value['spec_id'];
  395. $specAttr[$value['spec_id']]['spec_name'] = $ProductSpec->getOne($value['spec_id'],'name');
  396. $specAttr[$value['spec_id']]['attr_list'][] = $value;
  397. }
  398. // 获取规格详情数据
  399. $data['product_attr'] = $specAttr;
  400. // 获取SKU数据
  401. $data['product_sku'] = $ProductSkus->getListByProductId($id);
  402. // 返回结果
  403. return json_send(['code'=>'success','msg'=>'获取成功','data'=>$data]);
  404. }
  405. }