index.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  1. <template>
  2. <page :nav="false" ref="pageRef">
  3. <image :src="resource.lottery_bg" mode="aspectFill" class="bg" />
  4. <view class="mask-page"></view>
  5. <view class="wrapper flex-column-align" v-if="revealData && revealData.length > 0" :style="{paddingTop: padding + 'px'}">
  6. <view class="relative">
  7. <view :class="[revealData.length === 1 ? 'height1' : 'height5']">
  8. <view v-for="(pItem, pIndex) in revealData" :key="pIndex" class="overflow-hidden">
  9. <view :style="{width: pItem.length * itemWidth + 'px'}" class="flex-align animal-wrapper"
  10. :id="`animal-wrapper-${pIndex}`" :animation="animalCreateArray[pIndex]">
  11. <view v-for="item in pItem" :key="item.key" :style="{padding: '5px 0'}">
  12. <trans-card v-if="num > 1" :item="item" />
  13. <trans-card v-else :item="item" :width="90" :height="121" :fill="2" :image-width="74" :image-height="94" />
  14. </view>
  15. </view>
  16. </view>
  17. </view>
  18. </view>
  19. <view class="mask-left" :style="{width: width + 'px'}"></view>
  20. <view class="mask-right" :style="{width: width + 'px'}"></view>
  21. <image :src="revealData.length === 1 ? resource.lottery_middle_s : resource.lottery_middle_l" class="lottery_middle translateY"
  22. mode="widthFix" :style="{marginTop: (padding / 2) + 'px'}" />
  23. </view>
  24. <view class="bottom">
  25. <view class="bottom-btns flex-align-center" @click="skipAnimal">
  26. 跳过动画
  27. </view>
  28. </view>
  29. <result-com ref="result" :num="num" :isDemo="isDemo" :periodQuantity="periodQuantity" />
  30. <hiddenTask ref="hiddenTaskRef" @refresh="initGoods" />
  31. </page>
  32. </template>
  33. <script>
  34. import resource from '@/utils/resource'
  35. import { LEVEL_MAP } from '@/utils/config'
  36. import transCard from './trans_card'
  37. import resultCom from './result_com'
  38. import hiddenTask from '../hidden_activity/hidden_task_dialog.vue'
  39. export default {
  40. components: { transCard, resultCom, hiddenTask },
  41. data() {
  42. return {
  43. LEVEL_MAP,
  44. resource,
  45. num: 1,
  46. nums: [],
  47. animal: false,
  48. tableData: null,
  49. isDemo: false,
  50. total: 0,
  51. goods: null,
  52. revealData: null,
  53. animalCreateArray: [],
  54. itemWidth: 0,
  55. king: null,
  56. periodQuantity: null,
  57. magicFireworksList: null,
  58. spuIds: '',
  59. resultFlag: false,
  60. width: 140.5,
  61. padding: 32
  62. }
  63. },
  64. computed: {
  65. // width() {
  66. // if (this.$store.state.systemInfo) {
  67. // let screenWidth = this.$store.state.systemInfo.screenWidth
  68. // return (screenWidth - (this.num == 1 ? 94 : 72)) / 2
  69. // }
  70. // return 0
  71. // },
  72. // padding() {
  73. // if (this.$store.state.systemInfo) {
  74. // let screenWidth = this.$store.state.systemInfo.safeArea.height
  75. // return screenWidth > 650 ? 32 : 0
  76. // }
  77. // return 0
  78. // }
  79. },
  80. onLoad(options) {
  81. console.log('参数', options);
  82. this.goods = this.$cache.get(this.$cache.key.AWARD_GOODS)
  83. console.log('goods', this.goods);
  84. console.log("width", this.width);
  85. console.log("padding", this.padding);
  86. this.num = Number(options.num) || 5
  87. this.itemWidth = this.num == 1 ? 94 : 71
  88. this.initNums()
  89. //试玩
  90. if (options.tradeNo) {
  91. this.tradeNo = options.tradeNo
  92. } else {
  93. this.isDemo = true
  94. this.tableData = [this.$cache.get(this.$cache.key.AWARD_DEMO)]
  95. console.log('tableData', this.tableData);
  96. }
  97. this.initGoods()
  98. this.innerAudioContext = wx.createInnerAudioContext({
  99. useWebAudioImplement: false // 是否使用 WebAudio 作为底层音频驱动,默认关闭。对于短音频、播放频繁的音频建议开启此选项,开启后将获得更优的性能表现。由于开启此选项后也会带来一定的内存增长,因此对于长音频建议关闭此选项
  100. })
  101. this.innerAudioContext.src = resource.mp3_5
  102. },
  103. mounted() {
  104. setTimeout(
  105. () => {
  106. this.startAnimal()
  107. },
  108. this.num == 1 ? 500 : 700
  109. )
  110. if (this.tradeNo) {
  111. this.time = new Date().getTime()
  112. this.initData(0)
  113. } else {
  114. this.initDemo()
  115. }
  116. },
  117. onUnload() {
  118. this.stopPlay()
  119. },
  120. methods: {
  121. stopPlay() {
  122. try {
  123. this.innerAudioContext && this.innerAudioContext.stop()
  124. this.innerAudioContext && this.InnerAudioContext.destroy()
  125. this.innerAudioContext = null
  126. } catch (error) {}
  127. },
  128. initNums() {
  129. let array = []
  130. for (let i = 0; i < this.num; i++) {
  131. array.push(i)
  132. }
  133. this.nums = array
  134. },
  135. initGoods() {
  136. this.screenWidth = this.$store.state.systemInfo.screenWidth
  137. let array = []
  138. let animalArray = []
  139. this.nums.forEach((_) => {
  140. let tGoods = this.handleGoods(this.goods)
  141. array.push(tGoods.array)
  142. animalArray.push({
  143. active: tGoods.active,
  144. offset: tGoods.offset
  145. })
  146. })
  147. this.revealData = array
  148. this.animalArray = animalArray
  149. },
  150. handleGoods(goods) {
  151. let lastItem = goods[goods.length - 1]
  152. let array = goods.concat(goods)
  153. array = this.$common.shuffle(array)
  154. array = array.slice(0, Math.floor((array.length / 5) * 4))
  155. let active = Math.floor(Math.random() * 3 + array.length - 8)
  156. array[active] = lastItem
  157. array = array.map((item) => ({ ...item }))
  158. array.forEach((item, index) => {
  159. item.key = index
  160. })
  161. let offset =
  162. this.itemWidth * active +
  163. Math.floor(Math.random() * (this.itemWidth - 4 - 22) + 15) -
  164. this.screenWidth / 2
  165. return { array, active, offset }
  166. },
  167. // 主要
  168. startAnimal() {
  169. this.resultFlag = false
  170. let animalCreateArray = []
  171. this.animalArray.forEach((item, index) => {
  172. let animation = wx.createAnimation({
  173. duration: 7000,
  174. timingFunction: 'ease-out'
  175. })
  176. animation.translateX(-item.offset).step()
  177. let animationData = animation.export()
  178. animalCreateArray.push(animationData)
  179. })
  180. this.animalCreateArray = animalCreateArray
  181. setTimeout(() => {
  182. if(!this.resultFlag) {
  183. this.skipAnimal()
  184. }
  185. }, 7200)
  186. setTimeout(() => {
  187. this.innerAudioContext.play()
  188. }, 100)
  189. },
  190. skipAnimal() {
  191. this.stopPlay()
  192. this.resultFlag = true
  193. this.showResult()
  194. },
  195. async initDemo() {
  196. this.tableData.forEach((item, index) => {
  197. item.key = 1000
  198. this.$set(this.revealData[index], this.animalArray[index].active, item)
  199. })
  200. },
  201. async initData(count) {
  202. setTimeout(async () => {
  203. await this.getData()
  204. if (this.tableData && this.tableData.length > 0) {
  205. if (new Date().getTime() - this.time > 4000) {
  206. this.fail()
  207. } else {
  208. this.tableData.forEach((item, index) => {
  209. item.key = 10000
  210. this.$set(this.revealData[index], this.animalArray[index].active, item)
  211. })
  212. }
  213. } else {
  214. if (count < 4) {
  215. this.initData(count + 1)
  216. } else {
  217. this.fail()
  218. }
  219. }
  220. }, 500)
  221. },
  222. async getData() {
  223. const res = await this.$service.award.applyResult(this.tradeNo)
  224. if (res && res.inventoryList) {
  225. this.tableData = res.inventoryList
  226. if (res.kingRealtime && res.kingRealtime.periodQuantity) {
  227. this.periodQuantity = res.kingRealtime.periodQuantity
  228. }
  229. this.magicFireworksList = res.magicFireworksList
  230. if (res.richmanTicketRealtime && res.richmanTicketRealtime.changeTicket) {
  231. this.changeTicket = res.richmanTicketRealtime.changeTicket
  232. } else {
  233. this.changeTicket = 0
  234. }
  235. }
  236. this.spuIds = res.inventoryList.map(item => item.spu.id)
  237. return true
  238. },
  239. async fail() {
  240. this.stopPlay()
  241. this.goods = null
  242. this.tableData = null
  243. this.revealData = []
  244. this.$message.confirm(
  245. '购买结果请至订单详情查看',
  246. () => {
  247. this.$router.replace('order_award')
  248. },
  249. '',
  250. ['去查看', '返回'],
  251. () => this.$router.back()
  252. )
  253. },
  254. async skipOther() {
  255. this.stopPlay()
  256. this.goods = null
  257. this.revealData = []
  258. },
  259. async showResult() {
  260. if (this.tableData && this.tableData.length > 0) {
  261. let array = [...this.tableData]
  262. if (this.magicFireworksList && this.magicFireworksList.length > 0) {
  263. array = [...this.magicFireworksList, ...this.tableData]
  264. }
  265. if(!this.isDemo) {
  266. const hideRes = await this.$service.award.hideTaskStart(JSON.stringify(this.spuIds))
  267. if(hideRes === 1 || hideRes === 2) {
  268. this.$refs.hiddenTaskRef.show(hideRes)
  269. }
  270. }
  271. this.$refs.result.show(array, this.changeTicket)
  272. this.skipOther()
  273. } else {
  274. this.$message.showLoading()
  275. await this.getData()
  276. if (this.tableData && this.tableData.length > 0) {
  277. let array = [...this.tableData]
  278. if (this.magicFireworksList && this.magicFireworksList.length > 0) {
  279. array = [...this.magicFireworksList, ...this.tableData]
  280. }
  281. if(!this.isDemo) {
  282. const hideRes = await this.$service.award.hideTaskStart(JSON.stringify(this.spuIds))
  283. if(hideRes === 1 || hideRes === 2) {
  284. this.$refs.hiddenTaskRef.show(hideRes)
  285. }
  286. }
  287. this.$refs.result.show(array, this.changeTicket)
  288. this.skipOther()
  289. } else {
  290. this.fail()
  291. }
  292. this.$message.hideLoading()
  293. }
  294. }
  295. }
  296. }
  297. </script>
  298. <style>
  299. page {
  300. background: #222335;
  301. }
  302. </style>
  303. <style lang="scss" scoped>
  304. .mask-page {
  305. position: fixed;
  306. z-index: 0;
  307. left: 0;
  308. right: 0;
  309. top: 0;
  310. bottom: 0;
  311. background: rgba($color: #000000, $alpha: 0.4);
  312. }
  313. .mask-left {
  314. position: fixed;
  315. z-index: 0;
  316. left: 0;
  317. top: 0;
  318. bottom: 0;
  319. background: rgba($color: #000000, $alpha: 0.4);
  320. backdrop-filter: blur(1px);
  321. }
  322. .mask-right {
  323. position: fixed;
  324. z-index: 0;
  325. right: 0;
  326. top: 0;
  327. bottom: 0;
  328. background: rgba($color: #000000, $alpha: 0.4);
  329. backdrop-filter: blur(1px);
  330. }
  331. .bg {
  332. position: fixed;
  333. z-index: -1;
  334. left: 0;
  335. right: 0;
  336. top: 0;
  337. width: 100vw;
  338. height: 100vh;
  339. }
  340. .wrapper {
  341. height: calc(100vh - 115rpx - 40rpx);
  342. position: relative;
  343. .lottery_middle {
  344. position: absolute;
  345. left: 0;
  346. width: 100%;
  347. }
  348. }
  349. .bottom {
  350. position: fixed;
  351. left: 0;
  352. right: 0;
  353. bottom: 80rpx;
  354. animation: fade 0.3s;
  355. text-align: center;
  356. .bottom-btns {
  357. height: 162rpx;
  358. background: rgba(255, 255, 255, 0.3);
  359. width: 220rpx;
  360. height: 64rpx;
  361. font-size: 24rpx;
  362. line-height: 64rpx;
  363. text-align: center;
  364. display: inline-block;
  365. border-radius: 32rpx;
  366. }
  367. }
  368. .link {
  369. text-shadow: 0px 0px 20rpx #a76ef4;
  370. font-weight: 600;
  371. color: #a76ef4;
  372. font-size: 32rpx;
  373. padding-bottom: 75rpx;
  374. text-align: center;
  375. }
  376. .demo-btn {
  377. position: fixed;
  378. left: 0;
  379. right: 0;
  380. bottom: 0;
  381. padding-bottom: 150rpx;
  382. image {
  383. width: 356rpx;
  384. height: 128rpx;
  385. }
  386. }
  387. @keyframes fade {
  388. from {
  389. opacity: 0.3;
  390. }
  391. to {
  392. opacity: 1;
  393. }
  394. }
  395. .height1 {
  396. height: 131px;
  397. }
  398. .height5 {
  399. height: 500px;
  400. }
  401. </style>