index.vue 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674
  1. <template>
  2. <app-layout>
  3. <view class="index">
  4. <!-- 导航 -->
  5. <view class="page-width gift-navigation">
  6. <gift-navigation
  7. v-bind:theme="theme"
  8. v-bind:botHeight="BotHeight"
  9. v-bind:navBool="navBool"
  10. ></gift-navigation>
  11. </view>
  12. <!-- 挑选礼物 -->
  13. <view class="page-width pick-gift">
  14. <pick-gift
  15. v-bind:theme="theme"
  16. v-bind:gift_list="gift_list"
  17. v-on:giftNumber="giftNumber"
  18. v-on:giftInput="giftInput"
  19. ></pick-gift>
  20. </view>
  21. <!-- 送礼方式 -->
  22. <view class="page-width gift-method">
  23. <gift-method
  24. v-bind:method_type="method_type"
  25. v-bind:open_type="open_type"
  26. v-bind:select_str="select_str"
  27. v-bind:type="config.type"
  28. v-on:set_methods="set_methods"
  29. v-on:set_people_status="set_people_status"
  30. v-on:change_people="change_people"
  31. v-on:set_lottery_time="set_lottery_time"
  32. ></gift-method>
  33. </view>
  34. <!-- 祝福留言 -->
  35. <view class="page-width blessing-message">
  36. <blessing-message
  37. v-bind:bless_word="bless_word"
  38. v-on:changeTextarea="changeTextarea"
  39. v-bind:place_bless_word="config.bless_word"
  40. ></blessing-message>
  41. </view>
  42. <!-- #ifdef MP -->
  43. <!-- 语音 -->
  44. <view class="page-width voice">
  45. <voice
  46. v-bind:theme="theme"
  47. v-bind:botHeight="BotHeight"
  48. v-bind:is_play="is_play"
  49. v-on:play="play"
  50. v-bind:audio="audio"
  51. v-on:recorder="recorder"
  52. v-bind:voice_i="voice_i"
  53. v-on:click="voice_i = 0"
  54. v-on:close="close"
  55. ></voice>
  56. </view>
  57. <!-- #endif -->
  58. <!-- 生成礼包 -->
  59. <view class="page-width generate-package">
  60. <generate-package
  61. v-bind:theme="theme"
  62. v-bind:totalPrice="totalPrice"
  63. v-on:click="generatePackage"
  64. v-bind:template_message_captain="config.template_message_captain_gift_form_user"
  65. ></generate-package>
  66. </view>
  67. <!-- 空白格 -->
  68. <view class="page-width empty-nav">
  69. <app-empty-bottom
  70. backgroundColor="#f7f7f7"
  71. v-bind:height="Number(96)"
  72. ></app-empty-bottom>
  73. </view>
  74. <view class="page-width get-right-now" v-if="is_gift && Object.keys(gift).length > 0">
  75. <get-right-now
  76. v-bind:background="config.background"
  77. v-on:setGift="setGift"
  78. v-bind:gift_id="gift_id"
  79. v-bind:turn_no="turn_no"
  80. v-bind:bless_word="gift.list.bless_word"
  81. v-bind:nickname="gift.list.user.nickname"
  82. v-bind:avatar="gift.list.user.userInfo.avatar"
  83. v-bind:type="gift.list.type"
  84. v-bind:bless_music="gift.list.bless_music"
  85. v-bind:template_message="config.template_message_captain_gift_convert"
  86. v-bind:music_play="music_play"
  87. v-on:music="music"
  88. ></get-right-now>
  89. </view>
  90. <view v-bind:style="{width: `100%`, height: `${BotHeight}rpx`}" v-if="navBool"></view>
  91. </view>
  92. </app-layout>
  93. </template>
  94. <script>
  95. import { mapState, mapGetters } from 'vuex';
  96. import pickGift from '../components/index/pick-gift.vue';
  97. import giftMethod from '../components/index/gift-method.vue';
  98. import blessingMessage from '../components/index/blessing-message.vue';
  99. import generatePackage from '../components/index/generate-package.vue';
  100. import giftNavigation from '../components/announcement/gift-navigation.vue';
  101. import appEmptyBottom from'../../../components/basic-component/app-empty-bottom/app-empty-bottom.vue';
  102. import getRightNow from '../components/index/get-right-now.vue';
  103. import voice from '../components/index/voice.vue';
  104. export default {
  105. name: 'index',
  106. data() {
  107. return {
  108. // 礼物购物车
  109. gift_list: [],
  110. // 总价
  111. totalPrice: 0,
  112. // 送礼方式
  113. method_type: 'direct_open',
  114. // 领取方式
  115. open_type: 0,
  116. // 领取人数
  117. open_num: null,
  118. // 开奖时间
  119. select_str: ``,
  120. // 打开时间
  121. open_time: ``,
  122. // 祝福语
  123. bless_word: ``,
  124. // 插件配置
  125. config: {},
  126. // 是否领取礼物
  127. is_gift: false,
  128. // 礼物id
  129. gift_id: -1,
  130. // 转增码
  131. turn_no: '',
  132. // 礼物
  133. gift: {},
  134. // #ifdef MP
  135. currentRoute: this.$platDiff.route(),
  136. // #endif
  137. navBool: false,
  138. new_open_type: '',
  139. src: '',
  140. innerAudioContext: '',
  141. // 是否播放
  142. is_play: false,
  143. audio: {},
  144. recorderManager: null,
  145. music_play: false,
  146. bless_music: '',
  147. voice_i: 0,
  148. voice_time: -1
  149. }
  150. },
  151. onLoad(options) { this.$commonLoad.onload(options);
  152. if (!this.$user.isLogin()) {
  153. this.$user.getInfo().then(() => {
  154. if (options.gift_id && options.user_id) {
  155. this.gift_id = options.gift_id;
  156. this.is_gift = true;
  157. this.turn_no = options.turn_no;
  158. this.getGift(this.gift_id);
  159. }
  160. });
  161. } else {
  162. if (options.gift_id && options.user_id) {
  163. this.is_gift = true;
  164. this.gift_id = options.gift_id;
  165. this.turn_no = options.turn_no;
  166. this.getGift(this.gift_id);
  167. } else if (options.pay_data) {
  168. let gift_id = JSON.parse(options.pay_data).gift_id;
  169. this.$request({
  170. url: this.$api.gift.cancel,
  171. data: {
  172. gift_id: gift_id,
  173. }
  174. })
  175. }
  176. }
  177. this.request();
  178. let self = this;
  179. // #ifdef MP
  180. this.recorderManager = uni.getRecorderManager({
  181. duration: 30000
  182. });
  183. this.innerAudioContext = uni.createInnerAudioContext();
  184. this.innerAudioContext.onEnded(function(res) {
  185. self.is_play = false;
  186. self.music_play = false;
  187. });
  188. this.innerAudioContext.onStop(function() {
  189. });
  190. this.innerAudioContext.autoplay = true;
  191. this.recorderManager.onStop(function (res) {
  192. uni.uploadFile({
  193. url: self.$api.upload.file,
  194. filePath: res.tempFilePath,
  195. name: 'file',
  196. fileType: 'audio',
  197. formData: {
  198. file: res.tempFilePath,
  199. file_name: ''
  200. },
  201. success(e) {
  202. let {code, data} = JSON.parse(e.data);
  203. self.bless_music = data.url;
  204. }
  205. })
  206. self.audio = res;
  207. });
  208. // #endif
  209. // #ifdef MP-WEIXIN
  210. wx.showShareMenu({
  211. menus: ['shareAppMessage', 'shareTimeline']
  212. })
  213. // #endif
  214. },
  215. onShow() {
  216. this.gift_list = this.$storage.getStorageSync(`GIFT_CART`);
  217. for (let i = 0; i < this.gift_list.length; i++) {
  218. this.gift_list[i].number = Number(this.gift_list[i].number);
  219. this.gift_list[i].total_cost = parseFloat((this.gift_list[i].number * this.gift_list[i].price).toFixed(2));
  220. }
  221. },
  222. onUnload() {
  223. if (this.innerAudioContext) {
  224. this.music_play = false;
  225. this.is_play = false;
  226. this.innerAudioContext.stop();
  227. }
  228. },
  229. onHide() {
  230. if (this.innerAudioContext) {
  231. this.music_play = false;
  232. this.is_play = false;
  233. this.innerAudioContext.stop();
  234. }
  235. },
  236. // #ifdef MP
  237. onShareAppMessage() {
  238. return this.$shareAppMessage({
  239. path: '/plugins/gift/index/index',
  240. title: this.config.ask_gift,
  241. });
  242. },
  243. // #endif
  244. // #ifdef MP-WEIXIN
  245. onShareTimeline() {
  246. // 分享朋友圈beta
  247. return this.$shareTimeline({
  248. title: this.config.ask_gift,
  249. query: {
  250. } // 此处填写页面的参数
  251. });
  252. },
  253. // #endif
  254. methods: {
  255. // 请求配置
  256. async request() {
  257. this.$utils.showLoading();
  258. try {
  259. const res = await this.$request({
  260. url: this.$api.gift.config,
  261. method: 'get',
  262. });
  263. this.$utils.hideLoading();
  264. if (res.code === 0) {
  265. this.config = res.data;
  266. uni.setNavigationBarTitle({
  267. title: res.data.title,
  268. });
  269. let theme = '';
  270. switch (Number(res.data.theme.id)) {
  271. case 1:
  272. theme = 'streamer-gold-gift';
  273. break;
  274. case 2:
  275. theme = 'romantic-powder-gift';
  276. break;
  277. case 3:
  278. theme = 'taste-red-gift';
  279. break;
  280. case 4:
  281. theme = 'elegant-purple-gift';
  282. break;
  283. case 5:
  284. theme = 'fresh-green-gift';
  285. break;
  286. case 6:
  287. theme = 'business-blue-gift';
  288. break;
  289. default:
  290. theme = 'streamer-gold-gift';
  291. }
  292. this.$storage.setStorageSync('giftTheme', theme);
  293. this.$store.commit('gift/setTheme', Number(res.data.theme.id));
  294. this.$store.commit('gift/setGiftPic', res.data.big_gift_pic);
  295. this.method_type = this.config.type[0];
  296. } else {
  297. uni.showModal({
  298. title: '提示',
  299. content: res.msg,
  300. });
  301. }
  302. } catch (e) {
  303. this.$utils.hideLoading();
  304. throw new Error(e);
  305. }
  306. },
  307. //加减礼物数量
  308. giftNumber({index, type}) {
  309. if (type) {
  310. this.gift_list[index].number = this.gift_list[index].number + 1;
  311. } else {
  312. this.gift_list[index].number = this.gift_list[index].number - 1;
  313. }
  314. this.changeNumber(index);
  315. },
  316. //input改变礼物数量
  317. giftInput({index, quantity}) {
  318. // 数量大于规格库存
  319. if (quantity >= this.gift_list[index].attr.stock) {
  320. let gift = JSON.parse(JSON.stringify(this.gift_list[index]));
  321. gift.number = this.gift_list[index].attr.stock;
  322. this.$set(this.gift_list, index, gift);
  323. this.changeNumber(index);
  324. } else {
  325. this.$set(this.gift_list[index], 'number', quantity);
  326. this.changeNumber(index);
  327. }
  328. },
  329. // 改变数量
  330. changeNumber(index) {
  331. let { number, price } = this.gift_list[index];
  332. this.$set(this.gift_list[index], 'total_cost', parseFloat((number * price).toFixed(2)));
  333. if (this.gift_list[index].number === 0) {
  334. this.$delete(this.gift_list, index);
  335. }
  336. this.$storage.setStorageSync('GIFT_CART', this.gift_list);
  337. },
  338. async submit() {
  339. this.$utils.showLoading();
  340. let form_data = [
  341. {
  342. mch_id: 0,
  343. type: this.method_type,
  344. open_num: this.open_num,
  345. open_time: this.open_time,
  346. bless_word: this.bless_word ? this.bless_word : this.config.bless_word,
  347. bless_music: this.bless_music,
  348. open_type: this.open_type,
  349. goods_list: [],
  350. remark: '',
  351. use_integral: 0,
  352. user_coupon_id: 0
  353. }
  354. ];
  355. for (let i = 0; i < this.gift_list.length; i++) {
  356. let goods = {
  357. id: this.gift_list[i].attr.goods_id,
  358. attr: [],
  359. num: this.gift_list[i].number,
  360. cat_id: 0,
  361. goods_attr_id: this.gift_list[i].attr.id,
  362. };
  363. for (let j = 0; j < this.gift_list[i].attr.attr_list.length; j++) {
  364. goods.attr.push({
  365. attr_id: this.gift_list[i].attr.attr_list[j].attr_id,
  366. attr_group_id: this.gift_list[i].attr.attr_list[j].attr_group_id,
  367. })
  368. }
  369. form_data[0].goods_list.push(goods);
  370. }
  371. let data = {
  372. form_data: JSON.stringify({
  373. list: form_data,
  374. })
  375. };
  376. this.$store.commit('gift/setFormData', data);
  377. if (this.method_type === 'direct_open') {
  378. delete form_data[0].open_num;
  379. delete form_data[0].open_time;
  380. } else if (this.method_type === 'time_open') {
  381. delete form_data[0].open_num;
  382. } else if (this.method_type === 'num_open') {
  383. delete form_data[0].open_time;
  384. }
  385. this.$utils.hideLoading();
  386. uni.navigateTo({
  387. url: `/pages/order-submit/order-submit?preview_url=${encodeURIComponent(this.$api.gift.order_preview)}&submit_url=${encodeURIComponent(this.$api.gift.order_submit)}&pay_data_url=${encodeURIComponent(this.$api.gift.pay_data)}&show_pay_result=false&mch_list=${JSON.stringify(form_data)}&theme=${this.theme}&order_page_url=/plugins/gift/share/share&pay_cancel_url=/plugins/gift/index/index`
  388. });
  389. },
  390. // 生成礼物
  391. generatePackage() {
  392. this.submit();
  393. },
  394. // 设置方法
  395. set_methods(data) {
  396. this.method_type = data;
  397. },
  398. // 设置单人多人
  399. set_people_status(data) {
  400. this.open_type = data;
  401. },
  402. // 设置参与如数
  403. change_people(data) {
  404. this.open_num = data;
  405. },
  406. // 设置定时时间
  407. set_lottery_time(data, time) {
  408. this.select_str = data;
  409. this.open_time = time;
  410. },
  411. // 修改祝福语
  412. changeTextarea(data) {
  413. this.bless_word = data;
  414. },
  415. // 支付接口
  416. async pay_data(data) {
  417. try {
  418. const res = await this.$request({
  419. url: this.$api.gift.pay_data,
  420. method: 'post',
  421. data: {
  422. ...data
  423. },
  424. });
  425. if (res.code === 0) {
  426. if (res.data.hasOwnProperty('id')) {
  427. this.$payment.pay(res.data.id).then(() => {
  428. // 支付成功
  429. this.$storage.setStorageSync('GIFT_CART', []);
  430. uni.redirectTo({
  431. url: `/plugins/gift/share/share?gift_id=${res.data.gift_id}`,
  432. });
  433. }).catch(() => {
  434. // 支付失败
  435. });
  436. this.$utils.hideLoading();
  437. } else {
  438. setTimeout(() => {
  439. this.pay_data(data);
  440. }, 1000);
  441. }
  442. } else {
  443. this.$utils.hideLoading();
  444. uni.showModal({
  445. title: '提示',
  446. content: res.msg,
  447. });
  448. }
  449. } catch (e) {
  450. this.$utils.hideLoading();
  451. throw new Error(e);
  452. }
  453. },
  454. // 开启关闭领取礼物
  455. setGift(data) {
  456. this.is_gift = data;
  457. },
  458. async getGift(data) {
  459. this.$utils.showLoading();
  460. const res = await this.$request({
  461. url: this.$api.gift.gift,
  462. data: {
  463. gift_id: data,
  464. }
  465. });
  466. if (res.code === 0) {
  467. this.gift = res.data;
  468. this.wordYun(this.gift.list.bless_word);
  469. } else {
  470. uni.showModal({
  471. title: '提示',
  472. content: res.msg,
  473. })
  474. }
  475. this.$utils.hideLoading();
  476. },
  477. setNav() {
  478. let currentRoute = undefined;
  479. // #ifdef MP
  480. currentRoute = this.currentRoute;
  481. // #endif
  482. // #ifdef H5
  483. currentRoute = window.location.hash.split('#')[1].split('?')[0];
  484. // #endif
  485. if (!currentRoute) return;
  486. for (let i = 0; i < this.tabBarNavs.length; i++) {
  487. if(currentRoute.includes(this.tabBarNavs[i].url.split('?')[0])) {
  488. return this.navBool = true;
  489. }
  490. }
  491. return this.navBool = false;
  492. },
  493. play(status) {
  494. this.is_play = status;
  495. this.voice_i = 0;
  496. if (status) {
  497. // #ifdef MP
  498. this.innerAudioContext.src = this.audio.tempFilePath;
  499. this.innerAudioContext.play();
  500. // #endif
  501. // #ifdef H5
  502. this.$jwx.playVoice({
  503. localId: this.audio.localId
  504. });
  505. // #endif
  506. } else {
  507. // #ifdef MP
  508. this.innerAudioContext.stop();
  509. // #endif
  510. // #ifdef H5
  511. this.$jwx.stopVoice({
  512. localId: this.audio.localId
  513. });
  514. // #endif
  515. }
  516. },
  517. recorder(status) {
  518. if (status) {
  519. clearInterval(this.voice_time);
  520. this.voice_i = 0;
  521. this.voice_time = setInterval(() => {
  522. this.voice_i++;
  523. }, 1000);
  524. // #ifdef MP
  525. this.recorderManager.start();
  526. // #endif
  527. // #ifdef H5
  528. this.$jwx.startRecord();
  529. // #endif
  530. } else {
  531. // #ifdef MP
  532. this.recorderManager.stop();
  533. // #endif
  534. // #ifdef H5
  535. let _this = this;
  536. this.$jwx.stopRecord({
  537. success(res) {
  538. _this.audio = res;
  539. }
  540. });
  541. // #endif
  542. clearInterval(this.voice_time);
  543. }
  544. },
  545. music(status, bless_music) {
  546. this.music_play = status;
  547. if (status) {
  548. this.innerAudioContext.src = bless_music;
  549. this.innerAudioContext.play();
  550. } else {
  551. this.innerAudioContext.stop();
  552. }
  553. },
  554. close() {
  555. this.is_play = false;
  556. this.innerAudioContext.stop();
  557. }
  558. },
  559. watch: {
  560. gift_list: {
  561. handler(data) {
  562. this.totalPrice = 0;
  563. for (let i = 0; i < data.length; i++) {
  564. this.totalPrice += data[i].total_cost;
  565. }
  566. this.totalPrice = this.totalPrice.toFixed(2);
  567. },
  568. immediate: true,
  569. deep: true,
  570. },
  571. tabBarNavs: {
  572. handler: function() {
  573. this.setNav();
  574. },
  575. immediate: true,
  576. }
  577. },
  578. computed: {
  579. ...mapState('gift',{
  580. theme: state => state.theme,
  581. big_gift_pic: state => state.big_gift_pic,
  582. }),
  583. ...mapState({
  584. tabBarNavs: state => state.mallConfig.navbar.navs,
  585. }),
  586. ...mapGetters('iPhoneX', {
  587. BotHeight: 'getNavHei',
  588. }),
  589. },
  590. components: {
  591. 'pick-gift': pickGift,
  592. 'gift-method': giftMethod,
  593. 'blessing-message': blessingMessage,
  594. 'generate-package': generatePackage,
  595. 'gift-navigation': giftNavigation,
  596. 'app-empty-bottom': appEmptyBottom,
  597. 'get-right-now': getRightNow,
  598. 'voice': voice
  599. },
  600. }
  601. </script>
  602. <style lang="scss">
  603. /* 首页 */
  604. .index {
  605. position: absolute;
  606. min-height: 100%;
  607. width: 100%;
  608. background-color: #f7f7f7;
  609. }
  610. /* 挑选礼物 */
  611. .pick-gift {
  612. }
  613. /* 送礼方式 */
  614. .gift-method {
  615. position: relative;
  616. top: -20upx;
  617. }
  618. /* 祝福留言 */
  619. .blessing-message {
  620. position: relative;
  621. top: -20upx;
  622. }
  623. /* 生成礼包 */
  624. .generate-package {
  625. position: relative;
  626. top: -20upx;
  627. }
  628. /* 导航 */
  629. .gift-navigation {}
  630. </style>