index.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672
  1. <template>
  2. <div class="main-page">
  3. <view class="product-container u-skeleton" :style="{ height: productRefHeight }" ref="productRef" id="productRef">
  4. <scroll-view scroll-anchoring enableBackToTop="true" scroll-with-animation scroll-y class="scroll-page" :scroll-top="tabScrollTop">
  5. <!-- 基本信息 -->
  6. <view class="card-box">
  7. <view class="station-title">
  8. {{ stationInfo.stationName }}
  9. <view class="stition-image-wrapper">
  10. <u-image :src="stationInfo.imgs[0]" mode="aspectFill" width="80px" height="60px" @click="imgPreview(0)">
  11. <u-loading slot="loading"></u-loading>
  12. </u-image>
  13. </view>
  14. </view>
  15. <view class="time">营业时间:{{ stationInfo.busineHours }}</view>
  16. <view class="address">
  17. 地址:{{ stationInfo.address }}
  18. <view style="float:right;display:flex;" v-if="stationInfo.address" @click="toNavigation()">
  19. <u-image width="40rpx" height="40rpx" src="/static/index/navigation.png"></u-image>
  20. <text style="margin-left:12rpx;line-height: 40rpx;">{{ Number(stationDistance).toFixed(1) }}KM</text>
  21. </view>
  22. </view>
  23. </view>
  24. <!-- 价格 -->
  25. <PriceCom :stationData="stationInfo" :currentTimeIndex="curnetPrice.currentTimeIndex" />
  26. <!-- 枪 -->
  27. <ConnectorCom :stationData="stationInfo" />
  28. <view style="height:40rpx;text-align:center;padding-top:10rpx;"></view>
  29. </scroll-view>
  30. <view class="page-bottom">
  31. <view class="icon-btn">
  32. <view class="icon-btn-item" @click="linkMsgDetail()">
  33. <u-icon size="34" name="kefu-ermai"></u-icon>
  34. <view class="icon-btn-name">客服</view>
  35. </view>
  36. </view>
  37. <!-- 扫码充电 -->
  38. <view class="detail-btn">
  39. <view class="button scan" @click="scan()">
  40. <img class="list_img" src="/static/map/scan.png" alt />扫码充电
  41. </view>
  42. </view>
  43. </view>
  44. </view>
  45. <u-skeleton :loading="loading" :animation="true" bgcolor="#FFF"></u-skeleton>
  46. </div>
  47. </template>
  48. <script>
  49. /************接口API***************/
  50. import { getStation } from "@/api/station.js";
  51. import { mpScan, serviceCall } from "@/utils/tools.js";
  52. import config from "@/config/config";
  53. /************组件***************/
  54. import PriceCom from "./components/-price"; //价格组件
  55. import ConnectorCom from "./components/-connector";
  56. import { wait } from "@/utils/utils.js";
  57. export default {
  58. components: {
  59. PriceCom,
  60. ConnectorCom
  61. },
  62. data() {
  63. return {
  64. stationInfo: {},
  65. curnetPrice: {
  66. currentTimeIndex: null,
  67. price: null,
  68. },
  69. stationDistance: 0,
  70. loading: true,
  71. priceShow: false, //弹窗开关
  72. navbarOnlyBack: {
  73. background: "transparent",
  74. },
  75. navbar: {
  76. background: "#fff",
  77. },
  78. productRefHeight: "",
  79. tabScrollTop: null,
  80. scrollArr: [],
  81. scrollId: "1",
  82. scrollFlag: true,
  83. current: "1", //当前显示的轮播图页
  84. stationData: {}, //站点数据
  85. routerVal: "",
  86. pagesLength: getCurrentPages().length,
  87. };
  88. },
  89. mounted() {
  90. const { windowHeight } = uni.getSystemInfoSync();
  91. let bottomHeight = 0;
  92. let _this = this
  93. uni.getSystemInfo({
  94. success: function (res) {
  95. // res - 各种参数
  96. let bottom = uni.createSelectorQuery().select(".page-bottom");
  97. bottom
  98. .boundingClientRect(function (data) {
  99. if (data && data.height) {
  100. //data - 各种参数
  101. bottomHeight = data.height; // 获取元素宽度
  102. }
  103. _this.productRefHeight = windowHeight - bottomHeight + "px";
  104. console.log(bottomHeight);
  105. }).exec();
  106. },
  107. });
  108. },
  109. onLoad(options) {
  110. this.routerVal = options;
  111. // #ifdef MP-WEIXIN
  112. uni.showShareMenu({
  113. withShareTicket: true,
  114. menus: ["shareAppMessage", "shareTimeline"],
  115. });
  116. // #endif
  117. if (this.$options.filters.isLogin("auth")) {
  118. this.init(this.routerVal.id);
  119. }
  120. },
  121. onShow() {
  122. if (this.$options.filters.isLogin("auth")) {
  123. this.refreshConnector(this.routerVal.id);
  124. } else {
  125. this.$options.filters.navigateToLogin("navigateTo", true);
  126. }
  127. },
  128. methods: {
  129. toNavigation() {
  130. uni.openLocation({
  131. name: this.stationInfo.stationName,
  132. address: this.stationInfo.address,
  133. latitude: this.stationInfo.lat,
  134. longitude: this.stationInfo.lon,
  135. success(res) {
  136. // 打开成功
  137. }
  138. })
  139. },
  140. share() {
  141. return `/pages/station/inde?id=${this.routerVal.id}&goodsId=${this.routerVal.goodsId}`;
  142. },
  143. /**
  144. * 循环出当前促销是否为空
  145. */
  146. countPromotion() {
  147. return count
  148. },
  149. /**
  150. * 初始化信息
  151. */
  152. async init(id, distance, distributionId = "") {
  153. },
  154. /**
  155. * 刷新枪状态
  156. */
  157. async refreshConnector(id) {
  158. this.loading = true;
  159. let response = await getStation(id);
  160. this.stationInfo = response.data.data;
  161. this.stationInfo.lon = Number(this.stationInfo.lon)
  162. this.stationInfo.lat = Number(this.stationInfo.lat)
  163. if (response.data.code != 200) {
  164. uni.navigateBack(
  165. {
  166. complete: () => {
  167. uni.showToast({
  168. icon: "none",
  169. duration: 2000,
  170. title: "站点未开放",
  171. }
  172. )
  173. }
  174. })
  175. }
  176. let _this = this
  177. // 计算距离
  178. uni.getLocation({
  179. type: 'gcj02', // 默认为 wgs84 返回 gps 坐标,gcj02 返回可用于 wx.openLocation 的坐标
  180. success: async function (res) {
  181. const lat = parseFloat(res.latitude)
  182. const lon = parseFloat(res.longitude)
  183. while (_this.stationInfo.lon == null) {
  184. await wait(50)
  185. }
  186. _this.stationDistance = Math.round(_this.$options.filters.calcDistance(lon, lat, _this.stationInfo.lon, _this.stationInfo.lat) / 100) / 10;
  187. },
  188. fail: function (res) {
  189. console.log(res)
  190. },
  191. })
  192. // 获取当时时段价格
  193. let myDate = new Date();
  194. let currentTime = this.$u.timeFormat(myDate, 'hhMM');
  195. this.curnetPrice.currentTimeIndex = null;
  196. this.curnetPrice.price = null;
  197. let currentIndex = null;
  198. this.stationInfo.priceList.forEach((t, tIndex) => {
  199. if (Number(currentTime) >= Number(t.startTm)) {
  200. currentIndex = tIndex;
  201. }
  202. })
  203. this.curnetPrice.currentTimeIndex = currentIndex;
  204. if (currentIndex != null) {
  205. const price = this.stationInfo.priceList[currentIndex];
  206. this.curnetPrice.price = Number(price.elecPrice) + Number(price.servicePrice);
  207. } else {
  208. this.curnetPrice.price = null
  209. }
  210. this.loading = false;
  211. },
  212. linkMsgDetail() {
  213. serviceCall(this.stationInfo.servicePhone || config.customerServiceMobile)
  214. },
  215. /**
  216. * 返回
  217. */
  218. back() {
  219. console.log(this.pagesLength);
  220. if (this.pagesLength == 1) {
  221. uni.switchTab({
  222. url: "/pages/tabbar/station/stationList",
  223. });
  224. } else {
  225. uni.navigateBack();
  226. }
  227. },
  228. /**
  229. * 计算每个要跳转到的模块高度信息
  230. */
  231. calcSize() {
  232. let h = 0;
  233. let that = this;
  234. let arr = [
  235. "main1",
  236. "main2",
  237. "main3",
  238. "main4",
  239. "main5",
  240. "main6",
  241. "main7",
  242. "main8",
  243. "main9",
  244. "main10",
  245. "main11",
  246. ];
  247. arr.forEach((item) => {
  248. let view = uni.createSelectorQuery().select("#" + item);
  249. view
  250. .fields(
  251. {
  252. size: true,
  253. },
  254. (data) => {
  255. if (
  256. item === "main1" ||
  257. item === "main4" ||
  258. item === "main9" ||
  259. item === "main11"
  260. ) {
  261. that.scrollArr.push(h);
  262. }
  263. if (data && data.height) {
  264. h += data.height;
  265. }
  266. }
  267. )
  268. .exec();
  269. });
  270. this.scrollFlag = false;
  271. },
  272. /**
  273. * 点击顶部跳转到对应位置
  274. */
  275. headerTab(id) {
  276. if (this.scrollFlag) {
  277. this.calcSize();
  278. }
  279. this.scrollId = id;
  280. this.$nextTick(() => {
  281. this.tabScrollTop = this.scrollArr[id - 1];
  282. });
  283. },
  284. scan() {
  285. mpScan()
  286. },
  287. imgPreview(index) {
  288. uni.previewImage({
  289. current: index,
  290. indicator: "number",
  291. loop: true,
  292. urls: this.stationInfo.imgs
  293. })
  294. }
  295. },
  296. };
  297. </script>
  298. <style lang="scss" scoped>
  299. .detail-btn {
  300. display: flex;
  301. align-items: center;
  302. .button.scan {
  303. flex: 1;
  304. width: 100%;
  305. margin: 0 10rpx;
  306. background-image: linear-gradient(230deg, #00a5ff 7%, #0089c9 100%);
  307. box-shadow: 0 1px 12px 0 #0089c980;
  308. border-radius: 20px;
  309. font-size: 28rpx;
  310. line-height: 80rpx;
  311. color: #ffffff;
  312. text-align: center;
  313. margin: 0 16rpx;
  314. img {
  315. width: 40rpx;
  316. height: 40rpx;
  317. vertical-align: text-bottom;
  318. margin-right: 16rpx;
  319. }
  320. }
  321. }
  322. .header,
  323. .header-only-back {
  324. padding-left: 10rpx;
  325. position: fixed;
  326. top: var(--status-bar-height);
  327. width: 100%;
  328. z-index: 8;
  329. height: 90rpx;
  330. font-size: 30rpx;
  331. transition: all 0.5s;
  332. }
  333. /deep/ .u-navbar {
  334. padding-left: 10rpx;
  335. }
  336. .page-bottom {
  337. position: fixed;
  338. bottom: 0;
  339. left: 0;
  340. z-index: 9;
  341. background: #fff;
  342. width: 100%;
  343. display: flex;
  344. border-top: 2rpx solid #f2f2f2;
  345. box-sizing: border-box;
  346. height: 120rpx;
  347. height: calc(120rpx + constant(safe-area-inset-bottom));
  348. height: calc(120rpx + env(safe-area-inset-bottom));
  349. padding-bottom: 20rpx;
  350. padding-bottom: constant(safe-area-inset-bottom);
  351. padding-bottom: env(safe-area-inset-bottom);
  352. > .icon-btn {
  353. display: flex;
  354. align-items: center;
  355. padding-left: 20rpx;
  356. // flex: 1;
  357. > .icon-btn-item {
  358. // flex: 1;
  359. position: relative;
  360. text-align: center;
  361. font-size: 22rpx;
  362. color: #262626;
  363. display: flex;
  364. flex-direction: column;
  365. width: 60rpx;
  366. height: 100%;
  367. align-items: center;
  368. justify-content: center;
  369. > .icon-btn-name {
  370. margin: 4rpx 0;
  371. }
  372. }
  373. }
  374. > .detail-btn {
  375. flex: 1.5;
  376. }
  377. }
  378. .main-page {
  379. height: calc(100% - var(--status-bar-height));
  380. overflow: hidden;
  381. }
  382. .product-container {
  383. .header-line {
  384. height: 1px;
  385. background: #f2f2f2;
  386. position: fixed;
  387. top: 90rpx;
  388. left: 0;
  389. right: 0;
  390. z-index: 999;
  391. transition: all 0.5s;
  392. &.scroll-hide {
  393. background: none;
  394. }
  395. }
  396. .scroll-page {
  397. width: 100%;
  398. height: 100%;
  399. padding-bottom: 20rpx;
  400. }
  401. }
  402. .status_bar {
  403. background: #fff;
  404. height: var(--status-bar-height);
  405. }
  406. .card-box,
  407. .evaluate-box {
  408. border-radius: 20rpx;
  409. padding: 0rpx 20rpx;
  410. background: #ffffff;
  411. box-shadow: 0 3px 4px 2px rgba(0, 0, 0, 0.05);
  412. overflow: hidden;
  413. margin: 20rpx;
  414. }
  415. .evaluate-title {
  416. color: #262626;
  417. font-size: 28rpx;
  418. font-weight: 400;
  419. height: 90rpx;
  420. line-height: 90rpx;
  421. position: relative;
  422. &::before {
  423. background-color: #0974c5;
  424. content: "";
  425. position: absolute;
  426. border-radius: 3rpx;
  427. left: -20rpx;
  428. top: 50%;
  429. -webkit-transform: translateY(-50%);
  430. transform: translateY(-50%);
  431. width: 3px;
  432. height: 15px;
  433. }
  434. }
  435. .scroll_mask {
  436. // height: 868rpx;
  437. // padding-bottom: 100rpx;
  438. overflow-y: auto;
  439. }
  440. .mask {
  441. height: 600px;
  442. }
  443. .card-flex {
  444. padding: 30rpx 0;
  445. }
  446. .card-box {
  447. padding-top: 0 !important;
  448. }
  449. .card-content {
  450. padding: 0 20rpx;
  451. // flex: 6;
  452. }
  453. .card-p {
  454. display: block;
  455. padding-bottom: 20rpx;
  456. }
  457. .card-title {
  458. flex: 1;
  459. // color: #262626;
  460. font-weight: 700;
  461. }
  462. .station-title {
  463. font-size: 40rpx;
  464. line-height: 60rpx;
  465. font-weight: 500;
  466. margin: 20rpx 0 40rpx;
  467. }
  468. .time,
  469. .address {
  470. margin: 16rpx 0;
  471. }
  472. .stition-image-wrapper {
  473. float: right;
  474. margin: 16rpx;
  475. }
  476. .stationCard {
  477. position: relative;
  478. text-align: left;
  479. padding: 0 25rpx;
  480. line-height: 1.5;
  481. &.round-top {
  482. padding-top: 30rpx;
  483. margin-top: -30rpx;
  484. border-top-left-radius: 30rpx;
  485. border-top-right-radius: 30rpx;
  486. }
  487. .title {
  488. font-size: 32rpx;
  489. font-weight: 700;
  490. line-height: 64rpx;
  491. margin-bottom: 10rpx;
  492. }
  493. .time {
  494. font-size: 24rpx;
  495. color: #707070;
  496. margin-bottom: 10rpx;
  497. }
  498. .address {
  499. font-size: 24rpx;
  500. color: #707070;
  501. margin-bottom: 10rpx;
  502. }
  503. .price {
  504. font-size: 48rpx;
  505. font-weight: 500;
  506. margin-right: 10rpx;
  507. }
  508. .label {
  509. display: inline-block;
  510. float: right;
  511. height: 40rpx;
  512. line-height: 38rpx;
  513. font-size: 20rpx;
  514. padding: 0 20rpx 0 55rpx;
  515. background-position: left top;
  516. background-repeat: no-repeat;
  517. background-size: 42rpx 100%;
  518. border-radius: 5px;
  519. }
  520. .label.fast {
  521. margin-right: 20rpx;
  522. border: 1px solid #00a5ff;
  523. background-image: url(/static/map/fast-pile-count-l.png);
  524. }
  525. .label.slow {
  526. border: 1px solid #ff9920;
  527. background-image: url(/static/map/slow-pile-count-l.png);
  528. }
  529. .bottom {
  530. height: 100rpx;
  531. position: relative;
  532. }
  533. }
  534. /* DarkMode 下的样式 start */
  535. @media (prefers-color-scheme: dark) {
  536. .product-container {
  537. // background-image: linear-gradient(
  538. // 180deg,
  539. // #00c4b8 12%,
  540. // #015a54 29%,
  541. // #121425 40%
  542. // );
  543. background-color: #121425;
  544. }
  545. .gap-line {
  546. background-color: #121425;
  547. }
  548. .recommend-box,
  549. .detail-box,
  550. .store-recommend,
  551. .store-info,
  552. .evaluate-box,
  553. .card-box,
  554. .group-list {
  555. background: #222336;
  556. color: #ffffff;
  557. box-shadow: 0 1px 5px 2px rgba(255, 255, 255, 0.05);
  558. }
  559. .store-recommend-title,
  560. .evaluate-title,
  561. .group-name {
  562. color: #ffffff;
  563. }
  564. .money {
  565. color: #ffffff;
  566. }
  567. .card-row .lable {
  568. color: #a9a9a9;
  569. }
  570. .card-row .content {
  571. color: #ffffff;
  572. }
  573. .radio-button {
  574. background: #f6f6f720;
  575. }
  576. .page-bottom {
  577. background: #222336;
  578. border-top: 2rpx solid #343434;
  579. > .icon-btn > .icon-btn-item {
  580. color: #ffffff;
  581. }
  582. .detail-btn > .to-scan {
  583. background-image: linear-gradient(230deg, #00a5ff 7%, #0089c9 100%);
  584. border: 1px solid #f6f6f720;
  585. box-shadow: none;
  586. }
  587. }
  588. .title {
  589. color: #ffffff;
  590. }
  591. .time,
  592. .address {
  593. color: #a9a9a9;
  594. }
  595. }
  596. </style>
  597. <style lang="scss">
  598. page {
  599. background-color: #f7f7f7;
  600. }
  601. /* DarkMode 下的样式 start */
  602. @media (prefers-color-scheme: dark) {
  603. page {
  604. background-color: #121425;
  605. }
  606. }
  607. </style>