charge.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541
  1. <template>
  2. <view class="content">
  3. <u-navbar title="" :is-back="false" class="top-navbar">
  4. <text style="position: absolute;z-index: 1;left:40rpx;">收费明细</text>
  5. <u-dropdown ref="filterDropdown">
  6. <u-dropdown-item title="筛选">
  7. <view class="slot-content dropdown-filter-con">
  8. <view class="filter-item">
  9. <text class="filter-label">查询日期</text>
  10. <view class="filter-date" @tap="selectDateRange">
  11. <text>{{filter.endDate.length>0?(filter.startDate+' 至 '+filter.endDate):'请选择'}}</text>
  12. <u-icon name="search" style="margin:0rpx 20rpx;"></u-icon>
  13. </view>
  14. </view>
  15. <!-- <view class="filter-item">
  16. <text class="filter-label">收费状态</text>
  17. <view class="filter-con" @tap="selectFilter('chargeStat',$event)">
  18. <view class="filter-con-item" data-val='0' :class="{'selected-filter-item':filter.chargeStat=='0'}">全部</view>
  19. <view class="filter-con-item" data-val='1' :class="{'selected-filter-item':filter.chargeStat=='1'}">全部</view>
  20. <view class="filter-con-item" data-val='2' :class="{'selected-filter-item':filter.chargeStat=='2'}">全部</view>
  21. <view class="filter-con-item">全部</view>
  22. <view class="filter-con-item">全部</view>
  23. </view>
  24. </view> -->
  25. <!-- <view class="filter-item">
  26. <text class="filter-label">车牌类型</text>
  27. <view class="filter-con">
  28. <view class="filter-con-item">全部</view>
  29. <view class="filter-con-item">全部</view>
  30. <view class="filter-con-item">全部</view>
  31. </view>
  32. </view>
  33. -->
  34. <view class="filter-item">
  35. <text class="filter-label">停车场</text>
  36. <view class="filter-con">
  37. <view @tap="selectedParkVal='all'" class="filter-con-item" :class="{'selected-filter':selectedParkVal=='all'}" data-val="all">全部</view>
  38. <block v-for="(item,index) in myParkSites" :key="item.park_id">
  39. <view @tap="selectedParkVal=item.park_id" class="filter-con-item" :class="{'selected-filter':selectedParkVal==item.park_id}" :data-val="item.park_id">{{item.parking_name.length>7?(item.parking_name.substr(0,7)+'...'):item.parking_name}}</view>
  40. </block>
  41. </view>
  42. </view>
  43. <!-- <view class="filter-item">
  44. <text class="filter-label">闸口</text>
  45. <view class="filter-con">
  46. <view class="filter-con-item">全部</view>
  47. <view class="filter-con-item">全部</view>
  48. <view class="filter-con-item">全部</view>
  49. </view>
  50. </view> -->
  51. <view class="filter-btn">
  52. <view class="filter-btn-reset" @tap="resetFilter">重置</view>
  53. <view class="filter-btn-sure" @tap="sureFilter">确定</view>
  54. </view>
  55. </view>
  56. </u-dropdown-item>
  57. </u-dropdown>
  58. </u-navbar>
  59. <u-calendar v-model="showCalendar" mode="range" @change="changeCalendar"></u-calendar>
  60. <view class="content-top">
  61. <view class="top-item">
  62. <view>实收金额(元)</view>
  63. <text>{{rptPay.todayPayAmount}}</text>
  64. </view>
  65. <view class="top-item">
  66. <view>收款笔数</view>
  67. <text>{{rptPay.todayPayCount}}</text>
  68. </view>
  69. <view class="top-item">
  70. <view>应收金额(元)</view>
  71. <text>{{rptPay.shouldPayAmount}}</text>
  72. </view>
  73. </view>
  74. <view class="charge-list">
  75. <block v-for="(item,index) in pagedPayLog" :key="index">
  76. <view class="charge-date">
  77. <view class="charge-date-left">{{item.dayDate}}</view>
  78. <view class="charge-date-right">当日收费 {{item.dayTotal}}元</view>
  79. </view>
  80. <block v-for="(data,didx) in item.dayDatas">
  81. <view class="charge-item">
  82. <view class="charge-item-title">{{data.car_num}}</view>
  83. <view class="charge-item-body">
  84. <view class="charge-dtl">
  85. <view>停车位置:{{data.parking_name}}</view>
  86. <view>进入时间:{{data.in_parking_time}}</view>
  87. <view>离开时间:{{data.out_parking_time}}</view>
  88. <view>停车时长:{{data.parking_time_txt}}</view>
  89. <view>支付方式:{{data.pay_mode}}</view>
  90. </view>
  91. <view class="charge-money" @tap="showChargeDtl(data.parking_log_id)">
  92. <text>{{data.pay_amount}}元</text>
  93. <u-icon name="arrow-right"></u-icon>
  94. </view>
  95. </view>
  96. </view>
  97. </block>
  98. </block>
  99. <view v-show="reachbtm">
  100. <u-loadmore :status="loadMoreStat" :load-text="loadMoreText"/>
  101. </view>
  102. <view v-show="pagedPayLog.length==0" style="margin:50rpx;text-align: center;">未找到相关数据</view>
  103. </view>
  104. </view>
  105. </template>
  106. <script>
  107. import * as api from '@/apis/charge.js'
  108. export default {
  109. data() {
  110. return {
  111. reachbtm:false,
  112. showCalendar:false,
  113. loadMoreStat:'loadmore',
  114. loadMoreText: {
  115. loadmore: '轻轻上拉',
  116. loading: '努力加载中',
  117. nomore: '实在没有了'
  118. },
  119. filter:{
  120. startDate:'',
  121. endDate:''
  122. },
  123. rptPay:{
  124. todayPayAmount:'0.00',
  125. todayPayCount:'0',
  126. shouldPayAmount:'0.00'
  127. },
  128. myParkSites:[],
  129. selectedParkVal:'all',
  130. allParkIds:'',
  131. pagedPayLog:[],
  132. loadParams:{}
  133. }
  134. },
  135. onLoad(){
  136. this.myParkSites=api.getMyParkSites();
  137. let ids=[];
  138. this.myParkSites.forEach(function(item){
  139. ids.push(item.park_id);
  140. });
  141. this.allParkIds=ids.join(",");
  142. this.loadPageData(this.getLoadParams());
  143. },
  144. onShow(){
  145. this.loadPageData(this.getLoadParams());
  146. },
  147. onReachBottom(){
  148. this.reachbtm=true;
  149. if(!this.checkHadMore()){ //没有更多数据
  150. return;
  151. }
  152. this.loadMoreStat = 'loading';
  153. this.loadMoreData(this.getLoadParams(true));
  154. },
  155. methods: {
  156. getLoadParams(loadMore){
  157. let crtParams={...this.loadParams};
  158. if(loadMore){
  159. if(crtParams.pageNum<crtParams.pageCount){
  160. crtParams.pageNum+=1;
  161. }
  162. /* else{ //更换日期,重置页码,其它参数不变
  163. crtParams.chargeDate=api.addDate(crtParams.chargeDate,-1);
  164. crtParams.pageNum=1;
  165. crtParams.pageCount=0;
  166. } */
  167. }
  168. else{//全新查询
  169. crtParams.pageNum=1;
  170. crtParams.pageCount=0;
  171. let parkarg=this.selectedParkVal=="all"?this.allParkIds:this.selectedParkVal;
  172. crtParams.parkingIds=parkarg;
  173. crtParams.chargeStart=this.filter.startDate;
  174. crtParams.chargeEnd=this.filter.endDate;
  175. crtParams.pageSize=15;
  176. }
  177. return crtParams;
  178. },
  179. checkHadMore(){
  180. //let rst=this.loadParams.pageNum<this.loadParams.pageCount||this.loadParams.chargeDate>this.loadParams.chargeStart;
  181. let rst=this.loadParams.pageNum<this.loadParams.pageCount
  182. this.loadMoreStat=rst?'loadmore':'nomore';
  183. return rst;
  184. },
  185. selectDateRange(){
  186. this.showCalendar=true;
  187. },
  188. changeCalendar(e){
  189. //console.log(e);
  190. this.filter.startDate=e.startDate;
  191. this.filter.endDate=e.endDate;
  192. },
  193. selectFilter(filterSort,e){
  194. //console.log(filterSort);
  195. //console.log(e);
  196. if(e.target.dataset.val!=null){
  197. this.filter[filterSort]=e.target.dataset.val;
  198. }
  199. },
  200. resetFilter(){
  201. let resetObj={
  202. startDate:'',
  203. endDate:''
  204. };
  205. this.filter=resetObj;
  206. this.selectedParkVal='all';
  207. },
  208. sureFilter(){
  209. this.$refs.filterDropdown.close();
  210. this.loadPageData(this.getLoadParams());
  211. //console.log('query'+parkarg)
  212. },
  213. showChargeDtl(id){
  214. //console.log(id);
  215. uni.navigateTo({
  216. url:'chargedtl?parkingLogId='+id
  217. })
  218. },
  219. loadPageData(param){ //全新查询,按chargeStart-chargeEnd 先查chargeEnd的
  220. this.pagedPayLog=[] //新查先清空之前结果
  221. this.rptPay={}
  222. uni.showLoading({
  223. title:'加载中...'
  224. });
  225. this.reachbtm=false; //全新查询重置该值
  226. //console.log(param)
  227. api.loadPageData(param).then(resp => {
  228. //console.log(resp)
  229. uni.hideLoading();
  230. if(!resp.success){
  231. return;
  232. }
  233. if(resp.data){
  234. let rptData=resp.data.rptPay||{};
  235. let tmp={};
  236. tmp.todayPayAmount=rptData.today_pay_amount?rptData.today_pay_amount.toFixed(2):'0.00';
  237. tmp.todayPayCount=rptData.today_pay_count?rptData.today_pay_count.toFixed(0):'0';
  238. tmp.shouldPayAmount=rptData.should_pay_amount?rptData.should_pay_amount.toFixed(2):'0.00';
  239. this.rptPay=tmp;
  240. }
  241. this.pagedPayLog=this.parsePayLog(param,resp.data.payLogs.pagedData,resp.data.payLogs.dayGrp);
  242. this.loadParams=param; //更新查询参数
  243. /*
  244. if(!this.reachbtm&&this.checkHadMore()){ //未到底且还有数据,自动再加载一次
  245. this.loadMoreData(this.getLoadParams(true));
  246. }*/
  247. }).catch(error => {
  248. uni.hideLoading();
  249. });
  250. },
  251. parsePayLog(param,pagedObj,dayGrp){
  252. //console.log(pagedObj);
  253. let datas=pagedObj.records;
  254. param.pageNum=pagedObj.current;
  255. param.pageCount=pagedObj.pages;
  256. //let viewObj={pageNum:pagedObj.current,pageCount:pagedObj.pages,pageSize:pagedObj.size};
  257. if(datas==null||datas.length==0){
  258. return [];
  259. }
  260. else{
  261. let dayGrpMap={}
  262. let preListDatas=dayGrp.map( (grp,idx) =>{
  263. dayGrpMap[grp.pay_date]={dayDatas:[],dayDate:grp.pay_date,dayTotal:(grp.day_pay_amount||0).toFixed(2)}
  264. return dayGrpMap[grp.pay_date]
  265. })
  266. //在dayGrpMap中填充每日明细记录
  267. let tmp=null,pkh=null;
  268. datas.forEach((item,index)=>{
  269. item["pay_mode"]={"wechat":"微信","alipay":"支付宝"}[item.pay_name]||'其它';
  270. tmp=item.parking_time;
  271. pkh=Math.floor(tmp/60);
  272. item['parking_time_txt']=pkh>0?(pkh.toFixed(0)+"小时"+(tmp-pkh*60)+"分钟"):(tmp+"分钟");
  273. if(dayGrpMap[item['pay_date']]){
  274. dayGrpMap[item['pay_date']].dayDatas.push(item)
  275. }
  276. });
  277. return preListDatas;
  278. }
  279. },
  280. loadMoreData(param){
  281. //console.log(param);
  282. api.queryChargeLog(param).then(resp => {
  283. //console.log(resp)
  284. if(!resp.success){
  285. return;
  286. }
  287. let newDatas=this.parsePayLog(param,resp.data.pagedData,resp.data.dayGrp);
  288. this.loadParams=param; //更新查询参数
  289. if(newDatas==null || newDatas.length==0){
  290. return
  291. }
  292. //新旧数据拼接(只会发生在旧尾新首间 同日期合并明细记录)
  293. let oldLastGrp=this.pagedPayLog.pop()
  294. let newFirstGrp=newDatas.shift()
  295. if(oldLastGrp['dayDate']==newFirstGrp['dayDate']){
  296. oldLastGrp['dayDatas']=oldLastGrp['dayDatas'].concat(newFirstGrp['dayDatas'])
  297. }
  298. this.pagedPayLog.push(oldLastGrp,...newFirstGrp)
  299. this.checkHadMore();
  300. }).catch(error =>{
  301. console.log('load more data error',error)
  302. });
  303. }
  304. }
  305. }
  306. </script>
  307. <style>
  308. page{
  309. background-color: #f4f4f4;
  310. }
  311. .top-navbar/deep/ .u-slot-content{
  312. justify-content: space-between;
  313. padding:0rpx;
  314. }
  315. .top-navbar/deep/ .u-dropdown__menu{
  316. justify-content: flex-end;
  317. }
  318. .top-navbar/deep/ .u-dropdown__menu .u-dropdown__menu__item{
  319. flex:none;
  320. margin-right: 40rpx;
  321. }
  322. /* .top-navbar/deep/ .u-dropdown__menu__item__text{
  323. color:#ffffff !important;
  324. } */
  325. .content {
  326. display: flex;
  327. flex-direction: column;
  328. align-items: center;
  329. justify-content: center;
  330. }
  331. .dropdown-filter-con{
  332. display: flex;
  333. flex-direction: column;
  334. align-items: flex-start;
  335. justify-content: center;
  336. padding:20rpx 0rpx 0rpx;
  337. box-sizing: border-box;
  338. background-color: #fafafa;
  339. font-size: 26rpx;
  340. }
  341. .filter-item{
  342. width:100%;
  343. padding:0rpx 20rpx 30rpx;
  344. }
  345. .filter-item .filter-label{
  346. /* font-family: '楷体'; */
  347. }
  348. .filter-date{
  349. width:100%;
  350. height:55rpx;
  351. line-height: 55rpx;
  352. background-color: #f2f5fa;
  353. margin-top: 20rpx;
  354. display: flex;
  355. align-items:center;
  356. }
  357. .filter-date text{
  358. flex:1;
  359. }
  360. .filter-con{
  361. display: flex;
  362. flex-flow: row wrap;
  363. justify-content:flex-start;
  364. align-items: center;
  365. margin-top: 20rpx;
  366. }
  367. .filter-con .filter-con-item{
  368. padding:10rpx 10rpx;
  369. text-align: center;
  370. background-color: #f2f5fa;
  371. /* color:#ffffff; */
  372. /* height: 45rpx; */
  373. width:28vw;
  374. margin-right: 3vw;
  375. margin-bottom: 20rpx;
  376. }
  377. .filter-con .selected-filter{
  378. background-color: #185ac6;
  379. color:#ffffff;
  380. }
  381. .filter-btn{
  382. display: flex;
  383. flex-flow: row wrap;
  384. justify-content:flex-start;
  385. align-items: center;
  386. height: 80rpx;
  387. width:100vw;
  388. border-top:1px solid #f2f2f2;
  389. }
  390. .filter-btn-reset{
  391. flex:1;
  392. text-align: center;
  393. line-height: 80rpx;
  394. background-color: #f2f2f2;
  395. }
  396. .filter-btn-sure{
  397. flex:2;
  398. text-align: center;
  399. background-color: #185ac6;
  400. color:#ffffff;
  401. line-height: 80rpx;
  402. }
  403. .content-top{
  404. width:100vw;
  405. /* height:130rpx; */
  406. padding:20rpx 0rpx;
  407. display: flex;
  408. flex-flow: row nowrap;
  409. justify-content:space-around;
  410. align-items: center;
  411. background: linear-gradient(#0088ff,#1f58ff);
  412. color: #ffffff;
  413. /* position: fixed; */
  414. top:95rpx;
  415. }
  416. .content-top .top-item{
  417. text-align: center;
  418. }
  419. .content-top .top-item view{
  420. font-size: 24rpx;
  421. color:#efefef;
  422. margin-bottom:10rpx;
  423. }
  424. .content-top .top-item text{
  425. font-size: 36rpx;
  426. }
  427. .charge-list{
  428. width:100vw;
  429. }
  430. .charge-list .charge-date{
  431. padding:20rpx 30rpx;
  432. font-size: 26rpx;
  433. height: 80rpx;
  434. }
  435. .charge-list .charge-date .charge-date-left{
  436. float:left;
  437. }
  438. .charge-list .charge-date .charge-date-right{
  439. float:right;
  440. }
  441. .charge-list .charge-item{
  442. background-color: #ffffff;
  443. padding:10rpx 30rpx;
  444. border-bottom: 1px solid #f2f2f2;
  445. }
  446. .charge-list .charge-item .charge-item-title{
  447. font-size: 28rpx;
  448. font-weight: bold;
  449. padding:10rpx 0rpx;
  450. }
  451. .charge-list .charge-item .charge-dtl{
  452. font-size: 26rpx;
  453. color:#888888;
  454. float:left;
  455. }
  456. .charge-list .charge-item .charge-item-body{
  457. display: flex;
  458. flex-flow: row nowrap;
  459. justify-content:space-between;
  460. align-items: center;
  461. }
  462. .charge-list .charge-item .charge-dtl view{
  463. margin-bottom: 8rpx;
  464. }
  465. .charge-list .charge-item .charge-money{
  466. margin-right: 0rpx;
  467. float:right;
  468. width:180rpx;
  469. text-align: right;
  470. }
  471. .charge-list .charge-item .charge-money text{
  472. font-size:36rpx;
  473. font-weight: bold;
  474. margin-right: 10rpx;
  475. color:#1F58FF;
  476. }
  477. </style>