index.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581
  1. <template>
  2. <page title="大富翁" ref="pageRef" light nav-color="transparent">
  3. <view class="bg"></view>
  4. <image :src="resource.popularize_bg" class="bg-2" />
  5. <scroll-view scroll-y>
  6. <view class="flex-align-center" style="padding-top: 120rpx">
  7. <view class="content">
  8. <view
  9. v-for="(item, index) in grids"
  10. :key="item.seq"
  11. class="cell flex-align-center"
  12. :class="[
  13. item.seq == 0 && 'first',
  14. item.seq == 200 && 'last',
  15. item.seq == current && !isAnimal && 'current',
  16. item.event && 'luck',
  17. [10, 34, 58, 82, 106, 130, 154, 178].includes(item.seq) && 'tr',
  18. [12, 36, 60, 84, 108, 132, 156, 180].includes(item.seq) && 'br',
  19. [22, 46, 70, 94, 118, 142, 166, 190].includes(item.seq) && 'tl',
  20. [24, 48, 72, 96, 120, 144, 168, 192].includes(item.seq) && 'bl'
  21. ]"
  22. :style="{ left: item.position.x + 'rpx', top: item.position.y + 'rpx' }"
  23. >
  24. <view v-if="item.seq == 0" class="text">起</view>
  25. <image
  26. v-else-if="item.seq == 100"
  27. :src="resource.rick_star"
  28. class="radius4"
  29. style="width: 58rpx; height: 58rpx"
  30. />
  31. <view v-else-if="item.seq == 200" class="text">终</view>
  32. <image
  33. v-else-if="item.event && item.event.type === 'MAGIC'"
  34. :src="resource.rich_magic"
  35. class="radius4"
  36. style="width: 58rpx; height: 58rpx"
  37. />
  38. <image
  39. v-else-if="item.event && item.event.type === 'COUPON'"
  40. :src="resource.rich_coupon"
  41. class="radius4"
  42. style="width: 58rpx; height: 58rpx"
  43. />
  44. <image
  45. v-else-if="item.event && item.event.type === 'ADD_TICKET'"
  46. :src="resource.rich_dice_small"
  47. class="radius4"
  48. style="width: 58rpx; height: 58rpx"
  49. />
  50. <view
  51. v-else-if="item.event && item.event.type === 'RANDOM'"
  52. class="font0 flex-column-align-center color-white"
  53. >
  54. <view>随机</view>
  55. <view>事件</view>
  56. </view>
  57. <view
  58. v-else-if="item.event && item.event.type === 'FORWARD'"
  59. class="font1 flex-column-align-center color-white"
  60. >
  61. +{{ item.event.relation }}步
  62. </view>
  63. <view
  64. v-else-if="item.event && item.event.type === 'BACKWARD'"
  65. class="font1 flex-column-align-center color-white"
  66. >
  67. -{{ item.event.relation }}步
  68. </view>
  69. <view
  70. v-else-if="item.event && item.event.type === 'STAY'"
  71. class="font0 flex-column-align-center color-white"
  72. >
  73. <view>停留</view>
  74. <view>一次</view>
  75. </view>
  76. <view v-else class="text">{{ item.seq }}</view>
  77. </view>
  78. <view
  79. class="people"
  80. :class="[isAnimal && 'animal']"
  81. :style="{ left: map[current].x + 'rpx', top: map[current].y + 'rpx' }"
  82. >
  83. <view class="relative height100 width100">
  84. <image :src="resource.rich_people" class="image" />
  85. <image :src="user.avatar || resource.logo" class="tx" />
  86. </view>
  87. </view>
  88. </view>
  89. </view>
  90. </scroll-view>
  91. <view class="fill"></view>
  92. <view class="bottom paddingB25">
  93. <view v-if="point && isAnimal" class="flex-align-center res">+{{ point }}</view>
  94. <view class="flex-align-center relative">
  95. <image
  96. :src="resource.rich_dice"
  97. class="dice"
  98. :class="[isRequest && 'rock']"
  99. @click="apply"
  100. />
  101. <view class="num translateX">
  102. <view class="relative flex-align-center height100 width100">
  103. <image :src="resource.rich_num" class="image" />
  104. <view class="color-white font2 relative">X{{ num }}次</view>
  105. </view>
  106. </view>
  107. </view>
  108. <view class="flex-align-center paddingT8">
  109. <image
  110. :src="resource.prize_entrance"
  111. style="width: 336rpx; height: 108rpx"
  112. @click="$router.push('rich_prize')"
  113. />
  114. <image
  115. :src="resource.popularize_btn_2"
  116. style="width: 336rpx; height: 108rpx"
  117. @click="showRank"
  118. />
  119. </view>
  120. </view>
  121. <view class="index" @click="$router.index()">首页</view>
  122. <view class="rule" @click="showRule">规则</view>
  123. <rule ref="ruleRef" />
  124. <rank ref="rankRef" />
  125. <result-com ref="resultRef" />
  126. </page>
  127. </template>
  128. <script>
  129. import resource from '@/utils/resource'
  130. import rule from './rule.vue'
  131. import rank from './rank'
  132. import resultCom from './result'
  133. const size = 58
  134. const rowCount = 11
  135. export default {
  136. components: { rule, rank, resultCom },
  137. data() {
  138. return {
  139. resource,
  140. grids: [],
  141. isAnimal: false,
  142. isRequest: false,
  143. num: 3, //次数
  144. point: 0, //点数
  145. current: 0,
  146. map: {}
  147. }
  148. },
  149. computed: {
  150. user() {
  151. return this.$store.state.userInfo
  152. }
  153. },
  154. mounted() {
  155. this.getData(this.initGrid())
  156. },
  157. methods: {
  158. initGrid() {
  159. let array = []
  160. this.initHGrid(array, 0, 1)
  161. this.initVGrid(array, 11, rowCount, 2)
  162. this.initHGrid2(array, 12, 3)
  163. this.initVGrid(array, 23, 1, 4)
  164. this.initHGrid(array, 24, 5)
  165. this.initVGrid(array, 35, rowCount, 6)
  166. this.initHGrid2(array, 36, 7)
  167. this.initVGrid(array, 47, 1, 8)
  168. this.initHGrid(array, 48, 9)
  169. this.initVGrid(array, 59, rowCount, 10)
  170. this.initHGrid2(array, 60, 11)
  171. this.initVGrid(array, 71, 1, 12)
  172. this.initHGrid(array, 72, 13)
  173. this.initVGrid(array, 83, rowCount, 14)
  174. this.initHGrid2(array, 84, 15)
  175. this.initVGrid(array, 95, 1, 16)
  176. this.initHGrid(array, 96, 17)
  177. this.initVGrid(array, 107, rowCount, 18)
  178. this.initHGrid2(array, 108, 19)
  179. this.initVGrid(array, 119, 1, 20)
  180. this.initHGrid(array, 120, 21)
  181. this.initVGrid(array, 131, rowCount, 22)
  182. this.initHGrid2(array, 132, 23)
  183. this.initVGrid(array, 143, 1, 24)
  184. this.initHGrid(array, 144, 25)
  185. this.initVGrid(array, 155, rowCount, 26)
  186. this.initHGrid2(array, 156, 27)
  187. this.initVGrid(array, 167, 1, 28)
  188. this.initHGrid(array, 168, 29)
  189. this.initVGrid(array, 179, rowCount, 30)
  190. this.initHGrid2(array, 180, 31)
  191. this.initVGrid(array, 191, 1, 32)
  192. this.initHGrid(array, 192, 33)
  193. return array
  194. },
  195. initHGrid(array, offset, row) {
  196. let max = rowCount
  197. if (rowCount + offset > 200) {
  198. max = 200 - offset + 1
  199. }
  200. for (let i = 0; i < max; i++) {
  201. array.push({
  202. seq: offset + i,
  203. position: { x: i * size, y: (row - 1) * size }
  204. })
  205. this.map[offset + i] = {
  206. x: i * size + size / 2 - 68 / 2,
  207. y: (row - 1) * size + size / 2 - 70
  208. }
  209. }
  210. },
  211. initHGrid2(array, offset, row) {
  212. for (let i = 0; i < rowCount; i++) {
  213. array.push({
  214. seq: offset + i,
  215. position: { x: (rowCount - i - 1) * size, y: (row - 1) * size }
  216. })
  217. this.map[offset + i] = {
  218. x: (rowCount - i - 1) * size + size / 2 - 68 / 2,
  219. y: (row - 1) * size + size / 2 - 70
  220. }
  221. }
  222. },
  223. initVGrid(array, num, i, row) {
  224. array.push({
  225. seq: num,
  226. position: { x: (i - 1) * size, y: (row - 1) * size }
  227. })
  228. this.map[num] = {
  229. x: (i - 1) * size + size / 2 - 68 / 2,
  230. y: (row - 1) * size + size / 2 - 70
  231. }
  232. },
  233. async getData(array) {
  234. const res = await this.$service.weal.rich()
  235. if (res) {
  236. this.current = res.currentPosition
  237. this.num = res.currentTicket
  238. if (res.eventMap) {
  239. const eventMap = JSON.parse(res.eventMap)
  240. array.forEach((item) => {
  241. if (eventMap[item.seq + '']) {
  242. item.event = eventMap[item.seq + '']
  243. }
  244. })
  245. this.grids = array
  246. }
  247. }
  248. },
  249. async refreshTicket() {
  250. const res = await this.$service.weal.rich()
  251. if (res) {
  252. this.num = res.currentTicket
  253. }
  254. },
  255. showRule() {
  256. this.$refs.ruleRef.show()
  257. },
  258. showRank() {
  259. this.$refs.rankRef.show()
  260. },
  261. async apply() {
  262. if (this.num <= 0) {
  263. this.$refs.resultRef.show('请前往宝箱抽取骰子')
  264. return
  265. }
  266. if (this.current >= 200) {
  267. this.$refs.resultRef.show(
  268. '恭喜魔主抵达终点,(前十:奖励将于活动结束后三个工作日内发放至仓库。 十名之后:获奖结果将于活动结束后于公众号中公布。)',
  269. 4000
  270. )
  271. return
  272. }
  273. if (this.num <= 0 || this.current >= 200 || this.isRequest || this.isAnimal) return
  274. this.isRequest = true
  275. const res = await this.$service.weal.richRoll()
  276. if (res) {
  277. setTimeout(() => {
  278. this.point = res.point
  279. if (res.event) {
  280. res.event.eventDesc = res.eventDesc
  281. }
  282. this.beginAnimal(res.point, res.event)
  283. this.isRequest = false
  284. }, 1000)
  285. }
  286. this.refreshTicket()
  287. },
  288. beginAnimal(nums, result) {
  289. this.isAnimal = true
  290. if (nums > 0) {
  291. this.changeCurrent(nums, result)
  292. } else if (nums < 0) {
  293. this.changeCurrent2(nums, result)
  294. }
  295. },
  296. changeCurrent(num, result) {
  297. if (num <= 0 || this.current >= 200) {
  298. this.handleResult(result)
  299. return
  300. }
  301. setTimeout(() => {
  302. this.current += 1
  303. this.changeCurrent(num - 1, result)
  304. }, 500)
  305. },
  306. changeCurrent2(num, result) {
  307. if (num >= 0) return
  308. setTimeout(() => {
  309. this.current -= 1
  310. this.changeCurrent2(num + 1, result)
  311. }, 500)
  312. },
  313. handleResult(result) {
  314. this.endAnimal()
  315. if (this.current === 200) {
  316. this.$refs.resultRef.show(
  317. '恭喜魔主抵达终点,(前十:奖励将于活动结束后三个工作日内发放至仓库。 十名之后:获奖结果将于活动结束后于公众号中公布。)',
  318. 4000
  319. )
  320. }
  321. if (!result) return
  322. if (result.eventDesc) {
  323. this.$refs.resultRef.show(result.eventDesc)
  324. }
  325. if (result.type === 'FORWARD') {
  326. this.isAnimal = true
  327. setTimeout(() => {
  328. this.beginAnimal(result.relation)
  329. }, 350)
  330. } else if (result.type === 'BACKWARD') {
  331. this.isAnimal = true
  332. setTimeout(() => {
  333. this.beginAnimal(-result.relation)
  334. }, 350)
  335. }
  336. },
  337. endAnimal() {
  338. this.point = 0
  339. setTimeout(() => {
  340. this.isAnimal = false
  341. }, 350)
  342. }
  343. }
  344. }
  345. </script>
  346. <style lang="scss" scoped>
  347. .bg {
  348. position: fixed;
  349. left: 0;
  350. right: 0;
  351. top: 0;
  352. bottom: 0;
  353. background: linear-gradient(180deg, #8332f5 0%, #2f4abd 100%);
  354. z-index: -1;
  355. }
  356. .bg-2 {
  357. position: fixed;
  358. z-index: -1;
  359. left: 0;
  360. top: 0;
  361. width: 100%;
  362. height: 1624rpx;
  363. z-index: 0;
  364. }
  365. .index {
  366. position: fixed;
  367. top: 160rpx;
  368. right: 0;
  369. width: 96rpx;
  370. height: 48rpx;
  371. background: linear-gradient(315deg, #0bd1ce 0%, #3ba1ff 100%);
  372. border-radius: 200rpx 0px 0px 200rpx;
  373. line-height: 48rpx;
  374. text-align: center;
  375. color: #fff;
  376. font-size: 28rpx;
  377. z-index: 100;
  378. }
  379. .rule {
  380. position: fixed;
  381. top: 230rpx;
  382. right: 0;
  383. width: 96rpx;
  384. height: 48rpx;
  385. background: linear-gradient(315deg, #ff345a 0%, #ffa25e 100%);
  386. border-radius: 200rpx 0px 0px 200rpx;
  387. line-height: 48rpx;
  388. text-align: center;
  389. color: #fff;
  390. font-size: 28rpx;
  391. z-index: 100;
  392. }
  393. .fill {
  394. height: 328rpx;
  395. }
  396. .bottom {
  397. position: fixed;
  398. left: 0;
  399. right: 0;
  400. bottom: 0;
  401. .dice {
  402. width: 164rpx;
  403. height: 154rpx;
  404. }
  405. .res {
  406. font-size: 60rpx;
  407. color: #fff;
  408. font-weight: 500;
  409. background: #6c6fff;
  410. width: 150rpx;
  411. border-radius: 20rpx;
  412. margin: 0 auto;
  413. }
  414. .num {
  415. position: absolute;
  416. width: 81rpx;
  417. height: 42rpx;
  418. top: -20rpx;
  419. margin-left: 100rpx;
  420. .image {
  421. position: absolute;
  422. left: 0;
  423. top: 0;
  424. width: 81rpx;
  425. height: 42rpx;
  426. }
  427. }
  428. }
  429. .content {
  430. width: 638rpx;
  431. height: 986rpx;
  432. position: relative;
  433. .people {
  434. position: absolute;
  435. width: 68rpx;
  436. height: 81rpx;
  437. animation: updown 1.5s linear infinite;
  438. padding: 4rpx 4rpx 0;
  439. &.animal {
  440. transition: left 0.5s, top 0.5s;
  441. }
  442. .image {
  443. position: absolute;
  444. width: 68rpx;
  445. height: 81rpx;
  446. left: 0;
  447. top: 0;
  448. }
  449. .tx {
  450. width: 60rpx;
  451. height: 60rpx;
  452. border-radius: 30rpx;
  453. background: #7b9ebe;
  454. }
  455. }
  456. .cell {
  457. width: 58rpx;
  458. height: 58rpx;
  459. background: #ffffff;
  460. box-shadow: inset 0px 0px 4rpx 0px rgba(125, 84, 255, 0.5);
  461. position: absolute;
  462. border-radius: 2rpx;
  463. &.current {
  464. background: linear-gradient(270deg, #0bd1ce, #3ba1ff);
  465. }
  466. &.first {
  467. border-top-left-radius: 8rpx;
  468. border-bottom-left-radius: 8rpx;
  469. background: linear-gradient(270deg, #ffa959, #ffc72d);
  470. }
  471. &.last {
  472. border-top-right-radius: 8rpx;
  473. border-bottom-right-radius: 8rpx;
  474. background: linear-gradient(270deg, #6c6fff, #a948ff);
  475. }
  476. &.luck {
  477. background: linear-gradient(270deg, #ff345a, #ffa25e);
  478. }
  479. &.tr {
  480. border-top-right-radius: 8rpx;
  481. }
  482. &.br {
  483. border-bottom-right-radius: 8rpx;
  484. }
  485. &.tl {
  486. border-top-left-radius: 8rpx;
  487. }
  488. &.bl {
  489. border-bottom-left-radius: 8rpx;
  490. }
  491. .text {
  492. color: #7138e9;
  493. font-size: 30rpx;
  494. font-weight: 500;
  495. }
  496. &.first,
  497. &.last {
  498. .text {
  499. color: #fff;
  500. font-size: 32rpx;
  501. }
  502. }
  503. }
  504. }
  505. .rock {
  506. animation: rock 0.5s linear infinite;
  507. }
  508. @keyframes rock {
  509. 0% {
  510. transform: rotateZ(-20deg);
  511. }
  512. 25% {
  513. transform: rotateZ(0deg);
  514. }
  515. 50% {
  516. transform: rotateZ(20deg);
  517. }
  518. 75% {
  519. transform: rotateZ(0deg);
  520. }
  521. 100% {
  522. transform: rotateZ(-20deg);
  523. }
  524. }
  525. @keyframes updown {
  526. 0% {
  527. transform: translateY(0px);
  528. }
  529. 25% {
  530. transform: translateY(-3px);
  531. }
  532. 50% {
  533. transform: translateY(0px);
  534. }
  535. 75% {
  536. transform: translateY(3px);
  537. }
  538. 100% {
  539. transform: rotateZ(0px);
  540. }
  541. }
  542. </style>