index copy.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759
  1. <template>
  2. <view class="container">
  3. <page-navbar bgColor="#fff" title="商家详情"></page-navbar>
  4. <!-- 轮播图 -->
  5. <view class="carousel-map">
  6. <u-swiper
  7. :list="swiperList"
  8. previousMargin="30"
  9. nextMargin="30"
  10. circular
  11. bgColor="#000"
  12. height="430"
  13. />
  14. <!-- <image class='top-img' src='@/static/icon_test.jpg'></image> -->
  15. </view>
  16. <!-- 商家信息 -->
  17. <view class="center-box">
  18. <view class="merchant-info">
  19. <view class="info-title">
  20. <view>{{ merchant.name }}</view>
  21. </view>
  22. <view class="info-item">
  23. <view class="item-left">
  24. <view class="left-item">
  25. <view class="left-name">营业时间:</view>
  26. <view class="left-value">{{ merchant.opening }}</view>
  27. </view>
  28. <view class="left-item">
  29. <view class="left-name">营业状态:</view>
  30. <view class="left-value">{{
  31. merchant.businessStatus == '1' ? '休息中' : '营业中'
  32. }}</view>
  33. </view>
  34. </view>
  35. <view class="item-right">
  36. <view class="info-icon">
  37. <view class="info-map" @click="handlerFavouriteShop">
  38. <view class="icon-box">
  39. <u-icon :name="merchant.favorites ? 'heart-fill' : 'heart'" size="22" />
  40. </view>
  41. <view style="font-size: 20rpx; margin-top: 5rpx">收藏</view>
  42. </view>
  43. <view class="info-map" @click="handlerMakeCall">
  44. <view class="icon-box">
  45. <u-icon name="phone" size="22"></u-icon>
  46. </view>
  47. <view style="font-size: 20rpx; margin-top: 5rpx">电话</view>
  48. </view>
  49. </view>
  50. </view>
  51. </view>
  52. <view class="info-item" style="border: none">
  53. <view class="item-left">
  54. <view class="address"> {{ merchant.address }} </view>
  55. <view class="distance"> 距离您{{ (merchant.distance / 1000).toFixed(2) }}km </view>
  56. </view>
  57. <view class="item-right">
  58. <view class="info-map">
  59. <view class="icon-box">
  60. <u-icon name="map" size="22"></u-icon>
  61. </view>
  62. <view style="font-size: 20rpx; margin-top: 5rpx">导航</view>
  63. </view>
  64. </view>
  65. </view>
  66. </view>
  67. <u-gap height="8" bgColor="#F9F9F9"></u-gap>
  68. <view class="evaluate-context">
  69. <view class="flex">
  70. <view class="flex">
  71. <span class="evaluate-title">优惠</span>
  72. <view class="text_title"> 您有{{ coupons.length }}张购物券可领取 </view>
  73. </view>
  74. <view class="flex" style="color: #ed4444" @click="openPopup">
  75. <span class="text_title" style="margin-right: 6rpx">去领取</span>
  76. <u-icon name="arrow-right" size="14" color="#ED4444" />
  77. </view>
  78. </view>
  79. </view>
  80. <u-gap height="8" bgColor="#F9F9F9"></u-gap>
  81. <view class="categoryList">
  82. <u-tabs :list="categoryList" @change="handlerChangeTab"></u-tabs>
  83. </view>
  84. <u-gap height="8" bgColor="#F9F9F9"></u-gap>
  85. <view>
  86. <view
  87. class="list"
  88. :key="index"
  89. v-for="(item, index) of goods"
  90. @click="handlerSkipGoodsDetail(item, index)"
  91. >
  92. <image class="img" :src="!Boolean(item.logo) ? '@/static/QR57a.jpg' : item.logo"></image>
  93. <view class="listDetail">
  94. <view class="item-text">
  95. <view class="item-text-left"> {{ item.name }} </view>
  96. <view class="item-text-right">
  97. <image
  98. class="img"
  99. src="@/static/icon/shopCar.png"
  100. @click.stop="handlerAddCart(item)"
  101. ></image>
  102. </view>
  103. </view>
  104. <view class="item-flex">
  105. <view class="star">
  106. <u-rate count="5" v-model="item.score" readonly :size="14" />
  107. <text class="line">|</text>
  108. <text class="points">{{ item.score }}分</text>
  109. </view>
  110. <view> </view>
  111. </view>
  112. <view class="list-item">
  113. <view class="list-price">
  114. <view class="item-l">
  115. 优惠价 <span>¥{{ item.specialPrice.toFixed(2) }}</span>
  116. </view>
  117. <view class="item-r">
  118. 门市价 <span>¥{{ item.originalPrice.toFixed(2) }}</span>
  119. </view>
  120. </view>
  121. <view class="btn-box">
  122. <button class="btn" @click.stop="handlerService(item, index)">预约</button>
  123. </view>
  124. </view>
  125. </view>
  126. </view>
  127. <u-empty
  128. v-if="goods.length == 0"
  129. mode="data"
  130. icon="http://cdn.uviewui.com/uview/empty/data.png"
  131. >
  132. </u-empty>
  133. </view>
  134. </view>
  135. <!-- 底部购物车 -->
  136. <view class="bottom-box">
  137. <settleBottomComponent
  138. :goodsCateList.sync="goodsCateList"
  139. :ids="ids"
  140. @handlerDeleteGoods="handlerDeleteGoods"
  141. />
  142. </view>
  143. <!-- 弹窗 -->
  144. <u-popup :show="reserve_show" @close="reserve_show = false" round="20" mode="center">
  145. <view class="draw-box">
  146. <view class="draw-title"> 预约服务 </view>
  147. <view class="draw-item">
  148. <view class="item-text">时间</view>
  149. <view
  150. class="time-box"
  151. @click="time_show = true"
  152. :class="template_time == '' ? 'time-text' : ''"
  153. >
  154. {{ template_time == '' ? '请选择时间' : template_time }}
  155. </view>
  156. </view>
  157. <view class="draw-item">
  158. <view class="item-text">联系方式</view>
  159. <u--input
  160. placeholder="请输入联系方式"
  161. border="surround"
  162. type="number"
  163. maxlength="11"
  164. v-model="addParams.mobile"
  165. ></u--input>
  166. </view>
  167. <button class="draw-btn" @click="handlerDrawConfirmBtn">确定</button>
  168. </view>
  169. </u-popup>
  170. <!-- 时间 -->
  171. <u-datetime-picker
  172. :show="time_show"
  173. :minDate="Number(new Date())"
  174. :formatter="formatter"
  175. v-model="addParams.appointTime"
  176. @change="handlerTimeChange"
  177. @confirm="time_show = false"
  178. @cancel="time_show = false"
  179. mode="datetime"
  180. >
  181. </u-datetime-picker>
  182. <u-popup :show="show" mode="bottom" :safeAreaInsetBottom="true">
  183. <view>
  184. <cpuponComponents @close="closeCoupon" :coupons="coupons"></cpuponComponents>
  185. </view>
  186. </u-popup>
  187. </view>
  188. </template>
  189. <script>
  190. import {
  191. getSellsDetail,
  192. addReservation,
  193. addShoppingCart,
  194. getCartList,
  195. addFavorite,
  196. cancelFavorite,
  197. changeGoodsType,
  198. } from '@/api/client/business.js';
  199. import { hotMerchant } from '@/api/client/home';
  200. import { accountTotIdGetConponList } from '@/api/client/mine.js';
  201. // import cpuponComponents from '../components/couponComponent.vue';
  202. import cpuponComponents from '../components/couponComponent.vue';
  203. import settleBottomComponent from '../components/settleBottomComponent.vue';
  204. export default {
  205. components: {
  206. cpuponComponents,
  207. settleBottomComponent,
  208. },
  209. data() {
  210. return {
  211. show: false,
  212. merchant: {},
  213. goods: [],
  214. swiperList: [],
  215. categoryList: [
  216. {
  217. name: '全部',
  218. id: 0,
  219. },
  220. ], // 分类列表
  221. goodsCateList: [],
  222. queryParams: {
  223. //请求参数
  224. id: null, //商家ID
  225. region: null, //地区编码
  226. longitude: null, //经度
  227. latitude: null, //纬度
  228. },
  229. time_show: false,
  230. reserve_show: false,
  231. addParams: {
  232. merchantId: '',
  233. mobile: '',
  234. appointTime: '',
  235. goodsName: '',
  236. },
  237. template_time: '',
  238. ids: null, // 商家id
  239. coupons: [],
  240. };
  241. },
  242. onLoad(option) {
  243. console.log('@@@@option', option);
  244. this.ids = option.id;
  245. this.queryParams.id = option.id;
  246. },
  247. mounted() {
  248. let { latitude, longitude, region } = this.location;
  249. this.queryParams.latitude = latitude;
  250. this.queryParams.longitude = longitude;
  251. this.queryParams.region = region;
  252. this.handlerInitList();
  253. },
  254. onShow() {
  255. this.handletInitShopCarList();
  256. },
  257. watch: {
  258. reserve_show(newValue) {
  259. if (!newValue) {
  260. this.addParams.mobile = '';
  261. this.addParams.appointTime = '';
  262. this.template_time = '';
  263. }
  264. },
  265. },
  266. methods: {
  267. // 初始化购物车列表
  268. handletInitShopCarList() {
  269. this.swiperList = [];
  270. getCartList(this.ids).then(res => {
  271. let { merchantDTO, cartItems } = res.data;
  272. // 商品轮播图
  273. merchantDTO.banners.map(rs => {
  274. this.swiperList.push(rs.url);
  275. });
  276. if (cartItems.length == 0) {
  277. this.goodsCateList = [];
  278. } else {
  279. this.goodsCateList = cartItems;
  280. }
  281. });
  282. accountTotIdGetConponList(this.ids, {
  283. paging: '1,10',
  284. }).then(res => {
  285. this.coupons = res.data.records;
  286. });
  287. },
  288. // 初始化列表
  289. handlerInitList() {
  290. this.categoryList = [
  291. {
  292. name: '全部',
  293. id: 0,
  294. },
  295. ];
  296. getSellsDetail(this.queryParams.id, this.queryParams).then(res => {
  297. this.merchant = res.data.merchant;
  298. this.goods = res.data.goods;
  299. res.data.categories.map(rs => {
  300. this.categoryList.push(rs);
  301. });
  302. });
  303. // 获取锚点
  304. hotMerchant(this.queryParams.id).then();
  305. },
  306. // 点击拨打电话
  307. handlerMakeCall() {
  308. uni.makePhoneCall({
  309. phoneNumber: this.merchant.mobile,
  310. success: res => {
  311. console.log('@@@res', res);
  312. },
  313. fail: err => {
  314. console.log('@@@err', err);
  315. },
  316. });
  317. },
  318. // 点击跳转到商品详情
  319. handlerSkipGoodsDetail(item, index) {
  320. uni.navigateTo({
  321. url: `/pagesHome/productDetail/index?id=${item.id}&shopId=${this.queryParams.id}`,
  322. });
  323. },
  324. // 预约
  325. handlerService(item, index) {
  326. this.addParams.merchantId = this.ids;
  327. this.addParams.goodsId = item.id;
  328. this.addParams.goodsName = item.name;
  329. this.reserve_show = true;
  330. },
  331. // 点击预约确定按钮
  332. handlerDrawConfirmBtn() {
  333. if (this.addParams.appointTime == '') {
  334. uni.showToast({
  335. title: '请选择时间',
  336. icon: 'none',
  337. });
  338. return;
  339. } else if (this.addParams.mobile == '') {
  340. uni.showToast({
  341. title: '请填写手机号',
  342. icon: 'none',
  343. });
  344. return;
  345. } else if (!/^1[34578]\d{9}$/.test(this.addParams.mobile)) {
  346. uni.showToast({
  347. title: '请填写正确的手机号',
  348. icon: 'none',
  349. });
  350. return false;
  351. } else {
  352. addReservation(this.addParams.merchantId, this.addParams).then(res => {
  353. if (res.code === 'OK') {
  354. this.handlerInitList();
  355. this.reserve_show = false;
  356. uni.showToast({
  357. title: '预约成功',
  358. icon: 'success',
  359. });
  360. } else {
  361. uni.showToast({
  362. title: res.msg,
  363. icon: 'none',
  364. });
  365. return;
  366. }
  367. });
  368. }
  369. },
  370. // 收藏按钮
  371. handlerFavouriteShop() {
  372. if (this.merchant.favorites) {
  373. cancelFavorite(this.ids).then(res => {
  374. if (res.code === 'OK') {
  375. this.handlerInitList();
  376. uni.showToast({
  377. title: '取消成功',
  378. icon: 'none',
  379. });
  380. } else {
  381. uni.showToast({
  382. title: res.msg,
  383. icon: 'none',
  384. });
  385. return;
  386. }
  387. });
  388. } else {
  389. addFavorite(this.ids).then(res => {
  390. if (res.code === 'OK') {
  391. this.handlerInitList();
  392. uni.showToast({
  393. title: '收藏成功',
  394. icon: 'none',
  395. });
  396. } else {
  397. uni.showToast({
  398. title: res.msg,
  399. icon: 'none',
  400. });
  401. return;
  402. }
  403. });
  404. }
  405. },
  406. // 添加购物车
  407. handlerAddCart(e) {
  408. let params = {
  409. merchantId: this.ids,
  410. goodsId: e.id,
  411. quantity: 1,
  412. price: e.specialPrice,
  413. goodsName: e.name,
  414. goodsPic: e.logo,
  415. originalPrice: e.originalPrice,
  416. };
  417. addShoppingCart(params).then(res => {
  418. if (res.code === 'OK') {
  419. this.handletInitShopCarList();
  420. } else {
  421. uni.showToast({
  422. title: res.msg,
  423. icon: 'none',
  424. });
  425. return;
  426. }
  427. });
  428. },
  429. formatter(type, value) {
  430. if (type === 'minute') {
  431. return `00`;
  432. }
  433. return value;
  434. },
  435. // 选择时间
  436. handlerTimeChange(e) {
  437. if (e) {
  438. this.addParams.appointTime = uni.$u.timeFormat(e.value, 'yyyy-mm-dd hh:MM:ss');
  439. this.template_time = this.addParams.appointTime;
  440. }
  441. },
  442. handlerDeleteGoods(e) {
  443. this.handletInitShopCarList();
  444. },
  445. // 切换tab
  446. handlerChangeTab(e) {
  447. if (e.id == 0) {
  448. this.handlerInitList();
  449. } else {
  450. changeGoodsType(this.ids, {
  451. categoryId: e.id,
  452. size: 20,
  453. }).then(res => {
  454. this.goods = res.data;
  455. });
  456. }
  457. },
  458. openPopup() {
  459. this.show = true;
  460. },
  461. closeCoupon(data) {
  462. this.show = data;
  463. },
  464. },
  465. };
  466. </script>
  467. <style lang="scss" scoped>
  468. .container {
  469. position: relative;
  470. // 轮播图
  471. .carousel-map {
  472. width: 100%;
  473. height: 430rpx;
  474. // .top-img {
  475. // width: 100%;
  476. // }
  477. }
  478. .center-box {
  479. width: 100%;
  480. position: absolute;
  481. border-radius: 32rpx 32rpx 0 0;
  482. background-color: #fff;
  483. padding-bottom: 200rpx;
  484. // 商家信息
  485. .merchant-info {
  486. padding: 32rpx 32rpx 0;
  487. .info-title {
  488. color: #0c1223;
  489. font-size: 34rpx;
  490. font-weight: bold;
  491. border-bottom: 2rpx solid #d8d8d8;
  492. padding-bottom: 32rpx;
  493. }
  494. .info-item {
  495. display: flex;
  496. justify-content: space-between;
  497. padding: 24rpx 0;
  498. border-bottom: 2rpx solid #d8d8d8;
  499. align-items: center;
  500. color: #0c1223;
  501. font-size: 28rpx;
  502. .item-left {
  503. .left-item {
  504. display: flex;
  505. margin-bottom: 10rpx;
  506. .left-name {
  507. margin-right: 10rpx;
  508. }
  509. .left-value {
  510. }
  511. }
  512. .left-item:last-child {
  513. margin-bottom: 0;
  514. }
  515. .address {
  516. color: #0c1223;
  517. font-weight: bold;
  518. margin-bottom: 10rpx;
  519. }
  520. .distance {
  521. color: #999999;
  522. font-size: 24rpx;
  523. }
  524. }
  525. .item-right {
  526. .info-icon {
  527. display: flex;
  528. align-items: center;
  529. }
  530. .info-map {
  531. padding: 10rpx;
  532. font-size: 28rpx;
  533. text-align: center;
  534. .icon-box {
  535. background-color: #f5f5f5;
  536. border-radius: 50%;
  537. padding: 10rpx;
  538. }
  539. }
  540. }
  541. }
  542. }
  543. }
  544. }
  545. .evaluate-context {
  546. background-color: #fff;
  547. padding: 32rpx;
  548. .evaluate-title {
  549. color: #ed4444;
  550. font-size: 28rpx;
  551. font-weight: bold;
  552. margin-right: 16rpx;
  553. }
  554. .text_title {
  555. font-size: 24rpx;
  556. }
  557. }
  558. .flex {
  559. display: flex;
  560. justify-content: space-between;
  561. align-items: center;
  562. }
  563. .list {
  564. height: 220rpx;
  565. background-color: #fff;
  566. padding: 20rpx;
  567. margin-bottom: 20rpx;
  568. display: flex;
  569. .img {
  570. width: 140px;
  571. height: 100%;
  572. display: block;
  573. margin-right: 10rpx;
  574. border-radius: 10rpx;
  575. }
  576. .listDetail {
  577. width: calc(100% - 160rpx);
  578. }
  579. .item-text {
  580. display: flex;
  581. justify-content: space-between;
  582. align-items: center;
  583. font-weight: bold;
  584. margin: 10rpx 0 10rpx;
  585. color: #333;
  586. font-size: 36rpx;
  587. .item-text-left {
  588. }
  589. .item-text-right {
  590. .img {
  591. width: 50rpx;
  592. height: 50rpx;
  593. }
  594. }
  595. }
  596. .item-flex {
  597. display: flex;
  598. justify-content: space-between;
  599. align-items: center;
  600. font-size: 28rpx;
  601. margin: 0 20rpx 10rpx 0;
  602. color: #0d0d0d66;
  603. .star {
  604. display: flex;
  605. align-items: center;
  606. .line {
  607. margin: 0 12rpx;
  608. margin-top: 5rpx;
  609. font-size: 22rpx;
  610. }
  611. .points {
  612. color: #ff4b04;
  613. font-size: 22rpx;
  614. margin-top: 6rpx;
  615. margin-left: 10rpx;
  616. }
  617. }
  618. }
  619. .list-item {
  620. display: flex;
  621. justify-content: space-between;
  622. align-items: center;
  623. .list-price {
  624. .item-l {
  625. color: #e35240;
  626. font-weight: bold;
  627. font-size: 32rpx;
  628. span {
  629. font-size: 40rpx;
  630. }
  631. }
  632. .item-r {
  633. color: #a8a8a8;
  634. margin-top: 10rpx;
  635. span {
  636. text-decoration: line-through;
  637. }
  638. }
  639. }
  640. .btn-box {
  641. .btn {
  642. font-size: 26rpx;
  643. border-radius: 40rpx;
  644. border: 2rpx solid #ec5729;
  645. color: #ec5729;
  646. background-color: #fff;
  647. }
  648. }
  649. }
  650. }
  651. .draw-box {
  652. width: 560rpx;
  653. padding: 20rpx;
  654. .draw-title {
  655. font-size: 30rpx;
  656. font-weight: bold;
  657. color: #000;
  658. margin-bottom: 30rpx;
  659. }
  660. .draw-item {
  661. margin-bottom: 20rpx;
  662. .item-text {
  663. font-size: 28rpx;
  664. color: #303133;
  665. padding-left: 20rpx;
  666. margin-bottom: 8rpx;
  667. }
  668. .time-box {
  669. border-width: 0.5px !important;
  670. border-color: #dadbde !important;
  671. border-style: solid;
  672. padding: 12rpx 12rpx 18rpx 18rpx;
  673. border-radius: 8rpx;
  674. }
  675. }
  676. .draw-btn {
  677. width: 90%;
  678. background-color: #5992bb !important;
  679. color: #fff;
  680. font-size: 28rpx;
  681. border-radius: 20rpx;
  682. }
  683. }
  684. .time-text {
  685. color: #d4d6dc;
  686. }
  687. /* 分类 */
  688. .categoryList {
  689. background-color: #fff;
  690. padding-bottom: 10rpx;
  691. }
  692. .bottom-box {
  693. width: 100%;
  694. position: fixed;
  695. bottom: 5%;
  696. }
  697. </style>