order.html 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488
  1. {extend name="base"/}
  2. {block name="resources"}
  3. <style>
  4. /*时间选择*/
  5. .time-screen .screen{display: flex}
  6. .time-screen .screen .item {height: 32px;line-height: 32px;padding: 0 20px;border: 1px solid #D2D2D2;cursor: pointer;border-right: none;border-left: none;position: relative}
  7. .time-screen .screen .item:after{content: '';position: absolute;top: -1px;left: 0;bottom: -1px;right: -1px;border-right: 1px solid #D2D2D2;border-left: 1px solid #D2D2D2;}
  8. .time-screen .screen .selected,.time-screen .item:hover{color: #fff;background: var(--base-color);border-color: var(--base-color) }
  9. .time-screen .screen .selected:after, .time-screen .item:hover:after {border-right: 1px solid var(--base-color);border-left: 1px solid var(--base-color);}
  10. .data-wrap {display: flex;margin-top: 15px;}
  11. .data-wrap .data-item {flex: 1;display: flex}
  12. .data-wrap .data-item .box {flex: 1;margin-right: 15px;border: 1px solid #eee;box-sizing: border-box;padding: 15px;cursor: pointer}
  13. .data-wrap .data-item:last-child .box {margin-right: 0}
  14. .data-wrap .data-item .value {font-size: 25px;font-weight: bolder;line-height: 40px}
  15. .data-wrap .data-item .js-prompt-top {color:#C8C9CC;font-size:14px;z-index:999;cursor:pointer;}
  16. .data-wrap .data-item .info {font-size: 12px;color: #999;}
  17. .data-wrap .info .iconfont {font-size: 12px;}
  18. .data-wrap .data-item .text-color-green {color: #00A717}
  19. .data-wrap .data-item .text-color-red {color: #ff0000}
  20. .data-wrap .data-item.selected .box {border-color: var(--base-color);color: var(--base-color);}
  21. .statistics-wrap {position: relative}
  22. .statistics-wrap .loading {background: rgba(255,255,255,.5);position: absolute;left: 0; top: 0;text-align: center;width: 100%;height: 100%;box-sizing: border-box;padding-top: 100px;display: none}
  23. .statistics-wrap .loading i {font-size: 25px}
  24. .layui-layer-content .layui-form-label {width: 100px}
  25. .echart {margin-top: 15px}
  26. .echart-wrap {margin-top: 30px;display: flex;}
  27. .echart-wrap .main {flex: 1;height: 400px}
  28. .echart-wrap .main:nth-child(2) {margin-left: 15px}
  29. .survey {margin:15px 15px 15px 0;background:#f2f3f5;display:flex;box-shadow:unset;align-items: center}
  30. .survey .layui-card {background:#f2f3f5;vertical-align:top;width:50%;display:inline-block;border-radius:0;float:left;margin-top:10px;box-shadow:unset;}
  31. .survey .layui-card-header {font-size:14px;box-shadow:unset;border:0;white-space: nowrap}
  32. .survey .layui-card {margin-bottom: 10px;}
  33. .survey .layui-card-body {padding-top:0px;font-size: 24px;white-space: nowrap;}
  34. .survey .layui-card-footer {padding: 0 15px;}
  35. .survey .symbol { padding: 35px 20px; font-size: 18px; }
  36. .constitute-wrap {display: flex;}
  37. .constitute-wrap .survey:first-child {flex: 1}
  38. .constitute-wrap .survey:last-child {margin-right: 0}
  39. .date-input{width: 300px}
  40. </style>
  41. {/block}
  42. {block name="main"}
  43. <div class="main-wrap">
  44. <div class="time-screen statistics">
  45. <div class="screen">
  46. <div class="item selected" date-type="today">今日</div>
  47. <div class="item" date-type="yesterday">昨日</div>
  48. <div class="item" date-type="seven">7日内</div>
  49. <div class="item" date-type="thirty">30日内</div>
  50. <div class="item" date-type="custom">自定义</div>
  51. </div>
  52. </div>
  53. <div class="statistics-wrap">
  54. <div class="data-wrap">
  55. <div class="data-item selected" data-value="expected_earnings_total_money">
  56. <div class="box">
  57. <div class="title">
  58. <span class="title-text">预计收入</span>(元)
  59. <span class="iconfont iconwenhao js-prompt-top" data-tips="统计时间内,店铺收入金额减去支出的金额"></span>
  60. </div>
  61. <div class="value" data-type="money">0.00</div>
  62. </div>
  63. </div>
  64. <div class="data-item" data-value="earnings_total_money">
  65. <div class="box">
  66. <div class="title">
  67. <span class="title-text">营业收入</span>(元)
  68. <span class="iconfont iconwenhao js-prompt-top" data-tips="统计时间内,店铺收入的金额(订单、会员充值、会员开卡等)"></span>
  69. </div>
  70. <div class="value" data-type="money">0.00</div>
  71. </div>
  72. </div>
  73. <div class="data-item" data-value="expenditure_total_money">
  74. <div class="box">
  75. <div class="title">
  76. <span class="title-text">营业支出</span>(元)
  77. <span class="iconfont iconwenhao js-prompt-top" data-tips="统计时间内,店铺支出的金额(退款、会员提现)"></span>
  78. </div>
  79. <div class="value" data-type="money">0.00</div>
  80. </div>
  81. </div>
  82. </div>
  83. <div class="data-wrap">
  84. <div class="data-item" data-value="order_pay_money">
  85. <div class="box">
  86. <div class="title">
  87. <span class="title-text">商城订单</span>(元)
  88. <span class="iconfont iconwenhao js-prompt-top" data-tips="统计时间内,商城订单的支付金额的总额"></span>
  89. </div>
  90. <div class="value" data-type="money">0.00</div>
  91. </div>
  92. </div>
  93. <div class="data-item" data-value="cashier_order_pay_money">
  94. <div class="box">
  95. <div class="title">
  96. <span class="title-text">收银订单</span>(元)
  97. <span class="iconfont iconwenhao js-prompt-top" data-tips="统计时间内,收银台订单的支付金额的总额"></span>
  98. </div>
  99. <div class="value" data-type="money">0.00</div>
  100. </div>
  101. </div>
  102. <div class="data-item" data-value="member_recharge_total_money">
  103. <div class="box">
  104. <div class="title">
  105. <span class="title-text">会员充值</span>(元)
  106. <span class="iconfont iconwenhao js-prompt-top" data-tips="统计时间内,会员充值金额的总额"></span>
  107. </div>
  108. <div class="value" data-type="money">0.00</div>
  109. </div>
  110. </div>
  111. <div class="data-item" data-value="member_level_total_money">
  112. <div class="box">
  113. <div class="title">
  114. <span class="title-text">会员卡订单</span>(元)
  115. <span class="iconfont iconwenhao js-prompt-top" data-tips="统计时间内,会员卡订单金额的总额"></span>
  116. </div>
  117. <div class="value" data-type="money">0.00</div>
  118. </div>
  119. </div>
  120. {if addon_is_exit('giftcard')}
  121. <div class="data-item" data-value="member_giftcard_total_money">
  122. <div class="box">
  123. <div class="title">
  124. <span class="title-text">礼品卡订单</span>(元)
  125. <span class="iconfont iconwenhao js-prompt-top" data-tips="统计时间内,礼品卡订单金额的总额"></span>
  126. </div>
  127. <div class="value" data-type="money">0.00</div>
  128. </div>
  129. </div>
  130. {/if}
  131. <div class="data-item" data-value="refund_total">
  132. <div class="box">
  133. <div class="title">
  134. <span class="title-text">订单退款</span>(元)
  135. <span class="iconfont iconwenhao js-prompt-top" data-tips="统计时间内,店铺订单退款金额的总额"></span>
  136. </div>
  137. <div class="value" data-type="money">0.00</div>
  138. </div>
  139. </div>
  140. <div class="data-item" data-value="member_withdraw_total_money">
  141. <div class="box">
  142. <div class="title">
  143. <span class="title-text">会员提现</span>(元)
  144. <span class="iconfont iconwenhao js-prompt-top" data-tips="统计时间内,会员提现的金额的总额"></span>
  145. </div>
  146. <div class="value" data-type="money">0.00</div>
  147. </div>
  148. </div>
  149. </div>
  150. <div class="loading">
  151. <i class="common-loading-layer layui-icon layui-icon-loading layui-anim layui-anim-rotate layui-anim-loop"></i>
  152. </div>
  153. </div>
  154. <div class="constitute-wrap">
  155. <div class="survey stat">
  156. <div class="layui-card layui-input-inline" data-value="earnings_total_money">
  157. <div class="layui-card-header">
  158. <span class="hint">收入总额</span>
  159. </div>
  160. <div class="layui-card-body">
  161. <span class="num total_income value" data-type="money">0.00</span>
  162. </div>
  163. </div>
  164. <div class="symbol"> = </div>
  165. <div class="layui-card layui-input-inline" data-value="order_pay_money">
  166. <div class="layui-card-header">
  167. <span class="hint">商城订单(元)</span>
  168. </div>
  169. <div class="layui-card-body">
  170. <span class="num total_income value" data-type="money">0.00</span>
  171. </div>
  172. <div class="layui-card-footer">
  173. <a href="{:addon_url('shop/order/lists')}" class="text-color">明细</a>
  174. </div>
  175. </div>
  176. <div class="symbol"> + </div>
  177. {if addon_is_exit('cashier', request()->siteid())}
  178. <div class="layui-card layui-input-inline" data-value="cashier_order_pay_money">
  179. <div class="layui-card-header">
  180. <span class="hint">收银订单(元)</span>
  181. </div>
  182. <div class="layui-card-body">
  183. <span class="num total_income value" data-type="money">0.00</span>
  184. </div>
  185. <div class="layui-card-footer">
  186. <a href="{:addon_url('cashier://shop/order/lists')}" class="text-color">明细</a>
  187. </div>
  188. </div>
  189. <div class="symbol"> + </div>
  190. {/if}
  191. <div class="layui-card layui-input-inline" data-value="member_recharge_total_money">
  192. <div class="layui-card-header">
  193. <span class="hint">会员充值(元)</span>
  194. </div>
  195. <div class="layui-card-body">
  196. <span class="num total_income value" data-type="money">0.00</span>
  197. </div>
  198. <div class="layui-card-footer">
  199. <a href="{:addon_url('memberrecharge://shop/memberrecharge/orderlists')}" class="text-color">明细</a>
  200. </div>
  201. </div>
  202. <div class="symbol"> + </div>
  203. <div class="layui-card layui-input-inline" data-value="member_level_total_money">
  204. <div class="layui-card-header">
  205. <span class="hint">会员开卡(元)</span>
  206. </div>
  207. <div class="layui-card-body">
  208. <span class="num total_income value" data-type="money">0.00</span>
  209. </div>
  210. <div class="layui-card-footer">
  211. <a href="{:addon_url('supermember://shop/membercard/order')}" class="text-color">明细</a>
  212. </div>
  213. </div>
  214. {if addon_is_exit('giftcard')}
  215. <div class="symbol"> + </div>
  216. <div class="layui-card layui-input-inline" data-value="member_giftcard_total_money">
  217. <div class="layui-card-header">
  218. <span class="hint">礼品卡订单(元)</span>
  219. </div>
  220. <div class="layui-card-body">
  221. <span class="num total_income value" data-type="money">0.00</span>
  222. </div>
  223. <div class="layui-card-footer">
  224. <a href="{:addon_url('giftcard://shop/order/order')}" class="text-color">明细</a>
  225. </div>
  226. </div>
  227. {/if}
  228. </div>
  229. <div class="survey stat">
  230. <div class="layui-card layui-input-inline" data-value="expenditure_total_money">
  231. <div class="layui-card-header">
  232. <span class="hint">支出总额</span>
  233. </div>
  234. <div class="layui-card-body">
  235. <span class="num total_income value" data-type="money">0.00</span>
  236. </div>
  237. </div>
  238. <div class="symbol"> = </div>
  239. <div class="layui-card layui-input-inline" data-value="refund_total">
  240. <div class="layui-card-header">
  241. <span class="hint">订单退款(元)</span>
  242. </div>
  243. <div class="layui-card-body">
  244. <span class="num total_income value" data-type="money">0.00</span>
  245. </div>
  246. <div class="layui-card-footer">
  247. <a href="{:addon_url('shop/orderrefund/lists')}" class="text-color">明细</a>
  248. </div>
  249. </div>
  250. <div class="symbol"> + </div>
  251. <div class="layui-card layui-input-inline" data-value="member_withdraw_total_money">
  252. <div class="layui-card-header">
  253. <span class="hint">会员提现(元)</span>
  254. </div>
  255. <div class="layui-card-body">
  256. <span class="num total_income value" data-type="money">0.00</span>
  257. </div>
  258. <div class="layui-card-footer">
  259. <a href="{:addon_url('shop/memberwithdraw/lists')}" class="text-color">明细</a>
  260. </div>
  261. </div>
  262. </div>
  263. </div>
  264. <div class="echart-wrap">
  265. <div class="main" id="main"></div>
  266. </div>
  267. </div>
  268. <script type="text/html" id="custom-box">
  269. <div class="layui-form-item">
  270. <div class="layui-inline">
  271. <label class="layui-form-label">选择时间:</label>
  272. <div class="layui-inline layui-inline-margin" id="time_fission">
  273. <div class="layui-input-inline">
  274. <input type="text" id="date" name="date" autocomplete="off" class="layui-input date-input" placeholder="请选择日期">
  275. <i class="iconfont iconriqi"></i>
  276. </div>
  277. </div>
  278. <input type="hidden" name="start_time" value="">
  279. <input type="hidden" name="end_time" value="">
  280. </div>
  281. </div>
  282. </script>
  283. {/block}
  284. {block name="script"}
  285. <script src="SHOP_JS/echarts.min.js"></script>
  286. <script>
  287. $('.time-screen.statistics .item').click(function () {
  288. // if ($(this).hasClass('selected')) return;
  289. var type = $(this).attr('date-type'),
  290. self = this;
  291. if (type != 'custom') $(this).addClass('selected').siblings().removeClass('selected');
  292. switch (type) {
  293. case 'today':
  294. var time = {
  295. start_time: (new Date('{$today} 00:00:00')).getTime() / 1000,
  296. end_time: (new Date('{$today} 23:59:59')).getTime() / 1000,
  297. }
  298. getShopStatistics(time);
  299. getShopStatData(time, 'hour');
  300. break;
  301. case 'yesterday':
  302. var time = {
  303. start_time: (new Date('{$yesterday} 00:00:00')).getTime() / 1000,
  304. end_time: (new Date('{$yesterday} 23:59:59')).getTime() / 1000,
  305. }
  306. getShopStatistics(time);
  307. getShopStatData(time, 'hour');
  308. break;
  309. case 'seven':
  310. var dateObj = new Date(Date.now() - 604800000);
  311. var date = dateObj.getFullYear() + '-' + (dateObj.getMonth() + 1) + '-' + dateObj.getDate();
  312. getShopStatistics({start_time: new Date(date).getTime() / 1000});
  313. getShopStatData({start_time: new Date(date).getTime() / 1000}, 'day');
  314. break;
  315. case 'thirty':
  316. var dateObj = new Date(Date.now() - 2592000000);
  317. var date = dateObj.getFullYear() + '-' + (dateObj.getMonth() + 1) + '-' + dateObj.getDate();
  318. getShopStatistics({start_time: new Date(date).getTime() / 1000});
  319. getShopStatData({start_time: new Date(date).getTime() / 1000}, 'day');
  320. break;
  321. case 'custom':
  322. var _layer = layer.open({
  323. title: '自定义时间选择',
  324. type: 1,
  325. area: ['480px', '160px'], //自定义文本域宽高
  326. btn: ['确认', '取消'],
  327. content: $('#custom-box').html(),
  328. success: function (layero, index) {
  329. new LayDate({
  330. elem: '#date',
  331. type: 'datetime',
  332. rangeId:['start_time','end_time'],
  333. max: '{:date("Y-m-d")}',
  334. done: function(value, date, endDate){
  335. var time_arr = value.split(' - ');
  336. var start_time = time_arr[0];
  337. var end_time = time_arr[1];
  338. $('input[name="start_time"]').val(time_arr[0]);
  339. $('input[name="end_time"]').val(time_arr[1]);
  340. }
  341. });
  342. },
  343. yes: function () {
  344. var start_time = $('input[name="start_time"]').val();
  345. var end_time = $('input[name="end_time"]').val();
  346. if (start_time == ''){
  347. layer.msg('请选择时间');
  348. return;
  349. }
  350. var time = {
  351. start_time: (new Date(start_time)).getTime() / 1000,
  352. end_time: (new Date(end_time)).getTime() / 1000
  353. };
  354. getShopStatistics(time);
  355. getShopStatData(time, 'day');
  356. $(self).addClass('selected').siblings().removeClass('selected');
  357. layer.close(_layer);
  358. }
  359. })
  360. break;
  361. }
  362. })
  363. /**
  364. * 获取统计数据
  365. * */
  366. function getShopStatistics(data) {
  367. $('.statistics-wrap .loading').show();
  368. $.ajax({
  369. dataType: "JSON",
  370. type: "POST",
  371. data: data,
  372. url: ns.url("shop/stat/getstattotal"),
  373. success: function(res){
  374. $('.statistics-wrap .loading').hide();
  375. if (res.code == 0) {
  376. Object.keys(res.data).forEach(function (key) {
  377. var type = $('[data-value="'+ key +'"] .value').attr('data-type');
  378. var value = type == 'money' ? moneyFormat(res.data[key]) : parseInt(res.data[key]);
  379. $('[data-value="'+ key +'"] .value').text(value);
  380. })
  381. }
  382. }
  383. })
  384. }
  385. getShopStatistics({});
  386. /**
  387. * 获取趋势数据
  388. * */
  389. var statData = [];
  390. function getShopStatData(data, type) {
  391. $.ajax({
  392. dataType: 'JSON',
  393. type: 'POST',
  394. url: type == 'hour' ? ns.url("shop/stat/getstathourdata") : ns.url("shop/stat/getStatData"),
  395. data: data,
  396. success: function(res) {
  397. statData = res;
  398. fetchEchart();
  399. }
  400. });
  401. }
  402. getShopStatData({}, 'hour');
  403. // 图表
  404. var baseColor = getComputedStyle(document.documentElement).getPropertyValue('--base-color');
  405. var myChart = echarts.init(document.getElementById('main'));
  406. var option = {
  407. tooltip: {
  408. trigger: 'axis'
  409. },
  410. legend: {
  411. data: ['新增商品数'],
  412. textStyle: {
  413. fontSize: 14,
  414. color: "#000"
  415. }
  416. },
  417. grid: {
  418. left: '4%',
  419. right: '4%'
  420. },
  421. xAxis: {
  422. type: 'category',
  423. boundaryGap: false,
  424. data: []
  425. },
  426. yAxis: {
  427. type: 'value',
  428. axisLabel: {
  429. formatter: '{value} '
  430. },
  431. splitLine:{
  432. show:false
  433. },
  434. },
  435. color: [baseColor],
  436. series: [
  437. {
  438. name: '新增商品数',
  439. type: 'line',
  440. smooth: true,
  441. data: [],
  442. }
  443. ]
  444. };
  445. /**
  446. * 渲染echart图表
  447. */
  448. function fetchEchart() {
  449. var key = $('.statistics-wrap .data-item.selected').attr('data-value');
  450. option.xAxis.data = statData.time;
  451. option.legend.data[0] = $('.statistics-wrap .data-item.selected .title-text').text();
  452. option.series[0].name = $('.statistics-wrap .data-item.selected .title-text').text();
  453. option.series[0].data = statData[key];
  454. myChart.setOption(option);
  455. }
  456. $('.statistics-wrap .data-item').click(function () {
  457. if ($(this).hasClass('selected')) return;
  458. $('.statistics-wrap .data-item').removeClass('selected');
  459. $(this).addClass('selected');
  460. fetchEchart();
  461. })
  462. </script>
  463. {/block}