goods.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  1. <template>
  2. <app-layout>
  3. <view v-if="!goods" class="u-goods-detail"></view>
  4. <view class="app-goods" v-show="loading" v-if="goods">
  5. <app-banner
  6. :videoUrl="goods.video_url"
  7. :share="goods.share"
  8. :picList="goods.pic_url"
  9. :goods_id="goods_id"
  10. :isCart="false"
  11. sign="exchange"
  12. ></app-banner>
  13. <bd-info
  14. :theme="getTheme"
  15. :name="goods.name"
  16. :is-negotiable="goods.is_negotiable"
  17. :subtitle="goods.subtitle"
  18. :level-show="goods.level_show"
  19. :price="goods.price"
  20. :original-price="goods.original_price"
  21. :price-max="goods.price_max"
  22. :price-min="goods.price_min"
  23. :price-member-max="goods.price_member_max"
  24. :price-member-min="goods.price_member_min"
  25. :discount='discount'
  26. :is-vip-card-user="is_vip_card_user"
  27. :sales="goods.sales"
  28. :unit="goods.unit"
  29. :is-sales="goods.is_sales"
  30. :is-vip="is_vip"
  31. :flash-sale="flash_sale"
  32. :goods-id="goods.id"
  33. :extra-quick-share="goods.extra_quick_share"
  34. :app-share-pic="goods.app_share_pic"
  35. :app-share-title="goods.app_share_title"
  36. :poster-config="posterConfig"
  37. :poster-generate="posterGenerate"
  38. :has-poster-nav="true"
  39. v-bind:goods="goods"
  40. :share-url="url"
  41. :has-underline-price="false"
  42. @share="hShareAppMessage"
  43. :min-number="0"
  44. :limit-buy="goods.limit_buy"
  45. >
  46. </bd-info>
  47. <bd-coupon v-if="goods.goods_coupon_center" @change="setCoupon" :theme="getTheme" :coupons="goods.goods_coupon_center"></bd-coupon>
  48. <bd-xbc
  49. v-if="goods"
  50. :coAttr="false"
  51. :guarantee-title="goods.guarantee_title"
  52. :guarantee-pic="goods.guarantee_pic"
  53. :param_content="goods.param_content"
  54. :param_name="goods.param_name"
  55. :services="goods.services"
  56. ></bd-xbc>
  57. <!--商品信息-->
  58. <bd-hc
  59. v-if="goods.goods_marketing_award"
  60. :integral="goods.goods_marketing_award.integral"
  61. :coupon="goods.goods_marketing_award.coupon"
  62. :card="goods.goods_marketing_award.card"
  63. :balance="goods.goods_marketing_award.balance"
  64. :theme="getTheme"
  65. ></bd-hc>
  66. <bd-comments v-if="goods_id > 0" :goods-id="goods_id"></bd-comments>
  67. <bd-detail :detail="goods.detail"></bd-detail>
  68. <!-- 底部空格 -->
  69. <view class="safe-area-inset-bottom">
  70. <view :class="[uBottomHeight]"></view>
  71. </view>
  72. <!-- 底部按钮 -->
  73. <view v-if="is_open" class="safe-area-inset-bottom u-bottom-fixed">
  74. <view v-if="full_reduce">
  75. <app-goods-full-reduce
  76. :theme="getTheme"
  77. :full_reduce="full_reduce"
  78. >
  79. </app-goods-full-reduce>
  80. </view>
  81. <view v-if="goods.sell_time > 0">
  82. <app-sell-tip :time="goods.sell_time" @changeTime="changeTime"></app-sell-tip>
  83. </view>
  84. <app-jump-button form>
  85. <view class="buttons dir-left-nowrap">
  86. <view class="app-button main-center cross-center">
  87. <view @click="toExchange" v-if="goods.goods_num > 0 && !goods.is_finish_sell" class="app-exhange" :style="{'background': !goods || goods.buy_goods_auth ? getTheme.background_gradient_btn : '#999999'}">
  88. {{rightRemindText}}
  89. </view>
  90. <view class="app-over" :class="[disableBtn]" v-else>
  91. {{disableBtnText}}
  92. </view>
  93. </view>
  94. </view>
  95. </app-jump-button>
  96. </view>
  97. </view>
  98. <app-close v-if="showClose" :modal="false" @update="getMall"></app-close>
  99. </app-layout>
  100. </template>
  101. <script>
  102. import {mapGetters, mapState} from 'vuex';
  103. import appBanner from '../../../components/page-component/goods/app-goods-banner.vue';
  104. import appGoodsFullReduce from '../../../components/page-component/goods/app-goods-full-reduce.vue';
  105. import appClose from '@/components/basic-component/app-close/app-close.vue';
  106. import bdInfo from '@/components/page-component/goods/bd-info';
  107. import bdCoupon from '@/components/page-component/goods/bd-coupon.vue';
  108. import bdXbc from '@/components/page-component/goods/bd-xbc.vue';
  109. import bdKb from '@/components/page-component/goods/bd-kb.vue';
  110. import bdHc from '@/components/page-component/goods/bd-hc.vue';
  111. import bdDetail from '@/components/page-component/goods/bd-detail.vue';
  112. import bdComments from '@/components/page-component/goods/bd-comments.vue';
  113. import appSellTip from '@/components/page-component/goods/app-sell-tip.vue';
  114. import goodsMixin from '@/core/goods-mixin.js';
  115. export default {
  116. name: 'goods',
  117. mixins: [goodsMixin],
  118. data() {
  119. return {
  120. showClose: false,
  121. is_open: false,
  122. goods: {
  123. id: '',
  124. name: '',
  125. cover_pic: '',
  126. price: '',
  127. },
  128. posterConfig: this.$api.exchange.poster_config,
  129. posterGenerate: this.$api.exchange.poster_generate,
  130. url: '',
  131. is_vip: false,
  132. is_vip_card_user: 0,
  133. show: false,
  134. list: [],
  135. goods_id: -1,
  136. loading: false,
  137. first: true,
  138. discount: null,
  139. flash_sale: null,
  140. full_reduce: null,
  141. disable: 'disable',
  142. }
  143. },
  144. onLoad(options) { this.$commonLoad.onload(options);
  145. // #ifdef MP-WEIXIN
  146. wx.showShareMenu({
  147. menus: ['shareAppMessage', 'shareTimeline']
  148. })
  149. // #endif
  150. this.goods_id = +options.goods_id;
  151. this.posterConfig = this.posterConfig + '&goods_id=' + this.goods_id;
  152. this.posterGenerate = this.posterGenerate + '&goods_id=' + this.goods_id;
  153. this.$showLoading({
  154. type: 'global',
  155. text: '加载中...'
  156. });
  157. this.request({
  158. url: this.$api.exchange.detail,
  159. data: {
  160. id: this.goods_id,
  161. }
  162. }).then(response => {
  163. if(response) {
  164. this.first = false;
  165. let { goods } = response;
  166. this.goods = goods;
  167. this.loading = true;
  168. this.url = `${this.$api.goods.poster}&goods_id=${this.goods.id}`;
  169. if(this.goods.vip_card_appoint.discount) {
  170. this.is_vip = true;
  171. this.discount = this.goods.vip_card_appoint.discount
  172. }
  173. this.full_reduce = goods.goods_activity.full_reduce;
  174. this.flash_sale = this.goods.plugin_extra.flash_sale;
  175. this.is_vip_card_user = this.goods.vip_card_appoint.is_vip_card_user;
  176. // #ifdef H5
  177. this.hShareAppMessage();
  178. // #endif
  179. this.$hideLoading();
  180. }
  181. });
  182. },
  183. onShow() {
  184. this.showClose = false;
  185. setTimeout(()=>{
  186. this.showClose = true;
  187. })
  188. if(this.first) {
  189. return false
  190. }
  191. this.$showLoading();
  192. this.$nextTick(() => {
  193. this.request({
  194. url: this.$api.exchange.detail,
  195. data: {
  196. id: this.goods_id,
  197. }
  198. }).then(response => {
  199. let { goods } = response;
  200. this.goods = goods;
  201. this.loading = true;
  202. this.full_reduce = goods.goods_activity.full_reduce;
  203. this.url = `${this.$api.goods.poster}&goods_id=${this.goods.id}`;
  204. if(this.goods.vip_card_appoint.discount) {
  205. this.is_vip = true;
  206. this.discount = this.goods.vip_card_appoint.discount
  207. }
  208. this.flash_sale = this.goods.plugin_extra.flash_sale;
  209. this.is_vip_card_user = this.goods.vip_card_appoint.is_vip_card_user;
  210. this.$hideLoading();
  211. });
  212. })
  213. },
  214. computed: {
  215. ...mapState('gConfig',{
  216. iphone: (data) => {
  217. return data.iphone;
  218. },
  219. iphoneHeight: (state) =>{
  220. return state.iphoneHeight;
  221. },
  222. }),
  223. ...mapGetters('mallConfig', {
  224. getTheme: 'getTheme',
  225. }),
  226. ...mapState({
  227. mall: state => state.mallConfig.mall,
  228. userInfo: state => state.user.info,
  229. isTip: state => state.mallConfig.mall.setting.is_remind_sell_time
  230. }),
  231. themeObject:function() {
  232. return {
  233. back: this.getTheme + '-m-back ' + this.getTheme,
  234. backO: this.getTheme + '-m-back-o ' + this.getTheme,
  235. theme: this.getTheme,
  236. color: this.getTheme + '-m-text ' + this.getTheme,
  237. sBack: this.getTheme + '-s-back ' + this.getTheme
  238. }
  239. },
  240. buyBtn() {
  241. if (!this.goods || this.goods.buy_goods_auth) {
  242. return this.getTheme + '-m-gradient-o ' + this.getTheme
  243. } else {
  244. return this.disable + '-m-back ' + this.disable;
  245. }
  246. },
  247. uBottomHeight() {
  248. if (this.full_reduce && this.goods.sell_time > 0) {
  249. return 'u-bottom-height-2';
  250. } else if (this.full_reduce || this.goods.sell_time > 0) {
  251. return 'u-bottom-height-1';
  252. } else {
  253. return 'u-bottom-height-0';
  254. }
  255. },
  256. leftTip() {
  257. let leftTip = '';
  258. if (!(this.isTip == 0 && this.goods.sell_time > 0)) {
  259. leftTip = 'bd-btn-left bd-btn-half';
  260. } else {
  261. leftTip = 'box-grow-1';
  262. }
  263. return this.goods && this.goods.type === 'goods' ? leftTip : '';
  264. },
  265. disableBtn() {
  266. if (this.goods.is_finish_sell || this.goods.sell_time > 0) {
  267. return 'btn-finish-sell';
  268. } else {
  269. return 'bd-oversell-btn';
  270. }
  271. },
  272. disableBtnText() {
  273. if (this.goods.is_finish_sell) {
  274. return '商品已下架';
  275. } else if (this.goods.sell_time > 0) {
  276. return '商品未开售';
  277. } else {
  278. return '已售罄';
  279. }
  280. },
  281. remindParams() {
  282. return {
  283. sell_time: this.goods.sell_time,
  284. goods_id: this.goods.id,
  285. template_message_list: this.goods.template_message_list,
  286. buy_text: '立即购买'
  287. };
  288. },
  289. },
  290. // #ifdef MP-WEIXIN
  291. onShareTimeline() {
  292. // 分享朋友圈beta
  293. return this.$shareTimeline({
  294. title: this.goods.app_share_title ? this.goods.app_share_title : this.goods.name,
  295. imageUrl: this.goods.pic_url[0].pic_url,
  296. query: {
  297. goods_id: this.goods.id
  298. }
  299. });
  300. },
  301. // #endif
  302. // #ifdef MP
  303. onShareAppMessage() {
  304. return this.hShareAppMessage();
  305. },
  306. // #endif
  307. methods: {
  308. hShareAppMessage(s = false){
  309. return this.$shareAppMessage({
  310. path: '/plugins/exchange/goods/goods',
  311. title: this.goods.app_share_title ? this.goods.app_share_title : this.goods.name,
  312. imageUrl: this.goods.app_share_pic ? this.goods.app_share_pic : this.goods.pic_url[0].pic_url,
  313. desc: this.goods.subtitle,
  314. params: {
  315. goods_id: this.goods.id,
  316. }
  317. },s);
  318. },
  319. getMall(e) {
  320. this.is_open = e.is_open == 1 ? true : false;
  321. },
  322. toExchange() {
  323. if (!this.goods.buy_goods_auth) {
  324. this.$tips.showToast({
  325. title: '您暂无权限购买该商品',
  326. icon: 'none'
  327. });
  328. return;
  329. }
  330. if (this.goods.sell_time > 0) {
  331. this.rightTip();
  332. return ;
  333. }
  334. if (typeof this.goods.limit_buy !== 'undefined' && this.goods.limit_buy.status == 1 && this.goods.limit_buy.rest_number < 1) {
  335. this.$tips.showToast({
  336. title: this.goods.limit_buy.text,
  337. icon: 'none'
  338. });
  339. return false;
  340. }
  341. let attr = [];
  342. for (let i in this.goods.attr[0].attr_list) {
  343. attr.push({
  344. attr_id: this.goods.attr[0].attr_list[i].attr_id,
  345. attr_group_id: this.goods.attr[0].attr_list[i].attr_group_id
  346. });
  347. }
  348. let mch_list = [{
  349. mch_id: 0,
  350. goods_list: [{
  351. id: this.goods.id,
  352. attr: attr,
  353. num: 1,
  354. cat_id: 0,
  355. goods_attr_id: this.goods.attr[0].id
  356. }]
  357. }];
  358. let url = `/pages/order-submit/order-submit?mch_list=${JSON.stringify(mch_list)}`;
  359. url += `&preview_url=${encodeURIComponent(this.$api.exchange.order_preview)}&submit_url=${encodeURIComponent(this.$api.exchange.order_submit)}&plugin=exchange`;
  360. uni.navigateTo({
  361. url: url
  362. })
  363. },
  364. async request({url, data}) {
  365. const response = await this.$request({
  366. url: url,
  367. data: data,
  368. });
  369. if (response.code === 0) {
  370. return response.data;
  371. }else {
  372. uni.showModal({
  373. title: '提示',
  374. content: response.msg,
  375. showCancel: false,
  376. success: function (res) {
  377. uni.navigateBack();
  378. }
  379. });
  380. }
  381. },
  382. setCoupon(index) {
  383. this.$set(this.goods.goods_coupon_center[index], 'is_receive', 1);
  384. },
  385. changeTime(time) {
  386. this.goods.sell_time = time;
  387. },
  388. },
  389. components: {
  390. 'app-banner': appBanner,
  391. appClose,
  392. appGoodsFullReduce,
  393. bdInfo,
  394. bdCoupon,
  395. bdXbc,
  396. bdKb,
  397. bdHc,
  398. bdDetail,
  399. bdComments,
  400. appSellTip
  401. }
  402. }
  403. </script>
  404. <style lang="scss">
  405. .buttons {
  406. width: #{750rpx};
  407. height: #{110rpx};
  408. border-top: #{1rpx} solid #e2e2e2;
  409. .app-button {
  410. width: 100%;
  411. height: #{110rpx};
  412. text-align: center;
  413. line-height: #{110rpx};
  414. background-color: #fff;
  415. .app-exhange {
  416. width: #{702rpx};
  417. color: #fff;
  418. border-radius: #{41rpx};
  419. height: #{82rpx};
  420. line-height: #{82rpx};
  421. font-size: #{28rpx};
  422. }
  423. .app-over {
  424. width: #{702rpx};
  425. border-radius: #{41rpx};
  426. height: #{82rpx};
  427. line-height: #{82rpx};
  428. font-size: #{28rpx};
  429. }
  430. .bd-oversell-btn {
  431. background: #e9e9e9;
  432. color: #999999;
  433. }
  434. .btn-finish-sell {
  435. background: linear-gradient(to right, rgba(153, 153, 153, 1), rgba(153, 153, 153, 0.7)) ;
  436. color: #ffffff;
  437. }
  438. }
  439. }
  440. .u-bottom-height-0 {
  441. height: 110upx;
  442. }
  443. .u-bottom-height-1 {
  444. height: 190upx;
  445. }
  446. .u-bottom-fixed {
  447. position: fixed;
  448. bottom: 0;
  449. left: 0;
  450. width: 100%;
  451. z-index: 1602;
  452. background-color: #ffffff;
  453. }
  454. .u-bottom-height-2 {
  455. height: 270upx;
  456. }
  457. </style>