index.vue 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630
  1. <template>
  2. <view class="goods-detail">
  3. <navbarTransparent :title="page.title" />
  4. <!-- swiper -->
  5. <view class="home-swiper">
  6. <uni-swiper-dot :mode="mode" :info="info" :current="current1" :dots-styles="dotsStyles">
  7. <swiper class="swiper-box" @change="change1" circular>
  8. <swiper-item v-for="(item ,index) in info" :key="index" v-if="resource_type == 1 ">
  9. <view class="swiper-item">
  10. <image style="width: 100vw;height:100vw;" :src="item.img" mode="aspectFill"></image>
  11. </view>
  12. </swiper-item>
  13. <swiper-item v-if="resource_type == 2 ">
  14. <view class="swiper-item">
  15. <video class="baner-video" id="myVideo" ref="myVideo" style="width: 100%; height: 564rpx;"
  16. :src="video_url" controls :enable-progress-gesture="false">
  17. </video>
  18. </view>
  19. </swiper-item>
  20. </swiper>
  21. </uni-swiper-dot>
  22. </view>
  23. <view style="background-color: #f9f9f9;">
  24. <!-- 价格 -->
  25. <view class="price">
  26. <view class="price-top" v-if="produceType == 1 && productDetail.price !=0 ">
  27. <text>¥</text>
  28. <text>{{productDetail.price}}</text>
  29. </view>
  30. <view class="price-top" v-if="produceType == 2">
  31. <text>{{productDetail.integral}}</text>
  32. <text>积分</text>
  33. </view>
  34. <text class="price-text">{{productDetail.name}}</text>
  35. <view @click="goOther" class="price-banner" :style="{backgroundImage:'url('+backImageUrl+')'}" v-if="produceType == 1">
  36. <text>加入IHG优悦会会员享受更多福利</text>
  37. <image style="width: 12rpx;height: 20rpx;" src="/static/icon/right02.png" mode=""></image>
  38. </view>
  39. <view @click="goOtherIntegral" class="price-banner" :style="{backgroundImage:'url('+backImageUrl+')'}" v-if="produceType == 2">
  40. <text>加入IHG优悦会会员享受更多福利</text>
  41. <image style="width: 12rpx;height: 20rpx;" src="/static/icon/right02.png" mode=""></image>
  42. </view>
  43. <!--规格-->
  44. <view class="price-specs" @click="Recipientopen()">
  45. <view class="price-specs-left">
  46. <text>选择</text>
  47. </view>
  48. <view class="price-specs-main" @click="Recipientopen()">
  49. <text>{{showAttr||'请选择规格'}}</text>
  50. </view>
  51. <view @click="Recipientopen()">
  52. <image style="width: 12rpx;height: 20rpx;" src="/static/icon/right03.png" mode=""></image>
  53. </view>
  54. </view>
  55. </view>
  56. <!--酒店信息 -->
  57. <view class="about">
  58. <text class="about-title">可购买酒店信息</text>
  59. <text class="about-name">{{hotelDetail.name}}</text>
  60. <view class="about-address">
  61. <text style="margin-right:20rpx ;">地址:</text>
  62. <text>{{hotelDetail.address?hotelDetail.address:""}}</text>
  63. </view>
  64. <view class="about-phone">
  65. <text style="margin-right:20rpx ;">电话:</text>
  66. <text>{{hotelDetail.phone?hotelDetail.phone:""}}</text>
  67. </view>
  68. <view class="about-all">
  69. <text @click="goGoodsHotel(product_id)" style="margin-right: 16rpx;">全部酒店</text>
  70. <image @click="goGoodsHotel(product_id)" style="width: 12rpx;height: 20rpx;"
  71. src="/static/icon/right04.png" mode=""></image>
  72. </view>
  73. </view>
  74. <!-- 产品介绍 -->
  75. <view class="produce">
  76. <view class="produce-title">
  77. <text>产品简介</text>
  78. </view>
  79. <view class="produce-text">
  80. <u-parse :content="productDetail.details"></u-parse>
  81. </view>
  82. </view>
  83. </view>
  84. <view class="buy-btn">
  85. <view class="buy-btn-left" @click="goHome">
  86. <image style="width: 40rpx;height: 42rpx;" src="/static/icon/home01.png" mode=""></image>
  87. <text>首页</text>
  88. </view>
  89. <view class="buy-btn-right" @click="goIntegralOrder" v-if="produceType==1">
  90. <text>立即购买</text>
  91. </view>
  92. <view v-if="produceType==2" class="buy-btn-right" @click="goProductChange(product_id,flavorIsActive)">
  93. <text>立即兑换</text>
  94. </view>
  95. </view>
  96. <view style="height: 90px;background-color: #f9f9f9;"></view>
  97. <!-- 选择规格 -->
  98. <uni-popup ref="Recipient" type="bottom" mask-background-color=" rgba(0,0,0,0.3);">
  99. <view class="pop">
  100. <view class="pop-price">
  101. <view class="pop-price-left">
  102. <image style="width: 180rpx;height: 136rpx; border-radius:12rpx ;"
  103. :src="productDetail.cover_img" mode=""></image>
  104. <view class="pop-price-left-money" v-if="produceType == 1 && productDetail.price !=0 ">
  105. <text>¥</text>
  106. <text>{{productDetail.price}}</text>
  107. </view>
  108. <view class="pop-price-left-money" v-if="produceType == 2">
  109. <text>{{productDetail.integral}}</text>
  110. <text>积分</text>
  111. </view>
  112. </view>
  113. <image style="width: 52rpx;height: 52rpx;" src="/static/icon/close01.png" mode=""
  114. @click="Recipientclose"></image>
  115. </view>
  116. <view class="pop-flavor" v-for="i in attr_groups" :key="i.attr_group_id" style="margin-top: 44rpx;">
  117. <text>{{i.attr_group_name}}</text>
  118. <view class="tab_flavor">
  119. <view class="flavorTitle-item"
  120. :class="{'flavorTitle-item-active':flavorIsActive[i.attr_group_name] === item.attr_name}"
  121. v-for="(item,index) in i.attr_list" :key="item.attr_id"
  122. @click="flavorchecked(item.attr_name,i.attr_group_name)">
  123. <view :class="{'active-flavor':flavorIsActive[i.attr_group_name] === item.attr_name}">
  124. {{item.attr_name}}
  125. </view>
  126. </view>
  127. </view>
  128. </view>
  129. </view>
  130. <view class="purchase" v-if="produceType == 1" @click="goIntegralOrder">
  131. <view class="purchase-btn">立即购买</view>
  132. </view>
  133. <view class="purchase" v-if="produceType == 2" @click="selectSpecs(product_id,flavorIsActive)">
  134. <view class="purchase-btn">立即兑换</view>
  135. <!-- <view class="purchase-btn">确认</view> -->
  136. </view>
  137. </uni-popup>
  138. <!-- 二维码购买 -->
  139. <!-- <uni-popup ref="codePurchase" type="center">
  140. <view class="code-purchase">
  141. <view class="title"><text>识别下方二维码即可购买</text></view>
  142. <view style="margin-left:30rpx;width: 580rpx;height: 2rpx;background: #F0F0F0;"></view>
  143. <view class="img">
  144. <image src="http://t9.9026.com/imgs/Kudosbg.png"></image>
  145. </view>
  146. <view class="btn">
  147. <view class="cancel" @click="dialogClose"><text>取消</text></view>
  148. <view class="download" @click="dialogConfirm"><text>保存图片</text></view>
  149. </view>
  150. </view>
  151. </uni-popup> -->
  152. <!-- 弹出层/核销码 -->
  153. <dialogPanel ref="dialogPanel"/>
  154. </view>
  155. </template>
  156. <script>
  157. import navbarTransparent from "@/components/extra/navbarTransparent.vue"
  158. export default {
  159. components: {
  160. navbarTransparent
  161. },
  162. data() {
  163. return {
  164. //积分跳转h5,小程序,其他页面
  165. jump_type_integral: '',
  166. jump_config_integral: {},
  167. //产品跳转h5,小程序,其他页面
  168. jump_type_vip: '',
  169. jump_config_vip: {},
  170. //加入会员广告配置
  171. advise: '',
  172. jump_type: '',
  173. jump_config: '',
  174. resource_type: '',
  175. //1:第三方产品2:积分兑换产品
  176. produceType: '',
  177. // 规格
  178. specsText: '',
  179. specs: {
  180. pack: '',
  181. weight: '',
  182. flavor: '',
  183. },
  184. // 产品详情
  185. productDetail: '',
  186. // 酒店详情
  187. hotelDetail: '',
  188. // 产品id
  189. product_id: '',
  190. //激活指定table菜单
  191. isActive: 0,
  192. flavorIsActive: {},
  193. weightIsActive: 0,
  194. packIsActive: 0,
  195. backImageUrl: require('../../../static/icon/add01.png'),
  196. //轮播图
  197. info: [{
  198. img: 'http://t9.9026.com/imgs/swiper01.png',
  199. name: '酒店预订'
  200. }, ],
  201. dotsStyles: {
  202. backgroundColor: 'rgba(255, 255, 255, .3)',
  203. border: '1px rgba(255, 255, 255, .3) solid',
  204. color: '#fff',
  205. selectedBackgroundColor: 'rgba(255, 255, 255, 1)',
  206. selectedBorder: '1px rgba(255, 255, 255, 1) solid'
  207. },
  208. //指示点显示位置
  209. current1: 0,
  210. //指示点模式
  211. mode: 'dot',
  212. attr_groups: [],
  213. page: {
  214. title: '详情'
  215. },
  216. sku: {
  217. keys: [],
  218. }
  219. }
  220. },
  221. onReady: function() {
  222. this.videoContext = uni.createVideoContext('myVideo')
  223. },
  224. onLoad(op) {
  225. const {
  226. id,
  227. type
  228. } = op;
  229. this.admin = this.$store.getters.userInfo
  230. this.product_id = id
  231. this.produceType = type
  232. this.getProductDetail(this.product_id, true)
  233. //vip跳转
  234. this.advise = this.$store.getters.allset.add_member
  235. //产品购买vip图标
  236. this.productVipImg= this.advise.value.product
  237. //积分购买vip图标
  238. this.integralVopImg = this.advise.value.integral
  239. this.jump_type_vip = this.advise.value.product_jump_type
  240. if (this.jump_type_vip == 1) {
  241. this.jump_config_vip = this.advise.value.product_h5_url
  242. } else if (this.jump_type_vip == 2) {
  243. this.jump_config_vip.appid = this.advise.value.product_appid
  244. this.jump_config_vip.path = this.advise.value.product_path
  245. } else if (this.jump_type_vip == 3) {
  246. this.jump_config_vip = this.advise.value.product_other_path
  247. }
  248. this.jump_type_integral = this.advise.value.integral_jump_type
  249. if (this.jump_type_integral == 1) {
  250. this.jump_config_integral = this.advise.value.integral_h5_url
  251. } else if (this.jump_type_integral == 2) {
  252. this.jump_config_integral.appid = this.advise.value.integral_appid
  253. this.jump_config_integral.path = this.advise.value.integral_path
  254. } else if (this.jump_type_integral == 3) {
  255. this.jump_config_integral = this.advise.value.integral_other_path
  256. }
  257. if(this.produceType == 1){
  258. this.backImageUrl = this.productVipImg
  259. }else if(this.produceType == 2){
  260. this.backImageUrl = this.integralVopImg
  261. }
  262. },
  263. computed: {
  264. showAttr: function() {
  265. if (this.flavorIsActive.length <= 0) return false;
  266. let text = '';
  267. for (const k in this.flavorIsActive) {
  268. text += `${k}-${this.flavorIsActive[k]},`
  269. }
  270. return text.substr(0, text.length - 1);
  271. },
  272. selectedHotelId: function() {
  273. return this.$store.state.tab.selectedHotelId;
  274. },
  275. showProductAttr: function() {
  276. if (this.flavorIsActive.length <= 0) return false;
  277. let text = '';
  278. for (const k in this.flavorIsActive) {
  279. text += `${this.flavorIsActive[k]}-`
  280. }
  281. return text.substr(0, text.length - 1);
  282. },
  283. },
  284. methods: {
  285. //显示所选规格
  286. //获取当前页面路径
  287. getPageUrl() {
  288. const pages = getCurrentPages();
  289. if (pages.length == 1) {
  290. const currentPage = pages[0];
  291. console.log(currentPage.options, '--------->currentPage.options')
  292. let pageUrl = `/${currentPage.route}?type=${currentPage.options.type}`;
  293. return pageUrl
  294. console.log('当前页面url:', pageUrl);
  295. } else {
  296. const currentPage = pages[pages.length - 1];
  297. console.log(currentPage.options, '--------->currentPage.options')
  298. let pageUrl = `/${currentPage.route}?type=${currentPage.options.type}`;
  299. return pageUrl
  300. console.log('当前页面url:', pageUrl);
  301. }
  302. },
  303. // 跳转其他小程序
  304. jumpHAppID(id, urls) {
  305. if (id == 1) {
  306. const url = urls; // 跳转的外链
  307. const navtitle = 'H5'; // 这个标题是你自己可以设置的
  308. uni.navigateTo({
  309. // 跳转到webview页面
  310. url: `/pages/webview/webview?url=${url}&nav=${navtitle}`,
  311. success: () => {
  312. console.log('成功')
  313. },
  314. fail: (e) => {
  315. console.log(e, "失败")
  316. }
  317. });
  318. } else if (id == 2) {
  319. let _this = this
  320. let obj = urls;
  321. console.log(obj, '----->obj');
  322. wx.navigateToMiniProgram({
  323. appId: `${obj.appid}`, //appid
  324. path: `${obj.path}`, //path
  325. extraData: { //参数
  326. foo: 'bar'
  327. },
  328. // envVersion: 'develop', //开发版develop 开发版 trial 体验版 release 正式版
  329. success(res) {
  330. let page = _this.getPageUrl()
  331. let user_id = ''
  332. if (_this.admin != null) {
  333. user_id = _this.admin.id
  334. } else {
  335. user_id = 0
  336. }
  337. _this.$api.my.userMemberAdd({
  338. user_id,
  339. page,
  340. }).then(res => {
  341. console.log(res.data);
  342. })
  343. // 打开成功
  344. },
  345. fail(e) {
  346. console.log(e, '失败')
  347. }
  348. })
  349. } else if (id == 3) {
  350. uni.redirectTo({
  351. url: urls,
  352. fail: (err) => {
  353. uni.reLaunch({
  354. url: urls
  355. })
  356. }
  357. })
  358. }
  359. },
  360. // 跳转其他小程序
  361. goOther() {
  362. let _this = this
  363. this.jumpHAppID(this.jump_type_vip, this.jump_config_vip)
  364. },
  365. goOtherIntegral(){
  366. let _this = this
  367. this.jumpHAppID(this.jump_type_integral, this.jump_config_integral)
  368. },
  369. //视频自动播放
  370. openVideoPlay() {
  371. this.videoContext && this.videoContext.play()
  372. },
  373. // 获取商品详情
  374. getProductDetail(product_id, init = false) {
  375. this.$store.commit("tab/SET_SELECTEDHOTELId", 0)
  376. this.$api.product.getProductDetail({
  377. product_id: product_id
  378. }).then(res => {
  379. if (res.code == 0 && res.data) {
  380. this.productDetail = res.data
  381. this.info = JSON.parse(res.data.img_urls).map(item => {
  382. return {
  383. img: item
  384. }
  385. })
  386. //规格对接
  387. this.attr_groups = JSON.parse(res.data.attr_group)
  388. //获取默认酒店
  389. const hotel_ids = JSON.parse(res.data.hotel_ids);
  390. if ((hotel_ids.constructor == Array) && (hotel_ids.length > 0)) {
  391. this.$store.commit("tab/SET_SELECTEDHOTELId", hotel_ids[0])
  392. }
  393. //
  394. const sku = JSON.parse(res.data.sku);
  395. this.sku.keys = Object.keys(sku.attrs);
  396. this.sku.sku = sku.sku;
  397. //首次默认选中第一个规格
  398. if (init) {
  399. this.attr_groups.forEach(item => {
  400. this.flavorchecked(item.attr_list[0]?.attr_name, item.attr_group_name)
  401. })
  402. }
  403. //跳转h5和小程序
  404. this.jump_type = res.data.jump_type,
  405. this.jump_config = res.data.jump_config
  406. //banner展示视频或者图片
  407. this.resource_type = res.data.resource_type
  408. this.video_url = res.data.video_url
  409. //视频自动播放
  410. new Promise((resolve,reject)=>{
  411. try{
  412. this.openVideoPlay()
  413. }catch(err){
  414. reject(false)
  415. }
  416. resolve(true)
  417. })
  418. }else{
  419. uni.showToast({
  420. icon: 'error',
  421. title: res.msg?res.msg:"网络繁忙",
  422. })
  423. }
  424. }).catch(err => {
  425. uni.showToast({
  426. icon: 'none',
  427. title: err.msg?err.msg:"服务器繁忙",
  428. })
  429. })
  430. },
  431. // 获取酒店详情
  432. getHotelDetail(id) {
  433. this.$api.hotel.getHotelDetail({
  434. hotel_id: id
  435. }).then(res => {
  436. this.hotelDetail = res.data
  437. })
  438. },
  439. //跳转酒店列表
  440. goGoodsHotel(id) {
  441. uni.navigateTo({
  442. url: '/pages/goods/goods-hotel/index?product_id=' + id
  443. })
  444. },
  445. //首页
  446. goHome() {
  447. uni.switchTab({
  448. url: '/pages/index/index'
  449. })
  450. },
  451. //二维码购买确认按钮
  452. dialogConfirm() {
  453. console.log('确认');
  454. this.codePurchaseClose()
  455. },
  456. //二维码购买取消按钮
  457. dialogClose() {
  458. console.log('取消');
  459. this.codePurchaseClose()
  460. },
  461. //菜单index切换
  462. checked(index) {
  463. this.isActive = index
  464. },
  465. getAttrListId(name){
  466. for(let k in this.attr_groups){
  467. for(let k1 in this.attr_groups[k].attr_list){
  468. const v = this.attr_groups[k].attr_list[k1];
  469. if(v.attr_name == name){
  470. return v.attr_id;
  471. break;
  472. }
  473. }
  474. }
  475. },
  476. // 口味切换
  477. flavorchecked(index, name) {
  478. this.$set(this.flavorIsActive, name, index)
  479. this.specs.flavor = name
  480. let resTemp = []
  481. for(let k in this.flavorIsActive){
  482. resTemp.push(this.getAttrListId(this.flavorIsActive[k]));
  483. }
  484. const attr = resTemp.join(":");
  485. for(let k in this.productDetail.product_attr){
  486. if(this.productDetail.product_attr[k].attr == attr){
  487. const price = this.productDetail.product_attr[k].price;
  488. const integral = this.productDetail.product_attr[k].integral;
  489. const stock = this.productDetail.product_attr[k].stock;
  490. this.productDetail.price = price;
  491. this.productDetail.integral = integral;
  492. this.productDetail.stock = stock
  493. break;
  494. }
  495. }
  496. },
  497. // // 重量切换
  498. // weightchecked(index,name) {
  499. // this.weightIsActive = index
  500. // this.specs.weight=name
  501. // console.log(this.specs.weight);
  502. // },
  503. // // 包装切换
  504. // packchecked(index,name) {
  505. // this.packIsActive = index
  506. // this.specs.pack=name
  507. // console.log(this.specs.pack);
  508. // },
  509. // 立即兑换
  510. selectSpecs(id, flavorIsActive) {
  511. const resArr = [];
  512. outer: for (const k in this.flavorIsActive) {
  513. inner: for (const i in this.attr_groups) {
  514. if (this.attr_groups[i].attr_group_name == k) {
  515. laster: for (const l in this.attr_groups[i].attr_list) {
  516. if (this.attr_groups[i].attr_list[l].attr_name == this.flavorIsActive[k]) {
  517. resArr.push(this.attr_groups[i].attr_list[l].attr_id);
  518. break inner;
  519. }
  520. }
  521. }
  522. }
  523. }
  524. const selectedIds = resArr.join(':');
  525. console.log(this.productDetail.integral);
  526. console.log(this.productDetail.stock);
  527. if(this.productDetail.stock >=1 ){
  528. uni.navigateTo({
  529. url: `/pages/my/integral/integralOrder?product_id=${this.productDetail.id}&attr=${selectedIds}&integral=${this.productDetail.integral}&attrName=${this.showProductAttr}`
  530. })
  531. this.Recipientclose()
  532. }else{
  533. uni.showToast({
  534. icon:'none',
  535. title:'库存不足'
  536. })
  537. }
  538. },
  539. Recipientopen() {
  540. this.$refs.Recipient.open('bottom')
  541. },
  542. Recipientclose() {
  543. this.$refs.Recipient.close()
  544. },
  545. codePurchaseClose() {
  546. this.$refs.codePurchase.close()
  547. },
  548. // 切换轮播图指示点
  549. change1(e) {
  550. this.current1 = e.detail.current;
  551. },
  552. //积分兑换
  553. goProductChange(id, flavorIsActive) {
  554. this.Recipientopen()
  555. // const resArr = [];
  556. // outer: for (const k in this.flavorIsActive) {
  557. // inner: for (const i in this.attr_groups) {
  558. // if (this.attr_groups[i].attr_group_name == k) {
  559. // laster: for (const l in this.attr_groups[i].attr_list) {
  560. // if (this.attr_groups[i].attr_list[l].attr_name == this.flavorIsActive[k]) {
  561. // resArr.push(this.attr_groups[i].attr_list[l].attr_id);
  562. // break inner;
  563. // }
  564. // }
  565. // }
  566. // }
  567. // }
  568. // const selectedIds = resArr.join(':');
  569. // uni.navigateTo({
  570. // url: `/pages/my/integral/integralOrder?product_id=${this.productDetail.id}&attr=${selectedIds}&integral=${this.productDetail.integral}&attrName=${this.showAttr}`
  571. // })
  572. },
  573. // 跳转积分兑换
  574. goIntegralOrder() {
  575. if(this.hotelDetail.buy_jump_type == 3){
  576. this.$refs.dialogPanel.show(this.hotelDetail.buy_jump_config);
  577. return;
  578. }
  579. this.$utils.jump({
  580. jump_type: this.hotelDetail.buy_jump_type,
  581. jump_config: this.hotelDetail.buy_jump_config,
  582. attr: JSON.stringify(this.flavorIsActive)
  583. })
  584. },
  585. },
  586. watch: {
  587. selectedHotelId(newValue) {
  588. newValue && this.getHotelDetail(newValue);
  589. }
  590. }
  591. }
  592. </script>
  593. <style lang="scss" scoped src="./index.scss"></style>
  594. <style lang="scss">
  595. .produce-text img {
  596. width: 100%;
  597. object-fit: fill;
  598. }
  599. </style>