parkinglog.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  1. <template>
  2. <view class="content">
  3. <u-navbar title="" :is-back="false" :background="{backgroundColor: '#ffffff'}" 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="showCalendar=true">
  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">
  18. <view @tap="selectedParkVal='all'" class="filter-con-item" :class="{'selected-filter':selectedParkVal=='all'}" data-val="all">全部</view>
  19. <block v-for="(item,index) in myParkSites" :key="item.park_id">
  20. <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>
  21. </block>
  22. </view>
  23. </view>
  24. <view class="filter-item">
  25. <text class="filter-label">车牌号</text>
  26. <!-- <u-field v-model="mobile" label="" placeholder="请填写手机号"></u-field> -->
  27. <view style="background-color:#f2f5fa;height:72rpx;margin-top:15rpx;"><u-input type="text" v-model="filter.carNum" :border="false" placeholder="请输入车牌号" :custom-style="filterInputCss" :placeholder-style="filterInputCss.phstyle"/></view>
  28. </view>
  29. <view class="filter-btn">
  30. <view class="filter-btn-reset" @tap="resetFilter">重置</view>
  31. <view class="filter-btn-sure" @tap="sureFilter">确定</view>
  32. </view>
  33. </view>
  34. </u-dropdown-item>
  35. </u-dropdown>
  36. </u-navbar>
  37. <u-calendar v-model="showCalendar" mode="range" @change="changeCalendar"></u-calendar>
  38. <u-tabs :list="tablist" :is-scroll="false" :current="currentTab" @change="changeTab"></u-tabs>
  39. <scroll-view style="padding:20rpx;height:calc(100vh - 135px)" scroll-y="true" @scrolltolower="scrollbtm">
  40. <view class="tab-con-item" v-for="(item,index) in pagedData.records" :key="index">
  41. <view class="item-top">
  42. <u-image width="200rpx" height="160rpx" :src="item.car_img" border-radius="5rpx" @click="previewCarPhoto(item.car_img)"></u-image>
  43. <view class="item-top-right">
  44. <text style="">{{item.parking_name}}</text>
  45. <view class="top-right-con">
  46. <view>进场时间:{{item.in_parking_time}}</view>
  47. <view v-if="item.release_status=='1'">离场时间:{{item.out_parking_time}}</view>
  48. <view>停车时长:{{item.parking_time_txt}}</view>
  49. </view>
  50. </view>
  51. </view>
  52. <view class="item-footer">
  53. <text class="car-num">{{item.car_num}}</text>
  54. <view class="item-footer-btn" v-if="item.release_status=='0'" @tap="manualOut(item)">手动出场</view>
  55. </view>
  56. </view>
  57. <!-- <u-loadmore :status="loadMoreStat"/> -->
  58. <view v-show="showMoreTip">
  59. <u-loadmore :status="loadMoreStat" :load-text="loadMoreText"/>
  60. </view>
  61. </scroll-view>
  62. </view>
  63. </template>
  64. <script>
  65. import * as api from '@/apis/parkinglog.js'
  66. import app from '@/utils/app.js'
  67. export default {
  68. data() {
  69. return {
  70. showCalendar:false,
  71. tablist:[
  72. {
  73. name:'已离场'
  74. },
  75. {
  76. name:'未离场'
  77. }
  78. ],
  79. currentTab:0,
  80. loadMoreStat:'loadmore',
  81. showMoreTip:false,
  82. loadMoreText: {
  83. loadmore: '轻轻上拉',
  84. loading: '努力加载中',
  85. nomore: '实在没有了'
  86. },
  87. filter:{
  88. startDate:'',
  89. endDate:'',
  90. carNum:''
  91. },
  92. myParkSites:[],
  93. selectedParkVal:'all',
  94. allParkIds:'',
  95. filterInputCss:{
  96. 'background-color':'#f2f5fa',
  97. 'padding-left':'10rpx',
  98. 'phstyle':'font-size:24rpx;'
  99. },
  100. pagedData:{}
  101. }
  102. },
  103. onLoad(){
  104. this.myParkSites=api.getMyParkSites();
  105. let ids=[];
  106. this.myParkSites.forEach(function(item){
  107. ids.push(item.park_id);
  108. });
  109. this.allParkIds=ids.join(",");
  110. this.loadPageData(this.getLoadParams(1));
  111. },
  112. onShow(){
  113. this.loadPageData(this.getLoadParams(1));
  114. },
  115. methods: {
  116. getLoadParams(pnum){
  117. let parkarg=this.selectedParkVal=="all"?this.allParkIds:this.selectedParkVal;
  118. if(!pnum){
  119. pnum=this.pagedData.pageNum!=null?(this.pagedData.pageNum+1):1;
  120. }
  121. return {parkingIds:parkarg,status:(this.currentTab==0?"off":"in"),carNum:this.filter.carNum,queryStart:this.filter.startDate,queryEnd:this.filter.endDate,pageNum:pnum,pageSize:10};
  122. },
  123. checkHadMore(){
  124. let rst=this.pagedData.pageNum<this.pagedData.pageCount;
  125. this.showMoreTip=true;
  126. this.loadMoreStat=rst?'loadmore':'nomore';
  127. return rst;
  128. },
  129. changeCalendar(e){
  130. //console.log(e);
  131. this.filter.startDate=e.startDate;
  132. this.filter.endDate=e.endDate;
  133. },
  134. changeTab(idx){
  135. this.currentTab=idx;
  136. this.loadPageData(this.getLoadParams(1));
  137. },
  138. resetFilter(){
  139. let resetObj={
  140. startDate:'',
  141. endDate:'',
  142. carNum:''
  143. };
  144. this.filter=resetObj;
  145. this.selectedParkVal='all';
  146. },
  147. sureFilter(){
  148. this.$refs.filterDropdown.close();
  149. this.loadPageData(this.getLoadParams(1));
  150. },
  151. scrollbtm(){
  152. console.log('scroll btm')
  153. if(!this.checkHadMore()){ //没有更多数据
  154. return;
  155. }
  156. this.loadMoreStat = 'loading';
  157. this.loadPageData(this.getLoadParams(),true);
  158. },
  159. loadPageData(param,moreLoad){
  160. uni.showLoading({
  161. title:'加载中...'
  162. });
  163. api.loadPageData(param).then(resp => {
  164. console.log(resp)
  165. uni.hideLoading();
  166. if(!resp.success){
  167. return;
  168. }
  169. if(!moreLoad){
  170. this.renderRptData(resp.data.rptData);
  171. }
  172. let pagedData=resp.data.pagedData;
  173. this.parseDatas(pagedData);
  174. if(moreLoad){ //附加以前的数据
  175. pagedData.records=pagedData.records?this.pagedData.records.concat(pagedData.records):this.pagedData.records;
  176. }
  177. this.pagedData=pagedData;
  178. this.checkHadMore();
  179. }).catch(error => {
  180. uni.hideLoading();
  181. });
  182. },
  183. renderRptData(rptData){
  184. let tabtxts=[{name:`已离场(${rptData&&rptData['1']?rptData['1']:0})`},{name:`未离场(${rptData&&rptData['0']?rptData['0']:0})`}];
  185. this.tablist=tabtxts;
  186. },
  187. parseDatas(respData){
  188. respData['pageNum']=respData.current;
  189. respData['pageCount']=respData.pages;
  190. respData['pageSize']=respData.size;
  191. let datas=respData.records;
  192. let tmp=null,pkh=null;
  193. datas.forEach((item) => {
  194. tmp=item.release_status=='0'?item.cal_parking_time:item.parking_time;
  195. tmp=!tmp?0:tmp;
  196. pkh=Math.floor(tmp/60);
  197. item['parking_time_txt']=pkh>0?(pkh.toFixed(0)+"小时"+(tmp-pkh*60)+"分钟"):(tmp+"分钟");
  198. item['car_img']=item.release_status=='0'?item.in_image:item.out_image;
  199. if(!item['car_img']){
  200. item['car_img']='../../static/img/def_car.png';
  201. }
  202. });
  203. },
  204. chargingAndPass(id){
  205. uni.navigateTo({
  206. url:'charging?parkingLogId='+id
  207. })
  208. },
  209. previewCarPhoto(img){
  210. let array = [];
  211. array.push(img);
  212. uni.previewImage({
  213. urls: array,
  214. current: array[0]
  215. });
  216. },
  217. manualOut(record){
  218. let con=`确定要对车辆【${record.car_num}](停车${record.parking_time_txt})进行手动出场吗?`;
  219. uni.showModal({
  220. title:'手动出场确认',
  221. content:con,
  222. success:(res)=>{
  223. if (res.confirm) {
  224. this.manualOutSubmit(record.id)
  225. } else if (res.cancel) {
  226. console.log('用户取消手动出场');
  227. }
  228. }
  229. })
  230. },
  231. manualOutSubmit(recordId){
  232. api.manualOut(recordId,app.takeSetting('user_id')).then(resp=>{
  233. if(!resp.success){
  234. uni.showToast({
  235. title:resp.msg||'手动出场失败',
  236. icon:'none'
  237. })
  238. return;
  239. }
  240. uni.showToast({
  241. title:'操作成功',
  242. icon:'success'
  243. })
  244. //避免成功提示跳过
  245. setTimeout(()=>{
  246. this.loadPageData(this.getLoadParams(this.pagedData.pageNum));
  247. },1500)
  248. }).catch(err=>{
  249. uni.showToast({
  250. title:'手动出场出错',
  251. icon:'none'
  252. })
  253. })
  254. }
  255. }
  256. }
  257. </script>
  258. <style>
  259. page{
  260. background-color: #f4f4f4;
  261. overflow: hidden;
  262. }
  263. .top-navbar/deep/ .u-slot-content{
  264. justify-content: space-between;
  265. padding:0rpx;
  266. }
  267. .top-navbar/deep/ .u-dropdown__menu{
  268. justify-content: flex-end;
  269. }
  270. .top-navbar/deep/ .u-dropdown__menu .u-dropdown__menu__item{
  271. flex:none;
  272. margin-right: 40rpx;
  273. }
  274. .top-navbar{
  275. font-size:28rpx;
  276. }
  277. uni-scroll-view{
  278. box-sizing: border-box;
  279. }
  280. .tab-con-item{
  281. background-color: #ffffff;
  282. border-radius: 10rpx;
  283. padding:20rpx;
  284. margin-bottom: 20rpx;
  285. }
  286. .tab-con-item .item-top{
  287. padding:0rpx;
  288. display: flex;
  289. flex-flow: row nowrap;
  290. justify-content:flex-start;
  291. align-items: center;
  292. margin-bottom: 10rpx;
  293. }
  294. .tab-con-item .item-top-right{
  295. display: flex;
  296. flex-flow: column nowrap;
  297. justify-content:space-between;
  298. margin-left:20rpx;
  299. }
  300. .tab-con-item .item-top-right>text{
  301. color:#000000;
  302. margin-bottom:20rpx;
  303. }
  304. .tab-con-item .item-top-right .top-right-con{
  305. font-size:24rpx;
  306. }
  307. .tab-con-item .item-top-right .top-right-con>view{
  308. margin-bottom:10rpx;
  309. }
  310. .tab-con-item .item-footer{
  311. display: flex;
  312. flex-flow: row nowrap;
  313. justify-content:space-between;
  314. align-items: center;
  315. font-size:24rpx;
  316. }
  317. .tab-con-item .item-footer .car-num{
  318. font-size:28rpx;
  319. font-weight: bold;
  320. }
  321. .tab-con-item .item-footer .item-footer-btn{
  322. padding:10rpx 15rpx;
  323. color:#ffffff;
  324. background-color: #185AC6;
  325. border-radius: 6rpx;
  326. }
  327. .dropdown-filter-con{
  328. display: flex;
  329. flex-direction: column;
  330. align-items: flex-start;
  331. justify-content: center;
  332. padding:20rpx 0rpx 0rpx;
  333. box-sizing: border-box;
  334. background-color: #fafafa;
  335. font-size: 26rpx;
  336. }
  337. .filter-item{
  338. width:100%;
  339. padding:0rpx 20rpx 30rpx;
  340. }
  341. .filter-item .filter-label{
  342. /* font-family: '楷体'; */
  343. }
  344. .filter-item .uni-input-wrapper{
  345. background-color: #f2f5fa;
  346. }
  347. .filter-date{
  348. width:100%;
  349. height:72rpx;
  350. line-height: 55rpx;
  351. background-color: #f2f5fa;
  352. margin-top: 20rpx;
  353. display: flex;
  354. align-items:center;
  355. padding-left:10rpx;
  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. </style>