DataScreenRepository.php 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2016~2024 https://www.crmeb.com All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
  8. // +----------------------------------------------------------------------
  9. // | Author: CRMEB Team <admin@crmeb.com>
  10. // +----------------------------------------------------------------------
  11. namespace app\common\repositories\system;
  12. use app\common\dao\store\order\StoreOrderDao;
  13. use app\common\model\store\order\StoreGroupOrder;
  14. use app\common\model\store\order\StoreOrder;
  15. use app\common\repositories\BaseRepository;
  16. use app\common\repositories\store\CityAreaRepository;
  17. use app\common\repositories\store\order\StoreGroupOrderRepository;
  18. use app\common\repositories\store\order\StoreOrderProductRepository;
  19. use app\common\repositories\store\order\StoreOrderRepository;
  20. use app\common\repositories\user\UserRepository;
  21. use app\common\repositories\user\UserVisitRepository;
  22. use crmeb\services\SwooleTaskService;
  23. use think\exception\ValidateException;
  24. use think\facade\Cache;
  25. use think\facade\Db;
  26. class DataScreenRepository extends BaseRepository
  27. {
  28. /*
  29. 1. 今日交易商户数:今日发生交易的商户总数
  30. 2. 今日交易商品数:今日发生交易的商品总数
  31. 3. 今日交易新增用户数:今日交易用户中初次交易的用户数
  32. 4. 今日交易新增用户支付额:今日交易用户中初次交易的用户支付总额
  33. 5. 今日新老客户占比:今日新老交易客户数和客户交易金额分别占比(金额和数量可切换)
  34. 6. 商户销售排行top10:今日商户销售金额和销售数量排行前10(销售金额和销售数量可切换)
  35. 7. 今日订单支付金额:今日实时累计订单支付金额
  36. 8. 全国地图:按照平台发出的商品收货地址展示全国各省市商品销售地图热度
  37. 9. 本月销售情况统计:本月每日的销售额柱状图,横坐标为日期,竖坐标为销售额。
  38. 10.订单支付情况:当日订单支付折线图,订单支付数和购买人数
  39. 11. 实时订单:滚动显示实时订单数据:商品名称、订单支付时间、订单金额
  40. 12. 商品销售排行top10:商品名称、销售数量、销售金额(销售金额和销售数量可切换)
  41. */
  42. public $unique;
  43. public $params;
  44. public $date = 'today';
  45. public $time = '';
  46. public $ficit = true;
  47. public function __construct(StoreOrderDao $dao)
  48. {
  49. $this->dao = $dao;
  50. $this->cache_key = env('APP_KEY','merchant').'_data_screen';
  51. $this->time = $this->time ?: date('Y-m-d', time());
  52. }
  53. protected function cache($fn)
  54. {
  55. if (!$this->unique || !$this->params) return $fn();
  56. $cache_key = $this->cache_key .'_' . $this->unique . '_' . $this->params;
  57. $res = Cache::get($cache_key);
  58. if ($res) return json_decode($res, true);
  59. $res = $fn();
  60. Cache::set($cache_key, json_encode($res), 60);
  61. return $res;
  62. }
  63. public function getFuncName()
  64. {
  65. $funcs = [
  66. 'config',
  67. 'today_pay_count_number', // 1,2,3,4
  68. 'today_pay_merchant', // 1. 今日交易商户数:今日发生交易的商户总数
  69. 'today_pay_product', // 2. 今日交易商品数:今日发生交易的商品总数
  70. 'today_pay_user_first', // 3. 今日交易新增用户数:今日交易用户中初次交易的用户数
  71. 'today_pay_first_number', // 4. 今日交易新增用户支付额:今日交易用户中初次交易的用户支付总额
  72. 'today_pay_new_old', // 5. 今日新老客户占比:今日新老交易客户数和客户交易金额分别占比(金额和数量可切换)
  73. 'today_pay_merchant_rank', // 6. 商户销售排行top10:今日商户销售金额和销售数量排行前10(销售金额/销售数量; 当日/本周/本月数据可在后台设置,根据用户设置展示)
  74. 'today_pay_number', // 7. 今日订单支付金额:今日实时累计订单支付金额
  75. 'city_ranking', // 8. 全国地图:按照平台发出的商品收货地址展示全国各省市商品销售地图热度
  76. 'month_pay_count', // 9. 本月销售情况统计:本月每日的销售额柱状图,横坐标为日期,竖坐标为销售额
  77. 'today_pay_count', // 10.订单支付情况:当日订单支付折线图,订单支付数和购买人数,横坐标为当日时间每隔2小时,竖坐标为订单支付数和购买人数
  78. 'today_pay_info', // 11. 实时订单:滚动显示当日实时订单数据:商品名称、订单支付时间、订单金额
  79. 'pay_product_rank', // 12. 商品销售排行top10:商品名称、销售数量、销售金额(销售金额/销售数量; 当日/本周/本月数据可在后台设置,根据用户设置展示)
  80. ];
  81. return $funcs;
  82. }
  83. public function clearCache($func = '', $params = ['pid' => 0])
  84. {
  85. $cachekey = $this->cache_key. $func . '_'.json_encode($params);
  86. Cache::delete($cachekey);
  87. foreach ($this->getFuncName() as $func) {
  88. $cachekey = $this->cache_key. $func . '_'.json_encode($params);
  89. Cache::delete($cachekey);
  90. }
  91. }
  92. public function dataScreen($func = '', $params = [])
  93. {
  94. $funcs = $this->getFuncName();
  95. $this->unique = ($func == 'today_pay_count_number') ? '' : $func;
  96. $func = ($func != 'all') ? $func : '';
  97. if ($func && !in_array($func,$funcs)) throw new ValidateException('方法不存在');
  98. $this->params = json_encode($params);
  99. if ($func) {
  100. $data[$func] = $this->{$func}($params);
  101. } else {
  102. foreach ($funcs as $func) {
  103. $data[$func] = $this->{$func}();
  104. }
  105. }
  106. return $data;
  107. }
  108. public function config()
  109. {
  110. $config = systemConfig(['sys_pay_product_rank','sys_pay_product_rank_type','sys_pay_merchant_rank','sys_pay_merchant_rank_type','data_screen_title']);
  111. return $config;
  112. }
  113. /**
  114. * 获取四个数据
  115. * 浏览量、访客数、今日订单数、新增用户数
  116. * @param $params
  117. * @return array
  118. * @author Qinii
  119. * @day 2023/12/11
  120. */
  121. public function today_pay_count_number($params = [])
  122. {
  123. // visitNum 浏览量
  124. $userVisitRepository = app()->make(UserVisitRepository::class);
  125. $date = $this->date;
  126. $today_pay_count_number['visit_num'] = (int)$userVisitRepository->dateVisitNum($date);
  127. $today_pay_count_number['visit_user_num'] = (int)$userVisitRepository->dateVisitUserNum($date);
  128. // $today_pay_count_number['today_pay_merchant']= $this->today_pay_merchant();
  129. // $today_pay_count_number['today_pay_product'] = $this->today_pay_product();
  130. $today_pay_count_number['today_pay_user_first'] = (int)app()->make(UserRepository::class)->newUserNum($date);
  131. $today_pay_count_number['today_pay_number'] = (int)$this->today_pay_number()['count'];
  132. return $today_pay_count_number;
  133. }
  134. /**
  135. * 1. 今日交易商户数:今日发生交易的商户总数
  136. * @author Qinii
  137. * @day 2023/11/25
  138. */
  139. public function today_pay_merchant($params = [])
  140. {
  141. return $this->cache(function() use($params) {
  142. $storeOrderRepository = app()->make(StoreOrderRepository::class);
  143. $query = $storeOrderRepository->getSearch([]);
  144. $today_pay_merchant = $query->whereDay('create_time', $this->time)->where('paid',1)->group('mer_id')
  145. ->count();
  146. return $today_pay_merchant;
  147. });
  148. }
  149. /**
  150. * 2. 今日交易商品数:今日发生交易的商品总数
  151. * @return array
  152. * @author Qinii
  153. * @day 2023/11/25
  154. */
  155. public function today_pay_product($params = [])
  156. {
  157. return $this->cache(function() use($params) {
  158. $query = StoreOrder::alias('O')->join('StoreOrderProduct OP','O.order_id = OP.order_id');
  159. $today_pay_product = $query->whereDay('O.create_time', $this->time)
  160. ->where('paid',1)
  161. ->group('OP.product_id')
  162. ->count();
  163. return $today_pay_product;
  164. });
  165. }
  166. /**
  167. * 3. 今日交易新增用户数:今日交易用户中初次交易的用户数
  168. * @author Qinii
  169. * @day 2023/11/27
  170. */
  171. public function today_pay_user_first($params = [])
  172. {
  173. return $this->cache(function() use($params) {
  174. $storeGroupOrderRepository = app()->make(StoreGroupOrderRepository::class);
  175. $today_pay_user_first = $storeGroupOrderRepository->search(['paid' => 1])
  176. ->whereDay('create_time', $this->time)
  177. ->where('is_first',1)
  178. ->count();
  179. return $today_pay_user_first;
  180. });
  181. }
  182. /**
  183. * 4. 今日交易新增用户支付额:今日交易用户中初次交易的用户支付总额
  184. * @author Qinii
  185. * @day 2023/11/27
  186. */
  187. public function today_pay_first_number($params = [])
  188. {
  189. return $this->cache(function() use($params) {
  190. $storeGroupOrderRepository = app()->make(StoreGroupOrderRepository::class);
  191. $query = $storeGroupOrderRepository->search(['paid' => 1])
  192. ->whereDay('create_time', $this->time)
  193. ->where('is_first',1);
  194. $pay_price = $query->sum('pay_price');
  195. $pay_postage = $query->sum('pay_postage');
  196. $today_pay_first_number = (int)bcadd($pay_price,$pay_postage,2);
  197. return $today_pay_first_number;
  198. });
  199. }
  200. /**
  201. * 5. 今日新老客户占比:今日新老交易客户数和客户交易金额分别占比(金额和数量可切换)
  202. * @author Qinii
  203. * @day 2023/11/27
  204. */
  205. public function today_pay_new_old($params = [])
  206. {
  207. return $this->cache(function() use($params) {
  208. $newQuery = StoreGroupOrder::alias('g')
  209. ->join('user u','u.uid = g.uid')
  210. ->where('paid',1)
  211. ->whereDay('g.create_time', $this->time)
  212. ->whereDay('u.create_time', $this->time)
  213. // ->field("sum(g.pay_price + g.pay_postage) as number,g.uid")
  214. ->group('g.uid');
  215. $new_count = $newQuery->count();
  216. // if ($new_count) {
  217. // $newList = $newQuery->select()->toArray();
  218. // $_number = array_column($newList,'number');
  219. // $new_number = array_reduce($_number, function($sum, $value) {
  220. // return bcadd($sum,$value,2);
  221. // });
  222. // }
  223. $oldQuery = StoreGroupOrder::alias('g')
  224. ->join('user u','u.uid = g.uid')
  225. ->where('paid',1)
  226. ->whereDay('g.create_time', $this->time)
  227. ->whereTime('u.create_time','<',date('Y-m-d'))
  228. // ->field("sum(g.pay_price + g.pay_postage) as number,g.uid")
  229. ->group('g.uid');
  230. $old_count = $oldQuery->count();
  231. // if ($old_count) {
  232. // $oldList = $oldQuery->select()->toArray();
  233. // $_number = array_column($oldList,'number');
  234. // $old_number = array_reduce($_number, function($sum, $value) {
  235. // return bcadd($sum,$value,2);
  236. // });
  237. // }
  238. // $count = $new_count + $old_count;
  239. // $number = bcadd($new_number,$old_number,2);
  240. $today_pay_new_old = [
  241. // 'new_number' => $new_number,
  242. 'new_count' => $new_count,
  243. // 'new_rate_count' => $new_count > 0 ? (int)bcdiv($new_count,$count,2) * 100 : 0,
  244. // 'new_rate_number'=> $new_number > 0 ? (int)bcdiv($new_number,$number,2) * 100 : 0,
  245. // 'old_number' => $old_number,
  246. 'old_count' => $old_count,
  247. // 'old_rate_count'=> $old_count > 0 ? (int)bcdiv($old_count,$count,2) * 100 : 0,
  248. // 'old_rate_number'=> $new_number > 0 ? (int)bcdiv($old_number,$number,2) * 100 : 0,
  249. ];
  250. return $today_pay_new_old;
  251. });
  252. }
  253. /**
  254. * 6. 商户销售排行top10:今日商户销售金额和销售数量排行前10(销售金额和销售数量可切换)
  255. * @author Qinii
  256. * @day 2023/11/27
  257. */
  258. public function today_pay_merchant_rank($params = [])
  259. {
  260. return $this->cache(function() use($params) {
  261. $date = systemConfig('sys_pay_merchant_rank') ?($this->ficit ? $this->date : systemConfig('sys_pay_merchant_rank')): $this->date;
  262. if (systemConfig('sys_pay_merchant_rank_type')) {
  263. $today_pay_merchant_rank['type'] = '个';
  264. $_field = 'sum(total_num) as value';
  265. } else {
  266. $today_pay_merchant_rank['type']= '元';
  267. $_field = 'sum(pay_price + pay_postage) as value';
  268. }
  269. $storeOrderRepository = app()->make(StoreOrderRepository::class);
  270. $query = $storeOrderRepository->search(['paid' => 1])
  271. ->when($date, function($query) use($date) {
  272. getModelTime($query, $date,'StoreOrder.create_time');
  273. });
  274. $query->whereDay('StoreOrder.create_time', $this->date)
  275. ->setOption('field',[])
  276. ->field("$_field,StoreOrder.mer_id,Merchant.mer_name name,Merchant.mer_id")
  277. ->group('StoreOrder.mer_id');
  278. $list = $query->order("value DESC")->limit(20)->select();
  279. foreach ($list as &$item) {
  280. $item['value'] = (int)$item['value'];
  281. }
  282. $today_pay_merchant_rank['data'] = $list;
  283. return $today_pay_merchant_rank;
  284. });
  285. }
  286. /**
  287. * 7. 今日订单支付金额:今日实时累计订单支付金额
  288. * @author Qinii
  289. * @day 2023/11/27
  290. */
  291. public function today_pay_number($params = [])
  292. {
  293. return $this->cache(function() use($params) {
  294. $storeOrderRepository = app()->make(StoreOrderRepository::class);
  295. $query = $storeOrderRepository->getSearch([])
  296. ->whereDay('create_time', $this->time)
  297. ->where('paid', 1);
  298. $list = $query->field("sum(pay_price) as number,count(*) as count,paid,order_id")
  299. ->select()->toArray();
  300. $today_pay_number = $list[0] ?? ['number' => '0.00', 'count' => '0'];
  301. return $today_pay_number;
  302. });
  303. }
  304. /**
  305. * 8. 全国地图:按照平台发出的商品收货地址展示全国各省市商品销售地图热度
  306. * @author Qinii
  307. * @day 2023/11/28
  308. */
  309. public function city_ranking($params = [])
  310. {
  311. return $this->cache(function() use($params){
  312. $pid = $params['pid'] ?? 0;
  313. $address = app()->make(CityAreaRepository::class)->getSearch([])->where('parent_id', $pid)->column('id,name,code');
  314. if (isset($address['0']['name']) && $address['0']['name'] == '市辖区') {
  315. $address = app()->make(CityAreaRepository::class)->getSearch([])->where('parent_id', $address['0']['id'])->column('id,name,code');
  316. }
  317. $city_ranking = [];
  318. $ids = array_column($address, 'id');
  319. $recordRepository = app()->make(RecordRepository::class);
  320. $query = $recordRepository->getSearch(['type' => $recordRepository::TYPE_ADDRESS_RECORD]);
  321. $record = $query->whereIn('link_id', $ids)->column('num', 'link_id');
  322. foreach ($address as $item) {
  323. if (isset($record[$item['id']])) {
  324. $city_ranking[] = [
  325. 'id' => $item['id'],
  326. 'name' => $item['name'],
  327. 'value' => (int)$record[$item['id']],
  328. 'code' => $item['code'],
  329. ];
  330. }
  331. }
  332. return $city_ranking;
  333. });
  334. }
  335. /**
  336. * 9. 本月销售情况统计:本月每日的销售额柱状图,横坐标为日期,竖坐标为销售额。
  337. * @author Qinii
  338. * @day 2023/11/28
  339. */
  340. public function month_pay_count($params = [])
  341. {
  342. return $this->cache(function() use($params) {
  343. $dates = getDatesBetweenTwoDays(getStartModelTime('month'), $this->time, 'd');
  344. $storeGroupOrderRepository = app()->make(StoreGroupOrderRepository::class);
  345. $field = Db::raw('from_unixtime(unix_timestamp(create_time),\'%d\') as day,sum(pay_price) as total_sum');
  346. $query = $storeGroupOrderRepository->search(['paid' => 1])->whereMonth('create_time');
  347. $month = $query->field($field)->group('day')->select()->toArray();
  348. $month = array_combine(array_column($month, 'day'), array_column($month, 'total_sum'));
  349. $month_pay_count = [];
  350. foreach ($dates as $date) {
  351. $total_sum = $month[$date] ?? 0;
  352. if ($date !== date('d') && $this->ficit && !$total_sum) {
  353. $key = 'dataScreen_month_pay_count_' .$date;
  354. $total_sum = Cache::get($key);
  355. if (!$total_sum) {
  356. $total_sum = bcadd(rand(100,9999), 1,2);
  357. Cache::set($key,$total_sum, 3600);
  358. }
  359. }
  360. $month_pay_count[] = [
  361. 'day' => (string)$date,
  362. 'total_sum' => $total_sum,
  363. ];
  364. }
  365. return $month_pay_count;
  366. });
  367. }
  368. /**
  369. * 10.订单支付情况:当日订单支付折线图,订单支付数和购买人数
  370. * @author Qinii
  371. * @day 2023/11/28
  372. */
  373. public function today_pay_count($params = [])
  374. {
  375. return $this->cache(function() use($params) {
  376. $h = date('H');
  377. $j = ($h <= 12) ? 0 : 1;
  378. $i = '0';
  379. do {
  380. $dates[] = (string)($i < 10 ? '0' . $i : $i);
  381. $i++;
  382. $i = $i + $j;
  383. } while ($h >= $i);
  384. $storeOrderRepository = app()->make(StoreOrderRepository::class);
  385. $field = Db::raw('from_unixtime(unix_timestamp(create_time),\'%H\') as hours,count(order_id) order_count,count(distinct uid) as user_count');
  386. $query = $storeOrderRepository->getSearch([])->where('paid',1)->whereDay('create_time');
  387. $orderList = $query->field($field)->order('hours ASC')->group('hours')->select()->toArray();
  388. $orderList = array_combine(array_column($orderList, 'hours'), $orderList);
  389. $today_pay_count = [];
  390. foreach ($dates as $date) {
  391. if ($j) {
  392. $_k = $date + $j;
  393. $k = (string)($_k < 10 ? '0' . $_k : $_k);
  394. $arr = [
  395. 'hours' => (string)$date.'~'.$k,
  396. 'user_count' => $orderList[$date]['user_count'] ?? 0,
  397. 'order_count' => $orderList[$date]['order_count'] ?? 0,
  398. ];
  399. if (isset($orderList[$k])) {
  400. $arr['user_count'] = $arr['user_count'] + $orderList[$k]['user_count'];
  401. $arr['order_count'] = $arr['order_count'] + $orderList[$k]['order_count'];
  402. }
  403. } else {
  404. $arr = [
  405. 'hours' => (string)$date,
  406. 'user_count' => $orderList[$date]['user_count'] ?? 0,
  407. 'order_count' => $orderList[$date]['order_count'] ?? 0,
  408. ];
  409. }
  410. $today_pay_count[] = $arr;
  411. }
  412. return $today_pay_count;
  413. });
  414. }
  415. /**
  416. * 11. 实时订单:滚动显示实时订单数据:商品名称、订单支付时间、订单金额
  417. * @author Qinii
  418. * @day 2023/11/28
  419. */
  420. public function today_pay_info($params = [])
  421. {
  422. return $this->cache(function() use($params) {
  423. $storeOrderProductRepository = app()->make(StoreOrderProductRepository::class);
  424. $today_pay_info = $storeOrderProductRepository->getProductRate(0, $this->date, 'paytime', 10, false);
  425. return $today_pay_info;
  426. });
  427. }
  428. /**
  429. * 12. 今天/近7天 商品销售排行top10:商品名称、销售数量、销售金额(销售金额和销售数量可切换)
  430. * @author Qinii
  431. * @day 2023/11/28
  432. */
  433. public function pay_product_rank($params = [])
  434. {
  435. return $this->cache(function() use($params) {
  436. $date = systemConfig('sys_pay_product_rank') ?($this->ficit ? $this->date : systemConfig('sys_pay_product_rank')): $this->date;
  437. $type =systemConfig('sys_pay_product_rank_type') == 0 ? 'number' : 'count';
  438. $storeOrderProductRepository = app()->make(StoreOrderProductRepository::class);
  439. $pay_product_rank = $storeOrderProductRepository->getProductRate(0, $date, $type, 20);
  440. return $pay_product_rank;
  441. });
  442. }
  443. }