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.
 
 
 
 
 
 

341 regels
12 KiB

  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: zhengmingwei
  5. * Date: 2020/2/9
  6. * Time: 6:18 PM
  7. */
  8. namespace addons\unishop\controller;
  9. use addons\unishop\extend\Hashids;
  10. use addons\unishop\extend\Redis;
  11. use addons\unishop\model\Address as AddressModel;
  12. use addons\unishop\model\Area;
  13. use addons\unishop\model\Config;
  14. use addons\unishop\model\DeliveryRule as DeliveryRuleModel;
  15. use addons\unishop\model\Evaluate;
  16. use addons\unishop\model\FlashProduct;
  17. use addons\unishop\model\FlashSale;
  18. use addons\unishop\model\Product;
  19. use think\Db;
  20. use think\Exception;
  21. use think\Hook;
  22. use think\Loader;
  23. /**
  24. * 秒杀相关接口
  25. * Class Flash
  26. * @package addons\unishop\controller
  27. */
  28. class Flash extends Base
  29. {
  30. protected $noNeedLogin = ['index', 'navbar', 'product', 'productDetail'];
  31. public function _initialize()
  32. {
  33. parent::_initialize();
  34. }
  35. /**
  36. * 首页秒杀信息接口
  37. */
  38. public function index()
  39. {
  40. $flashSaleModel = new FlashSale();
  41. $hour = strtotime(date('Y-m-d H:00:00'));
  42. $flash = $flashSaleModel
  43. ->where('endtime', '>=', $hour)
  44. ->where([
  45. 'switch' => FlashSale::SWITCH_YES,
  46. 'status' => FlashSale::STATUS_NO,
  47. ])
  48. ->with([
  49. 'product' => function ($query) {
  50. //$query->with('product')->where(['switch' => FlashProduct::SWITCH_ON]);
  51. $query->alias('fp')->join('unishop_product p', 'fp.product_id = p.id')
  52. ->field('fp.id,fp.flash_id,fp.product_id,p.image,p.title,p.sales_price')
  53. ->where([
  54. 'fp.switch' => FlashProduct::SWITCH_ON,
  55. 'p.deletetime' => NULL
  56. ]);
  57. }
  58. ])
  59. ->order('starttime ASC')
  60. ->find();
  61. if ($flash) {
  62. $flash = $flash->toArray();
  63. foreach ($flash['product'] as &$product) {
  64. $product['image'] = Config::getImagesFullUrl($product['image']);
  65. }
  66. // 寻找下一场的倒计时
  67. $nextFlash = $flashSaleModel
  68. ->where('starttime', '>', $hour)
  69. ->where([
  70. 'switch' => FlashSale::SWITCH_YES,
  71. 'status' => FlashSale::STATUS_NO,
  72. ])
  73. ->order("starttime ASC")
  74. ->cache(10)
  75. ->find();
  76. $flash['starttime'] = $nextFlash['starttime'];
  77. $flash['countdown'] = FlashSale::countdown($flash['starttime']);
  78. }
  79. $this->success('', $flash);
  80. }
  81. /**
  82. * 获取秒杀时间段
  83. */
  84. public function navbar()
  85. {
  86. $flashSaleModel = new FlashSale();
  87. $flash = $flashSaleModel
  88. ->where('endtime', '>', time())
  89. ->where([
  90. 'switch' => FlashSale::SWITCH_YES,
  91. 'status' => FlashSale::STATUS_NO
  92. ])
  93. ->field('id,starttime,title,introdution,endtime')
  94. ->order('starttime ASC')
  95. ->cache(2)
  96. ->select();
  97. $this->success('', $flash);
  98. }
  99. /**
  100. * 获取秒杀的产品列表
  101. */
  102. public function product()
  103. {
  104. $flash_id = $this->request->request('flash_id', 0);
  105. $page = $this->request->request('page', 1);
  106. $pagesize = $this->request->request('pagesize', 15);
  107. $flash_id = Hashids::decodeHex($flash_id);
  108. $productModel = new FlashProduct();
  109. $products = $productModel
  110. ->with('product')
  111. ->where(['flash_id' => $flash_id, 'switch' => FlashProduct::SWITCH_ON])
  112. ->limit(($page - 1) * $pagesize, $pagesize)
  113. ->cache(2)
  114. ->select();
  115. foreach ($products as &$product) {
  116. $product['sold'] = $product['sold'] > $product['number'] ? $product['number'] : $product['sold'];
  117. }
  118. $this->success('', $products);
  119. }
  120. /**
  121. * 获取产品数据
  122. */
  123. public function productDetail()
  124. {
  125. $productId = $this->request->get('id');
  126. $productId = \addons\unishop\extend\Hashids::decodeHex($productId);
  127. $flashId = $this->request->get('flash_id');
  128. $flashId = \addons\unishop\extend\Hashids::decodeHex($flashId);
  129. try {
  130. $productModel = new Product();
  131. $data = $productModel->where(['id' => $productId])->cache(true, 20, 'flashProduct')->find();
  132. if (!$data) {
  133. $this->error(__('Product not exist'));
  134. }
  135. // 真实浏览量加一
  136. $data->real_look++;
  137. $data->look++;
  138. $data->save();
  139. //服务
  140. $server = explode(',', $data->server);
  141. $configServer = json_decode(Config::getByName('server')['value'],true);
  142. $serverValue = [];
  143. foreach ($server as $k => $v) {
  144. if (isset($configServer[$v])) {
  145. $serverValue[] = $configServer[$v];
  146. }
  147. }
  148. $data->server = count($serverValue) ? implode(' · ', $serverValue) : '';
  149. // 默认没有收藏
  150. $data->favorite = false;
  151. // 评价
  152. $data['evaluate_data'] = (new Evaluate)->where(['product_id' => $productId])
  153. ->field('COUNT(*) as count, IFNULL(CEIL(AVG(rate)/5*100),0) as avg')
  154. ->cache(true, 20, 'flashEvaluate')->find();
  155. $redis = new Redis();
  156. $flash['starttime'] = $redis->handler->hGet('flash_sale_' . $flashId . '_' . $productId, 'starttime');
  157. $flash['endtime'] = $redis->handler->hGet('flash_sale_' . $flashId . '_' . $productId, 'endtime');
  158. $flash['sold'] = $redis->handler->hGet('flash_sale_' . $flashId . '_' . $productId, 'sold');
  159. $flash['number'] = $redis->handler->hGet('flash_sale_' . $flashId . '_' . $productId, 'number');
  160. $flash['sold'] = $flash['sold'] > $flash['number'] ? $flash['number'] : $flash['sold'];
  161. $flash['text'] = $flash['starttime'] > time() ? '距开始:' : '距结束:';
  162. // 秒杀类型不加载优惠券、促销活动、是否已收藏、评价等等,会影响返回速度
  163. $targetTime = $flash['starttime'] > time() ? $flash['starttime'] : $flash['endtime'];
  164. $flash['countdown'] = FlashSale::countdown($targetTime);
  165. $data['coupon'] = [];
  166. // 秒杀数据
  167. $data['flash'] = $flash;
  168. $data->append(['images_text', 'spec_list', 'spec_table_list'])->toArray();
  169. // 购物车数量
  170. $data['cart_num'] = (new \addons\unishop\model\Cart)->where(['user_id' => $this->auth->id])->count();
  171. $this->success('', $data);
  172. } catch (Exception $e) {
  173. $this->error($e->getMessage());
  174. }
  175. }
  176. /**
  177. * 创建订单
  178. */
  179. public function createOrder()
  180. {
  181. $productId = $this->request->post('id', 0);
  182. $flashId = $this->request->post('flash_id', 0);
  183. $flashId = \addons\unishop\extend\Hashids::decodeHex($flashId);
  184. $productId = \addons\unishop\extend\Hashids::decodeHex($productId);
  185. try {
  186. $redis = new Redis();
  187. $sold = $redis->handler->hGet('flash_sale_' . $flashId . '_' . $productId, 'sold');
  188. $number = $redis->handler->hGet('flash_sale_' . $flashId . '_' . $productId, 'number');
  189. $switch = $redis->handler->hGet('flash_sale_' . $flashId . '_' . $productId, 'switch');
  190. $starttime = $redis->handler->hGet('flash_sale_' . $flashId . '_' . $productId, 'starttime');
  191. $endtime = $redis->handler->hGet('flash_sale_' . $flashId . '_' . $productId, 'endtime');
  192. //判断是否开始或结束
  193. if (time() < $starttime) {
  194. $this->error(__('Activity not started'));
  195. }
  196. if ($endtime < time()) {
  197. $this->error(__('Activity ended'));
  198. }
  199. // 截流
  200. if ($sold >= $number) {
  201. $this->error(__('Item sold out'));
  202. }
  203. if ($switch == FlashSale::SWITCH_NO || $switch == false) {
  204. $this->error(__('Item is off the shelves'));
  205. }
  206. $product = (new Product)->where(['id' => $productId, 'deletetime' => null])->find();
  207. /** 产品基础数据 **/
  208. $spec = $this->request->post('spec', '');
  209. $productData[0] = $product->getDataOnCreateOrder($spec);
  210. if (!$productData) {
  211. $this->error(__('Product not exist'));
  212. }
  213. $productData[0]['image'] = Config::getImagesFullUrl($productData[0]['image']);
  214. $productData[0]['sales_price'] = number_format($productData[0]['sales_price'], 2);
  215. $productData[0]['market_price'] = number_format($productData[0]['market_price'], 2);
  216. /** 默认地址 **/
  217. $address = AddressModel::get(['user_id' => $this->auth->id, 'is_default' => AddressModel::IS_DEFAULT_YES]);
  218. if ($address) {
  219. $area = (new Area)->whereIn('id', [$address->province_id, $address->city_id, $address->area_id])->column('name', 'id');
  220. $address = $address->toArray();
  221. $address['province']['name'] = $area[$address['province_id']];
  222. $address['city']['name'] = $area[$address['city_id']];
  223. $address['area']['name'] = $area[$address['area_id']];
  224. }
  225. /** 运费数据 **/
  226. $cityId = $address['city_id'] ? $address['city_id'] : 0;
  227. $delivery = (new DeliveryRuleModel())->getDelivetyByArea($cityId);
  228. $msg = '';
  229. // if ($delivery['status'] == 0) {
  230. // $msg = __('Your receiving address is not within the scope of delivery');
  231. // }
  232. $redis = new Redis();
  233. //$flash['starttime'] = $redis->handler->hGet('flash_sale_' . $flashId . '_' . $productId, 'starttime');
  234. //$flash['endtime'] = $redis->handler->hGet('flash_sale_' . $flashId . '_' . $productId, 'endtime');
  235. $flash['sold'] = $redis->handler->hGet('flash_sale_' . $flashId . '_' . $productId, 'sold');
  236. $flash['number'] = $redis->handler->hGet('flash_sale_' . $flashId . '_' . $productId, 'number');
  237. $flash['sold'] = $flash['sold'] > $flash['number'] ? $flash['number'] : $flash['sold'];
  238. //$flash['text'] = $flash['starttime'] > time() ? '距开始:' : '距结束:';
  239. // 秒杀类型不加载优惠券、促销活动、是否已收藏、评价等等,会影响返回速度
  240. //$targetTime = $flash['starttime'] > time() ? $flash['starttime'] : $flash['endtime'];
  241. //$flash['countdown'] = FlashSale::countdown($targetTime);
  242. $this->success($msg, [
  243. 'product' => $productData,
  244. 'address' => $address,
  245. 'delivery' => $delivery['list'],
  246. 'flash' => $flash
  247. ]);
  248. } catch (Exception $e) {
  249. $this->error($e->getMessage(), false);
  250. }
  251. }
  252. /**
  253. * 提交订单
  254. */
  255. public function submitOrder()
  256. {
  257. $data = $this->request->post();
  258. try {
  259. $validate = Loader::validate('\\addons\\unishop\\validate\\Order');
  260. if (!$validate->check($data, [], 'submitFlash')) {
  261. throw new Exception($validate->getError());
  262. }
  263. Db::startTrans();
  264. // 判断创建订单的条件
  265. if (empty(Hook::get('create_order_before'))) { // 由于自动化测试的时候会注册多个同名行为
  266. Hook::add('create_order_before', 'addons\\unishop\\behavior\\OrderFlash');
  267. }
  268. if (empty(Hook::get('create_order_after'))) {
  269. Hook::add('create_order_after', 'addons\\unishop\\behavior\\OrderFlash');
  270. }
  271. $data['flash_id'] = Hashids::decodeHex($data['flash_id']);
  272. $data['product_id'] = Hashids::decodeHex($data['product_id']);
  273. $orderModel = new \addons\unishop\model\Order();
  274. $result = $orderModel->createOrder($this->auth->id, $data);
  275. Db::commit();
  276. $this->success('', $result);
  277. } catch (Exception $e) {
  278. Db::rollback();
  279. $this->error($e->getMessage(), false);
  280. }
  281. }
  282. }