Statistics.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. <?php
  2. namespace app\admin\controller\cms;
  3. use addons\cms\model\SearchLog;
  4. use app\admin\model\User;
  5. use app\common\controller\Backend;
  6. /**
  7. * 统计控制台管理
  8. *
  9. * @icon fa fa-bar-chart
  10. */
  11. class Statistics extends Backend
  12. {
  13. /**
  14. * Archives模型对象
  15. */
  16. protected $model = null;
  17. protected $noNeedRight = [];
  18. protected $isSuperAdmin = false;
  19. protected $searchFields = 'id,title';
  20. /**
  21. * 查看
  22. */
  23. public function index()
  24. {
  25. try {
  26. \think\Db::execute("SET @@sql_mode='';");
  27. } catch (\Exception $e) {
  28. }
  29. $config = get_addon_config('cms');
  30. if ($this->request->isPost()) {
  31. $date = $this->request->post('date', '');
  32. $type = $this->request->post('type', '');
  33. if ($type == 'sale') {
  34. list($orderSaleCategory, $orderSaleAmount, $orderSaleNums) = $this->getSaleStatisticsData($date);
  35. $statistics = ['orderSaleCategory' => $orderSaleCategory, 'orderSaleAmount' => $orderSaleAmount, 'orderSaleNums' => $orderSaleNums];
  36. } elseif ($type == 'percent') {
  37. list($orderPercentCategory, $orderPercentAmount, $orderPercentNums) = $this->getPercentStatisticsData($date);
  38. $statistics = ['orderPercentCategory' => $orderPercentCategory, 'orderPercentAmount' => $orderPercentAmount, 'orderPercentNums' => $orderPercentNums];
  39. } elseif ($type == 'order') {
  40. list($category, $data) = $this->getOrderStatisticsData($date);
  41. $statistics = ['category' => $category, 'data' => $data];
  42. } elseif ($type == 'archives') {
  43. list($category, $data) = $this->getArchivesStatisticsData($date);
  44. $statistics = ['category' => $category, 'data' => $data];
  45. }
  46. $this->success('', '', $statistics);
  47. }
  48. //管理员发文统计图表
  49. list($category, $data) = $this->getArchivesStatisticsData('');
  50. $this->assignconfig('adminArchivesListCategory', $category);
  51. $this->assignconfig('adminArchivesListData', $data);
  52. //今日订单和会员
  53. $totalOrderAmount = round(\app\admin\model\cms\Order::where('status', 'paid')->sum('payamount'), 2);
  54. $yesterdayOrderAmount = round(\app\admin\model\cms\Order::where('status', 'paid')->whereTime('paytime', 'yesterday')->sum('payamount'), 2);
  55. $todayOrderAmount = round(\app\admin\model\cms\Order::where('status', 'paid')->whereTime('paytime', 'today')->sum('payamount'), 2);
  56. $todayOrderRatio = $yesterdayOrderAmount > 0 ? ceil((($todayOrderAmount - $yesterdayOrderAmount) / $yesterdayOrderAmount) * 100) : ($todayOrderAmount > 0 ? 100 : 0);
  57. $totalUser = User::count();
  58. $yesterdayUser = User::whereTime('jointime', 'yesterday')->count();
  59. $todayUser = User::whereTime('jointime', 'today')->count();
  60. $todayUserRatio = $yesterdayUser > 0 ? ceil((($todayUser - $yesterdayUser) / $yesterdayUser) * 100) : ($todayUser > 0 ? 100 : 0);
  61. //文档和评论统计
  62. $totalArchives = \app\admin\model\cms\Archives::count();
  63. $unsettleArchives = \app\admin\model\cms\Archives::where('status', 'hidden')->count();
  64. $totalComment = \app\admin\model\cms\Comment::count();
  65. $unsettleComment = \app\admin\model\cms\Comment::where('status', 'hidden')->count();
  66. $diyformList = \app\admin\model\cms\Diyform::all();
  67. foreach ($diyformList as $index => $item) {
  68. $item->nums = \think\Db::name($item['table'])->count();
  69. }
  70. //订单数和订单额统计
  71. list($orderSaleCategory, $orderSaleAmount, $orderSaleNums) = $this->getSaleStatisticsData();
  72. $this->assignconfig('orderSaleCategory', $orderSaleCategory);
  73. $this->assignconfig('orderSaleAmount', $orderSaleAmount);
  74. $this->assignconfig('orderSaleNums', $orderSaleNums);
  75. //订单占比统计
  76. list($orderPercentCategory, $orderPercentAmount, $orderPercentNums) = $this->getPercentStatisticsData();
  77. $this->assignconfig('orderPercentCategory', $orderPercentCategory);
  78. $this->assignconfig('orderPercentAmount', $orderPercentAmount);
  79. $this->assignconfig('orderPercentNums', $orderPercentNums);
  80. //热门标签
  81. $tagList = \app\admin\model\cms\Tag::order('nums', 'desc')->limit(10)->select();
  82. $tagsTotal = 0;
  83. foreach ($tagList as $index => $item) {
  84. $tagsTotal += $item['nums'];
  85. }
  86. foreach ($tagList as $index => $item) {
  87. $item['percent'] = $tagsTotal > 0 ? round($item['nums'] / $tagsTotal * 100, 2) : 0;
  88. }
  89. //热门搜索列表
  90. $hotSearchList = SearchLog::order('nums', 'desc')->cache(3600)->limit(10)->select();
  91. $hotTagList = \addons\cms\model\Tag::order('nums', 'desc')->cache(3600)->limit(10)->select();
  92. $hotArchivesList = \addons\cms\model\Archives::order('views', 'desc')->cache(3600)->limit(10)->select();
  93. //付费排行榜
  94. $todayPaidTotal = \app\admin\model\cms\Order::whereTime('paytime', 'today')->sum("payamount");
  95. $todayPaidList = \app\admin\model\cms\Order::with(['archives'])->whereTime('paytime', 'today')->group('archives_id')->field("COUNT(*) as nums,SUM(payamount) as amount,archives_id")->order("amount", "desc")->limit(10)->select();
  96. foreach ($todayPaidList as $index => $item) {
  97. $item->percent = $todayPaidTotal > 0 ? round(($item['amount'] / $todayPaidTotal) * 100, 2) : 0;
  98. }
  99. $weekPaidTotal = \app\admin\model\cms\Order::whereTime('paytime', 'week')->sum("payamount");
  100. $weekPaidList = \app\admin\model\cms\Order::with(['archives'])->whereTime('paytime', 'week')->group('archives_id')->field("COUNT(*) as nums,SUM(payamount) as amount,archives_id")->order("amount", "desc")->limit(10)->select();
  101. foreach ($weekPaidList as $index => $item) {
  102. $item->percent = $weekPaidTotal > 0 ? round(($item['amount'] / $weekPaidTotal) * 100, 2) : 0;
  103. }
  104. $monthPaidTotal = \app\admin\model\cms\Order::whereTime('paytime', 'month')->sum("payamount");
  105. $monthPaidList = \app\admin\model\cms\Order::with(['archives'])->whereTime('paytime', 'month')->group('archives_id')->field("COUNT(*) as nums,SUM(payamount) as amount,archives_id")->order("amount", "desc")->limit(10)->select();
  106. foreach ($monthPaidList as $index => $item) {
  107. $item->percent = $monthPaidTotal > 0 ? round(($item['amount'] / $monthPaidTotal) * 100, 2) : 0;
  108. }
  109. //投稿排行榜
  110. $todayContributeTotal = \app\admin\model\cms\Archives::whereTime('createtime', 'today')->count();
  111. $todayContributeList = \app\admin\model\cms\Archives::with(['user'])->where('user_id', '>', 0)->whereTime('createtime', 'today')->group('user_id')->field("COUNT(*) as nums,user_id")->order("nums", "desc")->limit(10)->select();
  112. foreach ($todayContributeList as $index => $item) {
  113. $item->percent = $todayContributeTotal > 0 ? round(($item['nums'] / $todayContributeTotal) * 100, 2) : 0;
  114. }
  115. $weekContributeTotal = \app\admin\model\cms\Archives::whereTime('createtime', 'week')->count();
  116. $weekContributeList = \app\admin\model\cms\Archives::with(['user'])->where('user_id', '>', 0)->whereTime('createtime', 'week')->group('user_id')->field("COUNT(*) as nums,user_id")->order("nums", "desc")->limit(10)->select();
  117. foreach ($weekContributeList as $index => $item) {
  118. $item->percent = $weekContributeTotal > 0 ? round(($item['nums'] / $weekContributeTotal) * 100, 2) : 0;
  119. }
  120. $monthContributeTotal = \app\admin\model\cms\Archives::whereTime('createtime', 'month')->count();
  121. $monthContributeList = \app\admin\model\cms\Archives::with(['user'])->where('user_id', '>', 0)->whereTime('createtime', 'month')->group('user_id')->field("COUNT(*) as nums,user_id")->order("nums", "desc")->limit(10)->select();
  122. foreach ($monthContributeList as $index => $item) {
  123. $item->percent = $monthContributeTotal > 0 ? round(($item['nums'] / $monthContributeTotal) * 100, 2) : 0;
  124. }
  125. $this->view->assign("totalOrderAmount", $totalOrderAmount);
  126. $this->view->assign("yesterdayOrderAmount", $yesterdayOrderAmount);
  127. $this->view->assign("todayOrderAmount", $todayOrderAmount);
  128. $this->view->assign("todayOrderRatio", $todayOrderRatio);
  129. $this->view->assign("totalUser", $totalUser);
  130. $this->view->assign("yesterdayUser", $yesterdayUser);
  131. $this->view->assign("todayUser", $todayUser);
  132. $this->view->assign("todayUserRatio", $todayUserRatio);
  133. $this->view->assign("totalArchives", $totalArchives);
  134. $this->view->assign("unsettleArchives", $unsettleArchives);
  135. $this->view->assign("totalComment", $totalComment);
  136. $this->view->assign("unsettleComment", $unsettleComment);
  137. $this->view->assign("tagsList", $tagList);
  138. $this->view->assign("hotTagList", $hotTagList);
  139. $this->view->assign("hotArchivesList", $hotArchivesList);
  140. $this->view->assign("hotSearchList", $hotSearchList);
  141. $this->view->assign("todayPaidList", $todayPaidList);
  142. $this->view->assign("weekPaidList", $weekPaidList);
  143. $this->view->assign("monthPaidList", $monthPaidList);
  144. $this->view->assign("todayContributeList", $todayContributeList);
  145. $this->view->assign("weekContributeList", $weekContributeList);
  146. $this->view->assign("monthContributeList", $monthContributeList);
  147. $this->view->assign("modelList", \app\admin\model\cms\Modelx::order('id asc')->select());
  148. return $this->view->fetch();
  149. }
  150. /**
  151. * 获取订单销量销售额统计数据
  152. * @param string $date
  153. * @return array
  154. */
  155. protected function getSaleStatisticsData($date = '')
  156. {
  157. $starttime = \fast\Date::unixtime();
  158. $endtime = \fast\Date::unixtime('day', 0, 'end');
  159. $format = '%H:00';
  160. $orderList = \app\admin\model\cms\Order::where('paytime', 'between time', [$starttime, $endtime])
  161. ->field('paytime, status, COUNT(*) AS nums, SUM(payamount) AS amount, MIN(paytime) AS min_paytime, MAX(paytime) AS max_paytime,
  162. DATE_FORMAT(FROM_UNIXTIME(paytime), "' . $format . '") AS paydate')
  163. ->group('paydate')
  164. ->select();
  165. $column = [];
  166. for ($time = $starttime; $time <= $endtime;) {
  167. $column[] = date("H:00", $time);
  168. $time += 3600;
  169. }
  170. $orderSaleNums = $orderSaleAmount = array_fill_keys($column, 0);
  171. foreach ($orderList as $k => $v) {
  172. $orderSaleNums[$v['paydate']] = $v['nums'];
  173. $orderSaleAmount[$v['paydate']] = round($v['amount'], 2);
  174. }
  175. $orderSaleCategory = array_keys($orderSaleAmount);
  176. $orderSaleAmount = array_values($orderSaleAmount);
  177. $orderSaleNums = array_values($orderSaleNums);
  178. return [$orderSaleCategory, $orderSaleAmount, $orderSaleNums];
  179. }
  180. /**
  181. * 获取订单占比统计数据
  182. * @param string $date
  183. * @return array
  184. */
  185. protected function getPercentStatisticsData($date = '')
  186. {
  187. $starttime = \fast\Date::unixtime();
  188. $endtime = \fast\Date::unixtime('day', 0, 'end');
  189. $modelList = [];
  190. $orderPercentCategory = $orderPercentAmount = $orderPercentNums = [];
  191. $list = \app\admin\model\cms\Order::with('archives')
  192. ->where('order.createtime', 'between time', [$starttime, $endtime])
  193. ->where('order.status', 'paid')
  194. ->field("archives.model_id,SUM(payamount) as amount,COUNT(*) as nums")
  195. ->group('archives.model_id')
  196. ->select();
  197. foreach ($list as $index => $item) {
  198. $modelList[$item['archives']['model']['name']] = $item['amount'];
  199. $name = $item['archives']['model']['name'];
  200. $name = $name ? $name : "其它";
  201. $orderPercentCategory[] = $name;
  202. $orderPercentAmount[] = ['value' => round($item['amount'], 2), 'name' => $name];
  203. $orderPercentNums[] = ['value' => $item['nums'], 'name' => $name];
  204. }
  205. if (!$orderPercentCategory) {
  206. $orderPercentCategory = [""];
  207. $orderPercentNums = [['value' => 0, 'name' => '订单数']];
  208. $orderPercentAmount = [['value' => 0, 'name' => '订单额']];
  209. }
  210. return [$orderPercentCategory, $orderPercentAmount, $orderPercentNums];
  211. }
  212. /**
  213. * 获取订单统计数据
  214. * @param string $date
  215. * @return array
  216. */
  217. protected function getOrderStatisticsData($date = '')
  218. {
  219. if ($date) {
  220. list($start, $end) = explode(' - ', $date);
  221. $starttime = strtotime($start);
  222. $endtime = strtotime($end);
  223. } else {
  224. $starttime = \fast\Date::unixtime('day', 0, 'begin');
  225. $endtime = \fast\Date::unixtime('day', 0, 'end');
  226. }
  227. $totalseconds = $endtime - $starttime;
  228. $format = '%Y-%m-%d';
  229. if ($totalseconds > 86400 * 30 * 2) {
  230. $format = '%Y-%m';
  231. } else {
  232. if ($totalseconds > 86400) {
  233. $format = '%Y-%m-%d';
  234. } else {
  235. $format = '%H:00';
  236. }
  237. }
  238. $model_id = $this->request->post("model_id");
  239. $orderList = \app\admin\model\cms\Order::where('paytime', 'between time', [$starttime, $endtime])
  240. ->where(function ($query) use ($model_id, $starttime, $endtime) {
  241. if ($model_id) {
  242. //如果指定模型
  243. $query->where('archives_id', 'in', function ($query) use ($model_id, $starttime, $endtime) {
  244. $query->name("cms_archives")->where('model_id', $model_id)->where('id', 'in', function ($query) use ($starttime, $endtime) {
  245. $query->name('cms_order')->where('paytime', 'between time', [$starttime, $endtime])->field('archives_id');
  246. })->field('id');
  247. });
  248. }
  249. })
  250. ->field('paytime, status, SUM(payamount) AS amount, MIN(paytime) AS min_paytime, MAX(paytime) AS max_paytime,
  251. DATE_FORMAT(FROM_UNIXTIME(createtime), "' . $format . '") AS pay_date')
  252. ->group('pay_date')
  253. ->select();
  254. if ($totalseconds > 84600 * 30 * 2) {
  255. $starttime = strtotime('last month', $starttime);
  256. while (($starttime = strtotime('next month', $starttime)) <= $endtime) {
  257. $column[] = date('Y-m', $starttime);
  258. }
  259. } else {
  260. if ($totalseconds > 86400) {
  261. for ($time = $starttime; $time <= $endtime;) {
  262. $column[] = date("Y-m-d", $time);
  263. $time += 86400;
  264. }
  265. } else {
  266. for ($time = $starttime; $time <= $endtime;) {
  267. $column[] = date("H:00", $time);
  268. $time += 3600;
  269. }
  270. }
  271. }
  272. $list = array_fill_keys($column, 0);
  273. foreach ($orderList as $k => $v) {
  274. $list[$v['pay_date']] = round($v['amount'], 2);
  275. }
  276. $category = array_keys($list);
  277. $data = array_values($list);
  278. return [$category, $data];
  279. }
  280. /**
  281. * 获取发文统计数据
  282. * @param string $date
  283. * @return array
  284. */
  285. protected function getArchivesStatisticsData($date = '')
  286. {
  287. if ($date) {
  288. list($start, $end) = explode(' - ', $date);
  289. $starttime = strtotime($start);
  290. $endtime = strtotime($end);
  291. } else {
  292. $starttime = \fast\Date::unixtime('day', 0, 'begin');
  293. $endtime = \fast\Date::unixtime('day', 0, 'end');
  294. }
  295. $totalseconds = $endtime - $starttime;
  296. $format = '%Y-%m-%d';
  297. if ($totalseconds > 86400 * 30 * 2) {
  298. $format = '%Y-%m';
  299. } else {
  300. if ($totalseconds > 86400) {
  301. $format = '%Y-%m-%d';
  302. } else {
  303. $format = '%H:00';
  304. }
  305. }
  306. $model_id = $this->request->post("model_id", "");
  307. $archivesList = \app\admin\model\cms\Archives::with(["admin"])
  308. ->where('createtime', 'between time', [$starttime, $endtime])
  309. ->where(function ($query) use ($model_id) {
  310. if ($model_id) {
  311. $query->where('model_id', $model_id);
  312. }
  313. })
  314. ->field('admin_id, createtime, status, COUNT(*) AS nums, MIN(createtime) AS min_createtime, MAX(createtime) AS max_createtime,
  315. DATE_FORMAT(FROM_UNIXTIME(createtime), "' . $format . '") AS create_date')
  316. ->group('admin_id,create_date')
  317. ->select();
  318. if ($totalseconds > 84600 * 30 * 2) {
  319. $starttime = strtotime('last month', $starttime);
  320. while (($starttime = strtotime('next month', $starttime)) <= $endtime) {
  321. $column[] = date('Y-m', $starttime);
  322. }
  323. } else {
  324. if ($totalseconds > 86400) {
  325. for ($time = $starttime; $time <= $endtime;) {
  326. $column[] = date("Y-m-d", $time);
  327. $time += 86400;
  328. }
  329. } else {
  330. for ($time = $starttime; $time <= $endtime;) {
  331. $column[] = date("H:00", $time);
  332. $time += 3600;
  333. }
  334. }
  335. }
  336. $list = [];
  337. $dataList = [];
  338. $columnList = array_fill_keys($column, 0);
  339. foreach ($archivesList as $k => $v) {
  340. $nickname = $v->admin ? $v->admin->nickname : "未知";
  341. if (!isset($list[$nickname])) {
  342. $list[$nickname] = $columnList;
  343. }
  344. $list[$nickname][$v['create_date']] = $v['nums'];
  345. }
  346. foreach ($list as $index => $item) {
  347. $dataList[] = [
  348. 'name' => $index,
  349. 'type' => 'line',
  350. 'smooth' => true,
  351. 'areaStyle' => [],
  352. 'data' => array_values($item)
  353. ];
  354. }
  355. $columnList = array_keys($columnList);
  356. return [$columnList, $dataList];
  357. }
  358. }