index.vue 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718
  1. <template>
  2. <view>
  3. <!-- 背景图 -->
  4. <view class="index-bg">
  5. <image src="../../static/pages/images/self/indexBg.png"></image>
  6. </view>
  7. <!-- 数据 -->
  8. <view class="data-box">
  9. <view>
  10. <view class="ljsy">{{statisticData.totalProfit?statisticData.totalProfit:0}}</view>
  11. <view class="ljsy-label">累计收益(元)</view>
  12. </view>
  13. <view class="jy ddflex">
  14. <view>
  15. <view class="jy-data">{{statisticData.todayOrderCount?statisticData.todayOrderCount:0}}</view>
  16. <view class="jy-label">今日订单数</view>
  17. </view>
  18. <view class="jy-line"></view>
  19. <view>
  20. <view class="jy-data"><text style="font-size: 22rpx;font-weight: 400;">¥</text>{{statisticData.todayTurnover?statisticData.todayTurnover:0}}</view>
  21. <view class="jy-label">今日营业额</view>
  22. </view>
  23. <view class="jy-line"></view>
  24. <view>
  25. <view class="jy-data"><text style="font-size: 22rpx;font-weight: 400;">¥</text>{{statisticData.todayProfit?statisticData.todayProfit:0}}</view>
  26. <view class="jy-label">今日收益额</view>
  27. </view>
  28. </view>
  29. </view>
  30. <!-- 总数 -->
  31. <view class="total-box ddflex">
  32. <view class="fflex" v-if="!userInfo.storeId">
  33. <view class="total-label">商家总数</view>
  34. <view class="total-data">{{statisticData.merchantCount?statisticData.merchantCount:0}}</view>
  35. </view>
  36. <view v-if="!userInfo.storeId" class="total-data-line"></view>
  37. <view class="fflex" v-if="!userInfo.storeId">
  38. <view class="total-label">门店总数</view>
  39. <view class="total-data">{{statisticData.storeCount?statisticData.storeCount:0}}</view>
  40. </view>
  41. <view v-if="!userInfo.storeId" class="total-data-line"></view>
  42. <view class="fflex">
  43. <view class="total-label">设备总数</view>
  44. <view class="total-data">{{statisticData.batteryCount?statisticData.batteryCount:0}}</view>
  45. </view>
  46. <view class="total-data-line"></view>
  47. <view class="fflex">
  48. <view class="total-label">订单总数</view>
  49. <view class="total-data">{{statisticData.totalOrderCount?statisticData.totalOrderCount:0}}</view>
  50. </view>
  51. </view>
  52. <!-- nav -->
  53. <view v-if="!userInfo.storeId" class="nav-box ddflex">
  54. <view class="nav-item">
  55. <image class="nav-item-icon" src="../../static/pages/images/wdsj.png" @click="jumpUrl('/pages/myStore/myStore')"></image>
  56. <view class="nav-item-title">我的商家</view>
  57. </view>
  58. <view class="nav-item" @click="jumpUrl('/pages/myMerchant/myMerchant')">
  59. <image class="nav-item-icon" src="../../static/pages/images/wdmd.png"></image>
  60. <view class="nav-item-title">我的门店</view>
  61. </view>
  62. <view class="nav-item" v-if="!userInfo.storeId&&!userInfo.merchantId" @click="jumpUrl('/mine/myUser/myUser')">
  63. <image class="nav-item-icon" src="../../static/pages/images/wdyh.png"></image>
  64. <view class="nav-item-title">我的用户</view>
  65. </view>
  66. <view class="nav-item" @click="jumpUrl('/pages/operationData/operationData')">
  67. <image class="nav-item-icon" src="../../static/pages/images/yysj.png"></image>
  68. <view class="nav-item-title">运营数据</view>
  69. </view>
  70. </view>
  71. <view v-if="userInfo.storeId" class="nav-box ddflex" style="padding: 10rpx 30rpx;justify-content: space-between;" @click="jumpUrl('/pages/operationData/operationData')">
  72. <view class="nav-item ddflex">
  73. <image class="nav-item-icon" src="../../static/pages/images/yysj.png"></image>
  74. <view class="nav-item-title">运营数据</view>
  75. </view>
  76. <image style="width: 36rpx;height:36rpx;" src="../../static/pages/images/ssicon.png"></image>
  77. </view>
  78. <!-- 图表统计 -->
  79. <view class="echart-box">
  80. <view class="echart-box-header ddflex">
  81. <view class="echart-box-title">交易趋势</view>
  82. <view class="echart-box-timeType ddflex">
  83. <view :class="'echart-box-timeType-item '+(timeType==1?'echart-box-timeType-item-acitve':'')"
  84. @click="timeTypeChange(1)">今日</view>
  85. <view :class="'echart-box-timeType-item '+(timeType==2?'echart-box-timeType-item-acitve':'')"
  86. @click="timeTypeChange(2)">近7日</view>
  87. <view :class="'echart-box-timeType-item '+(timeType==3?'echart-box-timeType-item-acitve':'')"
  88. @click="timeTypeChange(3)">近30日</view>
  89. </view>
  90. </view>
  91. <view style="height:500rpx">
  92. <l-echart ref="chart" @finished="init"></l-echart>
  93. </view>
  94. </view>
  95. <!-- 图表统计 -->
  96. <view class="echart-box">
  97. <view class="echart-box-header ddflex">
  98. <view class="echart-box-title">商家营业额排名</view>
  99. <view class="echart-box-timeType ddflex">
  100. <view :class="'echart-box-timeType-item '+(storeType==1?'echart-box-timeType-item-acitve':'')"
  101. @click="storeTypeChange(1)">商户</view>
  102. <view :class="'echart-box-timeType-item '+(storeType==2?'echart-box-timeType-item-acitve':'')"
  103. @click="storeTypeChange(2)">门店</view>
  104. </view>
  105. </view>
  106. <view>
  107. <l-echart ref="chart2" @finished="init"></l-echart>
  108. </view>
  109. </view>
  110. <!-- 图表统计 -->
  111. <view class="echart-box">
  112. <view class="echart-box-header ddflex">
  113. <view class="echart-box-title">设备状态</view>
  114. </view>
  115. <view class="ddflex">
  116. <view class="fflex" style="height: 250rpx;">
  117. <l-echart ref="chart4" @finished="init"></l-echart>
  118. </view>
  119. <view class="fflex" style="height: 250rpx;">
  120. <l-echart ref="chart5" @finished="init"></l-echart>
  121. </view>
  122. <view class="fflex" style="height: 250rpx;">
  123. <l-echart ref="chart6" @finished="init"></l-echart>
  124. </view>
  125. </view>
  126. <view class="echart-line"></view>
  127. <view class="ddflex">
  128. <view style="width: 100%;height: 300rpx;">
  129. <l-echart ref="chart3" @finished="init"></l-echart>
  130. </view>
  131. </view>
  132. </view>
  133. <view class="guide" @tap="hideGuide" v-if="first">
  134. <image src="/static/pages/images/guide.png" mode="widthFix"></image>
  135. </view>
  136. <foot channel="home" :isUpdate="isUpdate"></foot>
  137. </view>
  138. </template>
  139. <script>
  140. //index.js
  141. //获取应用实例
  142. const app = getApp();
  143. const req = require('../../utils/request.js');
  144. const api = require('../../utils/api.js');
  145. const utils = require('../../utils/util.js');
  146. const mes = require('../../utils/requestmessage.js');
  147. const route = require('../../utils/route');
  148. const QQMapWX = require("../../utils/qqmap.js");
  149. import foot from '../../components/nav-bar/index';
  150. import footerCopyright from '../../components/footer-copyright/footer-copyright';
  151. import LEchart from '../../components/l-echart/l-echart.vue';
  152. import * as echarts from '../../utils/echarts.min.js'
  153. export default {
  154. data() {
  155. return {
  156. systems: {},
  157. bottomBlankHeight: app.globalData.isIPhoneX ? 68 : 0,
  158. pxToRpxScale: 0,
  159. rpxTopxScale: 0,
  160. timeType: 1, //统计时间 1.按日 2.按月 3.按季度
  161. storeType:1,//营业额查询1.商家 2.门店
  162. statisticData:{},//统计数据
  163. echartData:{},//曲线图
  164. storeRanking:{},//营业额排行
  165. userInfo:{},
  166. // 交易趋势图表数据
  167. option: {
  168. tooltip: {
  169. trigger: 'axis',
  170. axisPointer: {
  171. type: 'shadow'
  172. },
  173. confine: true
  174. },
  175. legend: {
  176. data: ['订单数', '订单金额','收益金额'],
  177. x: 'center', //可设定图例在左、右、居中
  178. y: 'top', //可设定图例在上、下、居中
  179. padding: [15, 0, 0, 0]
  180. },
  181. grid: {
  182. left: 0,
  183. right: 8,
  184. bottom: 5,
  185. top: 45,
  186. containLabel: true
  187. },
  188. xAxis: [{
  189. type: 'category',
  190. data: [],
  191. axisLine: {
  192. lineStyle: {
  193. color: '#999999'
  194. }
  195. },
  196. axisLabel: {
  197. color: '#666666',
  198. // interval: 0,
  199. }
  200. }],
  201. yAxis: [{
  202. type: 'value',
  203. axisTick: {
  204. show: false
  205. },
  206. axisLine: {
  207. lineStyle: {
  208. color: '#999999'
  209. }
  210. },
  211. axisLabel: {
  212. color: '#666666'
  213. }
  214. }],
  215. series: [{
  216. name: '订单数',
  217. type: 'line',
  218. data: [300, 270, 340, 344, 300, 320, 310],
  219. showSymbol: false,
  220. smooth: true,
  221. itemStyle: {
  222. // 颜色
  223. color: '#5F50E6',
  224. // 给bar设置倒角
  225. barBorderRadius: [15, 15, 0, 0]
  226. }
  227. },
  228. {
  229. name: '订单金额',
  230. type: 'line',
  231. data: [120, 102, 141, 174, 190, 250, 220],
  232. showSymbol: false,
  233. smooth: true,
  234. itemStyle: {
  235. // 颜色
  236. color: '#FF7D00',
  237. // 给bar设置倒角
  238. barBorderRadius: [15, 15, 0, 0]
  239. }
  240. },
  241. {
  242. name: '收益金额',
  243. type: 'line',
  244. data: [120, 102, 141, 174, 190, 250, 120],
  245. showSymbol: false,
  246. smooth: true,
  247. itemStyle: {
  248. // 颜色
  249. color: '#FFDC0F',
  250. // 给bar设置倒角
  251. barBorderRadius: [15, 15, 0, 0]
  252. }
  253. },
  254. ]
  255. },
  256. // 商家营业额排名
  257. option2: {
  258. tooltip: {
  259. trigger: 'axis',
  260. axisPointer: {
  261. type: 'shadow'
  262. },
  263. confine: true
  264. },
  265. grid: {
  266. left: -60,
  267. right: 5,
  268. bottom: 40,
  269. top: 40,
  270. containLabel: true
  271. },
  272. xAxis: [{
  273. type: 'value',
  274. // data: [],
  275. show: false,
  276. axisLine: {
  277. lineStyle: {
  278. color: '#999999'
  279. }
  280. },
  281. axisLabel: {
  282. color: '#666666',
  283. // interval: 0,
  284. },
  285. splitLine:{
  286. show:false // 不显示网格线
  287. },
  288. }],
  289. yAxis: [{
  290. type: 'category',
  291. axisTick: {
  292. show: false
  293. },
  294. data: [],
  295. axisLine: {
  296. lineStyle: {
  297. color: '#999999'
  298. }
  299. },
  300. axisLabel: {
  301. color: '#666666',
  302. // inside:true,
  303. width:10,
  304. padding: [-20, -100, 0, 10],
  305. verticalAlign:'top',
  306. align:'left'
  307. },
  308. }],
  309. series: [{
  310. name: '营业额',
  311. type: 'bar',
  312. label: {
  313. normal: {
  314. show: true,
  315. position: 'right',
  316. color: '#4c4a4a',
  317. formatter:'¥{c}',
  318. padding: [-20, 5, 0, -100],
  319. verticalAlign:'top',
  320. align:'right'
  321. },
  322. },
  323. data: [300, 270, 340, 344, 300, 320, 310],
  324. barWidth: 5,
  325. itemStyle: {
  326. // 颜色
  327. color: '#FF770F',
  328. // 给bar设置倒角
  329. barBorderRadius: [0, 15, 15, 0]
  330. }
  331. }]
  332. },
  333. // 设备状态
  334. option3: {
  335. title: {
  336. text: '设备出租比例',
  337. textStyle: {
  338. fontSize: 14
  339. },
  340. left: '70%',
  341. top: '30%'
  342. },
  343. tooltip: {
  344. trigger: 'axis',
  345. axisPointer: {
  346. type: 'shadow'
  347. },
  348. confine: true
  349. },
  350. legend: {
  351. data: ['已租', '未租'],
  352. x: 'right', //可设定图例在左、右、居中
  353. y: '50%', //可设定图例在上、下、居中
  354. itemHeight:5,
  355. itemWidth:20
  356. },
  357. grid: {
  358. left: 0,
  359. containLabel: true
  360. },
  361. series: [{
  362. name: '设备出租比例',
  363. type: 'pie',
  364. center: ['30%', '50%'],
  365. radius: ['60%', '80%'],
  366. label: {
  367. show: false
  368. },
  369. data: [{
  370. value: 1055,
  371. name: '未租',
  372. itemStyle: {
  373. color: "#FF770F"
  374. }
  375. },
  376. {
  377. value: 735,
  378. name: '已租',
  379. itemStyle: {
  380. color: "#EAECF5"
  381. }
  382. }
  383. ]
  384. }]
  385. },
  386. // 已租设备
  387. option4: {
  388. title: {
  389. text: '已租设备',
  390. textStyle: {
  391. fontSize: 14,
  392. fontWeight: 500
  393. },
  394. left: 'center',
  395. bottom: '0'
  396. },
  397. series: [{
  398. type: 'pie',
  399. radius: ['60%', '70%'],
  400. label: {
  401. normal: {
  402. show: true,
  403. position: 'center',
  404. color: '#4c4a4a',
  405. formatter:'{c}',
  406. },
  407. emphasis: { //中间文字显示 
  408. show: true,
  409. textStyle:{
  410. }
  411. }
  412. },
  413. data: [{
  414. value: 1055,
  415. name: '已租',
  416. itemStyle: {
  417. color: "#0FCB27"
  418. }
  419. },
  420. {
  421. value: 735,
  422. name: '未租',
  423. itemStyle: {
  424. color: "#EAECF5"
  425. }
  426. }
  427. ]
  428. }]
  429. },
  430. // 未租设备
  431. option5: {
  432. title: {
  433. text: '未租设备',
  434. textStyle: {
  435. fontSize: 14,
  436. fontWeight: 500
  437. },
  438. left: 'center',
  439. bottom: '0'
  440. },
  441. series: [{
  442. type: 'pie',
  443. center: ['50%', '50%'],
  444. radius: ['60%', '70%'],
  445. label: {
  446. normal: {
  447. show: true,
  448. position: 'center',
  449. color: '#4c4a4a',
  450. formatter:'{c}',
  451. },
  452. emphasis: { //中间文字显示 
  453. show: true,
  454. textStyle:{
  455. }
  456. }
  457. },
  458. data: [{
  459. value: 1055,
  460. name: '未租设备',
  461. itemStyle: {
  462. color: "#666464"
  463. }
  464. },
  465. {
  466. value: 735,
  467. name: '已租设备',
  468. itemStyle: {
  469. color: "#EAECF5"
  470. }
  471. }
  472. ]
  473. }]
  474. },
  475. // 到期设备
  476. option6: {
  477. title: {
  478. text: '到期设备',
  479. textStyle: {
  480. fontSize: 14,
  481. fontWeight: 500
  482. },
  483. left: 'center',
  484. bottom: '0'
  485. },
  486. series: [{
  487. type: 'pie',
  488. center: ['50%', '50%'],
  489. radius: ['60%', '70%'],
  490. label: {
  491. normal: {
  492. show: true,
  493. position: 'center',
  494. color: '#4c4a4a',
  495. formatter:'{c}',
  496. },
  497. emphasis: { //中间文字显示 
  498. show: true,
  499. textStyle:{
  500. }
  501. }
  502. },
  503. data: [{
  504. value: 1055,
  505. name: '到期',
  506. itemStyle: {
  507. color: "#FF770F"
  508. }
  509. },
  510. {
  511. value: 735,
  512. name: '未到期',
  513. itemStyle: {
  514. color: "#EAECF5"
  515. }
  516. }
  517. ]
  518. }]
  519. },
  520. };
  521. },
  522. components: {
  523. foot,
  524. footerCopyright,
  525. LEchart
  526. },
  527. props: {},
  528. onLoad: async function(options) {
  529. },
  530. async onShow() {
  531. await this.getEchartData()
  532. await this.getStatisticData()
  533. await this.getStoreData()
  534. this.init()
  535. this.getUserInfo()
  536. },
  537. onUnload() {},
  538. onHide() {},
  539. onReachBottom() {},
  540. methods: {
  541. jumpUrl(url){
  542. if(req.isLogins(true)){
  543. uni.navigateTo({
  544. url:url
  545. })
  546. }
  547. },
  548. // 统计时间切换
  549. async timeTypeChange(val) {
  550. if (this.timeType == val) return false
  551. this.timeType = val
  552. await this.getEchartData()
  553. this.init()
  554. },
  555. // 营业额切换
  556. async storeTypeChange(val) {
  557. if (this.storeType == val) return false
  558. this.storeType = val
  559. await this.getStoreData()
  560. this.init()
  561. },
  562. init() {
  563. this.$refs.chart.init(echarts, async chart => {
  564. // let echartData = await this.getEchartData()
  565. this.option.yAxis[0].axisLabel.fontSize = 13 * this.rpxTopxScale
  566. this.option.xAxis[0].axisLabel.fontSize = 13 * this.rpxTopxScale
  567. this.option.legend.itemHeight = 10 * this.rpxTopxScale
  568. this.option.legend.itemWidth = 40 * this.rpxTopxScale
  569. if(this.echartData.orderList.length>0){
  570. this.option.xAxis[0].data = this.echartData.orderList.map(item=>{return item.showTime})
  571. this.option.series[0].data = this.echartData.orderList.map(item=>{return item.orderCount})
  572. }
  573. if(this.echartData.profitList.length>0){
  574. this.option.series[1].data = this.echartData.profitList.map(item=>{return item.profit})
  575. }
  576. if(this.echartData.turnoverList.length>0){
  577. this.option.series[2].data = this.echartData.turnoverList.map(item=>{return item.turnover})
  578. }
  579. chart.setOption(this.option);
  580. });
  581. if (this.$refs.chart2) {
  582. this.$refs.chart2.init(echarts, async chart => {
  583. // let echartData = await this.getEchartData()
  584. if(this.storeRanking.length>0){
  585. this.option2.yAxis[0].data = this.storeRanking.map(item=>{return item.name})
  586. this.option2.series[0].data = this.storeRanking.map(item=>{return item.turnover})
  587. }
  588. chart.setOption(this.option2);
  589. });
  590. }
  591. if (this.$refs.chart3) {
  592. this.$refs.chart3.init(echarts, async chart => {
  593. this.option3.title.textStyle.fontSize = 28 * this.rpxTopxScale
  594. this.option3.legend.itemHeight = 10 * this.rpxTopxScale
  595. this.option3.legend.itemWidth = 40 * this.rpxTopxScale
  596. this.option3.series[0].data[0].value = this.statisticData.noLeaseCount
  597. this.option3.series[0].data[1].value = this.statisticData.leaseCount
  598. chart.setOption(this.option3);
  599. });
  600. }
  601. if (this.$refs.chart4) {
  602. this.$refs.chart4.init(echarts, async chart => {
  603. this.option4.title.textStyle.fontSize = 24 * this.rpxTopxScale
  604. this.option4.series[0].data[0].value = this.statisticData.leaseCount
  605. this.option4.series[0].data[1].value = this.statisticData.noLeaseCount
  606. this.option4.series[0].label.normal.formatter = ()=>{return this.statisticData.leaseCount}
  607. chart.setOption(this.option4);
  608. });
  609. }
  610. if (this.$refs.chart5) {
  611. this.$refs.chart5.init(echarts, async chart => {
  612. this.option5.title.textStyle.fontSize = 24 * this.rpxTopxScale
  613. this.option5.series[0].data[0].value = this.statisticData.noLeaseCount
  614. this.option5.series[0].data[1].value = this.statisticData.leaseCount
  615. this.option4.series[0].label.normal.formatter = ()=>{return this.statisticData.noLeaseCount}
  616. chart.setOption(this.option5);
  617. });
  618. }
  619. if (this.$refs.chart6) {
  620. this.$refs.chart6.init(echarts, async chart => {
  621. this.option6.title.textStyle.fontSize = 24 * this.rpxTopxScale
  622. this.option6.series[0].data[0].value = this.statisticData.expireCount
  623. this.option6.series[0].data[1].value =Number(this.statisticData.batteryCount) - Number(this.statisticData.leaseCount)
  624. this.option6.series[0].label.normal.formatter = ()=>{return this.statisticData.expireCount}
  625. chart.setOption(this.option6);
  626. });
  627. }
  628. },
  629. // 获取图表数据
  630. getEchartData() {
  631. return new Promise((r, j) => {
  632. req.getRequest('/admin/v2/statistic/chart', {type: this.timeType}, res => {
  633. this.echartData = res
  634. console.log('statistic chart', res)
  635. r(res)
  636. })
  637. })
  638. },
  639. // 获取营业额数据
  640. getStoreData() {
  641. return new Promise((r, j) => {
  642. req.getRequest('/admin/v2/statistic/ranking', {type: this.storeType}, res => {
  643. this.storeRanking = res
  644. console.log('statistic ranking', res)
  645. r(res)
  646. })
  647. })
  648. },
  649. // 获取图表数据
  650. getStatisticData() {
  651. return new Promise((r, j) => {
  652. req.getRequest('/admin/v2/statistic/top', {}, res => {
  653. console.log('statistic top', res)
  654. this.statisticData = res
  655. r(res)
  656. })
  657. })
  658. },
  659. // 获取当前用户
  660. getUserInfo(){
  661. req.getRequest('/admin/v2/userInfo',{},res=>{
  662. this.userInfo = res
  663. })
  664. }
  665. },
  666. mounted() {
  667. const systemInfo = uni.getSystemInfoSync();
  668. // px转换到rpx的比例
  669. let pxToRpxScale = 750 / systemInfo.windowWidth;
  670. this.pxToRpxScale = pxToRpxScale
  671. this.rpxTopxScale = systemInfo.windowWidth / 750
  672. let systems = {
  673. ktxStatusHeight: systemInfo.statusBarHeight * pxToRpxScale, // 状态栏的高度
  674. navigationHeight: 44 * pxToRpxScale // 导航栏的高度
  675. };
  676. systems.barHeight = systems.ktxStatusHeight + systems.navigationHeight;
  677. this.systems = systems;
  678. }
  679. };
  680. </script>
  681. <style>
  682. @import './index.css';
  683. </style>