lottery.html 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>活动</title>
  6. <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
  7. <!--引入 element-ui 的样式,-->
  8. <link rel="stylesheet"
  9. href="https://wl-1306604067.cos.ap-guangzhou.myqcloud.com/production/ct/103548289110001/1742018383195/element-ui.css">
  10. <!-- 必须先引入vue, 后使用element-ui -->
  11. <script
  12. src="https://wl-1306604067.cos.ap-guangzhou.myqcloud.com/production/ct/103548289110001/1742017957144/vue.js"></script>
  13. <!-- 引入element 的组件库-->
  14. <script
  15. src="https://wl-1306604067.cos.ap-guangzhou.myqcloud.com/production/ct/103548289110001/1742017747738/element-ui.js"></script>
  16. <script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
  17. <!-- <script src="js/vconsole.min.js"></script>
  18. <script>
  19. var vConsole = new window.VConsole();
  20. </script> -->
  21. </head>
  22. <style>
  23. body {
  24. margin: 0;
  25. padding: 0;
  26. }
  27. #box {
  28. width: 100vw;
  29. height: 100vh;
  30. box-sizing: border-box;
  31. }
  32. .lotteryPage {
  33. width: 100%;
  34. height: 620px;
  35. background: url('./img/lottery-bg.png');
  36. background-size: 100% 620px;
  37. background-repeat: no-repeat;
  38. position: relative;
  39. }
  40. .prize_content {
  41. padding: 267px 61px 0 60px;
  42. display: flex;
  43. flex-wrap: wrap;
  44. justify-content: center;
  45. gap: 10px;
  46. }
  47. .prize_item {
  48. width: 78px;
  49. height: 78px;
  50. background: url('./img/prize-bg.png');
  51. background-size: 78px 78px;
  52. background-repeat: no-repeat;
  53. display: flex;
  54. justify-content: center;
  55. align-items: center;
  56. flex-direction: column;
  57. font-weight: 400;
  58. font-size: 10px;
  59. color: #CC745A;
  60. box-sizing: border-box;
  61. }
  62. .prize_img {
  63. width: 48px;
  64. height: 48px;
  65. padding-bottom: 3px;
  66. }
  67. .lottery_btn {
  68. position: absolute;
  69. bottom: -14px;
  70. display: flex;
  71. flex-direction: column;
  72. align-items: center;
  73. width: 100%;
  74. }
  75. .btn_img {
  76. width: 290px;
  77. }
  78. .lottery_tip {
  79. text-align: center;
  80. font-size: 14px;
  81. color: #FFFFFF;
  82. font-weight: 600;
  83. line-height: 14px;
  84. }
  85. .rule {
  86. width: 100%;
  87. height: 509px;
  88. background: linear-gradient(180deg, #FF6C52 0%, #FFBA9B 100%);
  89. margin-top: -50px;
  90. padding: 65px 15px 40px;
  91. box-sizing: border-box;
  92. }
  93. .rule_body {
  94. height: 404px;
  95. background: #FEE8D0;
  96. border-radius: 20px;
  97. padding: 20px 15px;
  98. box-sizing: border-box;
  99. }
  100. .tabs {
  101. display: flex;
  102. justify-content: space-around;
  103. align-items: center;
  104. padding: 0 2px;
  105. margin: 0 auto;
  106. width: 255px;
  107. height: 34px;
  108. background: rgba(255, 125, 97, 0.2);
  109. border-radius: 17px 17px 17px 17px;
  110. }
  111. .tab_link {
  112. border: none;
  113. outline: none;
  114. cursor: pointer;
  115. transition: 0.3s;
  116. color: #FF765B;
  117. background: unset;
  118. width: 125px;
  119. height: 30px;
  120. border-radius: 17px
  121. }
  122. .tab_link:active {
  123. background: rgba(255, 125, 97, 0.2);
  124. }
  125. .tab_link.active {
  126. background: #FFFFFF;
  127. }
  128. .tab_content {
  129. p {
  130. font-weight: 400;
  131. font-size: 14px;
  132. color: #CB4E35;
  133. margin-top: 20px;
  134. }
  135. }
  136. .record_list {
  137. overflow-y: auto;
  138. height: 300px;
  139. margin-top: 18px;
  140. }
  141. .record_item {
  142. width: 100%;
  143. height: 72px;
  144. background: #FEDFC9;
  145. border-radius: 10px;
  146. padding: 9px 10px 8px;
  147. display: flex;
  148. align-items: center;
  149. margin: 0 auto 10px;
  150. box-sizing: border-box;
  151. }
  152. .record_img {
  153. width: 55px;
  154. height: 55px;
  155. border-radius: 10px;
  156. margin-right: 8px;
  157. }
  158. .get_btn {
  159. width: 72px;
  160. height: 30px;
  161. background: #FF4646;
  162. border-radius: 17px;
  163. font-size: 14px;
  164. color: #FFFFFF;
  165. margin-left: 30px;
  166. padding: 0;
  167. }
  168. .prize_name {
  169. font-size: 14px;
  170. font-weight: 500;
  171. color: #FF4646;
  172. }
  173. .prize_time {
  174. font-size: 12px;
  175. color: #FF6767;
  176. }
  177. .el-dialog {
  178. width: 335px;
  179. border-radius: 20px;
  180. }
  181. .el-dialog__header {
  182. text-align: center;
  183. }
  184. .el-dialog__title {
  185. font-weight: 500;
  186. font-size: 16px;
  187. color: #222222;
  188. }
  189. .el-dialog__body {
  190. height: auto;
  191. max-height: 260px;
  192. overflow-y: auto;
  193. }
  194. .prize_form .el-form-item {
  195. padding: 0;
  196. }
  197. .prize_form .el-form-item__label {
  198. line-height: 20px;
  199. }
  200. .prize_form .el-input {
  201. width: 295px;
  202. }
  203. .prize_form .el-input__inner {
  204. text-align: left;
  205. }
  206. .prize_form .el-input.is-active .el-input__inner,
  207. .prize_form .el-input__inner:focus {
  208. border: 1px solid #FF4646;
  209. }
  210. .prize_form .el-textarea.is-active .el-textarea__inner,
  211. .prize_form .el-textarea__inner:focus {
  212. border: 1px solid #FF4646;
  213. }
  214. .el-radio__input.is-checked .el-radio__inner {
  215. border-color: #FF4646;
  216. background: #FF4646;
  217. }
  218. .el-radio__input.is-checked+.el-radio__label {
  219. color: #FF4646;
  220. }
  221. .el-select .el-input.is-focus .el-input__inner {
  222. border-color: #FF4646;
  223. }
  224. .dialog-footer {
  225. text-align: center;
  226. }
  227. .dialog-footer button {
  228. width: 100%;
  229. height: 46px;
  230. background: #FF4646;
  231. border-radius: 20px;
  232. font-weight: 500;
  233. font-size: 16px;
  234. color: #FFFFFF;
  235. border: none;
  236. }
  237. .prize_dialog {
  238. position: fixed;
  239. top: 0;
  240. left: 0;
  241. width: 100%;
  242. height: 100%;
  243. background-color: rgba(0, 0, 0, 0.5);
  244. /* 半透明黑色 */
  245. z-index: 1000;
  246. /* 确保遮罩层在顶部 */
  247. transition: opacity 0.5s ease;
  248. /* 可选:添加透明度过渡效果 */
  249. }
  250. .dialog-body {
  251. width: 100%;
  252. height: 100%;
  253. z-index: 1001;
  254. /* 确保遮罩层在顶部 */
  255. display: flex;
  256. flex-direction: column;
  257. align-items: center;
  258. justify-content: center;
  259. }
  260. .dialog-tip {
  261. width: 100%;
  262. height: 100px;
  263. }
  264. .dialog-bg {
  265. width: 295px;
  266. height: 251px;
  267. position: relative;
  268. }
  269. .prize-msg {
  270. position: absolute;
  271. text-align: center;
  272. }
  273. .money-title {
  274. font-weight: 500;
  275. font-size: 16px;
  276. color: #FF4E4E;
  277. padding-top: 90px;
  278. padding-bottom: 10px;
  279. }
  280. .money-content {
  281. margin-bottom: 30px;
  282. height: 60px;
  283. display: flex;
  284. justify-content: center;
  285. align-items: center;
  286. }
  287. .prize-money {
  288. font-weight: bold;
  289. font-size: 60px;
  290. color: #FF4E4E;
  291. }
  292. .prize-unit {
  293. font-weight: 500;
  294. font-size: 16px;
  295. color: #FF4E4E;
  296. padding-left: 10px;
  297. padding-top: 28px;
  298. }
  299. .dialog-btn {
  300. width: 235px;
  301. height: 52px;
  302. margin-bottom: 10px;
  303. }
  304. .money-tip {
  305. font-weight: 400;
  306. font-size: 12px;
  307. color: #999999;
  308. margin-bottom: 15px;
  309. }
  310. .goods-img {
  311. width: 100px;
  312. height: 100px;
  313. margin: 70px 0 10px;
  314. }
  315. .goods-name {
  316. font-weight: 500;
  317. font-size: 16px;
  318. color: #222222;
  319. margin-bottom: 20px;
  320. }
  321. .dialog-close {
  322. width: 30px;
  323. height: 30px;
  324. margin-top: 20px;
  325. }
  326. .actives {
  327. border: 2px solid #df2727;
  328. border-radius: 15px;
  329. }
  330. .event_notice {
  331. width: 30px;
  332. height: 84px;
  333. background: rgba(255, 255, 255, 0.5);
  334. border-radius: 15px 0px 0px 15px;
  335. border: 1px solid #FFFFFF;
  336. font-weight: 500;
  337. font-size: 14px;
  338. color: #FF4E4E;
  339. position: absolute;
  340. right: 0;
  341. top: 20%;
  342. writing-mode: vertical-rl;
  343. text-align: center;
  344. padding-right: 4px;
  345. }
  346. .qrcode {
  347. width: 100vw;
  348. height: 100vh;
  349. box-sizing: border-box;
  350. display: flex;
  351. align-items: center;
  352. justify-content: center;
  353. flex-direction: column;
  354. }
  355. .qrcode-msg {
  356. text-align: center;
  357. font-size: 18px;
  358. }
  359. .alert_dialog {
  360. z-index: 999;
  361. position: fixed;
  362. top: 0;
  363. left: 0;
  364. width: 100%;
  365. }
  366. @media screen and (max-width: 320px) {
  367. .prize_content {
  368. padding: 280px 31px 0 30px;
  369. }
  370. .prize_item {
  371. width: 68px;
  372. height: 68px;
  373. background-size: 68px 68px;
  374. }
  375. .prize_img {
  376. width: 38px;
  377. height: 38px;
  378. }
  379. .el-dialog {
  380. width: 280px;
  381. border-radius: 20px;
  382. }
  383. }
  384. </style>
  385. <body>
  386. <div id="box">
  387. <div v-if="h5Type == 19 || h5Type == 30">
  388. <!-- 二维码 -->
  389. <div class="qrcode" v-if="qrCodeData.qrCode || qrCodeData.msg">
  390. <img class="qrcode-img" :src="qrCodeData.qrCode" />
  391. <div class="qrcode-msg">{{qrCodeData.msg}}</div>
  392. </div>
  393. <div v-else>
  394. <div class="lotteryPage">
  395. <div class="event_notice" @click="handleRule">
  396. <span>活动须知</span>
  397. </div>
  398. <div class="prize_content">
  399. <div :class="['prize_item', { actives: isSpinning && index === currentIndex }]"
  400. v-for="(item, index) in prizesList" :key="index">
  401. <img class="prize_img" :src="item.img"></img>
  402. <div>{{item.name}}</div>
  403. </div>
  404. </div>
  405. <div class="lottery_btn">
  406. <img class="btn_img" src="./img/btn.png" @click="handleLottery"></img>
  407. <div class="lottery_tip">已抽奖{{useNum}}次,还剩{{remainNum}}次机会</div>
  408. </div>
  409. </div>
  410. <div class="rule">
  411. <div class="rule_body">
  412. <div class="tabs">
  413. <Button class="tab_link" :class="{ 'active': activeName === 'tab1' }"
  414. @click="changeTab('tab1')">活动信息</Button>
  415. <Button class="tab_link" :class="{ 'active': activeName === 'tab2' }"
  416. @click="changeTab('tab2')">抽奖记录</Button>
  417. </div>
  418. <div v-if="activeName === 'tab1'" class="tab_content record_list" v-html="activeMsg"></div>
  419. <div v-if="activeName === 'tab2'" class="record_list">
  420. <div class="record_item" v-for="(item, index) in lotteryRecords" :key="index">
  421. <img class="record_img" :src="item.img" mode="widthFix" />
  422. <div>
  423. <div class="prize_name">{{item.name}}</div>
  424. <div class="prize_time">{{timeFormat(item.raffleTime)}}</div>
  425. </div>
  426. <el-button :disabled="item.status == -1 || item.status == 1" class="get_btn"
  427. @click="handleOpenForm(item.id)">{{item.status == 1 ? '已发放' : (item.status == -1 ?
  428. '审核中'
  429. : '领取')}}</el-button>
  430. </div>
  431. </div>
  432. </div>
  433. </div>
  434. </div>
  435. <!-- 奖励弹窗 -->
  436. <div class="prize_dialog" v-if="showPrizeDialog">
  437. <div class="dialog-body">
  438. <img class="dialog-tip" src="./img/dialog-tip.png" />
  439. <img class="dialog-bg" src="./img/dialog-bg.png" />
  440. <div class="prize-msg" v-if="prizeData.acceptType === 2">
  441. <div class="money-title">微信红包</div>
  442. <div class="money-content">
  443. <span class="prize-money">{{prizeData.money}}</span>
  444. <span class="prize-unit">元</span>
  445. </div>
  446. <img class="dialog-btn" src="./img/dialog-btn.png" @click="showPrizeDialog = false" />
  447. <div class="money-tip">红包到账会有延迟情况,请以实际为准</div>
  448. </div>
  449. <div class="prize-msg" v-if="prizeData.acceptType === 0 || prizeData.acceptType === 1">
  450. <img class="goods-img" :src="prizeData.img" />
  451. <div class="goods-name">{{prizeData.name}}</div>
  452. <img class="dialog-btn" src="./img/dialog-btn.png" @click="showPrizeDialog = false" />
  453. </div>
  454. <img class="dialog-close" src="./img/dialog-close.png" @click="showPrizeDialog = false" />
  455. </div>
  456. </div>
  457. <!-- 活动须知弹框 -->
  458. <el-dialog title="活动须知" :visible.sync="showRuleDialog">
  459. <div class="tab_content" v-html="activeMsg"></div>
  460. </el-dialog>
  461. <el-dialog title="收货地址" :visible.sync="showDialog">
  462. <el-form :model="form" class="prize_form">
  463. <el-form-item label="姓名:">
  464. <el-input v-model="form.name" autocomplete="off"></el-input>
  465. </el-form-item>
  466. <el-form-item label="微信号:">
  467. <el-input v-model="form.wxAccount" autocomplete="off"></el-input>
  468. </el-form-item>
  469. <el-form-item label="手机号:">
  470. <el-input v-model="form.phone" autocomplete="off"></el-input>
  471. </el-form-item>
  472. <el-form-item label="地区:">
  473. <el-cascader v-model="cityData" :options="transformedData" @change="handleChangeCity">
  474. </el-cascader>
  475. </el-form-item>
  476. <el-form-item label="详细地址:">
  477. <el-input v-model="form.address" autocomplete="off"></el-input>
  478. </el-form-item>
  479. <el-form-item label="备注:">
  480. <el-input v-model="form.remark" type="textarea" autocomplete="off"></el-input>
  481. </el-form-item>
  482. </el-form>
  483. <div slot="footer" class="dialog-footer">
  484. <el-button type="primary" @click="handleSave">确 定</el-button>
  485. </div>
  486. </el-dialog>
  487. <el-dialog :title="dialogTitle" :visible.sync="showTipDialog" :show-close="false" :close-on-click-modal="false">
  488. <el-form :model="getInfoForm" class="prize_form" label-position="top">
  489. <div v-if="preFormType">
  490. <el-form-item label="手机号:">
  491. <el-input v-model="getInfoForm.phone" autocomplete="off" maxlength="11"
  492. oninput="value=value.replace(/[^\d]/g,'')"
  493. @blur="$event => {getInfoForm.phone = Number($event.target.value) || '';}"></el-input>
  494. </el-form-item>
  495. <el-form-item label="地址:" v-if="!preOnlyPhone">
  496. <el-cascader v-model="cityData" :options="transformedData" @change="handleInfoCity">
  497. </el-cascader>
  498. </el-form-item>
  499. <el-form-item label="意向车型:" v-if="!preOnlyPhone">
  500. <el-select v-model="getInfoForm.intenModel" placeholder="请选择">
  501. <el-option v-for="item in allCarList" :key="item" :label="item" :value="item">
  502. </el-option>
  503. </el-select>
  504. </el-form-item>
  505. </div>
  506. <div v-else>
  507. <el-form-item label="确认:">
  508. <el-radio-group v-model="getInfoForm.buyCar">
  509. <el-radio :label="1">是</el-radio>
  510. <el-radio :label="0">否</el-radio>
  511. </el-radio-group>
  512. </el-form-item>
  513. <el-form-item label="已购车型:" v-if="getInfoForm.buyCar">
  514. <el-select v-model="getInfoForm.car" placeholder="请选择">
  515. <el-option v-for="item in allCarList" :key="item" :label="item" :value="item">
  516. </el-option>
  517. </el-select>
  518. </el-form-item>
  519. </div>
  520. </el-form>
  521. <div slot="footer" class="dialog-footer">
  522. <el-button type="primary" @click="handleSaveCar">确 定</el-button>
  523. </div>
  524. </el-dialog>
  525. <el-alert v-if="showError" class="alert_dialog" :title="errorMsg" :closable="false" type="error" show-icon>
  526. </el-alert>
  527. </div>
  528. </div>
  529. <script>
  530. new Vue({
  531. el: '#box',
  532. data() {
  533. return {
  534. env: '',
  535. httpUrl: '',
  536. h5Type: null,
  537. qrCodeData: {
  538. qrCode: '',
  539. msg: '',
  540. },
  541. bId: null,
  542. shareTitle: '',
  543. shareDes: '',
  544. shareCover: '',
  545. prizesList: [],
  546. useNum: null,
  547. remainNum: null,
  548. activeMsg: '',
  549. lotteryRecords: [],
  550. activeName: 'tab1',
  551. showDialog: false,
  552. form: {
  553. name: '',
  554. wxAccount: '',
  555. phone: '',
  556. province: '',
  557. city: '',
  558. address: '',
  559. remark: '',
  560. recordId: null,
  561. },
  562. transformedData: [],
  563. cityData: '',
  564. showTipDialog: false,
  565. allCarList: [],
  566. getInfoForm: {
  567. buyCar: 1,
  568. phone: '',
  569. province: '',
  570. city: '',
  571. area: '',
  572. store: '',
  573. intenModel: '',
  574. car: '',
  575. },
  576. prizeData: {
  577. acceptType: null,
  578. name: '',
  579. img: '',
  580. money: '',
  581. id: null
  582. },
  583. showPrizeDialog: false,
  584. lotteryStatus: null,
  585. currentIndex: 0, // 当前活动的格子索引
  586. isSpinning: false,
  587. intervalId: null,
  588. showRuleDialog: false,
  589. preFormType: null,
  590. preOnlyPhone: null,
  591. showError: false,
  592. errorMsg: '',
  593. dialogTitle: ""
  594. }
  595. },
  596. created() {
  597. this.bId = this.getQueryParam('bId')
  598. this.env = this.getQueryParam('env')
  599. this.h5Type = this.getQueryParam('h5Type')
  600. if (!this.env || this.env === 'prod') {
  601. this.httpUrl = 'https://wlapi.wefanbot.com'
  602. } else {
  603. this.httpUrl = 'http://test.wefanbot.com:18993'
  604. }
  605. localStorage.removeItem('openId')
  606. this.ifH5Type()
  607. },
  608. methods: {
  609. // 公众号授权,获取code
  610. getAuth() {
  611. // 获取url上的code
  612. let code = this.getQueryParam('code')
  613. if (code) {
  614. // 判断业务id是否生产环境业务id
  615. fetch(this.httpUrl + `/p/insuite/p/isProdId?id=${this.bId}`)
  616. .then(res => {
  617. return res.json()
  618. }).then(result => {
  619. let { data, msg } = result
  620. if (typeof data === 'boolean' && data) {
  621. this.httpUrl = 'https://wlapi.wefanbot.com'
  622. } else {
  623. this.httpUrl = 'http://test.wefanbot.com:18993'
  624. }
  625. this.getInfoByh5Code(this.getQueryParam('code'))
  626. })
  627. } else {
  628. let redirect_uri = window.location.href
  629. // code 不存在,走微信网页授权逻辑
  630. let url = `https://open.weixin.qq.com/connect/oauth2/authorize?appId=wx99ec0d0828a4d2d3&redirect_uri=${redirect_uri}&scope=snsapi_userinfo&state=STATE#wechat_redirect`
  631. window.location.replace(url)
  632. }
  633. },
  634. getInfoByh5Code(code) {
  635. fetch(this.httpUrl + `/scrm/v1/mp-client/p/getInfoByh5Code?code=${code}&bId=${this.bId}`)
  636. .then(res => {
  637. return res.json()
  638. }).then(result => {
  639. let { data, code, msg } = result
  640. if (code === 1) {
  641. this.h5Type = data.h5Type
  642. localStorage.setItem('openId', data.openId)
  643. this.ifH5Type();
  644. }
  645. })
  646. },
  647. ifH5Type() {
  648. if (this.getQueryParam('openId') || localStorage.getItem('openId')) {
  649. if (!this.getQueryParam('externalUserid')) {
  650. this.gerQwAuth(this.bId);
  651. } else {
  652. if (this.isUnknownType(this.getQueryParam('externalUserid'))) {
  653. this.gerQwCode(this.bId);
  654. } else {
  655. this.raffleInfo();
  656. this.raffleRecord()
  657. this.getCityLevel()
  658. this.getAllCar()
  659. this.getQyWxSign()
  660. }
  661. }
  662. } else {
  663. // 走授权操作
  664. this.getAuth();
  665. }
  666. },
  667. // 企微授权
  668. gerQwAuth(bId) {
  669. let openId = this.getQueryParam('openId') || localStorage.getItem('openId')
  670. fetch(this.httpUrl + `/p/insuite/p/getOAUrl?openId=${openId}&bId=${bId}`)
  671. .then(res => {
  672. return res.json()
  673. }).then(result => {
  674. let { data, code, msg } = result
  675. if (code === 1) {
  676. window.location.replace(data)
  677. } else {
  678. this.$message({
  679. message: msg,
  680. type: 'warning'
  681. })
  682. }
  683. })
  684. },
  685. // 获取二维码
  686. gerQwCode(bId) {
  687. fetch(this.httpUrl + `/scrm/v1/wxcp-raffle/p/getUnknown?bId=${bId}&externalUserId=${this.getQueryParam('externalUserid')}`)
  688. .then(res => {
  689. return res.json()
  690. }).then(result => {
  691. let { data, code, msg } = result
  692. if (code === 1) {
  693. this.qrCodeData = data
  694. } else {
  695. this.$message({
  696. message: msg,
  697. type: 'warning'
  698. })
  699. }
  700. })
  701. },
  702. // 内容类型的分享页,获取企业微信的签名
  703. getQyWxSign() {
  704. let shareUrl = `${window.location.origin}?bId=${this.bId}&h5Type=${this.h5Type}`
  705. fetch(this.httpUrl + `/scrm/v1/ct-share/p/getSignature?url=${window.location.href}`)
  706. .then(res => {
  707. return res.json()
  708. }).then(result => {
  709. let { data, code, msg } = result
  710. if (code === 1) {
  711. wx.config({
  712. debug: false,
  713. appId: data.appId, // 必填,企业号的唯一标识,此处填写企业号corpid
  714. timestamp: data.timestamp, // 必填,生成签名的时间戳
  715. nonceStr: data.nonceStr, // 必填,生成签名的随机串
  716. signature: data.signature, // 必填,签名,见附录1
  717. jsApiList: ['updateAppMessageShareData', 'updateTimelineShareData'] // 必填,需要使用的JS接口列表
  718. })
  719. // 分享接口仅激活的成员数超过200人且已经认证的企业才可在微信上调用。
  720. wx.ready(() => {
  721. let shareData = {
  722. link: shareUrl,
  723. title: this.shareTitle, // 分享标题
  724. desc: this.shareDes, // 分享描述
  725. imgUrl: this.shareCover,
  726. }
  727. // 分享到朋友圈
  728. wx.updateAppMessageShareData(shareData)
  729. // 分享给朋友
  730. wx.updateTimelineShareData(shareData);
  731. // 配置失败的回调函数
  732. wx.error(function (res) {
  733. // 配置失败
  734. console.log('配置失败', res);
  735. })
  736. })
  737. } else {
  738. // this.$message({
  739. // message: msg,
  740. // type: 'warning'
  741. // })
  742. }
  743. })
  744. },
  745. // 获取抽奖信息
  746. raffleInfo() {
  747. fetch(this.httpUrl + `/scrm/v1/wxcp-raffle/p/raffleInfoByOpenId?openId=${this.getQueryParam('openId') || localStorage.getItem('openId')}&bId=${this.bId}`)
  748. .then(res => {
  749. return res.json()
  750. }).then(result => {
  751. let { data, code, msg } = result
  752. if (code === 1) {
  753. this.lotteryStatus = data.status
  754. this.prizesList = data.prizes
  755. this.useNum = data.useNum
  756. this.remainNum = data.raffleNum - data.useNum
  757. this.activeMsg = data.activityInfo
  758. this.shareTitle = data.name
  759. this.shareDes = data.description
  760. this.shareCover = data.cover
  761. this.preFormType = data.preFormType
  762. if (data.preForm && !data.isSubmit && this.getInfoForm.buyCar !== 0) {
  763. this.preOnlyPhone = data.preOnlyPhone
  764. if (this.preFormType) {
  765. this.dialogTitle = '五菱试驾体验报名'
  766. } else {
  767. this.dialogTitle = '请问您是否已购五菱/宝骏车型?'
  768. }
  769. // 此处加上this.getInfoForm.buyCar !== 0的条件是当用户点击过否的时候,不再弹出此框,除非用户重新进入页面,可再次弹出此框
  770. this.showTipDialog = true
  771. }
  772. } else {
  773. this.showError = true
  774. this.errorMsg = msg
  775. }
  776. })
  777. },
  778. // 抽奖记录
  779. raffleRecord() {
  780. fetch(this.httpUrl + '/scrm/v1/wxcp-raffle/p/raffleRecord', {
  781. method: 'post',
  782. body: JSON.stringify({
  783. openId: this.getQueryParam('openId') || localStorage.getItem('openId'),
  784. bid: this.bId,
  785. page: 1,
  786. pageCount: 1000,
  787. }),
  788. headers: {
  789. 'Content-Type': 'application/json'
  790. }
  791. }).then(res => {
  792. return res.json()
  793. }).then(result => {
  794. let { data, code, msg } = result
  795. if (code === 1) {
  796. this.lotteryRecords = data.records
  797. }
  798. })
  799. },
  800. changeTab(tabName) {
  801. this.activeName = tabName
  802. },
  803. handleOpenForm(id) {
  804. this.form.recordId = id
  805. this.showDialog = true
  806. },
  807. handleSave() {
  808. if (!this.form.name) {
  809. this.$message({
  810. message: '请填写姓名',
  811. type: 'warning'
  812. })
  813. return
  814. }
  815. if (!this.form.phone) {
  816. this.$message({
  817. message: '请输入手机号',
  818. type: 'warning'
  819. })
  820. return
  821. }
  822. if (!this.form.province) {
  823. this.$message({
  824. message: '请选择城市',
  825. type: 'warning'
  826. })
  827. return
  828. }
  829. fetch(this.httpUrl + '/scrm/v1/wxcp-raffle/p/raffleForm', {
  830. method: 'post',
  831. body: JSON.stringify(this.form),
  832. headers: {
  833. 'Content-Type': 'application/json'
  834. }
  835. }).then(res => {
  836. return res.json()
  837. }).then(result => {
  838. let { data, code, msg } = result
  839. if (code === 1) {
  840. this.$message({
  841. message: '提交成功!',
  842. type: 'success'
  843. })
  844. this.showDialog = false
  845. this.raffleRecord()
  846. }
  847. })
  848. },
  849. handleSaveCar() {
  850. if (this.preFormType) {
  851. if (!this.getInfoForm.phone) {
  852. this.$message({
  853. message: '请输入手机号',
  854. type: 'warning'
  855. })
  856. return
  857. }
  858. if (!this.preOnlyPhone) {
  859. if (!this.getInfoForm.city) {
  860. this.$message({
  861. message: '请选择城市',
  862. type: 'warning'
  863. })
  864. return
  865. }
  866. if (!this.getInfoForm.intenModel) {
  867. this.$message({
  868. message: '请选择意向车型',
  869. type: 'warning'
  870. })
  871. return
  872. }
  873. }
  874. this.getInfoForm.buyCar = null
  875. this.getInfoForm.car = ''
  876. } else {
  877. if (this.getInfoForm.buyCar) {
  878. if (!this.getInfoForm.car) {
  879. this.$message({
  880. message: '请选择已购车型',
  881. type: 'warning'
  882. })
  883. return
  884. }
  885. } else {
  886. this.getInfoForm.car = ''
  887. }
  888. this.getInfoForm.phone = ''
  889. this.getInfoForm.province = ''
  890. this.getInfoForm.city = ''
  891. this.getInfoForm.area = ''
  892. this.getInfoForm.store = ''
  893. this.getInfoForm.intenModel = ''
  894. }
  895. fetch(this.httpUrl + '/scrm/v1/wxcp-raffle/p/submitPreForm', {
  896. method: 'post',
  897. body: JSON.stringify({
  898. bid: this.bId,
  899. buyCar: this.getInfoForm.buyCar,
  900. car: this.getInfoForm.car,
  901. phone: this.getInfoForm.phone,
  902. province: this.getInfoForm.province,
  903. city: this.getInfoForm.city,
  904. area: this.getInfoForm.area,
  905. store: this.getInfoForm.store,
  906. intenModel: this.getInfoForm.intenModel,
  907. mpOpenId: this.getQueryParam('openId') || this.localStorage.getItem('openId'),
  908. }),
  909. headers: {
  910. 'Content-Type': 'application/json'
  911. }
  912. }).then(res => {
  913. return res.json()
  914. }).then(result => {
  915. let { data, code, msg } = result
  916. if (code === 1) {
  917. this.$message({
  918. message: '提交成功!',
  919. type: 'success'
  920. })
  921. this.showTipDialog = false
  922. } else {
  923. this.$message({
  924. message: msg,
  925. type:'warning'
  926. })
  927. }
  928. })
  929. },
  930. // 获取城市数据
  931. getCityLevel() {
  932. fetch(this.httpUrl + `//scrm/v1/tenancy-prov-city-area/p/lotteryArea?bid=${this.bId}`)
  933. .then(res => {
  934. return res.json()
  935. }).then(result => {
  936. let { data, code, msg } = result
  937. if (code === 1) {
  938. this.transformedData = this.transformData(data)
  939. }
  940. })
  941. },
  942. // 获取全部车型
  943. getAllCar() {
  944. fetch(this.httpUrl + `/scrm/v1/wxcp-raffle/p/getCarList?bId=${this.bId}`)
  945. .then(res => {
  946. return res.json()
  947. }).then(result => {
  948. let { data, code, msg } = result
  949. if (code === 1) {
  950. this.allCarList = data
  951. }
  952. })
  953. },
  954. handleChangeCity(value) {
  955. this.form.province = value[0]
  956. this.form.city = value[1]
  957. },
  958. handleInfoCity(value) {
  959. this.getInfoForm.province = value[0]
  960. this.getInfoForm.city = value[1]
  961. this.getInfoForm.area = value[2] || ''
  962. this.getInfoForm.store = value[3] || ''
  963. },
  964. // 点击抽奖
  965. handleLottery() {
  966. if (!this.remainNum) {
  967. this.$message({
  968. message: '暂无抽奖次数',
  969. type: 'warning'
  970. })
  971. return
  972. }
  973. if (this.lotteryStatus === -1) {
  974. this.$message({
  975. message: '活动已结束',
  976. type: 'warning'
  977. })
  978. } else if (this.lotteryStatus === 0) {
  979. this.$message({
  980. message: '活动未开始',
  981. type: 'warning'
  982. })
  983. } else if (this.lotteryStatus === 1) {
  984. if (this.isSpinning) return
  985. this.isSpinning = true
  986. this.currentIndex = 0
  987. let externalUserid = this.getQueryParam('externalUserid')
  988. let openId = this.getQueryParam('openId') || localStorage.getItem('openId')
  989. const headers = new Headers()
  990. headers.append('police', 110)
  991. // 开始转圈
  992. this.intervalId = setInterval(() => {
  993. this.currentIndex = (this.currentIndex + 1) % 9
  994. }, 200); // 每 200 毫秒转一次
  995. fetch(this.httpUrl + `/scrm/v1/wxcp-raffle/p/lottery?externalUserid=${externalUserid}&openId=${openId}&bId=${this.bId}`, {
  996. method: 'GET',
  997. headers: headers
  998. })
  999. .then(res => {
  1000. return res.json()
  1001. }).then(result => {
  1002. let { data, code, msg } = result
  1003. if (code === 1) {
  1004. this.prizeData = data
  1005. // 2. 添加等待逻辑
  1006. const checkInterval = setInterval(() => {
  1007. if (this.currentIndex >= 8) {
  1008. clearInterval(checkInterval)
  1009. this.showPrizeDialog = true
  1010. this.raffleInfo()
  1011. this.raffleRecord()
  1012. this.stopLottery() // 停止动画
  1013. }
  1014. }, 100) // 每100ms检查一次
  1015. } else {
  1016. this.stopLottery()
  1017. this.$message({
  1018. message: msg,
  1019. })
  1020. }
  1021. })
  1022. }
  1023. },
  1024. // 停止抽奖
  1025. stopLottery() {
  1026. clearInterval(this.intervalId);
  1027. this.isSpinning = false;
  1028. this.currentIndex = null;
  1029. },
  1030. handleRule() {
  1031. this.showRuleDialog = true
  1032. },
  1033. // 省市数据做转换
  1034. transformData(data) {
  1035. return data.map(item => {
  1036. // 创建一个新对象,避免直接修改原始对象
  1037. const newItem = { ...item };
  1038. // 重命名 text 为 label
  1039. if (newItem.text) {
  1040. newItem.label = newItem.text;
  1041. newItem.value = newItem.text;
  1042. delete newItem.text;
  1043. }
  1044. // 如果存在 children 数组,则递归处理每个子项
  1045. if (newItem.children && Array.isArray(newItem.children)) {
  1046. newItem.children = this.transformData(newItem.children);
  1047. }
  1048. return newItem;
  1049. })
  1050. },
  1051. // 截取url中的数据
  1052. getQueryParam(paramName) {
  1053. // 获取当前URL的查询字符串部分
  1054. const queryString = window.location.search;
  1055. // 创建一个URLSearchParams对象
  1056. const urlParams = new URLSearchParams(queryString);
  1057. // 返回指定参数的值,如果不存在则返回null
  1058. return urlParams.get(paramName);
  1059. },
  1060. timeFormat(time, format = 'yyyy-MM-dd hh:mm:ss') {
  1061. if (time === undefined || time === '' || time === null) {
  1062. return '/'
  1063. } else {
  1064. const date = new Date(time)
  1065. const o = {
  1066. 'M+': date.getMonth() + 1,
  1067. 'd+': date.getDate(),
  1068. 'h+': date.getHours(),
  1069. 'm+': date.getMinutes(),
  1070. 's+': date.getSeconds(),
  1071. 'q+': Math.floor((date.getMonth() + 3) / 3),
  1072. 'S': date.getMilliseconds()
  1073. }
  1074. if (/(y+)/.test(format)) {
  1075. format = format.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length))
  1076. }
  1077. for (let k in o) {
  1078. if (new RegExp('(' + k + ')').test(format)) {
  1079. format = format.replace(RegExp.$1, (RegExp.$1.length === 1) ? (o[k]) : (('00' + o[k]).substr(('' + o[k]).length)))
  1080. }
  1081. }
  1082. return format
  1083. }
  1084. },
  1085. isUnknownType(value) {
  1086. // 1. 先检查是否为字符串类型
  1087. // 2. 再检查是否以"unknown"开头(区分大小写)
  1088. return typeof value === 'string' && value.startsWith('unknown');
  1089. },
  1090. }
  1091. })
  1092. </script>
  1093. </body>
  1094. </html>