index.vue 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  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" tooltipFormat="toolTipParkingFlow"/></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 @tap="showParkDtl(item.park_id)">{{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. xAxis:{
  91. labelCount:8 ,//设置了X轴单屏数量 xAxis.itemCount 设置X轴密度
  92. //itemCount:5,
  93. //format:'xAxisDemo1'
  94. },
  95. yAxis:{
  96. showTitle: true,
  97. data:[
  98. {
  99. title:'车次'
  100. }
  101. ]
  102. }
  103. }
  104. }
  105. },
  106. onLoad() {
  107. this.loadParkSites();
  108. //this.getServerData();
  109. },
  110. onShow(){
  111. this.updatePageData(this.selparking!='all'?this.selparking:this.allParkIds);
  112. },
  113. methods: {
  114. showParkDtl(parkId){
  115. uni.navigateTo({
  116. url:'../parking/parkingSiteDes?park_id='+parkId
  117. })
  118. },
  119. changeFilterMenu(opt){
  120. //console.log(opt.label.length);
  121. //更换菜单后,将选中菜单名称显示在下拉标题中,字符过长进行截取
  122. if(opt.label.length>6){
  123. this.parkingMenuTitle=(opt.label).substr(0,6)+'...';
  124. }
  125. else{
  126. this.parkingMenuTitle=opt.label
  127. }
  128. this.updatePageData(opt.value!='all'?opt.value:this.allParkIds);
  129. },
  130. loadParkSites(){
  131. api.loadMyParkSites().then(resp => {
  132. if(!resp.success){
  133. uni.showToast({
  134. title: resp.msg||' 加载数据失败',
  135. icon: "none"
  136. })
  137. return;
  138. }
  139. this.parseForFilterMenu(resp.data);
  140. //this.parseAndUpdateData(resp.data.parkRunWrap);
  141. }).catch(error => {
  142. });
  143. },
  144. updatePageData(parkIds){
  145. api.loadParkTrends(parkIds).then(resp => {
  146. //console.log(resp)
  147. this.parseAndUpdateData(resp.data);
  148. }).catch(error => {
  149. });
  150. },
  151. parseForFilterMenu(dataObj){
  152. if(dataObj&&dataObj.parkBase){
  153. let parkIds=[],parkAry=[];
  154. dataObj.parkBase.forEach(function(item){
  155. parkIds.push(item.park_id);
  156. parkAry.push({park_id:item.park_id,parking_name:item.parking_name});
  157. });
  158. dataObj.parkBase.unshift({label:'全部停车场',value:'all'}); //因为引用关系 unshift 可能时vue内的改造过的方法
  159. this.parkingMenuItems=dataObj.parkBase;
  160. this.allParkIds=parkIds.join(",");
  161. app.putSetting('myParks',parkAry);
  162. }
  163. this.parseAndUpdateData(dataObj.parkRunWrap);
  164. },
  165. parseAndUpdateData(dataObj){ //dataObj:[parkRun]
  166. if(!dataObj||!dataObj.parkRun){
  167. return;
  168. }
  169. this.parksitList=dataObj.parkRun;
  170. //计算总车位信息,收入累计
  171. let seatrpt={total:0,idle:0,percent:0};
  172. let income={total:0,month:0,today:0};
  173. let tmp=0;
  174. for(let i=0,len=dataObj.parkRun.length;i<len;i++){
  175. seatrpt.total+=dataObj.parkRun[i].total_seat||0;
  176. tmp=dataObj.parkRun[i].idle_seat;
  177. seatrpt.idle+=tmp&&tmp>0?tmp:0;
  178. income.total+=dataObj.parkRun[i].total_pay_amount||0;
  179. income.month+=dataObj.parkRun[i].month_pay_amount||0;
  180. income.today+=dataObj.parkRun[i].today_pay_amount||0;
  181. }
  182. if(seatrpt.total>0){
  183. tmp=seatrpt.idle*100/seatrpt.total;
  184. seatrpt.percent=parseInt(tmp.toFixed(0));
  185. }
  186. this.seatpie=seatrpt;
  187. income.total=(income.total).toFixed(2);
  188. income.month=(income.month).toFixed(2);
  189. income.today=(income.today).toFixed(2);
  190. this.incomerpt=income;
  191. //折线图数据准备
  192. dataObj.chartDatas.categories.forEach(function(item,index){
  193. dataObj.chartDatas.categories[index]=item+"时";
  194. });
  195. let lineChartData={};
  196. lineChartData.categories=dataObj.chartDatas.categories;
  197. lineChartData.series=[];
  198. lineChartData.series.push({name:'入场',data:dataObj.chartDatas.seriesIn});
  199. lineChartData.series.push({name:'出场',data:dataObj.chartDatas.seriesOut});
  200. this.chartData=lineChartData;
  201. }
  202. }
  203. }
  204. </script>
  205. <style scoped>
  206. page{
  207. /* height:100%; */
  208. background-color: #f4f4f4;
  209. /* padding-bottom: 50px; */
  210. }
  211. .top-navbar/deep/ .u-slot-content{
  212. justify-content: space-between;
  213. padding:0rpx;
  214. color:#ffffff;
  215. }
  216. .top-navbar/deep/ .u-dropdown__menu{
  217. justify-content: flex-end;
  218. }
  219. .top-navbar/deep/ .u-dropdown__menu .u-dropdown__menu__item{
  220. flex:none;
  221. margin-right: 40rpx;
  222. }
  223. .top-navbar/deep/ .u-dropdown__menu__item__text{
  224. color:#ffffff !important;
  225. }
  226. .content {
  227. display: flex;
  228. flex-direction: column;
  229. align-items: center;
  230. justify-content: center;
  231. }
  232. .rpt-top{
  233. background: linear-gradient(#1f58ff, #00aaff);
  234. height:35vh;
  235. width:100vw;
  236. display: flex;
  237. flex-direction: column;
  238. align-items: center;
  239. justify-content: center;
  240. }
  241. .rpt-mid{
  242. background-color: #ffffff;
  243. /* height:45vh; */
  244. width:100vw;
  245. margin-bottom: 20rpx;
  246. /* position: absolute;
  247. z-index: 100; */
  248. }
  249. .rpt-mid .rpt-mid-title{
  250. font-size:28rpx;
  251. /* font-family: '宋体'; */
  252. margin:20rpx;
  253. padding-left:20rpx;
  254. border-left: 8rpx solid #1F58FF;
  255. }
  256. .parking-card{
  257. width:100%;
  258. box-sizing: border-box;
  259. margin:0rpx;
  260. }
  261. /deep/ .parking-card .u-card__head{
  262. padding: 20rpx !important;
  263. }
  264. .parking-card .card-head{
  265. display: flex;
  266. flex-flow: row nowrap;
  267. justify-content:space-between;
  268. align-items: center;
  269. color:#000000;
  270. /* font-family: '黑体'; */
  271. }
  272. .parking-card .card-body{
  273. padding:0rpx;
  274. display: flex;
  275. flex-flow: row nowrap;
  276. justify-content:space-around;
  277. align-items: center;
  278. }
  279. .parking-card .card-body .body-item{
  280. text-align: center;
  281. }
  282. .parking-card .card-body .body-item view{
  283. font-size: 24rpx;
  284. color:#6f867d;
  285. margin-bottom:10rpx;
  286. }
  287. .parking-card .card-body .body-item text{
  288. font-size: 36rpx;
  289. color:#007AFF;
  290. }
  291. .parking-card .card-foot{
  292. padding:0rpx;
  293. display: flex;
  294. flex-flow: row nowrap;
  295. justify-content:space-around;
  296. align-items: center;
  297. font-size: 24rpx;
  298. color:#6f867d;
  299. }
  300. .u-progress-content{
  301. color:#ffffff;
  302. display: flex;
  303. flex-direction: column;
  304. align-items: center;
  305. justify-content: center;
  306. }
  307. .u-progress-content .title{
  308. font-size: 48rpx;
  309. font-weight: bold;
  310. margin:10rpx 0rpx;
  311. }
  312. .u-progress-content .subtitle{
  313. font-size: 28rpx;
  314. }
  315. .rpt-top .income-rpt{
  316. width:100%;
  317. height:100rpx;
  318. padding:30rpx;
  319. display: flex;
  320. flex-flow: row nowrap;
  321. justify-content:space-around;
  322. align-items: center;
  323. color:#ffffff;
  324. }
  325. .rpt-top .income-rpt .income-item{
  326. text-align: center;
  327. }
  328. .rpt-top .income-rpt .income-item view{
  329. font-size: 26rpx;
  330. margin-bottom:5rpx;
  331. }
  332. .rpt-top .income-rpt .income-item text{
  333. font-size: 32rpx;
  334. }
  335. </style>