dashboard.html 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. {extend name="base"/}
  2. {block name="resources"}
  3. <style>
  4. .survey .layui-card {background:#f2f3f5;vertical-align:top;width:50%;display:inline-block;border-radius:0;float:left;margin-top:10px;box-shadow:unset;}
  5. .survey .layui-card-header {font-size:14px;box-shadow:unset;border:0;}
  6. .survey .layui-card:nth-child(3n) {margin-right:0;}
  7. .survey {box-shadow:unset;}
  8. .layui-card-body {font-size:24px;padding-top:0px;cursor:pointer;}
  9. .layui-card.layui-input-inline {padding-left:40px;box-sizing:border-box;}
  10. .tab-status {height:41px;}
  11. .layui-card.layui-input-inline {position:relative;}
  12. .stat-name {justify-content:space-between;}
  13. .layui-elem-quote .time {font-size:12px;margin-left:10px;}
  14. .screen-title {font-size:14px;font-weight:600;}
  15. .stat-list {margin-top:10px;display:flex;flex-wrap:wrap;}
  16. .stat-item {padding:15px;box-sizing:border-box;margin-right:10px;width:calc((100% - 30px) / 4);margin-bottom:10px;border:1px solid #eee;}
  17. .stat-name span {position:relative;}
  18. .stat-name .iconfont {margin-left:5px;cursor:pointer;}
  19. .stat-name>a {float:right;margin-top:1px;font-size:14px;font-weight:normal;}
  20. .stat-list .stat-item:nth-child(4n) {margin-right:0;}
  21. .stat-value {font-size:24px;margin-top:15px;}
  22. @media screen and (max-width:1580px) {.stat-list .stat-item {width:calc((100% - 20px) / 3);}
  23. .stat-list .stat-item:nth-child(4n) {margin-right:10px;}
  24. .stat-list .stat-item:nth-child(3n) {margin-right:0;}
  25. }
  26. .survey {margin:20px 0px;background:#f2f3f5;display:flex;}
  27. .survey.stat .layui-card {width:150px !important;}
  28. .survey.stat {margin-left:0;margin-right:0;height:90px;margin-top:10px;}
  29. .survey.stat .layui-card-body {padding-top:0px;}
  30. .symbol {padding:35px 20px;font-size:18px;}
  31. .stat-text {padding:35px 10px;font-size:14px;}
  32. .date-btn {height:32px;line-height:32px;font-size:14px;padding:0 10px;display:inline-block;box-sizing:border-box;float:left;cursor:pointer;}
  33. .layui-form-center {display:inline-block;}
  34. .js-prompt-top {color:#C8C9CC;font-size:14px;z-index:999;margin-left:5px;cursor:pointer;}
  35. #time_fission {border: 1px solid #eee;padding: 7px 10px;}
  36. </style>
  37. {/block}
  38. {block name="main"}
  39. <div id="app">
  40. <div class="main-wrap">
  41. <div class="screen">
  42. <div class="layui-elem-quote">统计报表<span class="time text-color-tip">更新时间:{:date('Y-m-d H:i:s')}</span></div>
  43. <div class="layui-input-inline">
  44. <div class="layui-inline layui-inline-margin" id="time_fission">
  45. <div class="layui-input-inline">
  46. <input type="text" id="start_time" name="start_time" autocomplete="off" class="layui-input" placeholder="请输入开始时间" value="{notempty name='$start_time'}{$start_time|date='Y-m-d H:i:s'}{/notempty}">
  47. <i class="iconfont iconriqi"></i>
  48. </div>
  49. <div class="layui-form-center">-</div>
  50. <div class="layui-input-inline">
  51. <input type="text" id="end_time" name="end_time" autocomplete="off" class="layui-input" placeholder="请输入结束时间" value="{notempty name='$end_time'}{$end_time|date='Y-m-d H:i:s'}{/notempty}">
  52. <i class="iconfont iconriqi"></i>
  53. </div>
  54. </div>
  55. </div>
  56. <div class="layui-input-inline">
  57. <div class="date-btn text-color selected" onclick="datePick(2, this)">今日</div>
  58. <div class="date-btn selected" onclick="datePick(1, this)">昨日</div>&nbsp;&nbsp;
  59. <div class="date-btn selected" onclick="datePick(3, this)">本周</div>&nbsp;&nbsp;
  60. <div class="date-btn selected" onclick="datePick(4, this)">本月</div>&nbsp;&nbsp;
  61. </div>
  62. </div>
  63. <div class="survey">
  64. <div class="layui-card layui-input-inline" >
  65. <div class="layui-card-header">
  66. <span class="hint">预计收入(元) </span>
  67. <span class="iconfont iconwenhao js-prompt-top" data-tips="统计时间内,店铺收入的金额减去支出的金额"></span>
  68. </div>
  69. <div class="layui-card-body">
  70. <span class="num total_income" v-text="$options.filters.moneyFormat(realIncome)">0.00</span>
  71. </div>
  72. </div>
  73. <div class="layui-card layui-input-inline" >
  74. <div class="layui-card-header">
  75. <span class="hint">收入总额(元) </span>
  76. <span class="iconfont iconwenhao js-prompt-top" data-tips="统计时间内,店铺收入的金额(订单收入、会员充值、会员开卡等)"></span>
  77. </div>
  78. <div class="layui-card-body">
  79. <span class="num total_income" v-text="$options.filters.moneyFormat(totalIncome)">0.00</span>
  80. </div>
  81. </div>
  82. <div class="layui-card layui-input-inline" >
  83. <div class="layui-card-header">
  84. <span class="hint">支出总额(元) </span>
  85. <span class="iconfont iconwenhao js-prompt-top" data-tips="统计时间内,店铺支出的金额(退款、会员提现、现金红包等)"></span>
  86. </div>
  87. <div class="layui-card-body">
  88. <span class="num total_expenditure" v-text="$options.filters.moneyFormat(totalDisburse)">0.00</span>
  89. </div>
  90. </div>
  91. <div class="layui-clear"></div>
  92. </div>
  93. <div class="screen">
  94. <div class="screen-title">收入概况</div>
  95. <div class="survey stat">
  96. <div class="layui-card layui-input-inline">
  97. <div class="layui-card-header">
  98. <span class="hint">收入总额</span>
  99. </div>
  100. <div class="layui-card-body">
  101. <span class="num total_income" v-text="$options.filters.moneyFormat(totalIncome)">0.00</span>
  102. </div>
  103. </div>
  104. <div class="symbol"> = </div>
  105. <template v-for="(item, index) in incomeData">
  106. <div class="symbol" v-if="index > 0"> + </div>
  107. <div class="stat-text" v-text="item.title"></div>
  108. </template>
  109. </div>
  110. <div class="stat-list">
  111. <div class="stat-item" v-for="(item, index) in incomeData" :key="index">
  112. <div class="stat-name">
  113. <span><span v-text="item.title"></span><i class="iconfont iconwenhao js-prompt-top" :data-tips="item.desc"></i></span>
  114. <a :href="url(item.url)" class="text-color" target="_blank">明细</a>
  115. </div>
  116. <div class="stat-value" v-text="$options.filters.moneyFormat(item.value)">0.00</div>
  117. </div>
  118. </div>
  119. </div>
  120. <div class="screen">
  121. <div class="screen-title">支出概况</div>
  122. <div class="survey stat">
  123. <div class="layui-card layui-input-inline">
  124. <div class="layui-card-header">
  125. <span class="hint">支出总额</span>
  126. </div>
  127. <div class="layui-card-body">
  128. <span class="num total_income" v-text="$options.filters.moneyFormat(totalDisburse)">0.00</span>
  129. </div>
  130. </div>
  131. <div class="symbol"> = </div>
  132. <template v-for="(item, index) in disburseData">
  133. <div class="symbol" v-if="index > 0"> + </div>
  134. <div class="stat-text" v-text="item.title"></div>
  135. </template>
  136. </div>
  137. <div class="stat-list">
  138. <div class="stat-item" v-for="(item, index) in disburseData" :key="index">
  139. <div class="stat-name">
  140. <span><span v-text="item.title"></span><i class="iconfont iconwenhao js-prompt-top" :data-tips="item.desc"></i></span>
  141. <a :href="url(item.url)" class="text-color" target="_blank">明细</a>
  142. </div>
  143. <div class="stat-value" v-text="$options.filters.moneyFormat(item.value)">0.00</div>
  144. </div>
  145. </div>
  146. </div>
  147. </div>
  148. </div>
  149. {/block}
  150. {block name="script"}
  151. <script src="STATIC_JS/vue.js"></script>
  152. <script>
  153. var laydate;
  154. layui.use(['laydate'], function () {
  155. laydate = layui.laydate;
  156. new LayDate({
  157. elem: '#time_fission',
  158. type: 'datetime',
  159. rangeId:['start_time','end_time'],
  160. max: '{:date("Y-m-d")}',
  161. done: function(value, date, endDate){
  162. var time_arr = value.split(' - ');
  163. var start_time = time_arr[0];
  164. var end_time = time_arr[1];
  165. getIncomeData({start_time: dateToTime(start_time), end_time: dateToTime(end_time)});
  166. getDisburseData({start_time: dateToTime(start_time), end_time: dateToTime(end_time)});
  167. $('input[name="start_time"]').val(time_arr[0]);
  168. $('input[name="end_time"]').val(time_arr[1]);
  169. }
  170. });
  171. });
  172. var vue = new Vue({
  173. el: '#app',
  174. data: {
  175. totalIncome: {$total_income}, //总收入
  176. totalDisburse: {$total_disburse}, // 总支出
  177. incomeData: {:json_encode($income_data)}, // 收入组成
  178. disburseData: {:json_encode($disburse_data)} // 支出组成
  179. },
  180. computed: {
  181. realIncome: function(){
  182. return this.totalIncome - this.totalDisburse;
  183. }
  184. },
  185. methods: {
  186. url: function(href){
  187. return ns.url(href)
  188. }
  189. },
  190. filters: {
  191. /**
  192. * 金额格式化输出
  193. * @param {Object} money
  194. */
  195. moneyFormat(money) {
  196. if (isNaN(parseFloat(money))) return money;
  197. return parseFloat(money).toFixed(2);
  198. }
  199. }
  200. })
  201. /**
  202. * 查询收入数据
  203. * @param data
  204. */
  205. function getIncomeData(data) {
  206. $.ajax({
  207. type: 'POST',
  208. dataType: 'JSON',
  209. url: ns.url("shop/account/income"),
  210. data: data,
  211. success: function(res) {
  212. vue.incomeData = res.data;
  213. var total = 0;
  214. res.data.forEach(function(item){
  215. total += parseFloat(item.value);
  216. });
  217. vue.totalIncome = total;
  218. }
  219. });
  220. }
  221. /**
  222. * 查询支出数据
  223. * @param data
  224. */
  225. function getDisburseData(data) {
  226. $.ajax({
  227. type: 'POST',
  228. dataType: 'JSON',
  229. url: ns.url("shop/account/disburse"),
  230. data: data,
  231. success: function(res) {
  232. vue.disburseData = res.data;
  233. var total = 0;
  234. res.data.forEach(function(item){
  235. total += parseFloat(item.value);
  236. });
  237. vue.totalDisburse = total;
  238. }
  239. });
  240. }
  241. function datePick(date_type,event_obj) {
  242. $(".date-btn").removeClass("select");
  243. $(".date-btn").removeClass("text-color");
  244. $(event_obj).addClass('select');
  245. $(event_obj).addClass('text-color');
  246. var beginTime, endTime;
  247. switch (date_type) {
  248. case 1:
  249. var now = new Date();
  250. now.setDate(now.getDate() - 1);
  251. var Year = now.getFullYear();
  252. var Month = now.getMonth() + 1;
  253. var Day = now.getDate();
  254. if (Month < 10) Month = '0' + Month;
  255. if (Day < 10) Day = '0' + Day;
  256. beginTime = Year + "-" + Month + "-" + Day + ' 00:00:00'; //格式 Y-m-d
  257. endTime = Year + "-" + Month + "-" + Day + ' 23:59:59'; //格式 Y-m-d
  258. break;
  259. case 2:
  260. var now = new Date();
  261. var Year = now.getFullYear();
  262. var Month = now.getMonth() + 1;
  263. var Day = now.getDate();
  264. if (Month < 10) Month = '0' + Month;
  265. if (Day < 10) Day = '0' + Day;
  266. beginTime = Year + "-" + Month + "-" + Day + ' 00:00:00'; //格式 Y-m-d
  267. endTime = Year + "-" + Month + "-" + Day + ' 23:59:59'; //格式 Y-m-d
  268. break;
  269. case 3:
  270. var now = new Date();
  271. var Year = now.getFullYear();
  272. var Month = now.getMonth() + 1;
  273. var Day = now.getDate();
  274. if (Month < 10) Month = '0' + Month;
  275. if (Day < 10) Day = '0' + Day;
  276. var week_day = now.getDay();
  277. if (week_day == 0) //星期天表示 0 故当星期天的时候,获取上周开始的时候
  278. {
  279. week_day = 7;
  280. }
  281. now.setDate(Day - week_day + 1);
  282. var prev_year = now.getFullYear();
  283. var prev_month = now.getMonth() + 1;
  284. var prev_day = now.getDate();
  285. if (prev_month < 10) prev_month = '0' + prev_month;
  286. if (prev_day < 10) prev_day = '0' + prev_day;
  287. beginTime = prev_year + "-" + prev_month + "-" + prev_day + ' 00:00:00'; //格式 Y-m-d
  288. endTime = Year + "-" + Month + "-" + Day + ' 23:59:59'; //格式 Y-m-d
  289. break;
  290. case 4:
  291. var now = new Date(); //获取当前时间
  292. var beginTimes = now.getFullYear(); //开始计算
  293. var Month = now.getMonth() + 1; //getMonth()是以0开始的月份
  294. var Day = now.getDate();
  295. if (Month < 10) Month = '0' + Month;
  296. if (Day < 10) Day = '0' + Day;
  297. beginTime = beginTimes + "-" + Month + "-01 00:00:00"; //格式 Y-m-d
  298. endTime = beginTimes + "-" + Month + "-" + Day + ' 23:59:59'; //格式 Y-m-d
  299. break;
  300. }
  301. new LayDate({
  302. elem: '#time_fission',
  303. type: 'datetime',
  304. rangeId: ['start_time', 'end_time'],
  305. value: beginTime + ' - ' + endTime,
  306. max: '{:date("Y-m-d")}'
  307. });
  308. $('#start_time').val(beginTime);
  309. $('#end_time').val(endTime);
  310. getIncomeData({start_time: dateToTime(beginTime), end_time: dateToTime(endTime)})
  311. getDisburseData({start_time: dateToTime(beginTime), end_time: dateToTime(endTime)})
  312. }
  313. function dateToTime(date){
  314. return new Date(date).getTime() / 1000;
  315. }
  316. </script>
  317. {/block}