dashboard.js 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696
  1. requirejs.config({
  2. paths: {
  3. // vue: "/assets/addons/shopro/libs/vue",
  4. g2: "/assets/addons/shopro/libs/antv"
  5. }
  6. })
  7. define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'g2'], function ($, undefined, Backend, Table, Form, G2) {
  8. var Controller = {
  9. index: function () {
  10. var vueChart = new Vue({
  11. el: "#antv-con",
  12. data() {
  13. return {
  14. chartsData: [],
  15. dataList: [{
  16. title: '支付订单',
  17. num: 0,
  18. checked: true,
  19. id: 1,
  20. type: 'payOrder',
  21. color: '#02C1FF',
  22. unit: '笔'
  23. }, {
  24. title: '支付金额',
  25. num: 0,
  26. checked: true,
  27. id: 5,
  28. type: 'payAmount',
  29. color: '#7299FF',
  30. unit: '元'
  31. }, {
  32. title: '待发货订单',
  33. num: 0,
  34. checked: false,
  35. id: 2,
  36. type: 'noSent',
  37. color: '#4BD067',
  38. unit: '笔'
  39. }, {
  40. title: '支付人数',
  41. num: 0,
  42. checked: false,
  43. id: 6,
  44. type: 'neworderArr',
  45. color: '#9682FF',
  46. unit: '人'
  47. },
  48. {
  49. title: '售后维权',
  50. num: 0,
  51. checked: false,
  52. id: 3,
  53. type: 'aftersale',
  54. color: '#FFA800',
  55. unit: '笔'
  56. },
  57. {
  58. title: '退款订单',
  59. num: 0,
  60. checked: false,
  61. id: 4,
  62. type: 'refund',
  63. color: '#FF7D61',
  64. unit: '笔'
  65. }],
  66. selectInputs: [],
  67. dropdownList: [{
  68. date: 'yesterday',
  69. name: '昨日'
  70. }, {
  71. date: 'today',
  72. name: '今日'
  73. }, {
  74. date: 'week',
  75. name: '近一周'
  76. }, {
  77. date: 'month',
  78. name: '近一月'
  79. }, {
  80. date: 'year',
  81. name: '近一年'
  82. }],
  83. dropdownName: '今日',
  84. dropdownDate: 'today',
  85. searchTime: [new Date(), new Date()],
  86. ringRightData: [
  87. { item: '微信支付', type: 'wechatPay', count: 0, percent: 0 },
  88. { item: '支付宝支付', type: 'alipayPay', count: 0, percent: 0 },
  89. { item: '钱包支付', type: 'walletPay', count: 0, percent: 0 },
  90. { item: '其他', type: 'otherPay', count: 0, percent: 0 }
  91. ],
  92. tableData: [],
  93. value2: [new Date(), new Date()],
  94. //环图总数
  95. allOrderNum: 0,
  96. //成交比例
  97. tranPeople: 0,
  98. tranPeoplescale: 0,
  99. //支付比例
  100. allOrderPayNum: 0,
  101. transcale: 0,
  102. orderFinish: {},
  103. payedFinish: {},
  104. loading: true
  105. }
  106. },
  107. mounted() {
  108. //请求数据
  109. this.changeTime();
  110. },
  111. methods: {
  112. //折线
  113. charts() {
  114. $("#main-chart").empty()
  115. const chart = new G2.Chart({
  116. container: 'main-chart',
  117. autoFit: true,
  118. height: 360,
  119. animate: true,
  120. });
  121. chart.data(this.chartsData);
  122. var dataBoxNum = 0
  123. this.selectInputs.forEach(e => {
  124. if (e.checked) {
  125. dataBoxNum++
  126. }
  127. })
  128. if (dataBoxNum == 1) {
  129. let title
  130. this.selectInputs.forEach(i => {
  131. if (i.checked) {
  132. title = i.title
  133. }
  134. })
  135. chart.scale({
  136. date: {
  137. alias: ' ',
  138. },
  139. y2: {
  140. alias: title,
  141. min: 0,
  142. sync: true,
  143. nice: true,
  144. },
  145. });
  146. chart
  147. .area()
  148. .position('date*y2')
  149. .color(this.selectInputs[0].color).tooltip(false).shape('smooth');
  150. chart
  151. .line()
  152. .position('date*y2')
  153. .color(this.selectInputs[0].color).shape('smooth');
  154. } else if (dataBoxNum == 2) {
  155. chart.scale({
  156. date: {
  157. alias: ' ',
  158. },
  159. y2: {
  160. alias: this.selectInputs[1].title,
  161. sync: true,
  162. nice: true,
  163. min: 0
  164. },
  165. y1: {
  166. alias: this.selectInputs[0].title,
  167. sync: true,
  168. nice: true,
  169. min: 0
  170. },
  171. });
  172. chart
  173. .area()
  174. .position('date*y1')
  175. .color(this.selectInputs[0].color).tooltip(false).shape('smooth');
  176. chart
  177. .line()
  178. .position('date*y1')
  179. .color(this.selectInputs[0].color).shape('smooth');
  180. chart
  181. .area()
  182. .position('date*y2')
  183. .color(this.selectInputs[1].color).tooltip(false).shape('smooth');
  184. chart
  185. .line()
  186. .position('date*y2')
  187. .color(this.selectInputs[1].color).shape('smooth');
  188. } else {
  189. return false
  190. }
  191. var margin = 1 / this.chartsData.length;
  192. chart.axis('date', {
  193. range: [margin / 4, 1 - margin / 4]
  194. });
  195. chart.axis('y1', {
  196. grid: null,
  197. title: {},
  198. });
  199. chart.axis('y2', {
  200. title: {},
  201. });
  202. chart.tooltip({
  203. showCrosshairs: true, //展示辅助线
  204. shared: true,
  205. });
  206. chart.render();
  207. },
  208. //选择显示数据
  209. selectLine(idx) {
  210. this.dataList[idx].checked = !this.dataList[idx].checked
  211. if (this.dataList[idx].checked == true) {
  212. this.selectInputs.push(this.dataList[idx]);
  213. if (this.selectInputs.length > 2) {
  214. this.selectInputs[0].checked = false;
  215. this.selectInputs.shift();
  216. }
  217. } else {
  218. this.selectInputs.forEach((item, index) => {
  219. if (this.dataList[idx].id == item.id)
  220. this.selectInputs.splice(index, 1);
  221. })
  222. }
  223. this.countOrderData()
  224. // this.charts()
  225. },
  226. //环图
  227. ringRight() {
  228. var that = this;
  229. $("#ring-right").empty()
  230. const chart = new G2.Chart({
  231. container: 'ring-right',
  232. autoFit: true,
  233. height: 300,
  234. width: 260,
  235. padding: [0, 0, 50, 0]
  236. });
  237. chart.data(this.ringRightData);
  238. chart.scale('percent', {
  239. formatter: (val) => {
  240. val = val * 100 + '%';
  241. return val;
  242. },
  243. });
  244. chart.coordinate('theta', {
  245. radius: 0.85,
  246. innerRadius: 0.8,
  247. });
  248. chart.tooltip({
  249. showTitle: false,
  250. showMarkers: false,
  251. itemTpl: '<li class="g2-tooltip-list-item"><span style="background-color:{color};" class="g2-tooltip-marker"></span>{name}: {value}({count})</li>',
  252. });
  253. // 辅助文本
  254. chart
  255. .annotation()
  256. .text({
  257. position: ['50%', '50%'],
  258. content: this.allOrderNum,
  259. style: {
  260. fontSize: 36,
  261. fill: '#753ECD',
  262. textAlign: 'center',
  263. },
  264. offsetX: -10,
  265. offsetY: -20,
  266. })
  267. .text({
  268. position: ['50%', '50%'],
  269. content: '笔',
  270. style: {
  271. fontSize: 16,
  272. fill: '#753ECD',
  273. textAlign: 'center',
  274. },
  275. offsetY: -20,
  276. offsetX: 30,
  277. })
  278. .text({
  279. position: ['50%', '50%'],
  280. content: '支付单数',
  281. style: {
  282. fontSize: 16,
  283. fill: '#753ECD',
  284. textAlign: 'center',
  285. },
  286. offsetY: 20,
  287. });
  288. chart
  289. .interval()
  290. .adjust('stack')
  291. .position('percent')
  292. .color('item', ['#38C769', '#627EFC', '#FF826C', '#F7B500'])
  293. .tooltip('item*percent', (item, percent) => {
  294. let counts = Math.round(that.allOrderNum * percent)
  295. percent = percent * 100 + '%';
  296. return {
  297. name: item,
  298. value: percent,
  299. count: counts
  300. };
  301. });
  302. chart.render();
  303. },
  304. //表格
  305. tableRowClassName({ row, rowIndex }) {
  306. if (rowIndex % 2 == 0) {
  307. return 'gray-row';
  308. }
  309. return '';
  310. },
  311. //选择时间段
  312. changeTime(index = 1) {
  313. this.dropdownDate = this.dropdownList[index].date;
  314. this.dropdownName = this.dropdownList[index].name;
  315. this.searchTime = this.getTimeSlot();
  316. this.getDataInfo();
  317. },
  318. //选择请求数据
  319. getDataInfo() {
  320. this.loading = true
  321. let that = this
  322. let timeSlot = moment(that.searchTime[0]).format("YYYY-MM-DD HH:mm:ss") + ' - ' + moment(that.searchTime[1]).format("YYYY-MM-DD HH:mm:ss");
  323. Fast.api.ajax({
  324. url: 'shopro/dashboard/index',
  325. loading: false,
  326. data: {
  327. datetimerange: timeSlot
  328. },
  329. success: function (res, ret) {
  330. let data = res.data;
  331. that.tableData = data.goodsList;
  332. that.orderFinish = data.orderFinish
  333. that.payedFinish = data.payedFinish
  334. that.dataList.forEach(d => {
  335. if (d.type != 'neworderArr') {
  336. d.num = data[d.type + 'Num']
  337. d.item = data[d.type + 'Arr']
  338. } else {
  339. let resorderArr = JSON.parse(JSON.stringify(data.payOrderArr));
  340. for (var i = 0; i < resorderArr.length; i++) {
  341. for (var j = i + 1; j < resorderArr.length; j++) {
  342. if (resorderArr[i].user_id == resorderArr[j].user_id) {
  343. resorderArr.splice(j, 1);
  344. j--;
  345. }
  346. }
  347. }
  348. d.num = resorderArr.length
  349. d.item = resorderArr
  350. }
  351. })
  352. that.allOrderNum = data.allTypePay
  353. that.ringRightData.forEach(p => {
  354. if (p.type != 'otherPay') {
  355. p.count = data[p.type]
  356. p.percent = that.scaleFunc(data[p.type], data.allTypePay)
  357. } else {
  358. p.count = data.allTypePay - data.wechatPay - data.alipayPay - data.walletPay
  359. p.percent = that.scaleFunc(p.count, data.allTypePay)
  360. }
  361. })
  362. that.ringRight()
  363. //成交比例
  364. that.tranPeople = data.tranPeople
  365. that.tranPeoplescale = that.scaleFunc(data.tranPeople, data.orderArr.length) * 100
  366. //支付比例
  367. that.allOrderPayNum = data.payAmountNum
  368. that.transcale = that.scaleFunc(data.payAmountNum, data.totalAmount) * 100
  369. //判断是否选中
  370. that.selectInputs = []
  371. that.dataList.forEach((item, index) => {
  372. if (item.checked == true) that.selectInputs.push(item);
  373. })
  374. // 请求数据
  375. that.countOrderData();
  376. }
  377. })
  378. },
  379. countOrderData() {
  380. let that = this;
  381. let time = (
  382. new Date(moment(that.searchTime[1]).format("YYYY-MM-DD HH:mm:ss").replace(/-/g, "/")).getTime() - new Date(moment(that.searchTime[0]).format("YYYY-MM-DD HH:mm:ss").replace(/-/g, "/")).getTime()
  383. ) / 1000 + 1;
  384. let kld = '';
  385. let interval = 0;
  386. if (time <= 60 * 60) {
  387. interval = parseInt(time / 60);
  388. kld = 'minutes';
  389. } else if (time <= 60 * 60 * 24) {
  390. interval = parseInt(time / (60 * 60));
  391. kld = 'hours';
  392. } else if (time <= 60 * 60 * 24 * 30 * 1.5) {
  393. interval = parseInt(time / (60 * 60 * 24));
  394. kld = 'days';
  395. } else if (time < 60 * 60 * 24 * 30 * 24) {
  396. interval = parseInt(time / (60 * 60 * 24 * 30));
  397. kld = 'months';
  398. } else if (time >= 60 * 60 * 24 * 30 * 24) {
  399. interval = parseInt(time / (60 * 60 * 24 * 30 * 12));
  400. kld = 'years';
  401. }
  402. this.drawX(interval, kld);
  403. },
  404. drawX(interval, kld) {
  405. let that = this
  406. let x = [];
  407. let selectInputLeng = 0
  408. this.selectInputs.forEach(e => {
  409. if (e.checked) {
  410. selectInputLeng++
  411. }
  412. })
  413. for (let i = 0; i <= interval; i++) {
  414. if (kld == 'minutes' || kld == 'hours') {
  415. x.push({
  416. date: moment(that.searchTime[0]).add(i, kld).format("DD HH:mm"),
  417. timeStamp: moment(that.searchTime[0]).add(i, kld).valueOf(),
  418. y2: 0,
  419. y1: 0
  420. });
  421. } else if (kld == 'days') {
  422. x.push({
  423. date: moment(that.searchTime[0]).add(i, kld).format("YYYY-MM-DD"),
  424. timeStamp: moment(that.searchTime[0]).add(i, kld).valueOf(),
  425. y2: 0,
  426. y1: 0
  427. });
  428. } else if (kld == 'months') {
  429. x.push({
  430. date: moment(that.searchTime[0]).add(i, kld).format("YYYY-MM"),
  431. timeStamp: moment(that.searchTime[0]).add(i, kld).valueOf(),
  432. y2: 0,
  433. y1: 0
  434. });
  435. } else {
  436. x.push({
  437. date: moment(that.searchTime[0]).add(i, kld).format("YYYY"),
  438. timeStamp: moment(that.searchTime[0]).add(i, kld).valueOf(),
  439. y2: 0,
  440. y1: 0
  441. });
  442. }
  443. }
  444. if (selectInputLeng == 1) {
  445. for (var y = 0; y < x.length; y++) {
  446. let y2 = 0
  447. let selectItem = []
  448. let id = 0
  449. this.selectInputs.forEach(element => {
  450. if (element.checked == true) {
  451. selectItem = element.item
  452. id = element.id
  453. }
  454. })
  455. if (id == 6) {
  456. let arr = JSON.parse(JSON.stringify(selectItem))
  457. selectItem.forEach(se => {
  458. if (y == x.length - 1) {
  459. y2 = x[x.length - 2].y2
  460. } else {
  461. if (se.createtime <= x[y + 1].timeStamp) {
  462. flag2 = true
  463. y2 = 0
  464. arr.forEach(aa => {
  465. if (aa.createtime <= se.createtime) {
  466. y2++
  467. }
  468. })
  469. }
  470. }
  471. })
  472. } else {
  473. selectItem.forEach(se => {
  474. if (y != x.length - 1) {
  475. if (se.createtime > x[y].timeStamp && se.createtime <= x[y + 1].timeStamp) {
  476. y2 += Number(se.counter)
  477. }
  478. } else {
  479. if (se.createtime > x[y].timeStamp) {
  480. y2 += Number(se.counter)
  481. }
  482. }
  483. })
  484. }
  485. x[y].y2 = y2
  486. }
  487. }
  488. if (selectInputLeng == 2) {
  489. for (var y = 0; y < x.length; y++) {
  490. let y1 = 0
  491. let y2 = 0
  492. this.selectInputs.forEach((si, sindex) => {
  493. if (si.id == 6) {
  494. let arr = JSON.parse(JSON.stringify(si.item))
  495. si.item.forEach(se => {
  496. if (y == x.length - 1) {
  497. if (sindex == 0) {
  498. y1 = x[x.length - 2].y1
  499. } else {
  500. y2 = x[x.length - 2].y2
  501. }
  502. } else {
  503. if (se.createtime <= x[y + 1].timeStamp) {
  504. if (sindex == 0) {
  505. y1 = 0
  506. arr.forEach(aa => {
  507. if (aa.createtime <= se.createtime) {
  508. y1++
  509. }
  510. })
  511. } else {
  512. y2 = 0
  513. arr.forEach(aa => {
  514. if (aa.createtime <= se.createtime) {
  515. y2++
  516. }
  517. })
  518. }
  519. }
  520. }
  521. })
  522. } else {
  523. si.item.forEach(se => {
  524. if (y != x.length - 1) {
  525. if (se.createtime > x[y].timeStamp && se.createtime <= x[y + 1].timeStamp) {
  526. if (sindex == 0) {
  527. y1 += Number(se.counter)
  528. } else {
  529. y2 += Number(se.counter)
  530. }
  531. }
  532. } else {
  533. if (se.createtime > x[y].timeStamp) {
  534. if (sindex == 0) {
  535. y1 += Number(se.counter)
  536. } else {
  537. y2 += Number(se.counter)
  538. }
  539. }
  540. }
  541. })
  542. }
  543. })
  544. x[y].y1 = y1
  545. x[y].y2 = y2
  546. }
  547. }
  548. that.chartsData = x
  549. that.loading = false
  550. that.charts()
  551. },
  552. //获取时间
  553. getTimeSlot() {
  554. let beginTime = '';
  555. let endTime = moment().format('YYYY-MM-DD');
  556. switch (this.dropdownDate) {
  557. case 'yesterday':
  558. endTime = moment().subtract(1, 'days').format('YYYY-MM-DD')
  559. beginTime = endTime
  560. break;
  561. case 'today':
  562. beginTime = endTime;
  563. break;
  564. case 'week':
  565. beginTime = moment().subtract(1, 'weeks').format('YYYY-MM-DD')
  566. break;
  567. case 'month':
  568. beginTime = moment().subtract(1, 'months').format('YYYY-MM-DD')
  569. break;
  570. case 'year':
  571. beginTime = moment().subtract(1, 'years').format('YYYY-MM-DD')
  572. break;
  573. }
  574. let timeSlot = [beginTime + ' 00:00:00', endTime + ' 23:59:59'];
  575. return timeSlot;
  576. },
  577. goDetail(id) {
  578. let that = this;
  579. let status = ''
  580. switch (id) {
  581. case 1:
  582. status = 'payed'
  583. break;
  584. case 2:
  585. status = 'nosend'
  586. break;
  587. case 3:
  588. status = 'aftersale'
  589. break;
  590. case 4:
  591. status = 'refund'
  592. break;
  593. }
  594. let times = encodeURI(that.searchTime.join(" - "))
  595. parent.Fast.api.open("shopro/order/order/index?status=" + status + "&datetimerange=" + times, "查看详情", { callback: function (data) { } });
  596. return false;
  597. },
  598. scaleFunc(a, b) {
  599. return (a <= 0 ? 0 : a / b).toFixed(2) - 0
  600. }
  601. },
  602. })
  603. },
  604. recyclebin: function () {
  605. // 初始化表格参数配置
  606. Table.api.init({
  607. extend: {
  608. 'dragsort_url': ''
  609. }
  610. });
  611. var table = $("#table");
  612. // 初始化表格
  613. table.bootstrapTable({
  614. url: 'shopro/decorate/recyclebin' + location.search,
  615. pk: 'id',
  616. sortName: 'id',
  617. columns: [
  618. [
  619. { checkbox: true },
  620. { field: 'id', title: __('Id') },
  621. { field: 'name', title: __('Name'), align: 'left' },
  622. {
  623. field: 'deletetime',
  624. title: __('Deletetime'),
  625. operate: 'RANGE',
  626. addclass: 'datetimerange',
  627. formatter: Table.api.formatter.datetime
  628. },
  629. {
  630. field: 'operate',
  631. width: '130px',
  632. title: __('Operate'),
  633. table: table,
  634. events: Table.api.events.operate,
  635. buttons: [
  636. {
  637. name: 'Restore',
  638. text: __('Restore'),
  639. classname: 'btn btn-xs btn-info btn-ajax btn-restoreit',
  640. icon: 'fa fa-rotate-left',
  641. url: 'shopro/decorate/restore',
  642. refresh: true
  643. },
  644. {
  645. name: 'Destroy',
  646. text: __('Destroy'),
  647. classname: 'btn btn-xs btn-danger btn-ajax btn-destroyit',
  648. icon: 'fa fa-times',
  649. url: 'shopro/decorate/destroy',
  650. refresh: true
  651. }
  652. ],
  653. formatter: Table.api.formatter.operate
  654. }
  655. ]
  656. ]
  657. });
  658. // 为表格绑定事件
  659. Table.api.bindevent(table);
  660. },
  661. add: function () {
  662. Controller.api.bindevent();
  663. },
  664. edit: function () {
  665. Controller.api.bindevent();
  666. },
  667. api: {
  668. bindevent: function () {
  669. Form.api.bindevent($("form[role=form]"));
  670. }
  671. }
  672. };
  673. return Controller;
  674. });