Core.php 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485
  1. <?php
  2. namespace addons\customcharts\library;
  3. use think\Db;
  4. class Core
  5. {
  6. /**
  7. * 数量统计
  8. * \addons\customcharts\library\Core::totalNumber();
  9. * @author Created by Xing <464401240@qq.com>
  10. */
  11. public static function totalNumber()
  12. {
  13. $result = [];
  14. $list = \app\admin\model\customcharts\Totalnumber::order('weigh ASC')->select();
  15. foreach ($list as $row) {
  16. $result[$row->id] = [
  17. 'icon_color' => $row->icon_color,
  18. 'is_money' => $row->is_money,
  19. 'total' => 0,
  20. 'lastTotal' => 0,
  21. 'ratio' => 404, //不等于404页面上才会显示
  22. 'title' => $row->title,
  23. 'icon' => $row->icon
  24. ];
  25. if ($row->type_total == 'sum') {
  26. if ($row->type_time == 'all') {
  27. $result[$row->id]['total'] = round(Db::table($row->name)
  28. ->where($row->where)
  29. ->sum($row->field_total), 2);
  30. } else {
  31. //本期
  32. $result[$row->id]['total'] = round(Db::table($row->name)
  33. ->where($row->where)
  34. ->whereTime($row->field_time, $row->type_time)
  35. ->sum($row->field_total), 2);
  36. //上期
  37. if ($row->type_time == 'today') {
  38. $lastTotal = round(Db::table($row->name)->where($row->where)
  39. ->whereTime($row->field_time, 'yesterday')
  40. ->sum($row->field_total), 2);
  41. } else {
  42. $lastTotal = round(Db::table($row->name)->where($row->where)
  43. ->whereTime($row->field_time, 'last ' . $row->type_time)
  44. ->sum($row->field_total), 2);
  45. }
  46. }
  47. } else {
  48. if ($row->type_time == 'all') {
  49. $result[$row->id]['total'] = round(Db::table($row->name)
  50. ->where($row->where)
  51. ->count($row->field_total), 2);
  52. } else {
  53. //本期
  54. $result[$row->id]['total'] = round(Db::table($row->name)
  55. ->where($row->where)
  56. ->whereTime($row->field_time, $row->type_time)
  57. ->count($row->field_total), 2);
  58. //上期
  59. if ($row->type_time == 'today') {
  60. $lastTotal = round(Db::table($row->name)->where($row->where)
  61. ->whereTime($row->field_time, 'yesterday')
  62. ->count($row->field_total), 2);
  63. } else {
  64. $lastTotal = round(Db::table($row->name)->where($row->where)
  65. ->whereTime($row->field_time, 'last ' . $row->type_time)
  66. ->count($row->field_total), 2);
  67. }
  68. }
  69. }
  70. if (isset($lastTotal)) {
  71. $result[$row->id]['lastTotal'] = $lastTotal;
  72. //同比增长
  73. if ($lastTotal > 0) {
  74. $result[$row->id]['ratio'] = ceil((($result[$row->id]['total'] - $lastTotal) / $lastTotal) * 100);
  75. } else {
  76. $result[$row->id]['ratio'] = ($result[$row->id]['total'] > 0 ? 100 : 0);
  77. }
  78. }
  79. }
  80. return $result;
  81. }
  82. /**
  83. * 图表统计
  84. * \addons\customcharts\library\Core::totalChart();
  85. * @author Created by Xing <464401240@qq.com>
  86. */
  87. public static function totalChart($date = '')
  88. {
  89. try {
  90. \think\Db::execute("SET @@sql_mode='';");
  91. } catch (\Exception $e) {
  92. }
  93. if ($date) {
  94. list($start, $end) = explode(' - ', $date);
  95. $starttime = strtotime($start);
  96. $endtime = strtotime($end);
  97. } else {
  98. $starttime = \fast\Date::unixtime('day', -29, 'begin');
  99. $endtime = \fast\Date::unixtime('day', 0, 'end');
  100. }
  101. $result = [];
  102. $list = \app\admin\model\customcharts\Chart::order('weigh ASC')->select();
  103. foreach ($list as $key => $row) {
  104. if ($row->chart_type == 'pie') {
  105. //饼状统计
  106. $result[$key] = self::totalChartPie($row, $starttime, $endtime);
  107. } else {
  108. //图表统计数据
  109. $result[$key] = self::totalChartGraph($row, $starttime, $endtime);
  110. }
  111. }
  112. return $result;
  113. }
  114. /**
  115. * 排行统计
  116. * \addons\customcharts\library\Core::totalRanking();
  117. * @author Created by Xing <464401240@qq.com>
  118. */
  119. public static function totalRanking()
  120. {
  121. try {
  122. \think\Db::execute("SET @@sql_mode='';");
  123. } catch (\Exception $e) {
  124. }
  125. $result = [];
  126. $list = \app\admin\model\customcharts\Ranking::order('weigh ASC')->select();
  127. foreach ($list as $row) {
  128. $row->show_num = $row->show_num < 1 ? 1 : intval($row->show_num);
  129. if ($row->type_total == 'sum') {
  130. //按和统计
  131. $result[$row->id] = self::totalRankingSum($row);
  132. } else {
  133. //按行统计
  134. $result[$row->id] = self::totalRankingCount($row);
  135. }
  136. }
  137. return $result;
  138. }
  139. /**
  140. * 饼状图统计
  141. * @author Created by Xing <464401240@qq.com>
  142. */
  143. private static function totalChartPie($row, $starttime, $endtime)
  144. {
  145. if ($row->type_total == 'sum') {
  146. //按和统计
  147. if ($row->join_table) {
  148. $data = Db::table($row->name)
  149. ->join($row->join_table, $row->join_table . '.' . $row->local_key . ' = ' . $row->name . '.' . $row->foreign_key)
  150. ->where($row->where)
  151. ->where($row->name . '.' . $row->field_time, 'between time', [$starttime, $endtime])
  152. ->field("{$row->join_table}.{$row->field_show} as field_show,{$row->name}.{$row->group_field},SUM({$row->name}.{$row->field_total}) as nums")
  153. ->group("{$row->name}.{$row->group_field}")
  154. ->select();
  155. } else {
  156. $data = Db::table($row->name)
  157. ->where($row->where)
  158. ->where($row->field_time, 'between time', [$starttime, $endtime])
  159. ->field("{$row->group_field},SUM({$row->field_total}) as nums")
  160. ->group($row->group_field)
  161. ->select();
  162. }
  163. } else {
  164. //按行统计
  165. if ($row->join_table) {
  166. $data = Db::table($row->name)
  167. ->join($row->join_table, $row->join_table . '.' . $row->local_key . ' = ' . $row->name . '.' . $row->foreign_key)
  168. ->where($row->where)
  169. ->where($row->name . '.' . $row->field_time, 'between time', [$starttime, $endtime])
  170. ->field("{$row->join_table}.{$row->field_show} as field_show,{$row->name}.{$row->group_field},COUNT({$row->name}.{$row->field_total}) as nums")
  171. ->group("{$row->name}.{$row->group_field}")
  172. ->select();
  173. } else {
  174. $data = Db::table($row->name)
  175. ->where($row->where)
  176. ->where($row->field_time, 'between time', [$starttime, $endtime])
  177. ->field("{$row->group_field},COUNT({$row->field_total}) as nums")
  178. ->group($row->group_field)
  179. ->select();
  180. }
  181. }
  182. $result = [
  183. 'category' => [],
  184. 'data' => [],
  185. 'id' => $row->id,
  186. 'legend_title' => $row->legend_title,
  187. 'unit' => $row->unit,
  188. 'chart_type' => $row->chart_type,
  189. 'title' => $row->title,
  190. 'subtext' => $row->subtext
  191. ];
  192. foreach ($data as $index => $item) {
  193. if ($row->join_table) {
  194. $name = $item['field_show'];
  195. } else {
  196. $dictionary = json_decode($row->dictionary, true);
  197. $name = $dictionary[$item[$row->group_field]] ?? $row->group_field . '(' . $item[$row->group_field] . ')';
  198. }
  199. $result['category'][] = $name;
  200. $result['data'][] = ['value' => $item['nums'], 'name' => $name];
  201. }
  202. return $result;
  203. }
  204. /**
  205. * 柱状图和曲线图统计
  206. * @author Created by Xing <464401240@qq.com>
  207. */
  208. private static function totalChartGraph($row, $starttime, $endtime)
  209. {
  210. $totalseconds = $endtime - $starttime;
  211. if ($totalseconds > 86400 * 30 * 2) {
  212. $format = '%Y-%m';
  213. } else {
  214. if ($totalseconds > 86400) {
  215. $format = '%Y-%m-%d';
  216. } else {
  217. $format = '%H:00';
  218. }
  219. }
  220. if ($row->type_total == 'sum') {
  221. if ($row->field_time_type == 'int' || $row->field_time_type == 'bigint') {
  222. $sql = $row->name . '.' . $row->group_field . ',SUM(' . $row->name . '.' . $row->field_total . ') AS amount,DATE_FORMAT(FROM_UNIXTIME(' . $row->name . '.' . $row->field_time . '), "' . $format . '") AS field_time';
  223. } else {
  224. $sql = $row->name . '.' . $row->group_field . ',SUM(' . $row->name . '.' . $row->field_total . ') AS amount,DATE_FORMAT(' . $row->name . '.' . $row->field_time . ', "' . $format . '") AS field_time';
  225. }
  226. } else {
  227. if ($row->field_time_type == 'int' || $row->field_time_type == 'bigint') {
  228. $sql = $row->name . '.' . $row->group_field . ',COUNT(' . $row->name . '.' . $row->field_total . ') AS amount,DATE_FORMAT(FROM_UNIXTIME(' . $row->name . '.' . $row->field_time . '), "' . $format . '") AS field_time';
  229. } else {
  230. $sql = $row->name . '.' . $row->group_field . ',COUNT(' . $row->name . '.' . $row->field_total . ') AS amount,DATE_FORMAT(' . $row->name . '.' . $row->field_time . ', "' . $format . '") AS field_time';
  231. }
  232. }
  233. if ($row->join_table) {
  234. $data = Db::table($row->name)
  235. ->join($row->join_table, $row->join_table . '.' . $row->local_key . ' = ' . $row->name . '.' . $row->foreign_key)
  236. ->where($row->where)
  237. ->where($row->name . '.' . $row->field_time, 'between time', [$starttime, $endtime])
  238. ->field("{$row->join_table}.{$row->field_show} as field_show,{$sql}")
  239. ->group("field_time,{$row->name}.{$row->group_field}")
  240. ->select();
  241. } else {
  242. $data = Db::table($row->name)
  243. ->where($row->where)
  244. ->where($row->field_time, 'between time', [$starttime, $endtime])
  245. ->field("{$sql}")
  246. ->group('field_time,' . $row->group_field)
  247. ->select();
  248. }
  249. if ($totalseconds > 84600 * 30 * 2) {
  250. $starttime = strtotime('last month', $starttime);
  251. while (($starttime = strtotime('next month', $starttime)) <= $endtime) {
  252. $column[] = date('Y-m', $starttime);
  253. }
  254. } else {
  255. if ($totalseconds > 86400) {
  256. for ($time = $starttime; $time <= $endtime;) {
  257. $column[] = date("Y-m-d", $time);
  258. $time += 86400;
  259. }
  260. } else {
  261. for ($time = $starttime; $time <= $endtime;) {
  262. $column[] = date("H:00", $time);
  263. $time += 3600;
  264. }
  265. }
  266. }
  267. $datalist = array_fill_keys($column, 0);
  268. $series = [];
  269. $names = [];
  270. foreach ($data as $k => $v) {
  271. if (!isset($series[$v[$row->group_field]])) {
  272. $series[$v[$row->group_field]] = $datalist;
  273. }
  274. $series[$v[$row->group_field]][$v['field_time']] = round($v['amount'], 2);
  275. if ($row->join_table) {
  276. $name = $v['field_show'];
  277. } else {
  278. $dictionary = json_decode($row->dictionary, true);
  279. $name = $dictionary[$v[$row->group_field]] ?? $row->group_field . '(' . $v[$row->group_field] . ')';
  280. }
  281. $names[$v[$row->group_field]] = $name;
  282. }
  283. foreach ($datalist as $tim => $v) {
  284. foreach ($series as &$item) {
  285. if (!isset($item[$tim])) {
  286. $item[$tim] = 0;
  287. }
  288. }
  289. unset($item);
  290. }
  291. //初始化结果数组
  292. $result = [
  293. 'category' => [],
  294. 'data' => [],
  295. 'id' => $row->id,
  296. 'legend_title' => [],
  297. 'unit' => $row->unit,
  298. 'chart_type' => $row->chart_type,
  299. 'title' => $row->title,
  300. 'subtext' => $row->subtext
  301. ];
  302. foreach ($series as $id => $item) {
  303. $name = $names[$id] ?? $row->group_field . '(' . $id . ')';
  304. $result['legend_title'][] = $name;
  305. $result['series'][] = [
  306. 'name' => $name,
  307. 'type' => $row->chart_type == 'graph' ? 'line' : 'bar',
  308. 'data' => array_values($item),
  309. 'markPoint' => [
  310. 'data' => [
  311. ['type' => 'max', 'name' => '最大值'],
  312. ['type' => 'min', 'name' => '最小值']
  313. ]
  314. ],
  315. 'markLine' => [
  316. 'data' => [
  317. ['type' => 'average', 'name' => '平均值']
  318. ]
  319. ]
  320. ];
  321. }
  322. $unit = '{b}';
  323. foreach ($result['legend_title'] as $lt_key => $lt) {
  324. $unit .= '<br>{a' . $lt_key . '} : ' . $lt . ' {c' . $lt_key . '} ' . $row->unit;
  325. }
  326. $result['unit'] = $unit;
  327. $result['category'] = array_keys($datalist);
  328. return $result;
  329. }
  330. /**
  331. * @notes 排行统计-和
  332. * @return array
  333. * @author 兴
  334. * @date 2022/9/19 14:17
  335. */
  336. private static function totalRankingSum($row)
  337. {
  338. if ($row->join_table) {
  339. //有关联
  340. $total = Db::table($row->name)
  341. ->join($row->join_table, $row->join_table . '.' . $row->local_key . ' = ' . $row->name . '.' . $row->foreign_key)
  342. ->where($row->where)
  343. ->whereTime("{$row->name}.{$row->field_time}", $row->type_time)
  344. ->sum("{$row->name}.{$row->field_total}");
  345. $data = Db::table($row->name)
  346. ->join($row->join_table, $row->join_table . '.' . $row->local_key . ' = ' . $row->name . '.' . $row->foreign_key)
  347. ->where($row->where)
  348. ->whereTime("{$row->name}.{$row->field_time}", $row->type_time)
  349. ->field("{$row->join_table}.{$row->field_show} as field_show,SUM({$row->name}.{$row->field_total}) as nums,{$row->name}.{$row->group_field}")
  350. ->group("{$row->name}.{$row->group_field}")
  351. ->order("nums", "desc")
  352. ->limit($row->show_num)
  353. ->select();
  354. } else {
  355. $total = Db::table($row->name)
  356. ->where($row->where)
  357. ->whereTime($row->field_time, $row->type_time)
  358. ->sum($row->field_total);
  359. $data = Db::table($row->name)
  360. ->where($row->where)
  361. ->whereTime($row->field_time, $row->type_time)
  362. ->field("SUM({$row->field_total}) as nums,{$row->group_field}")
  363. ->group($row->group_field)
  364. ->order("nums", "desc")
  365. ->limit($row->show_num)
  366. ->select();
  367. }
  368. foreach ($data as $index => $item) {
  369. if ($row->join_table) {
  370. $name = $item['field_show'];
  371. } else {
  372. $dictionary = json_decode($row->dictionary, true);
  373. $name = $dictionary[$item[$row->group_field]] ?? $row->group_field . '(' . $item[$row->group_field] . ')';
  374. }
  375. $data[$index]['name'] = $name;
  376. $data[$index]['ratio'] = $total > 0 ? round(($item['nums'] / $total) * 100, 2) : 0;
  377. }
  378. $typeTime = ['today' => '今日', 'week' => '本周', 'month' => '本月'];
  379. $row->title .= isset($typeTime[$row->type_time]) ? "({$typeTime[$row->type_time]})" : '';
  380. return [
  381. 'total' => $total,
  382. 'data' => $data,
  383. 'title' => $row->title,
  384. 'unit' => $row->unit,
  385. ];
  386. }
  387. /**
  388. * @notes 排行统计-行
  389. * @return array
  390. * @author 兴
  391. * @date 2022/9/19 14:17
  392. */
  393. private static function totalRankingCount($row)
  394. {
  395. if ($row->join_table) {
  396. //有关联
  397. $total = Db::table($row->name)
  398. ->join($row->join_table, $row->join_table . '.' . $row->local_key . ' = ' . $row->name . '.' . $row->foreign_key)
  399. ->where($row->where)
  400. ->whereTime("{$row->name}.{$row->field_time}", $row->type_time)
  401. ->count("{$row->name}.{$row->field_total}");
  402. $data = Db::table($row->name)
  403. ->join($row->join_table, $row->join_table . '.' . $row->local_key . ' = ' . $row->name . '.' . $row->foreign_key)
  404. ->where($row->where)
  405. ->whereTime("{$row->name}.{$row->field_time}", $row->type_time)
  406. ->field("{$row->join_table}.{$row->field_show} as field_show,COUNT({$row->name}.{$row->field_total}) as nums,{$row->name}.{$row->group_field}")
  407. ->group("{$row->name}.{$row->group_field}")
  408. ->order("nums", "desc")
  409. ->limit($row->show_num)
  410. ->select();
  411. } else {
  412. $total = Db::table($row->name)
  413. ->where($row->where)
  414. ->whereTime($row->field_time, $row->type_time)
  415. ->count($row->field_total);
  416. $data = Db::table($row->name)
  417. ->where($row->where)
  418. ->whereTime($row->field_time, $row->type_time)
  419. ->field("COUNT({$row->field_total}) as nums,{$row->group_field}")
  420. ->group($row->group_field)
  421. ->order("nums", "desc")
  422. ->limit($row->show_num)
  423. ->select();
  424. }
  425. foreach ($data as $index => $item) {
  426. if ($row->join_table) {
  427. $name = $item['field_show'];
  428. } else {
  429. $dictionary = json_decode($row->dictionary, true);
  430. $name = $dictionary[$item[$row->group_field]] ?? $row->group_field . '(' . $item[$row->group_field] . ')';
  431. }
  432. $data[$index]['name'] = $name;
  433. $data[$index]['ratio'] = $total > 0 ? round(($item['nums'] / $total) * 100, 2) : 0;
  434. }
  435. $typeTime = ['today' => '今日', 'week' => '本周', 'month' => '本月'];
  436. $row->title .= isset($typeTime[$row->type_time]) ? "({$typeTime[$row->type_time]})" : '';
  437. return [
  438. 'total' => $total,
  439. 'data' => $data,
  440. 'title' => $row->title,
  441. 'unit' => $row->unit,
  442. ];
  443. }
  444. }