index.vue 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059
  1. <template>
  2. <view class="luckyDraw">
  3. <image src="../../static/backImg.png" class="back" mode="widthFix"></image>
  4. <view class="luckyDrawContent">
  5. <!-- 个人信息模块 -->
  6. <view class="luckyDrawTop">
  7. <view class="left">
  8. <view class="avatarView">
  9. <open-data type="userAvatarUrl" class="avatar"></open-data>
  10. </view>
  11. <view class="userInfo">
  12. <view class="account">{{mpName}}</view>
  13. <view class="ID">ID:{{userId}}</view>
  14. </view>
  15. </view>
  16. <view class="right" @click="jumpSign">
  17. <text>签到有礼</text>
  18. </view>
  19. </view>
  20. <!-- 滚动通知 -->
  21. <view class="notice">
  22. <image src="../../static/horn.png" class="horn" mode="widthFix"></image>
  23. <view class="txts">
  24. <u-notice-bar mode="vertical" :volume-icon="false" color="#FFFFFF" type="none" :list="list"></u-notice-bar>
  25. </view>
  26. </view>
  27. <!-- 大转盘 -->
  28. <view class="turntable">
  29. <view class="decorate">
  30. <image src="../../static/decorate.png" class="decorateBack" mode="widthFix"></image>
  31. <image src="../../static/chassis.png" class="decorateChassis" mode="widthFix"></image>
  32. </view>
  33. <view class="turntableContent">
  34. <almost-lottery
  35. :canvasId="canvasConfig.canvasId"
  36. :canvasWidth="canvasConfig.width"
  37. :canvasHeight="canvasConfig.height"
  38. :outerWidth="canvasConfig.outerWidth"
  39. :outerHeight="canvasConfig.outerHeight"
  40. :colors="canvasConfig.colors"
  41. :ringCount="8"
  42. :duration="5"
  43. :prizeList="prizeList"
  44. :prizeIndex="prizeIndex"
  45. @reset-index="prizeIndex = -1"
  46. @draw-start="handleDrawStart"
  47. @draw-end="handleDrawEnd"
  48. @finish="handleDrawFinish"
  49. v-if="prizeList.length"
  50. />
  51. <view class="bottom">
  52. <view class="cont">今日剩余抽奖次数:<text>{{freeNum}}</text></view>
  53. <navigator :url="'../checkInRecord/checkInRecord' + getSerialize({...mpData, openId})" class="record" hover-class="none">
  54. <text>中奖记录</text>
  55. </navigator>
  56. </view>
  57. </view>
  58. </view>
  59. <!-- 我的奖品 -->
  60. <view class="myPrize">
  61. <view class="title">我的奖品</view>
  62. <view class="chips">
  63. <view class="chip" v-for="(item, index) in prizeCountDtoList" :key="index">
  64. <image src="../../static/iPhone12Chip.png" mode="widthFix" v-if="item.prizeType === 3"></image>
  65. <image src="../../static/vipChip.png" mode="widthFix" v-else></image>
  66. <view class="text">{{item.prizeName}}</view>
  67. <view class="progress">
  68. <view class="value" :style="{width: item.prizeCount && item.prizeCount > 0 ? (item.prizeCount/item.maxCount*100) + '%' : '0'}"></view>
  69. <text>{{item.prizeCount}}/{{item.maxCount}}</text>
  70. </view>
  71. </view>
  72. </view>
  73. <view class="clearTime" v-if="clearTime">碎片有效期至:{{clearTime | getTimerFilter}} </view>
  74. </view>
  75. <!-- 活动规则模块 -->
  76. <view class="activityRules">
  77. <view class="top" @click="activityRulesHandle">
  78. <text>活动规则</text>
  79. <image :src="!activityRules ? '../../static/unfold.png' : '../../static/retract.png'" mode="widthFix"></image>
  80. </view>
  81. <view class="bottom" v-if="activityRules">
  82. <view>1、每个用户账户每天最多有10次抽奖机会,每天0点刷新。</view>
  83. <view>2、每天前2次可直接领取抽奖奖品,其他8次抽奖机会需要通过观看激励视频来获得。</view>
  84. <view>3、用户必须在对应公众号内登陆抽奖,否则书币将无法顺利领取。</view>
  85. <view>4、书币及7天书城VIP会员抽中后自动发放至书城账号,可在中奖记录中查看,或进入书城的“个人中心-充值记录-赠送”查看。</view>
  86. <view>5、用户可以通过完成本产品抽奖获得碎片,碎片种类由系统随机发放,兑换手机需集满50个碎片, 兑换书城VIP需集满30个碎片。碎片累计有效期为7天,在碎片超出有效期后或用户成功兑换奖品后,此前已获得的该奖品碎片都将清零。</view>
  87. <view>6、实物奖品请联系公众号内客服领取,实物奖品颜色随机寄送,以中奖用户收到的实物为准。</view>
  88. <view>7、若发现用户恶意违规行为,开发者有权取消其获奖资格。</view>
  89. <view>8、本活动解释权由开发者所有,有任何疑问请联系公众号内客服。</view>
  90. </view>
  91. </view>
  92. <!-- 弹窗 -->
  93. <view class="popup" v-if="popupShow">
  94. <view class="popupContent">
  95. <view class="content">
  96. <image src="../../static/popupBack.png"></image>
  97. <view class="textCon">
  98. <text class="ts">恭喜您获得</text> </br>
  99. <text class="reward ts">{{luckyDay.name}}</text> </br>
  100. <image src="../../static/doubleBt.png" class="doubleBt" mode="widthFix" :style="{transform: `scale(${scale})`}" @click="lookVideo"></image> </br>
  101. <text class="bt" @click="receiveGold(false)">不了,单倍领取</text>
  102. </view>
  103. </view>
  104. <image src="../../static/close.png" class="close" mode="widthFix" @click="closeHandle"></image>
  105. </view>
  106. </view>
  107. <!-- 弹窗VIP -->
  108. <view class="popupVIP popup" v-if="popupVIPShow">
  109. <view class="popupContent" style="width: 524rpx;">
  110. <view class="content">
  111. <image src="../../static/vipBack.png"></image>
  112. <view class="textCon" style="display: flex; align-items: flex-end;">
  113. <view class="againLuckDrawBt btVip" @click="againLuckDraw('vip');startAni(2)" :style="{transform: `scale(${scale})`}">再次抽奖</view>
  114. </view>
  115. </view>
  116. <image src="../../static/close.png" class="close" mode="widthFix" @click="popupVIPShow = false;startAni(2)"></image>
  117. </view>
  118. </view>
  119. <!-- 弹窗12 -->
  120. <view class="popup12 popup" v-if="popup12Show">
  121. <view class="popupContent" style="width: 702rpx;">
  122. <view class="content">
  123. <image src="../../static/12Back.png" style="height: 722rpx;"></image>
  124. <view class="textCon" style="display: flex; align-items: flex-end;">
  125. <view class="againLuckDrawBt" @click="againLuckDraw('12'); startAni(3)" :style="{transform: `scale(${scale})`, marginBottom: 0}">再次抽奖</view>
  126. </view>
  127. </view>
  128. <image src="../../static/close.png" class="close" mode="widthFix" @click="popup12Show = false; startAni(3)"></image>
  129. </view>
  130. </view>
  131. <!-- 弹窗金币 -->
  132. <view class="popup12 popup" v-if="popupGoldShow">
  133. <view class="popupContent" style="width: 636rpx;">
  134. <view class="content">
  135. <image src="../../static/goldBack.png" style="height: 790rpx;"></image>
  136. <view class="textCon" style="display: flex; align-items: center; flex-direction: column; justify-content: flex-end;">
  137. <text class="goldText">恭喜您获得</text> </br>
  138. <text class="goldText" style="margin-bottom: 48rpx;">{{luckyDay.name}}</text>
  139. <view class="againLuckDrawBt btGold" @click="againLuckDraw('gold'); startGold(false)" :style="{transform: `translateX(12rpx) scale(${scale})`}">再次抽奖</view>
  140. </view>
  141. </view>
  142. <image src="../../static/close.png" class="close" mode="widthFix" @click="popupGoldShow = false; startGold(false)"></image>
  143. </view>
  144. </view>
  145. <!-- 碎片飞行 -->
  146. <view class="fragmentAni" :animation="animationData">
  147. <image :src="prizeType === 3 ? '../../static/turntable_iPhone12.png' : '../../static/turntable_VIP.png'" mode="widthFix"></image>
  148. </view>
  149. <!-- 金币飞行组 -->
  150. <view class="fragmentGold" :animation="animationDatas[index]" v-for="(item, index) in goldData" :key="index" :style="{top: item.top, left: item.left}">
  151. <image src="../../static/turntable_gold.png" mode="widthFix"></image>
  152. </view>
  153. <!-- 弹窗提示 -->
  154. <view class="receiveTs" :animation="animationDataTs">
  155. {{tsTitle}}
  156. </view>
  157. </view>
  158. </view>
  159. </template>
  160. <script>
  161. let timer = null
  162. import AlmostLottery from '@/uni_modules/almost-lottery/components/almost-lottery/almost-lottery.vue'
  163. import { config, getHome, getOpenId, getBanner, setDrawGain, getPond, setReceive } from '@/api/api.js'
  164. import { clearCacheFile } from '@/uni_modules/almost-lottery/utils/almost-utils.js'
  165. export default {
  166. components: {
  167. AlmostLottery
  168. },
  169. data() {
  170. return {
  171. title: 'Hello',
  172. list: [
  173. '恭喜用户 “9016” 成功提现 2000书币',
  174. '恭喜用户 “9017” 成功提现 10书币',
  175. '恭喜用户 “9018” 成功提现 20书币',
  176. '恭喜用户 “9019” 成功提现 100书币'
  177. ],
  178. // canvas id、宽、高
  179. canvasConfig: {
  180. canvasId: 'almostLotteryCanvas',
  181. width: 300,
  182. height: 300,
  183. outerWidth: 325,
  184. outerHeight: 325,
  185. colors: [
  186. '#FEE3C6',
  187. '#FFFFFF'
  188. ]
  189. },
  190. // 以下是奖品配置数据
  191. // 奖品数据
  192. prizeList: [],
  193. // 奖品是否设有库存
  194. onStock: false,
  195. // 中奖下标
  196. prizeIndex: -1,
  197. // 是否正在抽奖中,避免重复触发
  198. prizeing: false,
  199. // 以下为业务需求有关示例数据
  200. // 当日免费抽奖次数余额
  201. freeNum: 10,
  202. // 以下是
  203. // 活动规则开关控制
  204. activityRules: false,
  205. // 弹窗控制
  206. popupShow: false,
  207. // 抽到VIP碎片弹窗控制
  208. popupVIPShow: false,
  209. // 抽到12碎片弹窗控制
  210. popup12Show: false,
  211. // 抽到金币弹窗控制
  212. popupGoldShow: false,
  213. openId: '',
  214. mpData: {},
  215. prizeCountDtoList: [], // 碎片列表
  216. mpName: null, // 渠道号
  217. userId: null, //
  218. luckyDay: {}, // 中奖信息
  219. doubleKey: "", // 领取key
  220. clearTime: "", // 碎片有效期
  221. scale: 1,
  222. animation: null, // 动画实例
  223. animationData: null, // 动画
  224. animationDatas: [null, null, null, null, null, null, null, null], // 动画组
  225. animationDataTs: null,
  226. prizeType: 3, // 奖品类型
  227. durationMath: 20, // 防止动画每次都一样
  228. durationMath1: 20,
  229. durationMath2: 20,
  230. goldData: [
  231. {top: '404rpx', left: '300rpx'},
  232. {top: '434rpx', left: '240rpx'},
  233. {top: '430rpx', left: '398rpx'},
  234. {top: '448rpx', left: '424rpx'},
  235. {top: '380rpx', left: '412rpx'},
  236. {top: '332rpx', left: '332rpx'},
  237. {top: '356rpx', left: '240rpx'},
  238. {top: '474rpx', left: '294rpx'}
  239. ],
  240. tsTitle: '', //提示信息
  241. }
  242. },
  243. computed: {
  244. isApple() {
  245. return uni.getSystemInfoSync().platform === 'ios'
  246. }
  247. },
  248. onLoad(options) {
  249. // 请求奖品数据
  250. this.mpData = options
  251. this.getData()
  252. this.animation = uni.createAnimation({ timingFunction: 'ease' })
  253. },
  254. onUnload() {
  255. uni.hideLoading()
  256. timer && clearInterval(timer)
  257. },
  258. onShareAppMessage() {},
  259. filters: {
  260. getTimerFilter(value) { // 获取年月日时分秒
  261. if(!value) return ""
  262. let timestamp = Date.parse(new Date(value))
  263. let date = new Date(timestamp)
  264. let Y = date.getFullYear()
  265. let M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1)
  266. let D = date.getDate() < 10 ? '0' + date.getDate() : date.getDate()
  267. let H = date.getHours() < 10 ? '0' + date.getHours() : date.getHours()
  268. let minute = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes()
  269. let S = date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds()
  270. return `${Y}-${M}-${D} ${H}:${minute}:${S}`
  271. }
  272. },
  273. async onPullDownRefresh() {
  274. await this.handleInitCanvas()
  275. await this.getList()
  276. uni.stopPullDownRefresh();
  277. },
  278. watch: {
  279. // 监听获奖序号的变动
  280. popupShow(newVal, oldVal) {
  281. this.openAniBt(newVal)
  282. },
  283. popupVIPShow(newVal) {
  284. this.openAniBt(newVal)
  285. },
  286. popup12Show(newVal) {
  287. this.openAniBt(newVal)
  288. },
  289. popupGoldShow(newVal) {
  290. this.openAniBt(newVal)
  291. }
  292. },
  293. methods: {
  294. // 是否开始呼吸开关动画
  295. openAniBt(val) {
  296. if(val) {
  297. timer = setInterval(() => {
  298. if(this.scale === 1) {
  299. this.scale = 0.92
  300. }else {
  301. this.scale = 1
  302. }
  303. }, 500)
  304. } else {
  305. timer && clearInterval(timer)
  306. }
  307. },
  308. // 开始动画 12 vip 碎片
  309. startAni(prizeType = 3) {
  310. if(prizeType === 3 || prizeType === 2) {
  311. this.prizeType = prizeType
  312. this.startTsAni(false)
  313. let index = this.prizeCountDtoList.findIndex(item => item.prizeType === prizeType)
  314. let left = index !== -1 ? index === 0 ? '150rpx' : '500rpx' : '500rpx'
  315. this.animation.opacity(1).step({ duration: this.durationMath })
  316. if( this.durationMath >= 50 ) {
  317. this.durationMath = 20
  318. } else {
  319. this.durationMath = this.durationMath + 1
  320. }
  321. this.animation.top('1300rpx').left(left).step({ duration: 1200, delay: 100 })
  322. this.animation.opacity(0).top('453rpx').left('331rpx').step({ duration: 0 })
  323. this.animationData = this.animation.export()
  324. }
  325. },
  326. startGold(watchVideos) {
  327. this.prizeType = 1
  328. this.startTsAni(watchVideos)
  329. if( this.durationMath1 >= 50 ) {
  330. this.durationMath1 = 20
  331. } else {
  332. this.durationMath1 = this.durationMath1 + 1
  333. }
  334. this.animationDatas = this.goldData.map(item => {
  335. let animation = uni.createAnimation({ timingFunction: 'ease' })
  336. animation.opacity(1).step({ duration: this.durationMath1 })
  337. animation.top('76rpx').left('60rpx').step({ duration: Math.floor(Math.random() * 101) + 1000, delay: 100 }) //
  338. animation.opacity(0).top(item.top).left(item.left).step({ duration: 0 })
  339. return animation.export()
  340. })
  341. },
  342. startTsAni(watchVideos) {
  343. if(this.prizeType === 1) {
  344. if (watchVideos) {
  345. this.tsTitle = '+' + (this.luckyDay.prizeCount * 2) + this.luckyDay.prizeName
  346. } else {
  347. this.tsTitle = '+' + this.luckyDay.name
  348. }
  349. } else {
  350. this.tsTitle = this.luckyDay.prizeName + '+1'
  351. }
  352. if( this.durationMath2 >= 50 ) {
  353. this.durationMath2 = 20
  354. } else {
  355. this.durationMath2 = this.durationMath2 + 1
  356. }
  357. let animation = uni.createAnimation({ timingFunction: 'ease' })
  358. animation.opacity(1).step({ duration: this.durationMath2 })
  359. animation.top('250rpx').step({ duration: 1000, delay: 100 })
  360. animation.opacity(0).top('450rpx').step({ duration: 0 })
  361. this.animationDataTs = animation.export()
  362. },
  363. // 再次抽奖
  364. againLuckDraw(type) {
  365. if (type === 'vip') {
  366. this.popupVIPShow = false
  367. } else if (type === '12') {
  368. this.popup12Show = false
  369. } else {
  370. this.popupGoldShow = false
  371. }
  372. this.handleDrawStart()
  373. },
  374. // 看视频双倍
  375. lookVideo() {
  376. this.receiveGold(true)
  377. },
  378. // 领取金币
  379. receiveGold(watchVideos = false) {
  380. if(this.doubleKey) {
  381. setReceive({appId: config.appid, doubleKey: this.doubleKey, openId: this.openId, watchVideos, ...this.mpData }).then(res => {
  382. this.startGold(watchVideos)
  383. this.popupShow = false
  384. this.doubleKey = ""
  385. this.getList()
  386. })
  387. }
  388. },
  389. //
  390. getData() {
  391. uni.login({
  392. success: async res => {
  393. if (res.code) {
  394. let openIDInfo = await getOpenId({appId: config.appid, code: res.code})
  395. this.openId = openIDInfo.data
  396. let response = await this.getList()
  397. if(response) {
  398. await this.getPrizeList()
  399. getBanner({appId: config.appid, openId: this.openId, mpAppId: this.mpData.mpAppId}).then(res => {
  400. this.list = res.data
  401. })
  402. } else {
  403. this.prizeList = [{"prizeId":1,"name":"100书币","stock":100,"weight":10,"prizeImage":"/static/turntable_golds.png"},{"prizeId":2,"name":"书城VIP碎片","stock":100,"weight":10,"prizeImage":"/static/turntable_VIP.png"},{"prizeId":3,"name":"30书币","stock":100,"weight":10,"prizeImage":"/static/turntable_gold.png"},{"prizeId":4,"name":"书城VIP碎片","stock":100,"weight":10,"prizeImage":"/static/turntable_VIP.png"},{"prizeId":5,"name":"10书币","stock":100,"weight":10,"prizeImage":"/static/turntable_gold.png"},{"prizeId":6,"name":"50书币","stock":100,"weight":10,"prizeImage":"/static/turntable_golds.png"},{"prizeId":7,"name":"iPhone12碎片","stock":100,"weight":10,"prizeImage":"/static/turntable_iPhone12.png"},{"prizeId":8,"name":"20书币","stock":100,"weight":10,"prizeImage":"/static/turntable_gold.png"}]
  404. this.prizeCountDtoList = [{"prizeType":2,"prizeCount":0,"prizeName":"书城VIP碎片","maxCount":30},{"prizeType":3,"prizeCount":0,"prizeName":"iPhone12碎片","maxCount":50}]
  405. }
  406. }
  407. }
  408. })
  409. },
  410. // 跳转小程序
  411. jumpSign() {
  412. let path = 'pages/index/index'
  413. if(Object.keys(this.mpData).length > 0) {
  414. path = path + this.getSerialize(this.mpData)
  415. }
  416. uni.navigateToMiniProgram({
  417. appId: 'wxb21c3e030b8af425',
  418. path,
  419. success(res) {
  420. // 打开成功
  421. }
  422. })
  423. },
  424. // 对象序列化成 a=1&b=2
  425. getSerialize(value) {
  426. if(Object.prototype.toString.call(value) === "[object Object]") {
  427. let path = ""
  428. for (const key in value) {
  429. if (Object.prototype.hasOwnProperty.call(value, key)) {
  430. const element = value[key];
  431. if (path === "") {
  432. path = `?${key}=${element}`
  433. }else {
  434. path = path + `&${key}=${element}`
  435. }
  436. }
  437. }
  438. return path
  439. } else {
  440. return ""
  441. }
  442. },
  443. // 活动规则
  444. activityRulesHandle() {
  445. this.activityRules = !this.activityRules
  446. },
  447. // 关闭弹窗
  448. closeHandle() {
  449. this.receiveGold(false)
  450. this.popupShow = false
  451. },
  452. // 重新生成
  453. handleInitCanvas() {
  454. clearCacheFile()
  455. this.prizeList = []
  456. this.getPrizeList()
  457. },
  458. // 获取首页信息
  459. async getList() {
  460. let res = await getHome({appId: config.appid, openId: this.openId, userSource: 1, ...this.mpData})
  461. let data = res.data
  462. if(data) {
  463. this.userId = data.userId
  464. this.clearTime = data.clearTime
  465. this.prizeCountDtoList = data.prizeCountDtoList
  466. this.mpName = data.mpName
  467. this.freeNum = data.luckDraw
  468. this.mpData = {
  469. mpAppId: data.mpAppId,
  470. mpName: data.mpName,
  471. mpOpenId: data.mpOpenId
  472. }
  473. return Promise.resolve(true)
  474. } else {
  475. return Promise.resolve(false)
  476. }
  477. },
  478. // 获取奖品列表
  479. async getPrizeList() {
  480. uni.showLoading({
  481. title: '奖品准备中...'
  482. })
  483. let res = await getPond({appId: config.appid, openId: this.openId, mpAppId: this.mpData.mpAppId})
  484. if(res.data && res.data.length > 0) {
  485. this.prizeList = res.data.map(item => {
  486. let prizeImage = ""
  487. if (item.prizeType === 1) {
  488. prizeImage = '/static/turntable_gold.png'
  489. if(item.prizeCount > 30) {
  490. prizeImage = '/static/turntable_golds.png'
  491. }
  492. return {
  493. prizeId: item.id,
  494. name: item.prizeCount + item.prizeName,
  495. stock: 100,
  496. weight: 10,
  497. prizeImage,
  498. prizeType: item.prizeType,
  499. prizeCount: item.prizeCount,
  500. prizeName: item.prizeName,
  501. }
  502. } else {
  503. prizeImage = '/static/turntable_iPhone12.png'
  504. if(item.prizeType === 2){
  505. prizeImage = '/static/turntable_VIP.png'
  506. }
  507. return {
  508. prizeId: item.id,
  509. name: item.prizeName,
  510. stock: 100,
  511. weight: 10,
  512. prizeImage,
  513. prizeType: item.prizeType,
  514. prizeCount: item.prizeCount,
  515. prizeName: item.prizeName,
  516. }
  517. }
  518. })
  519. }else {
  520. uni.hideLoading()
  521. uni.showToast({
  522. title: '获取奖品失败'
  523. })
  524. }
  525. },
  526. // 本次抽奖开始
  527. handleDrawStart() {
  528. console.log('触发抽奖按钮')
  529. if (!this.mpName) { // 首次没有重公众号进入
  530. uni.navigateTo({
  531. url: '../officialAccount/officialAccount'
  532. })
  533. return
  534. }
  535. if (this.prizeing) return
  536. this.prizeing = true
  537. // 还有免费数次或者剩余金币足够抽一次
  538. if (this.freeNum > 0) {
  539. // 更新免费次数或金币余额
  540. if (this.freeNum > 0) {
  541. this.freeNum--
  542. }
  543. // 发起抽奖
  544. this.remoteGetPrizeIndex()
  545. } else {
  546. this.prizeing = false
  547. uni.showToast({
  548. title: '抽奖次数不足',
  549. icon:'none'
  550. })
  551. }
  552. },
  553. // 远程请求接口获取中奖下标
  554. remoteGetPrizeIndex() {
  555. console.warn('###当前处于模拟的请求接口,并返回了中奖信息###')
  556. let { mpName, ...mp } = this.mpData
  557. setDrawGain({appId: config.appid, openId: this.openId, ...mp}).then(res => {
  558. let data = res.data
  559. this.doubleKey = data.doubleKey
  560. let prizeIndex = this.prizeList.findIndex(item => item.prizeId === data.id)
  561. if(prizeIndex !== -1){
  562. this.prizeIndex = prizeIndex
  563. } else {
  564. uni.showToast({
  565. title: '抽奖异常,请稍后重试'
  566. })
  567. }
  568. })
  569. },
  570. // 本次抽奖结束
  571. handleDrawEnd() {
  572. console.log('旋转结束,执行拿到结果后到逻辑')
  573. // 旋转结束后,开始处理拿到结果后的逻辑
  574. this.prizeing = false
  575. let prizeName = this.prizeList[this.prizeIndex].name
  576. let { prizeType, prizeCount } = this.prizeList[this.prizeIndex]
  577. this.luckyDay = this.prizeList[this.prizeIndex]
  578. let tipContent = ''
  579. if (prizeName === '谢谢参与') {
  580. tipContent = '很遗憾,没有中奖,请再接再厉!'
  581. } else if (prizeName.indexOf('碎片') === -1 && this.freeNum >= 8) {
  582. this.popupShow = true
  583. return
  584. } else {
  585. // 如果奖品设有库存
  586. if (this.onStock) {
  587. let prizeStock = this.prizeList[this.prizeIndex].stock
  588. tipContent = prizeStock ? `恭喜您,获得 ${prizeName}` : `很抱歉,您来晚了,当前奖品 ${prizeName} 已无库存`
  589. } else {
  590. if (prizeType === 1) {
  591. this.popupGoldShow = true
  592. } else if (prizeType === 2) {
  593. this.popupVIPShow = true
  594. } else if (prizeType === 3) {
  595. this.popup12Show = true
  596. }
  597. }
  598. }
  599. this.getList()
  600. },
  601. // 抽奖转盘绘制完成
  602. handleDrawFinish(res) {
  603. console.log('抽奖转盘绘制完成', res)
  604. uni.showToast({
  605. title: res.msg,
  606. duration: 800,
  607. mask: true,
  608. icon: 'none'
  609. })
  610. }
  611. }
  612. }
  613. </script>
  614. <style lang="scss">
  615. page{
  616. background-color: #F0524C;
  617. }
  618. .luckyDraw {
  619. position: relative;
  620. &>.back {
  621. width: 100%;
  622. }
  623. }
  624. .luckyDrawContent {
  625. overflow-x: hidden;
  626. position: absolute;
  627. top: 0;
  628. width: 100%;
  629. padding: 40rpx 0;
  630. margin-bottom: 20rpx;
  631. font-family: PingFangSC-Medium, PingFang SC;
  632. // 用户信息
  633. .luckyDrawTop {
  634. padding: 0 28rpx;
  635. height: 104rpx;
  636. display: flex;
  637. justify-content: space-between;
  638. align-items: center;
  639. .left{
  640. display: flex;
  641. justify-content: flex-start;
  642. align-items: center;
  643. &>.avatarView {
  644. overflow: hidden;
  645. width: 104rpx;
  646. height: 104rpx;
  647. background: #D8D8D8;
  648. border-radius: 10px;
  649. }
  650. .userInfo{
  651. margin-left: 28rpx;
  652. &>view{
  653. font-size: 32rpx;
  654. font-weight: 500;
  655. color: #FFFFFF;
  656. &.account {
  657. display: flex;
  658. justify-content: flex-start;
  659. align-items: center;
  660. &>image {
  661. width: 36rpx;
  662. height: 36rpx;
  663. margin-right: 10rpx;
  664. }
  665. }
  666. &.ID{
  667. margin-top: 4rpx;
  668. }
  669. }
  670. }
  671. }
  672. .right{
  673. width: 212rpx;
  674. height: 76rpx;
  675. background: #FEC435;
  676. border-radius: 40rpx;
  677. display: flex;
  678. justify-content: center;
  679. align-items: center;
  680. &>text {
  681. font-size: 28rpx;
  682. font-weight: 400;
  683. color: #FFFFFF;
  684. margin-left: 18rpx;
  685. }
  686. }
  687. }
  688. // 滚动通知
  689. .notice {
  690. width: 656rpx;
  691. height: 68rpx;
  692. background: #C7322C;
  693. box-shadow: 0px 4rpx 8rpx 0rpx rgba(49, 49, 49, 0.08);
  694. border-radius: 38rpx;
  695. opacity: 0.53;
  696. margin: 58rpx auto 0;
  697. padding: 0 30rpx;
  698. box-sizing: border-box;
  699. display: flex;
  700. justify-content: flex-start;
  701. align-items: center;
  702. .horn {
  703. width: 28rpx;
  704. height: 28rpx;
  705. }
  706. .txts {
  707. // flex: 1;
  708. height: 68rpx;
  709. width: 600rpx;
  710. }
  711. }
  712. // 大转盘
  713. .turntable {
  714. position: relative;
  715. margin-top: 40rpx;
  716. .decorate{
  717. position: relative;
  718. width: 100%;
  719. height: 890rpx;
  720. &>image {
  721. width: 100%;
  722. position: absolute;
  723. z-index: 10;
  724. &.decorateBack {
  725. top: 0;
  726. }
  727. &.decorateChassis{
  728. position: absolute;
  729. z-index: 1;
  730. bottom: 0;
  731. }
  732. }
  733. }
  734. .turntableContent {
  735. position: absolute;
  736. top: 0;
  737. left: 0;
  738. right: 0;
  739. bottom: 0;
  740. width: 100%;
  741. height: 100%;
  742. z-index: 20;
  743. padding-top: 20rpx;
  744. .bottom {
  745. margin-top: 20rpx;
  746. text-align: center;
  747. position: absolute;
  748. bottom: 35rpx;
  749. left: 50%;
  750. transform: translateX(-50%);
  751. .cont{
  752. font-size: 28rpx;
  753. font-weight: 400;
  754. color: #FFFFFF;
  755. margin-bottom: 22rpx;
  756. text {
  757. font-size: 36rpx;
  758. color: #FEED22;
  759. font-weight: 500;
  760. }
  761. }
  762. .record{
  763. font-size: 28rpx;
  764. font-weight: 500;
  765. color: #FFFFFF;
  766. }
  767. }
  768. }
  769. }
  770. // 我的奖品
  771. .myPrize {
  772. margin: 40rpx 26rpx 0;
  773. min-height: 352rpx;
  774. background: #F4E2CA;
  775. border-radius: 20rpx;
  776. position: relative;
  777. padding: 58rpx 0 20rpx;
  778. .title {
  779. position: absolute;
  780. width: 232rpx;
  781. height: 64rpx;
  782. background: linear-gradient(180deg, #FFEDD1 0%, #FFC954 100%);
  783. box-shadow: 0 4rpx 8rpx 0 rgba(0, 0, 0, 0.07);
  784. border-radius: 0 0 24rpx 24rpx;
  785. font-size: 32rpx;
  786. font-weight: 500;
  787. color: #F33938;
  788. text-align: center;
  789. line-height: 64rpx;
  790. left: 50%;
  791. transform: translateX(-50%);
  792. top: -12rpx;
  793. }
  794. .chips {
  795. display: flex;
  796. justify-content: space-between;
  797. }
  798. .chip {
  799. display: flex;
  800. flex-direction: column;
  801. align-items: center;
  802. width: 50%;
  803. &>image {
  804. width: 208rpx;
  805. height: 160rpx;
  806. }
  807. .text{
  808. font-size: 32rpx;
  809. font-weight: 500;
  810. color: #F33938;
  811. line-height: 44rpx;
  812. margin-top: 12rpx;
  813. }
  814. .progress{
  815. position: relative;
  816. width: 200rpx;
  817. height: 40rpx;
  818. margin-top: 12rpx;
  819. background: #FFFCF7;
  820. border-radius: 26rpx;
  821. overflow: hidden;
  822. .value{
  823. position: absolute;
  824. width: 1%;
  825. height: 100%;
  826. top: 0;
  827. left: 0;
  828. z-index: 1;
  829. background: #F37938;
  830. }
  831. &>text {
  832. font-size: 28rpx;
  833. font-weight: 500;
  834. color: #333333;
  835. position: absolute;
  836. top: 50%;
  837. left: 50%;
  838. transform: translate(-50%, -50%);
  839. z-index: 2;
  840. }
  841. }
  842. }
  843. .clearTime{
  844. margin: 20rpx 0 0;
  845. text-align: center;
  846. font-size: 24rpx;
  847. font-weight: 400;
  848. color: #F33938;
  849. }
  850. }
  851. // 活动规则
  852. .activityRules {
  853. margin: 40rpx 28rpx 0;
  854. background: #F4E2CA;
  855. border-radius: 20rpx;
  856. color: #F33938;
  857. font-size: 32rpx;
  858. font-weight: 400;
  859. &>.top {
  860. height: 92rpx;
  861. padding: 0 28rpx;
  862. box-sizing: border-box;
  863. display: flex;
  864. justify-content: space-between;
  865. align-items: center;
  866. &>image {
  867. width: 40rpx;
  868. }
  869. }
  870. &>.bottom {
  871. padding: 0 28rpx 30rpx;
  872. box-sizing: border-box;
  873. &> view {
  874. margin-bottom: 12rpx;
  875. font-size: 28rpx;
  876. font-weight: 400;
  877. color: #666666;
  878. line-height: 46rpx;
  879. }
  880. }
  881. }
  882. // 弹窗
  883. .popup {
  884. position: fixed;
  885. width: 100%;
  886. height: 100vh;
  887. background: rgba(0, 0, 0, 0.6);
  888. top: 0;
  889. left: 0;
  890. right: 0;
  891. bottom: 0;
  892. z-index: 100;
  893. .popupContent {
  894. width: 632rpx;
  895. position: absolute;
  896. top: 50%;
  897. left: 50%;
  898. transform: translate(-50%, -50%);
  899. text-align: center;
  900. &>.content {
  901. position: relative;
  902. &>image {
  903. width: 100%;
  904. height: 652rpx;
  905. }
  906. &>.textCon {
  907. position: absolute;
  908. width: 100%;
  909. top: 0;
  910. left: 0;
  911. right: 0;
  912. bottom: 0;
  913. padding-top: 192rpx;
  914. .ts {
  915. font-size: 60rpx;
  916. font-weight: 500;
  917. color: #F5631D;
  918. }
  919. .reward {
  920. height: 60rpx;
  921. // background: #FFD9A2;
  922. // border-radius: 31rpx;
  923. font-size: 50rpx;
  924. font-weight: 400;
  925. display: inline-block;
  926. padding: 0 32rpx;
  927. color: #F5631E;
  928. line-height: 60rpx;
  929. margin-top: 20rpx;
  930. }
  931. .goldText {
  932. font-size: 64rpx;
  933. font-family: FZZZHONGJW--GB1-0, FZZZHONGJW--GB1;
  934. font-weight: normal;
  935. color: #FFFFFF;
  936. margin-bottom: 25rpx;
  937. transform: translateX(12rpx);
  938. }
  939. .doubleBt {
  940. width: 456rpx;
  941. height: 104rpx;
  942. margin-top: 90rpx;
  943. transition: all linear .5s;
  944. }
  945. .bt {
  946. margin-top: 14rpx;
  947. font-size: 32rpx;
  948. font-weight: 400;
  949. color: #FCE8CD;
  950. }
  951. .againLuckDrawBt {
  952. width: 424rpx;
  953. height: 86rpx;
  954. background: linear-gradient(180deg, #FDDEA5 0%, #FFC981 75%, #FFC983 100%);
  955. border-radius: 43rpx;
  956. font-size: 36rpx;
  957. font-family: SourceHanSansCN-Medium, SourceHanSansCN;
  958. font-weight: 500;
  959. color: #854007;
  960. text-align: center;
  961. line-height: 86rpx;
  962. margin: 0 auto 40rpx;
  963. transition: all linear .5s;
  964. }
  965. .btGold {
  966. width: 448rpx;
  967. height: 104rpx;
  968. border-radius: 52rpx;
  969. line-height: 104rpx;
  970. font-size: 40rpx;
  971. box-shadow: 0px 2rpx 8rpx 4rpx rgba(183, 2, 2, 0.37);
  972. background: linear-gradient(180deg, #FFFCBE 0%, #F87527 100%);
  973. }
  974. .btVip {
  975. width: 426rpx;
  976. height: 88rpx;
  977. background: linear-gradient(180deg, #F6E5CA 0%, #EDC388 100%);
  978. box-shadow: 0rpx 6rpx 16rpx 0rpx rgba(162, 58, 20, 0.77);
  979. border-radius: 44rpx;
  980. }
  981. }
  982. }
  983. &>.close {
  984. width: 54rpx;
  985. height: 54rpx;
  986. margin-top: 76rpx;
  987. }
  988. }
  989. }
  990. // 碎片飞行初始样式 // 金币飞行
  991. .fragmentAni, .fragmentGold {
  992. position: absolute;
  993. z-index: 100;
  994. top: 453rpx;
  995. left: 330rpx;
  996. opacity: 0;
  997. &>image {
  998. width: 100rpx;
  999. height: 100rpx;
  1000. }
  1001. }
  1002. .fragmentGold {
  1003. // opacity: 1;
  1004. }
  1005. .receiveTs {
  1006. position: absolute;
  1007. border: 2rpx solid rgb(242, 69, 69);
  1008. top: 450rpx;
  1009. z-index: 100;
  1010. color: #FFFFFF;
  1011. left: 50%;
  1012. transform: translateX(-50%);
  1013. padding: 10rpx 20rpx;
  1014. background-color: rgba(131, 37, 37, 0.6);
  1015. border-radius: 5rpx;
  1016. opacity: 0;
  1017. }
  1018. }
  1019. </style>