index.vue 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. <template>
  2. <view class="content">
  3. <u-navbar title="" :is-back="false" :background="{backgroundColor: '#1f58ff'}" class="top-navbar">
  4. <text style="position: absolute;z-index: 1;left:40rpx;">收费统计</text>
  5. <u-dropdown>
  6. <u-dropdown-item v-model="selparking" :title="parkingMenuTitle" :options="parkingMenuItems" @change="changeFilterMenu"></u-dropdown-item>
  7. </u-dropdown>
  8. </u-navbar>
  9. <view class="rpt-top">
  10. <u-circle-progress :percent="seatpie.percent" active-color="#22fd8d" bg-color="rgba(0,0,0,0)" inactive-color="#65a8ff" width="280">
  11. <view class="u-progress-content">
  12. <text class="subtitle">空闲/总车位</text>
  13. <text class='title'>{{seatpie.idle}}/{{seatpie.total}}</text>
  14. </view>
  15. </u-circle-progress>
  16. <view class="income-rpt">
  17. <view class="income-item">
  18. <view>总收入(元)</view>
  19. <text>{{incomerpt.total}}</text>
  20. </view>
  21. <view class="income-item">
  22. <view>本月收入(元)</view>
  23. <text>{{incomerpt.month}}</text>
  24. </view>
  25. <view class="income-item">
  26. <view>今日收入(元)</view>
  27. <text>{{incomerpt.today}}</text>
  28. </view>
  29. </view>
  30. </view>
  31. <view class="rpt-mid">
  32. <view class="rpt-mid-title">车流量趋势</view>
  33. <view style="height:30vh;"><qiun-data-charts type="line" :chartData="chartData" :opts="lineChartOpt"/></view>
  34. </view>
  35. <u-card class="parking-card" full margin="0rpx 0rpx 20rpx" v-for="(item,index) in parksitList" :key="item.park_id">
  36. <view class="card-head" slot="head">
  37. <view>{{item.parking_name}}</view>
  38. <u-icon :name="item.offline_count>0?'wifi-off':'wifi'" :color="item.offline_count>0?'#909090':'#48bc28'" size="32"></u-icon>
  39. </view>
  40. <view class="card-body" slot="body">
  41. <view class="body-item">
  42. <view>今日实收</view>
  43. <text>{{item.today_pay_amount?item.today_pay_amount.toFixed(2):'0.00'}}</text>
  44. </view>
  45. <view class="body-item">
  46. <view>收款笔数</view>
  47. <text>{{item.today_pay_count?item.today_pay_count.toFixed(0):'0'}}</text>
  48. </view>
  49. <view class="body-item">
  50. <view>应收金额</view>
  51. <text>{{item.should_pay?item.should_pay.toFixed(2):'0.00'}}</text>
  52. </view>
  53. </view>
  54. <view class="card-foot" slot="foot">
  55. <text>异常放行:0</text>
  56. <text>免单车次:{{item.free_pay_count?item.free_pay_count.toFixed(0):'0'}}</text>
  57. <text>剩余车位:{{item.idle_seat>0?item.idle_seat:0}}</text>
  58. </view>
  59. </u-card>
  60. </view>
  61. </template>
  62. <script>
  63. import * as api from '@/apis/index.js'
  64. import app from '@/utils/app.js'
  65. export default {
  66. data() {
  67. return {
  68. allParkIds:'',
  69. selparking:'all',
  70. parkingMenuTitle:'停车场',
  71. parkingMenuItems:[
  72. ],
  73. seatpie:{
  74. total:0,
  75. idle:0,
  76. percent:0
  77. },
  78. incomerpt:{
  79. total:0,
  80. month:0,
  81. today:0
  82. },
  83. parksitList:[
  84. ],
  85. chartData:{},
  86. lineChartOpt:{
  87. legend:{
  88. position:'bottom'
  89. }
  90. }
  91. }
  92. },
  93. onLoad() {
  94. this.loadParkSites();
  95. //this.getServerData();
  96. },
  97. methods: {
  98. changeFilterMenu(opt){
  99. //console.log(opt.label.length);
  100. //更换菜单后,将选中菜单名称显示在下拉标题中,字符过长进行截取
  101. if(opt.label.length>6){
  102. this.parkingMenuTitle=(opt.label).substr(0,6)+'...';
  103. }
  104. else{
  105. this.parkingMenuTitle=opt.label
  106. }
  107. this.updatePageData(opt.value!='all'?opt.value:this.allParkIds);
  108. },
  109. loadParkSites(){
  110. api.loadMyParkSites().then(resp => {
  111. if(!resp.success){
  112. uni.showToast({
  113. title: resp.msg||' 加载数据失败',
  114. icon: "none"
  115. })
  116. return;
  117. }
  118. this.parseForFilterMenu(resp.data);
  119. //this.parseAndUpdateData(resp.data.parkRunWrap);
  120. }).catch(error => {
  121. });
  122. },
  123. updatePageData(parkIds){
  124. api.loadParkTrends(parkIds).then(resp => {
  125. //console.log(resp)
  126. this.parseAndUpdateData(resp.data);
  127. }).catch(error => {
  128. });
  129. },
  130. parseForFilterMenu(dataObj){
  131. if(dataObj&&dataObj.parkBase){
  132. let parkIds=[];
  133. dataObj.parkBase.forEach(function(item){
  134. parkIds.push(item.park_id);
  135. });
  136. dataObj.parkBase.unshift({label:'全部停车场',value:'all'}); //因为引用关系 unshift 可能时vue内的改造过的方法
  137. this.parkingMenuItems=dataObj.parkBase;
  138. this.allParkIds=parkIds.join(",");
  139. }
  140. this.parseAndUpdateData(dataObj.parkRunWrap);
  141. },
  142. parseAndUpdateData(dataObj){ //dataObj:[parkRun]
  143. if(!dataObj||!dataObj.parkRun){
  144. return;
  145. }
  146. this.parksitList=dataObj.parkRun;
  147. //计算总车位信息,收入累计
  148. let seatrpt={total:0,idle:0,percent:0};
  149. let income={total:0,month:0,today:0};
  150. let tmp=0;
  151. for(let i=0,len=dataObj.parkRun.length;i<len;i++){
  152. seatrpt.total+=dataObj.parkRun[i].total_seat||0;
  153. tmp=dataObj.parkRun[i].idle_seat;
  154. seatrpt.idle+=tmp&&tmp>0?tmp:0;
  155. income.total+=dataObj.parkRun[i].total_pay_amount||0;
  156. income.month+=dataObj.parkRun[i].month_pay_amount||0;
  157. income.today+=dataObj.parkRun[i].today_pay_amount||0;
  158. }
  159. if(seatrpt.total>0){
  160. tmp=seatrpt.idle*100/seatrpt.total;
  161. seatrpt.percent=parseInt(tmp.toFixed(0));
  162. }
  163. this.seatpie=seatrpt;
  164. income.total=(income.total).toFixed(2);
  165. income.month=(income.month).toFixed(2);
  166. income.today=(income.today).toFixed(2);
  167. this.incomerpt=income;
  168. //折线图数据准备
  169. let lineChartData={};
  170. lineChartData.categories=dataObj.chartDatas.categories;
  171. lineChartData.series=[];
  172. lineChartData.series.push({name:'入场',data:dataObj.chartDatas.seriesIn});
  173. lineChartData.series.push({name:'出场',data:dataObj.chartDatas.seriesOut});
  174. this.chartData=lineChartData;
  175. }
  176. }
  177. }
  178. </script>
  179. <style scoped>
  180. page{
  181. /* height:100%; */
  182. background-color: #f4f4f4;
  183. /* padding-bottom: 50px; */
  184. }
  185. .top-navbar/deep/ .u-slot-content{
  186. justify-content: space-between;
  187. padding:0rpx;
  188. color:#ffffff;
  189. }
  190. .top-navbar/deep/ .u-dropdown__menu{
  191. justify-content: flex-end;
  192. }
  193. .top-navbar/deep/ .u-dropdown__menu .u-dropdown__menu__item{
  194. flex:none;
  195. margin-right: 40rpx;
  196. }
  197. .top-navbar/deep/ .u-dropdown__menu__item__text{
  198. color:#ffffff !important;
  199. }
  200. .content {
  201. display: flex;
  202. flex-direction: column;
  203. align-items: center;
  204. justify-content: center;
  205. }
  206. .rpt-top{
  207. background: linear-gradient(#1f58ff, #00aaff);
  208. height:35vh;
  209. width:100vw;
  210. display: flex;
  211. flex-direction: column;
  212. align-items: center;
  213. justify-content: center;
  214. }
  215. .rpt-mid{
  216. background-color: #ffffff;
  217. /* height:45vh; */
  218. width:100vw;
  219. margin-bottom: 20rpx;
  220. /* position: absolute;
  221. z-index: 100; */
  222. }
  223. .rpt-mid .rpt-mid-title{
  224. font-size:28rpx;
  225. /* font-family: '宋体'; */
  226. margin:20rpx;
  227. padding-left:20rpx;
  228. border-left: 8rpx solid #1F58FF;
  229. }
  230. .parking-card{
  231. width:100%;
  232. box-sizing: border-box;
  233. margin:0rpx;
  234. }
  235. /deep/ .parking-card .u-card__head{
  236. padding: 20rpx !important;
  237. }
  238. .parking-card .card-head{
  239. display: flex;
  240. flex-flow: row nowrap;
  241. justify-content:space-between;
  242. align-items: center;
  243. color:#000000;
  244. /* font-family: '黑体'; */
  245. }
  246. .parking-card .card-body{
  247. padding:0rpx;
  248. display: flex;
  249. flex-flow: row nowrap;
  250. justify-content:space-around;
  251. align-items: center;
  252. }
  253. .parking-card .card-body .body-item{
  254. text-align: center;
  255. }
  256. .parking-card .card-body .body-item view{
  257. font-size: 24rpx;
  258. color:#6f867d;
  259. margin-bottom:10rpx;
  260. }
  261. .parking-card .card-body .body-item text{
  262. font-size: 36rpx;
  263. color:#007AFF;
  264. }
  265. .parking-card .card-foot{
  266. padding:0rpx;
  267. display: flex;
  268. flex-flow: row nowrap;
  269. justify-content:space-around;
  270. align-items: center;
  271. font-size: 24rpx;
  272. color:#6f867d;
  273. }
  274. .u-progress-content{
  275. color:#ffffff;
  276. display: flex;
  277. flex-direction: column;
  278. align-items: center;
  279. justify-content: center;
  280. }
  281. .u-progress-content .title{
  282. font-size: 48rpx;
  283. font-weight: bold;
  284. margin:10rpx 0rpx;
  285. }
  286. .u-progress-content .subtitle{
  287. font-size: 28rpx;
  288. }
  289. .rpt-top .income-rpt{
  290. width:100%;
  291. height:100rpx;
  292. padding:30rpx;
  293. display: flex;
  294. flex-flow: row nowrap;
  295. justify-content:space-around;
  296. align-items: center;
  297. color:#ffffff;
  298. }
  299. .rpt-top .income-rpt .income-item{
  300. text-align: center;
  301. }
  302. .rpt-top .income-rpt .income-item view{
  303. font-size: 26rpx;
  304. margin-bottom:5rpx;
  305. }
  306. .rpt-top .income-rpt .income-item text{
  307. font-size: 32rpx;
  308. }
  309. </style>