GoodsCon.vue 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224
  1. <template>
  2. <div
  3. :class="[posterImageStatus ? 'noscroll product-con' : 'product-con']"
  4. ref="box"
  5. @scroll.native="onScroll"
  6. >
  7. <div
  8. class="header acea-row row-center-wrapper"
  9. :style="'opacity:' + opacity"
  10. ref="header"
  11. >
  12. <div
  13. class="item"
  14. :class="navActive === index ? 'on' : ''"
  15. v-for="(item, index) in navList"
  16. :key="index"
  17. @click="asideTap(index)"
  18. >
  19. {{ item }}
  20. </div>
  21. </div>
  22. <div id="title0">
  23. <product-con-swiper
  24. :img-urls="storeInfo.slider_image"
  25. :videoline="storeInfo.video_link"
  26. ></product-con-swiper>
  27. <div class="wrapper">
  28. <div class="share acea-row row-between row-bottom">
  29. <div class="money font-color-red">
  30. ¥<span class="num">{{ storeInfo.price }}</span
  31. ><span
  32. class="vip-money"
  33. v-if="storeInfo.vip_price && storeInfo.vip_price > 0"
  34. >¥{{ storeInfo.vip_price }}</span
  35. ><img
  36. src="@assets/images/vip.png"
  37. class="image"
  38. v-if="storeInfo.vip_price && storeInfo.vip_price > 0"
  39. />
  40. </div>
  41. <div
  42. class="iconfont icon-fenxiang"
  43. @click="listenerActionSheet"
  44. ></div>
  45. </div>
  46. <div class="introduce">{{ storeInfo.store_name }}</div>
  47. <div class="label acea-row row-between-wrapper">
  48. <div>原价:¥{{ storeInfo.ot_price }}</div>
  49. <div>库存:{{ storeInfo.stock }}{{ storeInfo.unit_name }}</div>
  50. <div>销量:{{ storeInfo.fsales }}{{ storeInfo.unit_name }}</div>
  51. </div>
  52. <div
  53. class="coupon acea-row row-between-wrapper"
  54. @click="couponTap"
  55. v-if="couponList.length"
  56. >
  57. <div class="hide line1 acea-row">
  58. 优惠券:
  59. <div
  60. class="activity"
  61. v-for="(item, index) in couponList"
  62. :key="index"
  63. >
  64. 满{{ item.use_min_price }}减{{ item.coupon_price }}
  65. </div>
  66. </div>
  67. <div class="iconfont icon-jiantou"></div>
  68. </div>
  69. <div class="coupon acea-row row-between-wrapper" v-if="activity.length">
  70. <div class="line1 acea-row">
  71. 活&nbsp;&nbsp;&nbsp;动:
  72. <div
  73. v-for="(item, index) in activity"
  74. :key="index"
  75. @click="goDetail(item)"
  76. >
  77. <div
  78. class="acea-row row-center-wrapper"
  79. v-if="item.type === '1'"
  80. :class="{
  81. activity_pin: index === 0,
  82. activity_miao: index === 1,
  83. activity_kan: index === 2
  84. }"
  85. >
  86. <span class="iconfonts iconfont icon-shenhezhong"></span>
  87. <span class="activity_title">&nbsp;参与秒杀</span>
  88. </div>
  89. <div
  90. class="acea-row row-center-wrapper"
  91. v-if="item.type === '2'"
  92. :class="{
  93. activity_pin: index === 0,
  94. activity_miao: index === 1,
  95. activity_kan: index === 2
  96. }"
  97. >
  98. <span class="iconfonts iconfont icon-kanjia"></span>
  99. <span class="activity_title">&nbsp;参与砍价</span>
  100. </div>
  101. <div
  102. class="acea-row row-center-wrapper"
  103. v-if="item.type === '3'"
  104. :class="{
  105. activity_pin: index === 0,
  106. activity_miao: index === 1,
  107. activity_kan: index === 2
  108. }"
  109. >
  110. <span class="iconfonts iconfont icon-pintuan"></span>
  111. <span class="activity_title">&nbsp;参与拼团</span>
  112. </div>
  113. </div>
  114. </div>
  115. </div>
  116. </div>
  117. <div
  118. class="attribute acea-row row-between-wrapper"
  119. @click="selecAttrTap"
  120. v-if="attr.productAttr.length"
  121. >
  122. <div>
  123. {{ attrTxt }}:<span class="atterTxt">{{ attrValue }}</span>
  124. </div>
  125. <div class="iconfont icon-jiantou"></div>
  126. </div>
  127. <!--<div-->
  128. <!--class="store-info"-->
  129. <!--v-if="system_store.id !== undefined && storeSelfMention"-->
  130. <!--&gt;-->
  131. <!--<div-->
  132. <!--class="acea-row row-between-wrapper store-box"-->
  133. <!--@click="showStoreList"-->
  134. <!--&gt;-->
  135. <!--<div class="title">门店信息</div>-->
  136. <!--<div class="iconfont icon-jiantou"></div>-->
  137. <!--</div>-->
  138. <!--<div class="info acea-row row-between-wrapper">-->
  139. <!--<div class="pictrue"><img :src="storeItems.image" /></div>-->
  140. <!--<div class="text">-->
  141. <!--<div class="name line1">-->
  142. <!--{{ storeItems.name }}-->
  143. <!--</div>-->
  144. <!--<div class="address acea-row row-middle" @click="showChang">-->
  145. <!--<span class="addressTxt line1 address_tit"-->
  146. <!--&gt;{{ storeItems.address-->
  147. <!--}}{{ ", " + storeItems.detailed_address }}</span-->
  148. <!--&gt;<span class="iconfont icon-youjian"></span>-->
  149. <!--</div>-->
  150. <!--</div>-->
  151. <!--<div class="addressBox">-->
  152. <!--<a-->
  153. <!--class="iconfont icon-dadianhua01 font-color-red phone"-->
  154. <!--:href="'tel:' + storeItems.phone"-->
  155. <!--&gt;</a>-->
  156. <!--<div-->
  157. <!--class="addressTxt corlor-red"-->
  158. <!--@click="showChang"-->
  159. <!--v-if="storeItems.range"-->
  160. <!--&gt;-->
  161. <!--距离{{ storeItems.range }}千米-->
  162. <!--</div>-->
  163. <!--</div>-->
  164. <!--</div>-->
  165. <!--</div>-->
  166. </div>
  167. <div class="userEvaluation" id="title1">
  168. <div class="title acea-row row-between-wrapper">
  169. <div>用户评价({{ replyCount }})</div>
  170. <router-link :to="{ path: '/evaluate_list/' + id }" class="praise"
  171. ><span class="font-color-red">{{ replyChance }}%</span>好评率<span
  172. class="iconfont icon-jiantou"
  173. ></span
  174. ></router-link>
  175. </div>
  176. <user-evaluation :reply="reply"></user-evaluation>
  177. </div>
  178. <div class="superior" v-if="goodList.length > 0" id="title2">
  179. <div class="title acea-row row-center-wrapper">
  180. <img src="@assets/images/ling.png" />
  181. <div class="titleTxt">优品推荐</div>
  182. <img src="@assets/images/ling.png" />
  183. </div>
  184. <template>
  185. <div class="slider-banner banner">
  186. <swiper :options="swiperRecommend">
  187. <swiper-slide v-for="(item, index) in goodList" :key="index">
  188. <div class="list acea-row row-middle">
  189. <div
  190. class="item"
  191. v-for="val in item.list"
  192. :key="val.image"
  193. @click="goGoods(val)"
  194. >
  195. <div class="pictrue">
  196. <img :src="val.image" />
  197. <span
  198. class="pictrue_log pictrue_log_class"
  199. v-if="val.activity && val.activity.type === '1'"
  200. >秒杀</span
  201. >
  202. <span
  203. class="pictrue_log pictrue_log_class"
  204. v-if="val.activity && val.activity.type === '2'"
  205. >砍价</span
  206. >
  207. <span
  208. class="pictrue_log pictrue_log_class"
  209. v-if="val.activity && val.activity.type === '3'"
  210. >拼团</span
  211. >
  212. </div>
  213. <div class="name line1">{{ val.store_name }}</div>
  214. <div class="money font-color-red">¥{{ val.price }}</div>
  215. </div>
  216. </div>
  217. </swiper-slide>
  218. <div class="swiper-pagination" slot="pagination"></div>
  219. </swiper>
  220. </div>
  221. </template>
  222. </div>
  223. <div class="product-intro" id="title3">
  224. <div class="title">产品介绍</div>
  225. <div class="conter" v-html="storeInfo.description"></div>
  226. </div>
  227. <div style="height:1.2rem;"></div>
  228. <div class="footer acea-row row-between-wrapper">
  229. <div class="item" @click="$router.push({ path: '/customer/list/' + id })">
  230. <div class="iconfont icon-kefu"></div>
  231. <div>客服</div>
  232. </div>
  233. <div class="item" @click="setCollect">
  234. <div
  235. class="iconfont"
  236. :class="storeInfo.userCollect ? 'icon-shoucang1' : 'icon-shoucang'"
  237. ></div>
  238. <div>收藏</div>
  239. </div>
  240. <router-link
  241. :to="'/cart'"
  242. class="item animated"
  243. :class="animated === true ? 'bounceIn' : ''"
  244. >
  245. <div class="iconfont icon-gouwuche1">
  246. <span class="num bg-color-red" v-if="CartCount > 0">{{
  247. CartCount
  248. }}</span>
  249. </div>
  250. <div>购物车</div>
  251. </router-link>
  252. <div class="bnt acea-row">
  253. <div class="joinCart" @click="joinCart">加入购物车</div>
  254. <div class="buy" @click="tapBuy">立即购买</div>
  255. </div>
  256. </div>
  257. <Share-red-packets
  258. :priceName="priceName"
  259. v-on:changeFun="changeFun"
  260. v-if="priceName !== 0"
  261. ></Share-red-packets>
  262. <CouponPop v-on:changeFun="changeFun" :coupon="coupon"></CouponPop>
  263. <Product-window v-on:changeFun="changeFun" :attr="attr"></Product-window>
  264. <StorePoster
  265. v-on:setPosterImageStatus="setPosterImageStatus"
  266. :posterImageStatus="posterImageStatus"
  267. :posterData="posterData"
  268. ></StorePoster>
  269. <ShareInfo
  270. v-on:setShareInfoStatus="setShareInfoStatus"
  271. :shareInfoStatus="shareInfoStatus"
  272. ></ShareInfo>
  273. <div
  274. class="generate-posters acea-row row-middle"
  275. :class="posters ? 'on' : ''"
  276. >
  277. <div
  278. class="item"
  279. v-if="weixinStatus === true"
  280. @click="setShareInfoStatus"
  281. >
  282. <div class="iconfont icon-weixin3"></div>
  283. <div class="">发送给朋友</div>
  284. </div>
  285. <div class="item" @click="setPosterImageStatus">
  286. <div class="iconfont icon-haibao"></div>
  287. <div class="">生成海报</div>
  288. </div>
  289. </div>
  290. <div
  291. class="mask"
  292. @touchmove.prevent
  293. @click="listenerActionClose"
  294. v-show="posters"
  295. ></div>
  296. <div class="geoPage" v-if="mapShow">
  297. <iframe
  298. width="100%"
  299. height="100%"
  300. frameborder="0"
  301. scrolling="no"
  302. :src="
  303. 'https://apis.map.qq.com/uri/v1/geocoder?coord=' +
  304. system_store.latitude +
  305. ',' +
  306. system_store.longitude +
  307. '&referer=' +
  308. mapKey
  309. "
  310. >
  311. </iframe>
  312. </div>
  313. </div>
  314. </template>
  315. <script>
  316. import { swiper, swiperSlide } from "vue-awesome-swiper";
  317. import "@assets/css/swiper.min.css";
  318. import ProductConSwiper from "@components/ProductConSwiper";
  319. import UserEvaluation from "@components/UserEvaluation";
  320. import ShareRedPackets from "@components/ShareRedPackets";
  321. import CouponPop from "@components/CouponPop";
  322. import ProductWindow from "@components/ProductWindow";
  323. import StorePoster from "@components/StorePoster";
  324. import ShareInfo from "@components/ShareInfo";
  325. import { goShopDetail } from "@libs/order";
  326. import debounce from "lodash.debounce";
  327. import {
  328. getProductDetail,
  329. postCartAdd,
  330. getCartCount,
  331. getProductCode,
  332. storeListApi
  333. } from "@api/store";
  334. import {
  335. getCoupon,
  336. getCollectAdd,
  337. getCollectDel,
  338. getUserInfo
  339. } from "@api/user";
  340. import { isWeixin } from "@utils/index";
  341. import { wechatEvevt } from "@libs/wechat";
  342. import { imageBase64 } from "@api/public";
  343. import { mapGetters } from "vuex";
  344. import cookie from "@utils/store/cookie";
  345. let NAME = "GoodsCon";
  346. const LONGITUDE = "user_longitude";
  347. const LATITUDE = "user_latitude";
  348. export default {
  349. name: NAME,
  350. components: {
  351. swiper,
  352. swiperSlide,
  353. ProductConSwiper,
  354. UserEvaluation,
  355. ShareRedPackets,
  356. CouponPop,
  357. ProductWindow,
  358. StorePoster,
  359. ShareInfo
  360. },
  361. data: function() {
  362. return {
  363. shareInfoStatus: false,
  364. weixinStatus: false,
  365. mapShow: false,
  366. mapKey: "",
  367. posterData: {
  368. image: "",
  369. title: "",
  370. price: "",
  371. code: ""
  372. },
  373. posterImageStatus: false,
  374. animated: false,
  375. coupon: {
  376. coupon: false,
  377. list: []
  378. },
  379. attr: {
  380. cartAttr: false,
  381. productAttr: [],
  382. productSelect: {}
  383. },
  384. isOpen: false, //是否打开属性组件
  385. productValue: [],
  386. id: 0,
  387. storeInfo: {},
  388. couponList: [],
  389. attrTxt: "请选择",
  390. attrValue: "",
  391. cart_num: 1, //购买数量
  392. replyCount: "",
  393. replyChance: "",
  394. reply: [],
  395. priceName: 0,
  396. CartCount: 0,
  397. posters: false,
  398. banner: [{}, {}],
  399. swiperRecommend: {
  400. pagination: {
  401. el: ".swiper-pagination",
  402. clickable: true
  403. },
  404. autoplay: false,
  405. loop: false,
  406. speed: 1000,
  407. observer: true,
  408. observeParents: true
  409. },
  410. goodList: [],
  411. system_store: {},
  412. storeSelfMention: true,
  413. storeItems: {},
  414. activity: [],
  415. navList: [],
  416. lock: false,
  417. navActive: 0,
  418. opacity: 0
  419. };
  420. },
  421. computed: mapGetters(["isLogin"]),
  422. watch: {
  423. $route(n) {
  424. if (n.name === NAME) {
  425. this.id = n.params.id;
  426. this.storeInfo.slider_image = [];
  427. this.productCon();
  428. }
  429. }
  430. },
  431. updated() {
  432. // window.scroll(0, 0);
  433. },
  434. mounted: function() {
  435. document.addEventListener("scroll", this.onScroll, false);
  436. this.id = this.$route.params.id;
  437. this.storeInfo.slider_image = [];
  438. this.productCon();
  439. this.coupons();
  440. window.addEventListener("scroll", this.handleScroll);
  441. this.getList();
  442. },
  443. methods: {
  444. // 商品详情跳转
  445. goDetail(item) {
  446. if (item.type === "1") {
  447. this.$router.push({
  448. path: "/activity/seckill_detail/" + item.id + "/" + item.time + "/1"
  449. });
  450. } else if (item.type === "2") {
  451. this.$router.push({
  452. path: "/activity/dargain_detail/" + item.id
  453. });
  454. } else {
  455. this.$router.push({
  456. path: "/activity/group_detail/" + item.id
  457. });
  458. }
  459. },
  460. // 获取门店列表数据
  461. getList() {
  462. let data = {
  463. latitude: cookie.get(LATITUDE) || "", //纬度
  464. longitude: cookie.get(LONGITUDE) || "", //经度
  465. page: 1,
  466. limit: 10
  467. };
  468. storeListApi(data)
  469. .then(res => {
  470. this.storeItems = res.data.list[0];
  471. })
  472. .catch(err => {
  473. console.log(err);
  474. });
  475. },
  476. handleScroll() {
  477. let top = document.body.scrollTop || document.documentElement.scrollTop;
  478. let opacity = top / 350;
  479. opacity = opacity > 1 ? 1 : opacity;
  480. this.opacity = opacity;
  481. },
  482. asideTap(a) {
  483. this.$nextTick(() => {
  484. let index = a;
  485. this.navActive = index;
  486. if (!this.goodList.length && index === 2) {
  487. index = 3;
  488. }
  489. let element = document.querySelector("#title" + index);
  490. const top =
  491. element.offsetTop - this.$refs.header.offsetHeight - window.scrollY;
  492. this.lock = true;
  493. window.scrollBy({ top, left: 0, behavior: "smooth" });
  494. });
  495. },
  496. onScroll: debounce(function() {
  497. if (this.lock) {
  498. this.lock = false;
  499. return;
  500. }
  501. const headerHeight = this.$refs.header.offsetHeight,
  502. { scrollY } = window,
  503. titles = [];
  504. titles.push(document.querySelector("#title0"));
  505. titles.push(document.querySelector("#title1"));
  506. if (this.goodList.length) {
  507. titles.push(document.querySelector("#title2"));
  508. }
  509. titles.push(document.querySelector("#title3"));
  510. titles.reduce((initial, title, index) => {
  511. if (
  512. !document.querySelector("#title0") &&
  513. !document.querySelector("#title1") &&
  514. !document.querySelector("#title2")
  515. ) {
  516. return;
  517. }
  518. if (initial) return initial;
  519. if (scrollY + headerHeight < title.offsetTop + title.offsetHeight) {
  520. initial = true;
  521. this.navActive = index;
  522. }
  523. return initial;
  524. }, false);
  525. }, 500),
  526. showChang: function() {
  527. if (isWeixin()) {
  528. let config = {
  529. latitude: parseFloat(this.storeItems.latitude),
  530. longitude: parseFloat(this.storeItems.longitude),
  531. name: this.storeItems.name,
  532. address: this.storeItems.address + this.system_store.detailed_address
  533. };
  534. wechatEvevt("openLocation", config)
  535. .then(res => {
  536. console.log(res);
  537. })
  538. .catch(res => {
  539. if (res.is_ready) {
  540. res.wx.openLocation(config);
  541. }
  542. });
  543. } else {
  544. if (!this.mapKey)
  545. return this.$dialog.error(
  546. "暂无法使用查看地图,请配置您的腾讯地图key"
  547. );
  548. this.mapShow = true;
  549. }
  550. },
  551. updateTitle() {
  552. document.title = this.storeInfo.store_name || this.$route.meta.title;
  553. },
  554. // 调转到门店列表
  555. showStoreList() {
  556. this.$store.commit("GET_TO", "details");
  557. this.$router.push("/shop/storeList/details");
  558. },
  559. setOpenShare: function() {
  560. var data = this.storeInfo;
  561. var href = location.href;
  562. if (isWeixin()) {
  563. if (this.isLogin) {
  564. getUserInfo().then(res => {
  565. href =
  566. href.indexOf("?") === -1
  567. ? href + "?spread=" + res.data.uid
  568. : href + "&spread=" + res.data.uid;
  569. var configAppMessage = {
  570. desc: data.store_info,
  571. title: data.store_name,
  572. link: href,
  573. imgUrl: data.image
  574. };
  575. wechatEvevt(
  576. ["updateAppMessageShareData", "updateTimelineShareData"],
  577. configAppMessage
  578. )
  579. .then(res => {
  580. console.log(res);
  581. })
  582. .catch(res => {
  583. if (res.is_ready) {
  584. res.wx.updateAppMessageShareData(configAppMessage);
  585. res.wx.updateTimelineShareData(configAppMessage);
  586. }
  587. });
  588. });
  589. } else {
  590. var configAppMessage = {
  591. desc: data.store_info,
  592. title: data.store_name,
  593. link: href,
  594. imgUrl: data.image
  595. };
  596. wechatEvevt(
  597. ["updateAppMessageShareData", "updateTimelineShareData"],
  598. configAppMessage
  599. )
  600. .then(res => {
  601. console.log(res);
  602. })
  603. .catch(res => {
  604. if (res.is_ready) {
  605. res.wx.updateAppMessageShareData(configAppMessage);
  606. res.wx.updateTimelineShareData(configAppMessage);
  607. }
  608. });
  609. }
  610. }
  611. },
  612. setShareInfoStatus: function() {
  613. this.shareInfoStatus = !this.shareInfoStatus;
  614. this.posters = false;
  615. },
  616. shareCode: function(value) {
  617. var that = this;
  618. getProductCode(that.id).then(res => {
  619. if (res.data.code) that.posterData.code = res.data.code;
  620. value === false && that.listenerActionSheet();
  621. });
  622. },
  623. setPosterImageStatus: function() {
  624. var sTop = document.body || document.documentElement;
  625. sTop.scrollTop = 0;
  626. this.posterImageStatus = !this.posterImageStatus;
  627. this.posters = false;
  628. },
  629. //产品详情接口;
  630. productCon: function() {
  631. let that = this;
  632. getProductDetail(that.id)
  633. .then(res => {
  634. that.$set(that, "storeInfo", res.data.storeInfo);
  635. that.$set(that.attr, "productAttr", res.data.productAttr);
  636. that.$set(that, "productValue", res.data.productValue);
  637. that.$set(that, "replyCount", res.data.replyCount);
  638. that.$set(that, "replyChance", res.data.replyChance);
  639. that.reply = res.data.reply ? [res.data.reply] : [];
  640. that.$set(that, "reply", that.reply);
  641. that.$set(that, "priceName", res.data.priceName);
  642. that.posterData.image = that.storeInfo.image_base;
  643. that.activity = res.data.activity ? res.data.activity : [];
  644. if (that.storeInfo.store_name.length > 30) {
  645. that.posterData.title =
  646. that.storeInfo.store_name.substring(0, 30) + "...";
  647. } else {
  648. that.posterData.title = that.storeInfo.store_name;
  649. }
  650. that.storeSelfMention = res.data.store_self_mention ? true : false;
  651. that.posterData.price = that.storeInfo.price;
  652. that.posterData.code = that.storeInfo.code_base;
  653. that.system_store = res.data.system_store;
  654. let good_list = res.data.good_list || [];
  655. let goodArray = [];
  656. let count = Math.ceil(good_list.length / 6);
  657. for (let i = 0; i < count; i++) {
  658. var list = good_list.slice(i * 6, i * 6 + 6);
  659. if (list.length) goodArray.push({ list: list });
  660. }
  661. that.mapKey = res.data.mapKey;
  662. that.$set(that, "goodList", goodArray);
  663. let navList = ["商品", "评价", "详情"];
  664. if (goodArray.length) {
  665. navList.splice(2, 0, "推荐");
  666. }
  667. that.navList = navList;
  668. that.updateTitle();
  669. that.DefaultSelect();
  670. that.getCartCount();
  671. that.getImageBase64();
  672. that.setOpenShare();
  673. })
  674. .catch(res => {
  675. that.$dialog.error(res.msg);
  676. that.$router.go(-1);
  677. });
  678. },
  679. getImageBase64: function() {
  680. let that = this;
  681. imageBase64(this.posterData.image, that.posterData.code)
  682. .then(res => {
  683. that.posterData.image = res.data.image;
  684. that.posterData.code = res.data.code;
  685. that.isLogin && that.shareCode();
  686. })
  687. .catch(() => {
  688. that.isLogin && that.shareCode();
  689. });
  690. },
  691. //默认选中属性;
  692. DefaultSelect: function() {
  693. let productAttr = this.attr.productAttr,
  694. value = [];
  695. for (var key in this.productValue) {
  696. if (this.productValue[key].stock > 0) {
  697. value = this.attr.productAttr.length ? key.split(",") : [];
  698. break;
  699. }
  700. }
  701. for (let i = 0; i < productAttr.length; i++) {
  702. this.$set(productAttr[i], "index", value[i]);
  703. }
  704. //sort();排序函数:数字-英文-汉字;
  705. let productSelect = this.productValue[value.sort().join(",")];
  706. if (productSelect && productAttr.length) {
  707. this.$set(
  708. this.attr.productSelect,
  709. "store_name",
  710. this.storeInfo.store_name
  711. );
  712. this.$set(this.attr.productSelect, "image", productSelect.image);
  713. this.$set(this.attr.productSelect, "price", productSelect.price);
  714. this.$set(this.attr.productSelect, "stock", productSelect.stock);
  715. this.$set(this.attr.productSelect, "unique", productSelect.unique);
  716. this.$set(this.attr.productSelect, "cart_num", 1);
  717. this.$set(this, "attrValue", value.sort().join(","));
  718. this.$set(this, "attrTxt", "已选择");
  719. } else if (!productSelect && productAttr.length) {
  720. this.$set(
  721. this.attr.productSelect,
  722. "store_name",
  723. this.storeInfo.store_name
  724. );
  725. this.$set(this.attr.productSelect, "image", this.storeInfo.image);
  726. this.$set(this.attr.productSelect, "price", this.storeInfo.price);
  727. this.$set(this.attr.productSelect, "stock", 0);
  728. this.$set(this.attr.productSelect, "unique", "");
  729. this.$set(this.attr.productSelect, "cart_num", 0);
  730. this.$set(this, "attrValue", "");
  731. this.$set(this, "attrTxt", "请选择");
  732. } else if (!productSelect && !productAttr.length) {
  733. this.$set(
  734. this.attr.productSelect,
  735. "store_name",
  736. this.storeInfo.store_name
  737. );
  738. this.$set(this.attr.productSelect, "image", this.storeInfo.image);
  739. this.$set(this.attr.productSelect, "price", this.storeInfo.price);
  740. this.$set(this.attr.productSelect, "stock", this.storeInfo.stock);
  741. this.$set(
  742. this.attr.productSelect,
  743. "unique",
  744. this.storeInfo.unique || ""
  745. );
  746. this.$set(this.attr.productSelect, "cart_num", 1);
  747. this.$set(this, "attrValue", "");
  748. this.$set(this, "attrTxt", "请选择");
  749. }
  750. },
  751. //购物车;
  752. ChangeCartNum: function(changeValue) {
  753. //changeValue:是否 加|减
  754. //获取当前变动属性
  755. let productSelect = this.productValue[this.attrValue];
  756. //如果没有属性,赋值给商品默认库存
  757. if (productSelect === undefined && !this.attr.productAttr.length)
  758. productSelect = this.attr.productSelect;
  759. //无属性值即库存为0;不存在加减;
  760. if (productSelect === undefined) return;
  761. let stock = productSelect.stock || 0;
  762. let num = this.attr.productSelect;
  763. if (changeValue) {
  764. num.cart_num++;
  765. if (num.cart_num > stock) {
  766. this.$set(this.attr.productSelect, "cart_num", stock);
  767. this.$set(this, "cart_num", stock);
  768. }
  769. } else {
  770. num.cart_num--;
  771. if (num.cart_num < 1) {
  772. this.$set(this.attr.productSelect, "cart_num", 1);
  773. this.$set(this, "cart_num", 1);
  774. }
  775. }
  776. },
  777. //将父级向子集多次传送的函数合二为一;
  778. changeFun: function(opt) {
  779. if (typeof opt !== "object") opt = {};
  780. let action = opt.action || "";
  781. let value = opt.value === undefined ? "" : opt.value;
  782. this[action] && this[action](value);
  783. },
  784. //打开优惠券插件;
  785. couponTap: function() {
  786. let that = this;
  787. that.coupons();
  788. that.coupon.coupon = true;
  789. },
  790. changecoupon: function(msg) {
  791. this.coupon.coupon = msg;
  792. this.coupons();
  793. },
  794. currentcoupon: function(res) {
  795. let that = this;
  796. that.coupon.coupon = false;
  797. that.$set(that.coupon.list[res], "is_use", true);
  798. },
  799. //可领取优惠券接口;
  800. coupons: function() {
  801. let that = this,
  802. q = { page: 1, limit: 20, type: 1, product_id: that.id };
  803. getCoupon(q).then(res => {
  804. that.$set(that, "couponList", res.data || []);
  805. that.$set(that.coupon, "list", res.data);
  806. });
  807. },
  808. //打开属性插件;
  809. selecAttrTap: function() {
  810. this.attr.cartAttr = true;
  811. this.isOpen = true;
  812. },
  813. changeattr: function(msg) {
  814. this.attr.cartAttr = msg;
  815. this.isOpen = false;
  816. },
  817. //选择属性;
  818. ChangeAttr: function(res) {
  819. let productSelect = this.productValue[res];
  820. if (productSelect) {
  821. this.$set(this.attr.productSelect, "image", productSelect.image);
  822. this.$set(this.attr.productSelect, "price", productSelect.price);
  823. this.$set(this.attr.productSelect, "stock", productSelect.stock);
  824. this.$set(this.attr.productSelect, "unique", productSelect.unique);
  825. this.$set(this.attr.productSelect, "cart_num", 1);
  826. this.$set(this, "attrValue", res);
  827. this.$set(this, "attrTxt", "已选择");
  828. } else {
  829. this.$set(this.attr.productSelect, "image", this.storeInfo.image);
  830. this.$set(this.attr.productSelect, "price", this.storeInfo.price);
  831. this.$set(this.attr.productSelect, "stock", 0);
  832. this.$set(this.attr.productSelect, "unique", "");
  833. this.$set(this.attr.productSelect, "cart_num", 0);
  834. this.$set(this, "attrValue", "");
  835. this.$set(this, "attrTxt", "请选择");
  836. }
  837. },
  838. //收藏商品
  839. setCollect: function() {
  840. let that = this,
  841. id = that.storeInfo.id,
  842. category = "product";
  843. if (that.storeInfo.userCollect) {
  844. getCollectDel(id, category).then(function() {
  845. that.storeInfo.userCollect = !that.storeInfo.userCollect;
  846. });
  847. } else {
  848. getCollectAdd(id, category).then(function() {
  849. that.storeInfo.userCollect = !that.storeInfo.userCollect;
  850. });
  851. }
  852. },
  853. goGoods(item) {
  854. goShopDetail(item).then(() => {
  855. window.scroll(0, 0);
  856. this.$router.push({ path: "/detail/" + item.id });
  857. });
  858. },
  859. // 点击加入购物车按钮
  860. joinCart: function() {
  861. //0=加入购物车
  862. this.goCat(0);
  863. },
  864. // 加入购物车;
  865. goCat: function(news) {
  866. let that = this,
  867. productSelect = that.productValue[this.attrValue];
  868. //打开属性
  869. if (that.attrValue) {
  870. //默认选中了属性,但是没有打开过属性弹窗还是自动打开让用户查看默认选中的属性
  871. that.attr.cartAttr = !that.isOpen ? true : false;
  872. } else {
  873. if (that.isOpen) that.attr.cartAttr = true;
  874. else that.attr.cartAttr = !that.attr.cartAttr;
  875. }
  876. //只有关闭属性弹窗时进行加入购物车
  877. if (that.attr.cartAttr === true && that.isOpen === false)
  878. return (that.isOpen = true);
  879. if (
  880. !this.attr.productSelect.cart_num ||
  881. parseInt(this.attr.productSelect.cart_num) <= 0
  882. )
  883. return that.$dialog.toast({ mes: "请输入购买数量" });
  884. //如果有属性,没有选择,提示用户选择
  885. if (
  886. that.attr.productAttr.length &&
  887. productSelect === undefined &&
  888. that.isOpen === true
  889. )
  890. return that.$dialog.toast({ mes: "产品库存不足,请选择其它" });
  891. let q = {
  892. productId: that.id,
  893. cartNum: that.attr.productSelect.cart_num,
  894. new: news,
  895. uniqueId:
  896. that.attr.productSelect !== undefined
  897. ? that.attr.productSelect.unique
  898. : ""
  899. };
  900. postCartAdd(q)
  901. .then(function(res) {
  902. that.isOpen = false;
  903. that.attr.cartAttr = false;
  904. if (news) {
  905. that.$router.push({ path: "/order/submit/" + res.data.cartId });
  906. } else {
  907. that.$dialog.toast({
  908. mes: "添加购物车成功",
  909. callback: () => {
  910. that.getCartCount(true);
  911. }
  912. });
  913. }
  914. })
  915. .catch(res => {
  916. that.isOpen = false;
  917. return that.$dialog.toast({ mes: res.msg });
  918. });
  919. },
  920. //获取购物车数量
  921. getCartCount: function(isAnima) {
  922. let that = this;
  923. const isLogin = that.isLogin;
  924. if (isLogin) {
  925. getCartCount({ numType: 0 }).then(res => {
  926. that.CartCount = res.data.count;
  927. //加入购物车后重置属性
  928. if (isAnima) {
  929. that.animated = true;
  930. setTimeout(function() {
  931. that.animated = false;
  932. }, 500);
  933. }
  934. });
  935. }
  936. },
  937. //立即购买;
  938. tapBuy: function() {
  939. // 1=直接购买
  940. this.goCat(1);
  941. },
  942. listenerActionSheet: function() {
  943. if (isWeixin() === true) {
  944. this.weixinStatus = true;
  945. }
  946. this.posters = true;
  947. },
  948. listenerActionClose: function() {
  949. this.posters = false;
  950. }
  951. },
  952. beforeDestroy: function() {
  953. document.removeEventListener("scroll", this.onScroll, false);
  954. window.removeEventListener("scroll", this.handleScroll);
  955. }
  956. };
  957. </script>
  958. <style scoped>
  959. .mask {
  960. z-index: 888 !important;
  961. }
  962. .activity_pin {
  963. width: auto;
  964. height: 0.44rem;
  965. background: linear-gradient(
  966. 90deg,
  967. rgba(233, 51, 35, 1) 0%,
  968. rgba(250, 101, 20, 1) 100%
  969. );
  970. opacity: 1;
  971. border-radius: 0.22rem;
  972. padding: 0 0.2rem;
  973. margin-left: 0.19rem;
  974. }
  975. .activity_miao {
  976. width: auto;
  977. height: 0.44rem;
  978. padding: 0 0.2rem;
  979. background: linear-gradient(
  980. 90deg,
  981. rgba(250, 102, 24, 1) 0%,
  982. rgba(254, 161, 15, 1) 100%
  983. );
  984. opacity: 1;
  985. border-radius: 0.22rem;
  986. margin-left: 0.19rem;
  987. }
  988. .iconfonts {
  989. color: #fff !important;
  990. font-size: 0.28rem;
  991. display: block;
  992. }
  993. .activity_title {
  994. font-size: 0.24rem;
  995. color: #fff;
  996. }
  997. .activity_kan {
  998. width: auto;
  999. height: 0.44rem;
  1000. padding: 0 0.2rem;
  1001. background: linear-gradient(
  1002. 90deg,
  1003. rgba(254, 159, 15, 1) 0%,
  1004. rgba(254, 178, 15, 1) 100%
  1005. );
  1006. opacity: 1;
  1007. border-radius: 0.22rem;
  1008. margin-left: 0.19rem;
  1009. }
  1010. .addressBox .phone {
  1011. margin-left: 1.1rem;
  1012. }
  1013. .corlor-red {
  1014. color: #fc4141;
  1015. }
  1016. .store-box {
  1017. padding: 0 0.3rem;
  1018. border-bottom: 1px solid #f5f5f5;
  1019. }
  1020. .geoPage {
  1021. position: fixed;
  1022. width: 100%;
  1023. height: 100%;
  1024. top: 0;
  1025. z-index: 10000;
  1026. }
  1027. .product-con .header {
  1028. position: fixed;
  1029. left: 0;
  1030. top: 0;
  1031. width: 100%;
  1032. height: 0.96rem;
  1033. font-size: 0.3rem;
  1034. color: #050505;
  1035. background-color: #fff;
  1036. z-index: 11;
  1037. border-bottom: 0.01rem solid #eee;
  1038. }
  1039. .product-con .header .item {
  1040. position: relative;
  1041. margin: 0 0.35rem;
  1042. }
  1043. .product-con .header .item.on:before {
  1044. position: absolute;
  1045. width: 0.6rem;
  1046. height: 0.05rem;
  1047. background-repeat: no-repeat;
  1048. content: "";
  1049. background: linear-gradient(to left, #ff3366 0%, #ff6533 100%);
  1050. background: -webkit-linear-gradient(to left, #ff3366 0%, #ff6533 100%);
  1051. background: -moz-linear-gradient(to left, #ff3366 0%, #ff6533 100%);
  1052. bottom: -0.1rem;
  1053. }
  1054. .product-con .store-info {
  1055. margin-top: 0.2rem;
  1056. background-color: #fff;
  1057. }
  1058. .product-con .store-info .title {
  1059. font-size: 0.28rem;
  1060. color: #282828;
  1061. height: 0.8rem;
  1062. line-height: 0.8rem;
  1063. border-bottom: 0.01rem solid #f5f5f5;
  1064. }
  1065. .product-con .store-info .info {
  1066. padding: 0 0.3rem;
  1067. height: 1.26rem;
  1068. }
  1069. .store-info .icon-jiantou {
  1070. color: #7a7a7a;
  1071. font-size: 0.28rem;
  1072. }
  1073. .product-con .store-info .info .pictrue {
  1074. width: 0.76rem;
  1075. height: 0.76rem;
  1076. }
  1077. .product-con .store-info .info .pictrue img {
  1078. width: 100%;
  1079. height: 100%;
  1080. border-radius: 0.06rem;
  1081. }
  1082. .product-con .store-info .info .text {
  1083. width: 56%;
  1084. }
  1085. .product-con .store-info .info .text .name {
  1086. font-size: 0.3rem;
  1087. color: #282828;
  1088. }
  1089. .product-con .store-info .info .text .address {
  1090. font-size: 0.24rem;
  1091. color: #666;
  1092. margin-top: 0.03rem;
  1093. }
  1094. .product-con .store-info .info .text .address .iconfont {
  1095. color: #707070;
  1096. font-size: 0.18rem;
  1097. margin-left: 0.1rem;
  1098. }
  1099. .address_tit {
  1100. max-width: 88% !important;
  1101. }
  1102. .addressTxt {
  1103. width: auto;
  1104. font-size: 0.24rem;
  1105. }
  1106. .product-con .store-info .info .iconfont {
  1107. font-size: 0.4rem;
  1108. }
  1109. .product-con .superior {
  1110. background-color: #fff;
  1111. margin-top: 0.2rem;
  1112. }
  1113. .product-con .superior .title {
  1114. height: 0.98rem;
  1115. }
  1116. .product-con .superior .title img {
  1117. width: 0.3rem;
  1118. height: 0.3rem;
  1119. }
  1120. .product-con .superior .title .titleTxt {
  1121. margin: 0 0.2rem;
  1122. font-size: 0.3rem;
  1123. background-image: linear-gradient(to right, #f57a37 0%, #f21b07 100%);
  1124. background-image: -webkit-linear-gradient(to right, #f57a37 0%, #f21b07 100%);
  1125. background-image: -moz-linear-gradient(to right, #f57a37 0%, #f21b07 100%);
  1126. -webkit-background-clip: text;
  1127. -webkit-text-fill-color: transparent;
  1128. }
  1129. .product-con .superior .slider-banner {
  1130. width: 6.9rem;
  1131. margin: 0 auto;
  1132. padding-bottom: 0.2rem;
  1133. }
  1134. .product-con .superior .slider-banner .list {
  1135. width: 100%;
  1136. padding-bottom: 0.2rem;
  1137. }
  1138. .product-con .superior .slider-banner .list .item {
  1139. width: 2.15rem;
  1140. margin: 0 0.21rem 0.2rem 0;
  1141. font-size: 0.26rem;
  1142. }
  1143. .product-con .superior .slider-banner .list .item:nth-of-type(3n) {
  1144. margin-right: 0;
  1145. }
  1146. .product-con .superior .slider-banner .list .item .pictrue {
  1147. width: 100%;
  1148. height: 2.15rem;
  1149. position: relative;
  1150. }
  1151. .product-con .superior .slider-banner .list .item .pictrue img {
  1152. width: 100%;
  1153. height: 100%;
  1154. border-radius: 0.06rem;
  1155. }
  1156. .product-con .superior .slider-banner .list .item .name {
  1157. color: #282828;
  1158. margin-top: 0.12rem;
  1159. }
  1160. .product-con .superior .slider-banner .swiper-pagination-bullet {
  1161. background-color: #999;
  1162. }
  1163. .product-con .superior .slider-banner .swiper-pagination-bullet-active {
  1164. background-color: #e93323;
  1165. }
  1166. .mask {
  1167. -webkit-filter: blur(2px);
  1168. -moz-filter: blur(2px);
  1169. -ms-filter: blur(2px);
  1170. filter: blur(2px);
  1171. z-index: 888 !important;
  1172. }
  1173. .footer .icon-shoucang1 {
  1174. color: #e93323;
  1175. }
  1176. .product-con .product-intro .conter div {
  1177. width: 100% !important;
  1178. }
  1179. .generate-posters {
  1180. width: 100%;
  1181. height: 1.7rem;
  1182. background-color: #fff;
  1183. position: fixed;
  1184. left: 0;
  1185. bottom: 0;
  1186. z-index: 999;
  1187. transform: translate3d(0, 100%, 0);
  1188. -webkit-transform: translate3d(0, 100%, 0);
  1189. -ms-transform: translate3d(0, 100%, 0);
  1190. -moz-transform: translate3d(0, 100%, 0);
  1191. -o-transform: translate3d(0, 100%, 0);
  1192. transition: all 0.3s cubic-bezier(0.25, 0.5, 0.5, 0.9);
  1193. -webkit-transition: all 0.3s cubic-bezier(0.25, 0.5, 0.5, 0.9);
  1194. -moz-transition: all 0.3s cubic-bezier(0.25, 0.5, 0.5, 0.9);
  1195. -o-transition: all 0.3s cubic-bezier(0.25, 0.5, 0.5, 0.9);
  1196. opacity: 0;
  1197. }
  1198. .generate-posters.on {
  1199. transform: translate3d(0, 0, 0);
  1200. -webkit-transform: translate3d(0, 0, 0);
  1201. -ms-transform: translate3d(0, 0, 0);
  1202. -moz-transform: translate3d(0, 0, 0);
  1203. -o-transform: translate3d(0, 0, 0);
  1204. opacity: 1;
  1205. }
  1206. .generate-posters .item {
  1207. flex: 50%;
  1208. -webkit-flex: 50%;
  1209. -ms-flex: 50%;
  1210. text-align: center;
  1211. }
  1212. .generate-posters .item .iconfont {
  1213. font-size: 0.8rem;
  1214. color: #5eae72;
  1215. }
  1216. .generate-posters .item .iconfont.icon-haibao {
  1217. color: #5391f1;
  1218. }
  1219. .noscroll {
  1220. height: 100%;
  1221. overflow: hidden;
  1222. }
  1223. </style>