drawCard_last.vue 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824
  1. <template>
  2. <view class="container">
  3. <view class="head">
  4. <image class="img" :src="detail.prizeIcon" mode="aspectFill"></image>
  5. <view class="info">
  6. <view class="title row">
  7. {{ detail.name }}
  8. </view>
  9. <view class="row">
  10. <view class="price">
  11. ¥{{ detail.price }}
  12. <span class="text">/张明信片</span>
  13. </view>
  14. <image
  15. @click="$navigateTo('/pages/rule/rule', { type: 5 })"
  16. class="button"
  17. :src="'https://file.rongcyl.cn/festatic/bkm/imgv2/invite/button1.png'"
  18. mode="widthFix"
  19. ></image>
  20. </view>
  21. <view class="row">
  22. <!-- <view class="users">
  23. <image
  24. class="photo"
  25. :style="'left:' + index * 11 + 'px'"
  26. :src="'https://file.rongcyl.cn/festatic/bkm/imgv2/Frame1.png'"
  27. v-for="(item, index) in userList"
  28. mode="widthFix"
  29. ></image>
  30. </view>
  31. <view class="hot">
  32. <image :src="'https://file.rongcyl.cn/festatic/bkm/imgv2' + /first/hot.png" mode="widthFix"></image>
  33. {{ detail.hotNum }}
  34. </view> -->
  35. </view>
  36. </view>
  37. </view>
  38. <view class="cardList">
  39. <image class="bk" :src="'https://file.rongcyl.cn/festatic/bkm/imgv2/first/bk1.png'" mode="widthFix"></image>
  40. <view class="leftButton" @click="left"></view>
  41. <view class="rightButton" @click="right"></view>
  42. <view class="list">
  43. <view :class="['item', item.check ? 'active' : '']" v-for="(item, index) in cardList" @click="clickCard(item)">
  44. <image
  45. v-if="item.check"
  46. class="kaBkActive"
  47. :src="'https://file.rongcyl.cn/festatic/bkm/imgv2/ka/kabk' + cardType(2, item) + 'Active.png'"
  48. mode="heightFix"
  49. ></image>
  50. <image
  51. class="kaBk"
  52. :src="'https://file.rongcyl.cn/festatic/bkm/imgv2/ka/kabk' + cardType(2, item) + '.png'"
  53. mode="widthFix"
  54. ></image>
  55. <numImg class="num" :value="item" :type="2" />
  56. </view>
  57. </view>
  58. </view>
  59. <view class="examples">
  60. <view class="example">
  61. <image
  62. class="exampleImg"
  63. :src="'https://file.rongcyl.cn/festatic/bkm/imgv2/ka/kabk' + cardType(2, { status: 0 }) + '.png'"
  64. mode="widthFix"
  65. ></image>
  66. <image class="tip" :src="'https://file.rongcyl.cn/festatic/bkm/imgv2/ka/bkType1.png'" mode="widthFix"></image>
  67. </view>
  68. <view class="example">
  69. <image
  70. class="exampleImg"
  71. :src="'https://file.rongcyl.cn/festatic/bkm/imgv2/ka/kabk' + cardType(2, { status: 2 }) + '.png'"
  72. mode="widthFix"
  73. ></image>
  74. <image class="tip" :src="'https://file.rongcyl.cn/festatic/bkm/imgv2/ka/bkType5.png'" mode="widthFix"></image>
  75. </view>
  76. <view class="example">
  77. <image
  78. class="exampleImg"
  79. :src="'https://file.rongcyl.cn/festatic/bkm/imgv2/ka/kabk' + cardType(2, { status: 1 }) + '.png'"
  80. mode="widthFix"
  81. ></image>
  82. <image class="tip" :src="'https://file.rongcyl.cn/festatic/bkm/imgv2/ka/bkType4.png'" mode="widthFix"></image>
  83. </view>
  84. </view>
  85. <view class="buttons">
  86. <image
  87. class="button1"
  88. @click="toKnapsack"
  89. :src="'https://file.rongcyl.cn/festatic/bkm/imgv2/first/button6.png'"
  90. mode="widthFix"
  91. ></image>
  92. <view class="">
  93. <image
  94. class="button2"
  95. @click="submit"
  96. :src="'https://file.rongcyl.cn/festatic/bkm/imgv2/first/button4.png'"
  97. mode="widthFix"
  98. ></image>
  99. <!-- <image class="button2" :src="'https://file.rongcyl.cn/festatic/bkm/imgv2' + /first/button1.png" mode="widthFix"></image> -->
  100. </view>
  101. <image
  102. @click="toWinningRecord"
  103. class="button1"
  104. :src="'https://file.rongcyl.cn/festatic/bkm/imgv2/first/button3.png'"
  105. mode="widthFix"
  106. ></image>
  107. </view>
  108. <view class="lockBox">
  109. <view class="text" v-if="!lockData.userId">本福袋连续购买10发,即开启保护机制</view>
  110. <view class="info" v-else>
  111. <image class="photo" :src="lockData.userAvtar" mode="aspectFill"></image>
  112. <view class="right">
  113. <view class="row">
  114. <view class="name">{{ lockData.userName }}</view>
  115. <view class="tip">目前已开启自动保护机制</view>
  116. </view>
  117. <view class="row">
  118. 保护倒计时:
  119. <span v-if="lockHour != '00'">
  120. <span class="time">{{ lockHour }}</span>
  121. :
  122. </span>
  123. <span>
  124. <span class="time">{{ lockMin }}</span>
  125. :
  126. </span>
  127. <span>
  128. <span class="time">{{ lockSecond }}</span>
  129. </span>
  130. </view>
  131. </view>
  132. </view>
  133. </view>
  134. <view class="prizes">
  135. <image class="title" :src="'https://file.rongcyl.cn/festatic/bkm/imgv2/first/title.png'" mode="widthFix"></image>
  136. <view class="prizesList" v-for="(item, index) in prizeList">
  137. <image class="bk" :src="'https://file.rongcyl.cn/festatic/bkm/imgv2/first/bk2.png'" mode="scaleToFill"></image>
  138. <view class="prizesTitle">
  139. {{ $selectDictLabel(rewardType, item.type) }}
  140. </view>
  141. <view class="prizesImgOne" v-if="item.type == 22">
  142. <view class="image" v-for="(item2, index2) in item.prizeList" @click="showImg(item2)">
  143. <image :class="item2.leftNum == 0 ? 'grey' : ''" :src="item2.icon" mode="aspectFill"></image>
  144. </view>
  145. </view>
  146. <view class="prizesImg" v-else>
  147. <view class="image" v-for="(item2, index2) in item.prizeList" @click="showImg(item2)">
  148. <image :class="item2.leftNum == 0 ? 'grey' : ''" :src="item2.icon" mode="aspectFill"></image>
  149. </view>
  150. </view>
  151. </view>
  152. </view>
  153. <image
  154. class="refresh"
  155. @click="refresh"
  156. :src="'https://file.rongcyl.cn/festatic/bkm/imgv2/first/refresh.png'"
  157. mode="widthFix"
  158. ></image>
  159. <paymentPopup ref="paymentPopup" @callBack="paymentSuccess" />
  160. <imgPopup ref="imgPopup" />
  161. </view>
  162. </template>
  163. <script>
  164. import imgPopup from '@/component/imgPopup.vue'
  165. import { rewardType } from '@/utils/commonConfig.js'
  166. import { prizePoolStatusApi, drawCardSubmitApi, raffleDetailApi, prizeListApi, getLockInfoApi } from '@/api/drawCard.js'
  167. import { cardType, formatSeconds } from '@/utils/utils.js'
  168. import numImg from '@/component/numImg.vue'
  169. import paymentPopup from '@/component/paymentPopup.vue'
  170. const { v4: uuidv4 } = require('uuid')
  171. export default {
  172. components: {
  173. numImg,
  174. paymentPopup,
  175. imgPopup,
  176. },
  177. data() {
  178. return {
  179. userId: wx.getStorageSync('userId'),
  180. uuid: '',
  181. socketTimer: null,
  182. lockTimeCountdown: null,
  183. lockData: null,
  184. lockTime: '',
  185. cardType: cardType,
  186. rewardType: rewardType,
  187. params: {
  188. raffleId: '',
  189. limit: 12,
  190. page: 1,
  191. },
  192. detail: {},
  193. total: 0,
  194. userList: 8,
  195. cardList: [],
  196. selectIndex: [],
  197. prizeList: [],
  198. }
  199. },
  200. onLoad(query) {
  201. if (query.id) {
  202. this.params.raffleId = query.id
  203. this.init()
  204. }
  205. this.paymentSuccess()
  206. },
  207. onHide() {
  208. this.leave()
  209. },
  210. onUnload() {
  211. this.leave()
  212. },
  213. computed: {
  214. // 锁箱小时
  215. lockHour() {
  216. let tiem = this.lockTime * 1000
  217. let timeText = formatSeconds(tiem)
  218. timeText = timeText.split(':')[0]
  219. return timeText
  220. },
  221. // 锁箱分钟
  222. lockMin() {
  223. let tiem = this.lockTime * 1000
  224. let timeText = formatSeconds(tiem)
  225. timeText = timeText.split(':')[1]
  226. return timeText
  227. },
  228. // 锁箱秒
  229. lockSecond() {
  230. let tiem = this.lockTime * 1000
  231. let timeText = formatSeconds(tiem)
  232. timeText = timeText.split(':')[2]
  233. return timeText
  234. },
  235. },
  236. methods: {
  237. init() {
  238. // 获取卡牌商品列表
  239. this.getCardList()
  240. // 获取卡包详情
  241. this.getDetail()
  242. //获取奖池
  243. this.getPrizeList()
  244. // 初始化锁箱
  245. this.initLock()
  246. // 连接锁箱Socket
  247. this.connectSocket()
  248. },
  249. showImg(value) {
  250. this.$refs.imgPopup.show(value)
  251. },
  252. leave() {
  253. console.log('离开页面')
  254. // 离开页面
  255. // 关闭倒计时
  256. clearInterval(this.lockTimeCountdown)
  257. // 关闭心跳测试
  258. clearInterval(this.socketTimer)
  259. // 关闭对话连接
  260. wx.closeSocket()
  261. },
  262. initLock() {
  263. // 获取锁箱信息
  264. let _this = this
  265. let params = {
  266. raffleId: this.params.raffleId,
  267. }
  268. getLockInfoApi(params).then(res => {
  269. console.log(res, '锁箱')
  270. if (res.data.userId) {
  271. _this.lockData = res.data
  272. _this.lockTime = res.data.expireTime
  273. _this.initLockTimeCountdown()
  274. } else {
  275. _this.lockData = {}
  276. _this.lockTime = ''
  277. }
  278. })
  279. },
  280. initLockTimeCountdown() {
  281. let _this = this
  282. if (_this.lockTimeCountdown) {
  283. clearInterval(_this.lockTimeCountdown)
  284. _this.lockTimeCountdown = null
  285. }
  286. _this.lockTimeCountdown = setInterval(() => {
  287. console.log('22')
  288. _this.lockTime = _this.lockTime - 1
  289. if (_this.lockTime <= 0) {
  290. clearInterval(_this.lockTimeCountdown)
  291. _this.lockTimeCountdown = null
  292. _this.initLock()
  293. }
  294. }, 1000)
  295. },
  296. connectSocket() {
  297. let _this = this
  298. let uuid = uuidv4()
  299. let url = 'wss://mall.rongtongh.cn/websocket/raffleId' + this.params.raffleId + ':' + uuid
  300. function connect() {
  301. wx.connectSocket({
  302. url: url,
  303. })
  304. wx.onSocketOpen(function (res) {
  305. console.log(res, 'WebSocket连接已打开!')
  306. // wx.sendSocketMessage({
  307. // data: JSON.stringify(user),
  308. // })
  309. _this.socketTimer = setInterval(function () {
  310. console.log('发送消息')
  311. wx.sendSocketMessage({
  312. data: '12313',
  313. })
  314. }, 30 * 1000)
  315. })
  316. wx.onSocketMessage(function (res) {
  317. console.log(data, 'WebSocket接受信息')
  318. let data = JSON.parse(res.data)
  319. if (res.data.userId) {
  320. _this.lockData = data
  321. _this.lockTime = data.expireTime
  322. _this.initLockTimeCountdown()
  323. }
  324. })
  325. wx.onSocketClose(function (res) {
  326. console.log('WebSocket连接已关闭!')
  327. setTimeout(() => {
  328. console.log('re connect')
  329. // connect()
  330. }, 2000)
  331. })
  332. }
  333. connect()
  334. },
  335. toKnapsack() {
  336. // 跳转背包界面
  337. wx.navigateTo({
  338. url: '/pages/knapsack/knapsack',
  339. })
  340. },
  341. refresh() {
  342. wx.showLoading()
  343. setTimeout(function () {
  344. wx.hideLoading()
  345. }, 1000)
  346. this.init()
  347. this.selectIndex = []
  348. for (var i = 0; i < this.cardList.length; i++) {
  349. this.cardList[i].check = false
  350. }
  351. },
  352. getPrizeList() {
  353. let params = {
  354. raffleId: this.params.raffleId,
  355. }
  356. prizeListApi(params).then(res => {
  357. console.log(res, '奖池预览')
  358. let newArray = res.data
  359. for (var i = 0; i < res.data.length; i++) {
  360. if (res.data[i].type == 22) {
  361. newArray = []
  362. newArray.push(res.data[i])
  363. res.data.splice(i, 1)
  364. newArray.push(...res.data)
  365. break
  366. }
  367. }
  368. this.prizeList = newArray
  369. })
  370. },
  371. toWinningRecord() {
  372. let params = {
  373. raffleId: this.params.raffleId,
  374. }
  375. this.$navigateTo('/pages/winningRecord/winningRecord', params)
  376. },
  377. getDetail() {
  378. let params = {
  379. raffleId: this.params.raffleId,
  380. }
  381. raffleDetailApi(params).then(res => {
  382. console.log(res, '详情')
  383. this.detail = res.data
  384. })
  385. },
  386. submit() {
  387. // 购买时判断锁箱
  388. if (this.lockData?.userId && this.userId != this.lockData.userId) {
  389. wx.showToast({
  390. title: '锁箱中无法购买。',
  391. icon: 'none',
  392. })
  393. return
  394. }
  395. if (this.selectIndex.length == 0) {
  396. wx.showToast({
  397. title: '请选则要购买的卡牌。',
  398. icon: 'none',
  399. })
  400. return
  401. }
  402. let params = {
  403. raffleId: this.params.raffleId,
  404. }
  405. this.$refs.paymentPopup.show(params, this.selectIndex, this.detail)
  406. },
  407. // 支付成功后回调
  408. paymentSuccess() {
  409. let _this = this
  410. console.log('刷新抽卡界面')
  411. // 刷新界面
  412. _this.refresh()
  413. },
  414. // 选中取消选中卡牌
  415. clickCard(item) {
  416. if (item.status == 0) {
  417. item.check = !item.check
  418. }
  419. // 如果是选中
  420. let index = this.selectIndex.indexOf(item.number)
  421. if (item.check && index == -1) {
  422. this.selectIndex.push(item.number)
  423. } else if (!item.check && index != -1) {
  424. this.selectIndex.splice(index, 1)
  425. }
  426. },
  427. // 标记已经选中卡牌
  428. selectFormat() {
  429. for (var i = 0; i < this.cardList.length; i++) {
  430. if (this.selectIndex.includes(this.cardList[i].number)) {
  431. this.cardList[i].check = true
  432. }
  433. }
  434. },
  435. getCardList() {
  436. prizePoolStatusApi(this.params).then(res => {
  437. console.log(res, '卡牌分页')
  438. for (var i = 0; i < res.data.list.length; i++) {
  439. res.data.list[i].check = false
  440. }
  441. this.cardList = res.data.list
  442. this.selectFormat()
  443. this.total = res.data.total
  444. })
  445. },
  446. left() {
  447. console.log('上一页')
  448. if (this.params.page > 1) {
  449. this.params.page = this.params.page - 1
  450. }
  451. this.getCardList()
  452. },
  453. right() {
  454. console.log('下一页')
  455. let pages = Math.ceil(this.total / this.params.limit)
  456. if (this.params.page < pages) {
  457. this.params.page = this.params.page + 1
  458. }
  459. this.getCardList()
  460. },
  461. },
  462. }
  463. </script>
  464. <style scoped lang="scss">
  465. .container {
  466. background: #9ec8f9;
  467. padding-top: 15px;
  468. overflow: auto;
  469. .refresh {
  470. position: fixed;
  471. right: 4px;
  472. top: 55%;
  473. width: 45px;
  474. }
  475. .head {
  476. background: #fff;
  477. border: 10px;
  478. padding: 15px;
  479. border-radius: 10px 10px 0 0;
  480. display: flex;
  481. justify-content: space-between;
  482. .img {
  483. width: 106px;
  484. height: 106px;
  485. border-radius: 5px;
  486. overflow: hidden;
  487. margin-right: 10px;
  488. }
  489. .info {
  490. display: flex;
  491. flex-direction: column;
  492. justify-content: space-around;
  493. flex: 1;
  494. .row {
  495. display: flex;
  496. justify-content: space-between;
  497. color: #999999;
  498. .button {
  499. width: 67px;
  500. }
  501. .hot {
  502. display: flex;
  503. font-size: 12px;
  504. color: #999999;
  505. image {
  506. width: 16px;
  507. }
  508. }
  509. .users {
  510. position: relative;
  511. .photo {
  512. position: absolute;
  513. width: 20px;
  514. height: 20px;
  515. border-radius: 50%;
  516. }
  517. }
  518. }
  519. .title {
  520. font-weight: 600;
  521. color: #000;
  522. }
  523. .price {
  524. font-size: 14px;
  525. font-weight: 600;
  526. color: #ff2c43;
  527. .text {
  528. color: #999999;
  529. font-weight: 500;
  530. }
  531. }
  532. }
  533. }
  534. .cardList {
  535. margin-top: 10px;
  536. position: relative;
  537. .bk {
  538. width: 100%;
  539. }
  540. .leftButton {
  541. position: absolute;
  542. top: 50%;
  543. transform: translateY(-50%);
  544. left: 20px;
  545. height: 40px;
  546. width: 20px;
  547. z-index: 5;
  548. }
  549. .rightButton {
  550. position: absolute;
  551. top: 50%;
  552. transform: translateY(-50%);
  553. right: 20px;
  554. height: 40px;
  555. width: 20px;
  556. z-index: 5;
  557. }
  558. .list {
  559. padding: 35px 40px;
  560. width: calc(100% - 80px);
  561. height: calc(100% - 70px);
  562. position: absolute;
  563. top: 0;
  564. display: grid;
  565. grid-template-columns: 1fr 1fr 1fr 1fr;
  566. grid-template-rows: 1fr 1fr 1fr;
  567. .item {
  568. display: inline-flex;
  569. justify-content: center;
  570. align-items: center;
  571. position: relative;
  572. .kaBkActive {
  573. height: 132%;
  574. width: 100%;
  575. position: absolute;
  576. z-index: 1;
  577. }
  578. .kaBk {
  579. width: 70%;
  580. border-radius: 4px;
  581. z-index: 2;
  582. }
  583. .num {
  584. position: absolute;
  585. width: 100%;
  586. height: 100%;
  587. top: 0;
  588. z-index: 2;
  589. }
  590. }
  591. .active {
  592. .kaBk {
  593. // box-shadow: 0px 1px 6px 3px rgba(255,77,0,0.65);
  594. }
  595. }
  596. }
  597. }
  598. .buttons {
  599. display: flex;
  600. justify-content: space-between;
  601. align-items: flex-start;
  602. .button1 {
  603. width: 25vw;
  604. }
  605. .button2 {
  606. width: 35vw;
  607. margin-bottom: 5px;
  608. }
  609. }
  610. .lockBox {
  611. margin: 10px 20px;
  612. padding: 10px;
  613. height: 16vw;
  614. background: #fff;
  615. border-radius: 15px;
  616. display: flex;
  617. justify-content: center;
  618. align-items: center;
  619. box-shadow: 1px 2px 2px #459bff;
  620. .text {
  621. color: #459bff;
  622. font-weight: 600;
  623. font-size: 14px;
  624. }
  625. .info {
  626. display: flex;
  627. width: 100%;
  628. justify-content: center;
  629. .photo {
  630. width: 14vw;
  631. height: 14vw;
  632. border-radius: 50%;
  633. }
  634. .right {
  635. margin-left: 10px;
  636. flex: 1;
  637. display: flex;
  638. flex-direction: column;
  639. align-items: center;
  640. justify-content: center;
  641. .row {
  642. width: 100%;
  643. color: #459bff;
  644. font-size: 14px;
  645. margin-bottom: 10px;
  646. position: relative;
  647. display: flex;
  648. align-items: center;
  649. .time {
  650. padding: 5px;
  651. color: #fff;
  652. background: #459bff;
  653. margin: 0 8px;
  654. border-radius: 5px;
  655. font-weight: 600;
  656. font-size: 16px;
  657. }
  658. .name {
  659. font-size: 15px;
  660. font-weight: 600;
  661. color: #459bff;
  662. width: 40%;
  663. white-space: nowrap;
  664. text-overflow: ellipsis;
  665. overflow: hidden;
  666. }
  667. .tip {
  668. font-size: 11px;
  669. position: absolute;
  670. right: 0;
  671. font-weight: 500;
  672. color: #459bff;
  673. }
  674. }
  675. }
  676. }
  677. }
  678. .prizes {
  679. .title {
  680. width: 103px;
  681. margin: 0 auto;
  682. }
  683. .prizesList {
  684. margin: 20px;
  685. position: relative;
  686. overflow: hidden;
  687. // z-index: 5;
  688. .bk {
  689. width: 100%;
  690. height: 100%;
  691. position: absolute;
  692. top: 0;
  693. }
  694. .prizesTitle {
  695. position: relative;
  696. height: 30px;
  697. line-height: 30px;
  698. width: 100%;
  699. margin-left: 1px;
  700. margin-top: 15px;
  701. padding-left: 15px;
  702. color: #fff;
  703. font-weight: 800;
  704. background: linear-gradient(90deg, rgba(89, 166, 255, 0.8) 0%, rgba(158, 200, 249, 0) 100%);
  705. }
  706. .prizesImg {
  707. position: relative;
  708. display: grid;
  709. grid-template-columns: 1fr 1fr;
  710. margin: 15px;
  711. white-space: wrap;
  712. text-align: center;
  713. // overflow: auto;
  714. .image {
  715. text-align: center;
  716. image {
  717. display: inline-block;
  718. width: 36vw;
  719. height: 36vw;
  720. border-radius: 10px;
  721. margin: 0 5px;
  722. }
  723. }
  724. }
  725. .prizesImgOne {
  726. position: relative;
  727. display: flex;
  728. justify-content: center;
  729. margin: 15px;
  730. .image {
  731. text-align: center;
  732. image {
  733. display: inline-block;
  734. width: 45vw;
  735. height: 45vw;
  736. border-radius: 10px;
  737. margin: 0 5px;
  738. }
  739. }
  740. }
  741. }
  742. }
  743. }
  744. .examples {
  745. width: 100%;
  746. margin-bottom: 20px;
  747. padding: 0 10px;
  748. display: flex;
  749. .example {
  750. width: 14vw;
  751. margin-right: 10px;
  752. display: flex;
  753. justify-content: center;
  754. flex-wrap: wrap;
  755. position: relative;
  756. .exampleImg {
  757. width: 13vw;
  758. }
  759. .tip {
  760. width: 100%;
  761. position: absolute;
  762. bottom: 0;
  763. transform: translateY(50%);
  764. }
  765. }
  766. }
  767. </style>