index.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856
  1. <template>
  2. <view>
  3. <ujp-navbar title="充电">
  4. <view class="slot-wrap">
  5. <view class="navbar-left"></view>
  6. <!-- <view class="navbar-right"><u-icon name="iconfontscan" custom-prefix="custom-icon" color="#1677ff" size="40"></u-icon></view>
  7. -->
  8. </view>
  9. </ujp-navbar>
  10. <view class="charge" style="padding-bottom: 0px;">
  11. <view class="chargeInfo">
  12. <view class="chargeInfo-row">
  13. <view class="u-flex">
  14. <p>站点:</p>
  15. <h4>{{detail.stationName}}</h4>
  16. </view>
  17. </view>
  18. <view class="chargeInfo-row">
  19. <view class="u-flex">
  20. <p>桩号:</p>
  21. <h4>{{detail.deviceNo}}</h4>
  22. </view>
  23. <view class="u-flex" @click="switchCharge">
  24. <span>切换充电桩</span>
  25. <u-icon name="arrow-right" color="#999" size="24"></u-icon>
  26. </view>
  27. </view>
  28. <view class="chargeInfo-row">
  29. <view class="u-flex">
  30. <p>桩名:</p>
  31. <h4>{{detail.name}}</h4>
  32. </view>
  33. <view class="u-flex" @click="showTips()">
  34. <span>费用说明</span>
  35. <u-icon name="error-circle" color="#1677ff" size="32"></u-icon>
  36. </view>
  37. </view>
  38. </view>
  39. <view class="chargeMain">
  40. <template v-for="(item,i) in list">
  41. <view :key="i" class="chargeMain-item " @click="selectItem(item)" :class="{
  42. 'active':item.channelNo==submitForm.channelNo,
  43. 'occupy':item.status==1,
  44. 'fault':item.status==2,
  45. }">
  46. <p>{{i+1}}</p>
  47. <p>{{item.statusStr}}</p>
  48. </view>
  49. </template>
  50. <h2 v-if="isReady&&list.length==0">无可用通道<br />请联系客服人员</h2>
  51. </view>
  52. </view>
  53. <view class="charge">
  54. <view class="chargeInfo" style="margin-bottom: 10px;">
  55. <p><span style="color:red">*</span>充电{{listTypeIndex==0?'时长':'金额'}} <span style="color:#1677FF;margin-left:10px ">{{getListName()}}</span></p>
  56. </view>
  57. <u-subsection :list="listType" mode="subsection" active-color="#3786f4" :current="0"
  58. @change="changeListType"></u-subsection>
  59. <view class="chargeMain" v-show="listTypeIndex==0">
  60. <template v-for="(item,i) in timelist">
  61. <view :key="i" class="chargeMain-item " style="width: 30%;padding: 5px;"
  62. @click="submitForm.hour=item.id" :class="{
  63. 'active':submitForm.hour==item.id,
  64. }">
  65. <p>{{item.name}}</p>
  66. </view>
  67. </template>
  68. </view>
  69. <view class="chargeMain" v-show="listTypeIndex==1">
  70. <template v-for="(item,i) in moneylist">
  71. <view :key="i" class="chargeMain-item " style="width: 30%;padding: 5px;"
  72. @click="submitForm.amount=item.id" :class="{
  73. 'active':submitForm.amount==item.id,
  74. }">
  75. <p>{{item.name}}</p>
  76. </view>
  77. </template>
  78. </view>
  79. <view class="chargeInfo" style="margin-bottom: 10px;">
  80. <p v-show="listTypeIndex==0"><span style="color:red">*</span>按时间付费:需要先充值,从余额中扣费,适用会员用户。</p>
  81. <p v-show="listTypeIndex==1"><span style="color:red">*</span>按金额付费:无需充值,先付费后使用,未使用完的费用原路退回。</p>
  82. </view>
  83. </view>
  84. <view class="charge" v-if="false">
  85. <view class="chargeTime">
  86. <view v-for="(item,i) in timelist" class="chargeTime-item " style="width: 32%;" :key="i"
  87. @click="submitForm.hour=item.id" :class="{
  88. 'chargeTime-active':submitForm.hour==item.id,
  89. 'chargeTime-first':i==0
  90. }">
  91. <template v-if="i==0">
  92. <p>充满</p>
  93. <p>自停</p>
  94. </template>
  95. <template v-else>
  96. {{item.name}}
  97. </template>
  98. </view>
  99. </view>
  100. <view class="chargeTime-text">
  101. </view>
  102. </view>
  103. <view style="padding-bottom: 100px;">
  104. <view class="charge">
  105. <view class="chargeRadio">
  106. <view class="u-flex">
  107. <u-icon name="rmb-circle-fill" color="#ff9502" size="90"></u-icon>
  108. <view class="chargeRadio-text">
  109. <p>余额支付</p>
  110. <p>现有余额¥{{user.availableBalance}} </p>
  111. </view>
  112. </view>
  113. <u-button type="warning" style=" height: 34px;z-index: 0;"
  114. @click='gotoUrl("pages/user/recharge")'>我要充值</u-button>
  115. </view>
  116. </view>
  117. </view>
  118. <view class="foot-btn">
  119. <u-button type="primary" :custom-style="customStyle" @click="submit" shape="square">开始充电</u-button>
  120. </view>
  121. <u-modal v-model="showPriceList" title="费用说明">
  122. <p v-for="(item,i) in detail.priceList" class="showPriceList" :key="i">{{item.minPower}}W-{{item.maxPower}}W
  123. <span>{{item.price}}元每小时</span></p>
  124. <p style=" padding: 15px;" v-if="detail.roundingMinute!=null&&detail.roundingMinute!=-1">
  125. 超过{{detail.roundingMinute}}分钟,按1小时记,不足{{detail.roundingMinute}}分钟,不计费</p>
  126. <p style=" padding: 15px;" v-if="detail.priceList.length==0">无费用说明或为免费充电模式</p>
  127. </u-modal>
  128. <u-modal v-model="showmodel" @confirm="confirm" :showCancelButton="true" title="订单信息">
  129. <div class="showmodel">
  130. <p>桩号</p>{{detail.deviceNo}}
  131. </div>
  132. <div class="showmodel">
  133. <p>充电通道</p>{{submitForm.channelNo}}
  134. </div>
  135. <div class="showmodel">
  136. <p>支付方式</p>{{listTypeIndex==0?'余额支付':'微信支付'}}
  137. </div>
  138. <div class="showmodel">
  139. <p>充电{{listTypeIndex==0?'时长':'金额'}}</p>{{getListName()}}
  140. </div>
  141. <p class="showmodel" style="color: red;" v-if="listTypeIndex==0&&submitForm.hour==0">充满自停模式,设备充满后会自动停止计费,剩余费用会原路返还</p>
  142. <p class="showmodel" style="color: red;" v-if="listTypeIndex==1">按金额付费:无需充值,先付费后使用,未使用完的费用原路退回。</p>
  143. </u-modal>
  144. <u-modal v-model="showmodal2" :show-cancel-button="true" title="余额不足" confirm-text="前往充值"
  145. content="账户余额不足,充值成功后开始充电" @confirm="wxpay"></u-modal>
  146. </view>
  147. </template>
  148. <script>
  149. import * as API from '@/apis/index.js'
  150. import * as Pay from '@/apis/weixin.js'
  151. import {
  152. wxPayJs
  153. } from '@/utils/wxpay'
  154. export default {
  155. data() {
  156. return {
  157. showmodal: false,
  158. show: false,
  159. otherNum_f: '',
  160. moneyList_f: [],
  161. showmodal2: false,
  162. moneyActiveClass_f: "-1",
  163. fee:"",
  164. id: "",
  165. showPriceList: false,
  166. showmodel: false,
  167. //充电桩信息
  168. detail: {
  169. roundingMinute: -1,
  170. priceList: [],
  171. },
  172. user: {},
  173. //充电位子list
  174. listTypeIndex: 0,
  175. listType: [{
  176. name: '按时间付费'
  177. },
  178. {
  179. name: '按金额付费(临时充电)'
  180. }
  181. ],
  182. list: [
  183. ],
  184. recordId:"",
  185. moneylist: [{
  186. id: '0.5',
  187. name: '0.5元'
  188. },
  189. {
  190. id: '1',
  191. name: '1元'
  192. },
  193. {
  194. id: '2',
  195. name: '2元'
  196. },
  197. {
  198. id: '3',
  199. name: '3元'
  200. },
  201. {
  202. id: '4',
  203. name: '4元'
  204. },
  205. {
  206. id: '5',
  207. name: '5元'
  208. },
  209. ],
  210. timelist: [{
  211. id: '0',
  212. name: '充满自停'
  213. },
  214. {
  215. id: '1',
  216. name: '1小时'
  217. },
  218. {
  219. id: '2',
  220. name: '2小时'
  221. },
  222. {
  223. id: '3',
  224. name: '3小时'
  225. },
  226. {
  227. id: '4',
  228. name: '4小时'
  229. },
  230. {
  231. id: '5',
  232. name: '5小时'
  233. },
  234. {
  235. id: '6',
  236. name: '6小时'
  237. },
  238. {
  239. id: '8',
  240. name: '8小时'
  241. },
  242. {
  243. id: '10',
  244. name: '10小时'
  245. },
  246. ],
  247. selectItemObj: {},
  248. //提交信息
  249. submitForm: {
  250. deviceNo: '',
  251. channelNo: '',
  252. hour: '0',
  253. amount: "0.5",
  254. //paytype:'YE',
  255. },
  256. isReady: false,
  257. customStyle: {
  258. background: '#1677ff'
  259. }
  260. }
  261. },
  262. onLoad(op) {
  263. if (op.id) {
  264. this.id = op.id;
  265. this.carhelp.set("qr-default-id", op.id);
  266. } else {
  267. //用于支付后返回系统 -- 点金计划
  268. var id = this.carhelp.get("qr-default-id")
  269. if (id) {
  270. this.id = this.carhelp.get("qr-default-id");
  271. }
  272. }
  273. this.init()
  274. },
  275. methods: {
  276. wxpay(){
  277. uni.showLoading({
  278. title: "加载中",
  279. mask: true,
  280. })
  281. Pay.wxpay2({
  282. recordId:this.recordId,
  283. amount:this.fee
  284. }).then((response) => {
  285. if(!response.result){
  286. uni.showToast({
  287. title: response.message
  288. })
  289. return
  290. }
  291. var data = response.data
  292. uni.hideLoading()
  293. console.log("Pay+"+new Date().getTime())
  294. wxPayJs(data);
  295. }).catch(error => {
  296. uni.showToast({
  297. title: error
  298. })
  299. })
  300. },
  301. getListName() {
  302. var list = [];
  303. var value = [];
  304. if (this.listTypeIndex == 0) {
  305. list = this.timelist;
  306. value = this.submitForm.hour;
  307. } else {
  308. list = this.moneylist;
  309. value = this.submitForm.amount;
  310. }
  311. for (var i in list) {
  312. var obj = list[i];
  313. if (obj.id == value) {
  314. return obj.name
  315. }
  316. }
  317. return ""
  318. },
  319. changeListType(e) {
  320. console.log(e)
  321. this.listTypeIndex = e;
  322. },
  323. switchCharge() {
  324. var stationId = this.detail.stationId;
  325. console.log("switchCharge")
  326. uni.redirectTo({
  327. url: '/pages/charge/switchCharge?id=' + this.id + '&stationId=' + stationId
  328. })
  329. },
  330. moneyClick_f(index, item) {
  331. this.otherNum_f = '';
  332. this.moneyActiveClass_f = index;
  333. if (item) {
  334. this.selectItemObj = item;
  335. // if(item.imgUrl){
  336. // this.selectImg=item
  337. // }
  338. }
  339. },
  340. init() {
  341. if (!this.id) {
  342. this.switchCharge()
  343. } else {
  344. var data = {
  345. //type:1 ,
  346. };
  347. API.marketingData(data).then((res) => {
  348. this.moneyList_f = res.data.chargingMarketingList
  349. if (this.moneyList_f.length > 0) {
  350. this.selectItemObj = this.moneyList_f[0];
  351. this.moneyActiveClass_f = this.moneyList_f[0].id
  352. //(this.moneyActiveClass)
  353. }
  354. }).catch(error => {
  355. uni.showToast({
  356. title: error
  357. })
  358. })
  359. uni.showLoading({
  360. title: "加载中",
  361. mask: true,
  362. })
  363. var data = {
  364. };
  365. if (this.id) {
  366. data.deviceId = this.id
  367. }
  368. API.chargingData(data).then((res) => {
  369. this.detail = res.data.chargingDevice;
  370. if (!this.detail.online) {
  371. uni.showToast({
  372. title: '设备不在线,请扫描其他二维码'
  373. })
  374. return
  375. }
  376. this.carhelp.set("qr-default-id", this.id);
  377. this.user = res.data.userAccount;
  378. this.list = this.detail.chargeStatusArray
  379. this.isReady = true;
  380. uni.hideLoading()
  381. }).catch(error => {
  382. this.isReady = true;
  383. uni.hideLoading()
  384. uni.showToast({
  385. title: error
  386. })
  387. })
  388. }
  389. },
  390. selectItem(row) {
  391. if (row.status == 0) {
  392. this.submitForm.channelNo = row.channelNo
  393. } else {
  394. uni.showToast({
  395. title: '当前设备不可选'
  396. })
  397. }
  398. },
  399. confirm(bl) {
  400. uni.showLoading({
  401. title: "加载中",
  402. mask: true,
  403. })
  404. this.submitForm.deviceNo = this.detail.deviceNo;
  405. //提交信息
  406. var submitForm = {
  407. deviceNo: this.submitForm.deviceNo,
  408. channelNo: this.submitForm.channelNo,
  409. };
  410. if (this.listTypeIndex == 0) {
  411. submitForm.hour = this.submitForm.hour
  412. } else {
  413. submitForm.amount = this.submitForm.amount
  414. }
  415. //paytype:'YE',
  416. API.startCharging(submitForm).then((res) => {
  417. if(res.data.status=="5"){
  418. uni.hideLoading()
  419. this.recordId=res.data.recordId;
  420. var fee=res.data.fee;
  421. this.fee=(fee-this.user.availableBalance).toFixed(2);
  422. //this.otherNum_f=this.fee;
  423. if(bl){
  424. this.wxpay();
  425. }else{
  426. this.showmodal2=true;
  427. }
  428. }else{
  429. this.gotoUrl("pages/index/index");
  430. }
  431. // uni.showModal({
  432. // title: '提示',
  433. // showCancel:false,
  434. // content: '启动成功',
  435. // success: res=> {
  436. // if (res.confirm) {
  437. // //付钱 改为组件
  438. // this.gotoUrl("pages/index/index");
  439. // } else if (res.cancel) {
  440. // console.log('用户点击取消');
  441. // }
  442. // }
  443. // });
  444. // uni.showToast({
  445. // title: '启动中..'
  446. // })
  447. // setTimeout(()=>{
  448. // },3000)
  449. // uni.hideLoading()
  450. }).catch(error => {
  451. uni.hideLoading()
  452. if (error == '用户账户余额不足!') {
  453. uni.showModal({
  454. title: '支付',
  455. content: '用户账户余额不足,是否充值?',
  456. success: res => {
  457. if (res.confirm) {
  458. //付钱 改为组件
  459. this.gotoUrl("pages/user/recharge");
  460. } else if (res.cancel) {
  461. console.log('用户点击取消');
  462. }
  463. }
  464. });
  465. } else {
  466. uni.showToast({
  467. title: error
  468. })
  469. }
  470. })
  471. },
  472. submit() {
  473. if (!this.submitForm.channelNo) {
  474. uni.showToast({
  475. title: '请先选择充电通道'
  476. })
  477. return
  478. }
  479. var obj = this.list.find(item => {
  480. return item.channelNo == this.submitForm.channelNo
  481. })
  482. if (!obj || obj.status != 0) {
  483. uni.showToast({
  484. title: '当前设备不可选'
  485. })
  486. return
  487. }
  488. if ( this.listTypeIndex==0&& this.submitForm.hour == 0 && this.user.availableBalance < 5) {
  489. uni.showModal({
  490. title: '支付',
  491. content: '余额不足5元无法开启充满自停,是否充值?',
  492. success: res => {
  493. if (res.confirm) {
  494. //付钱 改为组件
  495. this.gotoUrl("pages/user/recharge");
  496. } else if (res.cancel) {
  497. console.log('用户点击取消');
  498. }
  499. }
  500. });
  501. } else {
  502. if( this.listTypeIndex==0){
  503. this.showmodel = true;
  504. }else{
  505. this.confirm(true)
  506. }
  507. }
  508. },
  509. showTips() {
  510. this.showPriceList = true
  511. }
  512. },
  513. onShow() {
  514. if (this.isReady) {
  515. if (this.id) {
  516. this.carhelp.set("qr-default-id", this.id);
  517. } else {
  518. //用于支付后返回系统 -- 点金计划
  519. this.id = this.carhelp.get("qr-default-id");
  520. }
  521. this.init()
  522. }
  523. }
  524. }
  525. </script>
  526. <style>
  527. page {
  528. background-color: #f7f7f7;
  529. }
  530. </style>
  531. <style lang="scss" scoped>
  532. .showmodel {
  533. margin-left: 20px;
  534. margin-right: 20px;
  535. p {
  536. display: inline-block;
  537. width: 100px;
  538. }
  539. }
  540. .showPriceList {
  541. margin-left: 20px;
  542. margin-right: 20px;
  543. span {
  544. float: right;
  545. }
  546. }
  547. .slot-wrap {
  548. display: flex;
  549. align-items: center;
  550. justify-content: space-between;
  551. flex: 1;
  552. }
  553. .navbar-right {
  554. display: flex;
  555. margin-right: 20rpx;
  556. align-items: center;
  557. }
  558. .charge {
  559. padding: 15px;
  560. background-color: #fff;
  561. margin-bottom: 10px;
  562. }
  563. .chargeRadio {
  564. display: flex;
  565. justify-content: space-between;
  566. align-items: center;
  567. width: 100%;
  568. .chargeRadio-text {
  569. margin-left: 5px;
  570. }
  571. }
  572. .chargeTime {
  573. display: flex;
  574. overflow: scroll;
  575. padding-bottom: 15px;
  576. .chargeTime-item {
  577. border: 1px solid #1677ff;
  578. border-radius: 50%;
  579. min-width: 56px;
  580. height: 56px;
  581. text-align: center;
  582. line-height: 56px;
  583. margin-right: 20px;
  584. }
  585. .chargeTime-first {
  586. line-height: 20px !important;
  587. padding-top: 6px;
  588. margin-right: 20px;
  589. }
  590. .chargeTime-active {
  591. color: #fff;
  592. background-color: #1677ff;
  593. }
  594. }
  595. .chargeTime-text {
  596. border-top: 1px solid #f7f7f7;
  597. padding-top: 15px;
  598. display: flex;
  599. align-items: center;
  600. span {
  601. margin-left: 20px;
  602. color: #1677ff;
  603. }
  604. }
  605. .chargeInfo {
  606. .chargeInfo-row {
  607. display: flex;
  608. align-items: center;
  609. justify-content: space-between;
  610. margin-bottom: 10px;
  611. p {
  612. color: #999;
  613. }
  614. h4 {
  615. font-weight: normal;
  616. }
  617. span {
  618. color: #1677ff;
  619. margin-right: 5px;
  620. }
  621. }
  622. }
  623. .chargeMain {
  624. display: flex;
  625. flex-wrap: wrap;
  626. justify-content: space-between;
  627. margin-top: 20px;
  628. .chargeMain-item {
  629. width: 18%;
  630. text-align: center;
  631. padding: 10px;
  632. border: 1px solid #1677ff;
  633. margin-bottom: 10px;
  634. border-radius: 10px;
  635. color: #1677ff;
  636. }
  637. .active {
  638. background-color: #1677ff;
  639. color: #fff;
  640. }
  641. .fault {
  642. background-color: #e1e1e1;
  643. color: #666;
  644. border: 1px solid #ccc;
  645. }
  646. .occupy {
  647. color: #FF4F3F;
  648. border: 1px solid #FF4F3F;
  649. }
  650. }
  651. .foot-btn {
  652. padding: 10px;
  653. position: fixed;
  654. left: 0;
  655. right: 0;
  656. bottom: 0;
  657. background-color: #fff;
  658. }
  659. .recharge {
  660. padding: 16px;
  661. // padding-bottom: 80px;
  662. .title {
  663. font-size: 16px;
  664. position: relative;
  665. }
  666. p {
  667. color: #666;
  668. margin-top: 4px;
  669. }
  670. .self-stop.active {
  671. background-color: #EFFFF7;
  672. border-color: #00B962;
  673. color: #00B962;
  674. }
  675. .rechargeMain {
  676. display: flex;
  677. flex-wrap: wrap;
  678. // justify-content: space-between;
  679. margin-top: 12px;
  680. margin-bottom: 5px;
  681. .recharge-item {
  682. .u-input {
  683. text-align: center !important;
  684. }
  685. width: 31%;
  686. border: 1px solid #e3e3e3;
  687. padding: 10px 0;
  688. border-radius: 4px;
  689. text-align: center;
  690. margin-bottom: 10px;
  691. position: relative;
  692. margin-left: 5px;
  693. font-size: 16px;
  694. }
  695. .active {
  696. background-color: #EFFFF7;
  697. border-color: #00B962;
  698. color: #00B962;
  699. }
  700. }
  701. .self-stop {
  702. width: 105px;
  703. height: 48px;
  704. line-height: 48px;
  705. border-radius: 4px;
  706. color: #101010;
  707. font-size: 16px;
  708. text-align: center;
  709. font-family: Arial;
  710. border: 1px solid rgba(227, 227, 227, 100);
  711. margin-top: 12px;
  712. }
  713. }
  714. .recharge-input {
  715. margin-top: 8px;
  716. margin-bottom: 32px;
  717. }
  718. .recharge-radio {
  719. margin-top: 10px;
  720. .recharge-radio-item {
  721. display: flex;
  722. align-items: center;
  723. }
  724. .recharge-radio-name {
  725. margin-left: 8px;
  726. }
  727. }
  728. </style>