registrationActivity.html 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  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="js/vconsole.min.js"></script>
  17. <script>
  18. var vConsole = new window.VConsole();
  19. </script> -->
  20. </head>
  21. <style>
  22. body {
  23. margin: 0;
  24. padding: 0;
  25. }
  26. .box {
  27. width: 100vw;
  28. height: 100%;
  29. box-sizing: border-box;
  30. background: #FAFAFA;
  31. }
  32. .page6 {
  33. width: 100vw;
  34. height: 100%;
  35. background-size: 100vw 300px;
  36. background-repeat: no-repeat;
  37. position: relative;
  38. overflow-y: auto;
  39. }
  40. .enrollment {
  41. width: 100%;
  42. height: 25px;
  43. background: #C30011;
  44. opacity: 0.8;
  45. font-weight: 400;
  46. font-size: 12px;
  47. color: #FFFFFF;
  48. line-height: 25px;
  49. text-align: center;
  50. position: fixed;
  51. top: 0;
  52. left: 0;
  53. }
  54. .activity_content {
  55. width: 100%;
  56. margin-top: 250px;
  57. background: #FFFFFF;
  58. border-radius: 20px 20px 0px 0px;
  59. padding: 30px 20px 66px;
  60. box-sizing: border-box;
  61. }
  62. .activity_item {
  63. display: flex;
  64. align-items: flex-start;
  65. margin-bottom: 30px;
  66. }
  67. .item_title {
  68. font-weight: 500;
  69. font-size: 14px;
  70. color: #222222;
  71. min-width: 100px;
  72. }
  73. .item_content {
  74. font-weight: 400;
  75. font-size: 14px;
  76. color: #222222;
  77. }
  78. .item_content p {
  79. margin: 0;
  80. }
  81. .foot_btn {
  82. position: fixed;
  83. bottom: 14px;
  84. padding: 0 35px;
  85. width: 100%;
  86. box-sizing: border-box;
  87. }
  88. .signUp_btn {
  89. height: 52px;
  90. width: 100%;
  91. background: #1677FF;
  92. border-radius: 20px;
  93. font-weight: 500;
  94. font-size: 16px;
  95. color: #FFFFFF;
  96. text-align: center;
  97. padding: 0;
  98. line-height: 22px;
  99. }
  100. .signUp_btn_tip {
  101. font-weight: bold;
  102. font-size: 12px;
  103. line-height: 17px;
  104. }
  105. .form_content {
  106. width: 100%;
  107. margin-top: 250px;
  108. background: #FFFFFF;
  109. border-radius: 20px 20px 0px 0px;
  110. padding: 20px 20px 66px;
  111. box-sizing: border-box;
  112. }
  113. .form_title {
  114. font-weight: 500;
  115. font-size: 16px;
  116. color: #222222;
  117. text-align: center;
  118. line-height: 24px;
  119. }
  120. .form_title_tip {
  121. font-weight: bold;
  122. font-size: 12px;
  123. color: #FF4E4E;
  124. text-align: center;
  125. line-height: 17px;
  126. }
  127. .el-form-item__label {
  128. padding-right: 0;
  129. font-weight: 500;
  130. font-size: 14px;
  131. color: #666666;
  132. }
  133. .el-input__inner {
  134. border: none;
  135. font-weight: 500;
  136. font-size: 14px;
  137. color: #222222;
  138. text-align: right;
  139. }
  140. .el-input--prefix .el-input__inner {
  141. padding-left: 0;
  142. padding-right: 0;
  143. }
  144. .el-form-item {
  145. margin-bottom: 0;
  146. border-bottom: 1px solid #F9F9F9;
  147. padding: 10px 0;
  148. }
  149. .el-textarea__inner {
  150. border: none;
  151. font-weight: 500;
  152. font-size: 14px;
  153. color: #222222;
  154. text-align: right;
  155. }
  156. .el-form-item__content .el-select {
  157. margin-left: 55px;
  158. }
  159. .el-form-item__content .el-cascader {
  160. margin-left: 55px;
  161. }
  162. .el-select-dropdown__item {
  163. white-space: normal;
  164. overflow: unset;
  165. height: auto;
  166. }
  167. .signup_page {
  168. width: 100vw;
  169. height: 100vh;
  170. background: url('./img/sign_up.png') no-repeat center;
  171. background-size: 100vw 100vh;
  172. background-repeat: no-repeat;
  173. }
  174. .signupSucc_page {
  175. width: 100vw;
  176. height: 100vh;
  177. background: url('./img/signup_success.png') no-repeat center;
  178. background-size: 100vw 100vh;
  179. background-repeat: no-repeat;
  180. }
  181. .succ_tip {
  182. padding-top: 240px;
  183. font-weight: bold;
  184. font-size: 24px;
  185. color: #222222;
  186. line-height: 40px;
  187. text-align: center;
  188. width: 100%;
  189. word-break: keep-all;
  190. }
  191. .signup_title {
  192. font-weight: bold;
  193. font-size: 24px;
  194. color: #FFFFFF;
  195. padding-top: 80px;
  196. text-align: center;
  197. line-height: 41px;
  198. }
  199. .signup_box {
  200. margin: 30px 20px 0;
  201. height: 469px;
  202. background: linear-gradient(#D5E6FF 50%, #FFFFFF 100%);
  203. border-radius: 20px;
  204. box-sizing: border-box;
  205. border: 1px solid #FFFFFF;
  206. }
  207. .signup_tip {
  208. font-weight: 400;
  209. font-size: 16px;
  210. color: #222222;
  211. padding: 40px 31px 10px 32px;
  212. text-align: center;
  213. line-height: 27px;
  214. }
  215. .store_msg {
  216. display: flex;
  217. align-items: center;
  218. justify-content: center;
  219. font-weight: 400;
  220. font-size: 12px;
  221. color: #1677FF;
  222. margin-bottom: 15px;
  223. padding-left: 30px;
  224. padding-right: 36px;
  225. }
  226. .store_icon {
  227. width: 24px;
  228. height: 24px;
  229. margin-right: 5px;
  230. }
  231. .signup_code {
  232. font-weight: 500;
  233. font-size: 30px;
  234. color: #222222;
  235. padding: 15px 36px;
  236. background: #D3E0F5;
  237. border-radius: 20px;
  238. margin: 0 20px;
  239. text-align: center;
  240. }
  241. .copy_text {
  242. display: flex;
  243. align-items: center;
  244. justify-content: center;
  245. padding-top: 10px;
  246. font-weight: 400;
  247. font-size: 12px;
  248. color: #9FB3C7;
  249. }
  250. .copy_icon {
  251. width: 11px;
  252. height: 11px;
  253. margin-right: 3px;
  254. }
  255. .attention {
  256. font-weight: 400;
  257. font-size: 12px;
  258. color: #999999;
  259. line-height: 24px;
  260. text-align: start;
  261. padding-top: 20px;
  262. padding-left: 20px;
  263. padding-bottom: 20px;
  264. }
  265. .qrcode_info {
  266. display: flex;
  267. align-items: center;
  268. padding: 20px 0 20px 35px;
  269. border-top: 1px dashed #AEBFCE;
  270. font-weight: 400;
  271. font-size: 14px;
  272. color: #222222;
  273. }
  274. .bm_qrcode {
  275. width: 70px;
  276. height: 70px;
  277. margin-right: 25px;
  278. }
  279. .bm_title {
  280. padding-bottom: 10px;
  281. }
  282. .fail_box {
  283. margin: 80px 20px 0;
  284. height: 287px;
  285. background: linear-gradient(#D5E6FF 50%, #FFFFFF 100%);
  286. border-radius: 20px;
  287. box-sizing: border-box;
  288. text-align: center;
  289. }
  290. .fail_img {
  291. width: 246px;
  292. height: 144px;
  293. margin-top: -20px;
  294. }
  295. .fail_title {
  296. font-weight: 500;
  297. font-size: 20px;
  298. color: #222222;
  299. line-height: 30px;
  300. padding: 20px 0;
  301. }
  302. .fail_tip {
  303. font-weight: 400;
  304. font-size: 16px;
  305. color: #666666;
  306. line-height: 30px;
  307. }
  308. </style>
  309. <body>
  310. <div id="box" class="box">
  311. <div class="signup_page" v-if="step === 3">
  312. <div class="signup_title">
  313. <div>恭喜您已经报名</div>
  314. <div>{{toshopData.name}}</div>
  315. </div>
  316. <div class="signup_box">
  317. <div class="signup_tip">请您于活动结束前,凭以下核销码前往预约到店门店领取礼品</div>
  318. <div class="store_msg">
  319. <img class="store_icon" src="./img/store.png" />
  320. <span>{{storeName}}</span>
  321. </div>
  322. <div class="signup_code">{{verificationCode}}</div>
  323. <div class="copy_text" @click="handleCopy(verificationCode)">
  324. <img class="copy_icon" src="./img/copy_icon.png" />
  325. <span>点击复制核销码</span>
  326. </div>
  327. <div class="attention">
  328. <div>注意:</div>
  329. <div>1.凭证码仅可核销一次,请注意保管</div>
  330. <div>2.不记名,不挂失</div>
  331. </div>
  332. <div class="qrcode_info">
  333. <img class="bm_qrcode" src="./img/bm-qrcode.png" />
  334. <div>
  335. <div class="bm_title">还差最后一步!</div>
  336. <div class="bm_tip">扫码添加企微还有额外抽奖!</div>
  337. </div>
  338. </div>
  339. </div>
  340. </div>
  341. <div class="signupSucc_page" v-else-if="step === 4">
  342. <div class="succ_tip">
  343. {{toshopData.verificationGuide}}
  344. </div>
  345. </div>
  346. <div class="signup_page" v-else-if="step === 5">
  347. <div class="signup_title">{{toshopData.name}}</div>
  348. <div class="fail_box">
  349. <img class="fail_img" src="./img/fail_img.png" />
  350. <div class="fail_title">{{toshopData.verificationFailGuide}}</div>
  351. <div class="fail_tip">{{toshopData.verificationFailGuide2}}</div>
  352. </div>
  353. </div>
  354. <div class="page6" :style="{'background-image': 'url('+toshopData.banner+')'}" v-else-if="step === 1 || step === 2">
  355. <div class="enrollment">已有23333人参与活动</div>
  356. <div class="activity_content" v-if="step === 1">
  357. <div class="activity_item">
  358. <div class="item_title">活动主题:</div>
  359. <div class="item_content">{{toshopData.name}}</div>
  360. </div>
  361. <div class="activity_item">
  362. <div class="item_title">活动对象:</div>
  363. <div class="item_content">{{toshopData.target}}</div>
  364. </div>
  365. <div class="activity_item">
  366. <div class="item_title">活动时间:</div>
  367. <div class="item_content">{{toshopData.startTime.slice(0, 10) + '~' + toshopData.endTime.slice(0, 10)}}</div>
  368. </div>
  369. <div class="activity_item">
  370. <div class="item_title">活动规则:</div>
  371. <div class="item_content" v-html="toshopData.activityInfo"></div>
  372. </div>
  373. </div>
  374. <div class="form_content" v-else-if="step === 2">
  375. <div class="form_title">报名表单</div>
  376. <div class="form_title_tip">【 报名成功还能抽华为手机! 】</div>
  377. <el-form ref="form" label-position="left" label-width="120px">
  378. <el-form-item v-for="(item, index) in toshopData.formProList" :key="index" :label="item.name"
  379. :required="Boolean(item.isNeed)">
  380. <el-cascader v-if="item.type === 10" v-model="item.value" :options="transformedData"
  381. @change="handleInfoCity">
  382. </el-cascader>
  383. <el-select v-if="item.type === 11" v-model="item.value" placeholder="请选择" @change="handlechange">
  384. <el-option v-for="(sto, sindex) in storeList" :key="sindex" :label="sto.name" :value="sto.name">
  385. </el-option>
  386. </el-select>
  387. <el-input v-if="item.type === 0" v-model="item.value" placeholder="请输入"></el-input>
  388. <el-input v-if="item.type === 1" type="textarea" autosize v-model="item.value" placeholder="请输入"></el-input>
  389. <el-input v-if="item.type === 2" type="number" v-model="item.value" placeholder="请输入"></el-input>
  390. <el-select v-if="item.type === 3" v-model="item.value" placeholder="请选择">
  391. <el-option v-for="sto in item.formProTagReqs" :key="sto.proValue" :label="sto.proValue"
  392. :value="sto.proValue">
  393. </el-option>
  394. </el-select>
  395. <el-col :span="22" v-if="item.type === 5">
  396. <el-date-picker v-model="item.value" type="date" placeholder="选择日期" style="width: 100%;">
  397. </el-col>
  398. <el-col :span="22" v-if="item.type === 6">
  399. <el-time-picker v-model="item.value" placeholder="请选择"></el-time-picker>
  400. </el-col>
  401. <el-col :span="22" v-if="item.type === 7">
  402. <el-date-picker v-if="item.type === 7" v-model="item.value" type="datetime"
  403. placeholder="选择日期时间"></el-date-picker>
  404. </el-col>
  405. </el-form-item>
  406. </el-form>
  407. </div>
  408. <div class="foot_btn">
  409. <el-button class="signUp_btn" :loading="loading" @click="toSignUp" v-if="step === 1">
  410. <div>去报名</div>
  411. <div class="signUp_btn_tip">【 报名成功还能抽华为手机 】</div>
  412. </el-button>
  413. <el-button class="signUp_btn" :loading="loading" @click="toSignUp" v-else>确定</el-button>
  414. </div>
  415. </div>
  416. </div>
  417. </body>
  418. <script>
  419. new Vue({
  420. el: '#box',
  421. data () {
  422. return {
  423. httpUrl: '',
  424. bId: null,
  425. env: '',
  426. toshopData: {
  427. id: null,
  428. banner: '',
  429. name: '',
  430. target: '',
  431. startTime: '',
  432. endTime: '',
  433. activityInfo: '',
  434. formProList: [],
  435. verificationGuide: '',
  436. verificationFailGuide: '',
  437. verificationFailGuide2: '',
  438. browseId: null,
  439. },
  440. step: 1,
  441. verificationCode: '',
  442. storeName: '',
  443. transformedData: [],
  444. storeList: [],
  445. province: '',
  446. city: '',
  447. loading: false,
  448. intervalId: null, // 定时任务的ID
  449. loadTime: null, // 页面加载的时间戳
  450. }
  451. },
  452. created () {
  453. var hrt = document.documentElement.clientHeight; //获取当前可视区域的高度存到hrt变量
  454. document.getElementById('box').style.height = hrt + 'px'//把获取到的高度赋值给根div
  455. this.bId = this.getQueryParam('bId')
  456. this.env = this.getQueryParam('env')
  457. if (!this.env || this.env === 'prod') {
  458. this.httpUrl = 'https://wlapi.wefanbot.com'
  459. } else {
  460. this.httpUrl = 'https://test.wefanbot.com:28993'
  461. // this.httpUrl = 'http://192.168.1.147:18993'
  462. }
  463. localStorage.removeItem('openId')
  464. if (this.isWeChatBrowser()) {
  465. // 微信浏览器
  466. this.ifH5Type()
  467. } else {
  468. // 不是微信浏览器
  469. this.lightenShare()
  470. }
  471. },
  472. beforeDestroy() {
  473. this.clearIntervalTask() // 在组件销毁前清除定时任务
  474. },
  475. methods: {
  476. ifH5Type () {
  477. if (this.getQueryParam('openId') || localStorage.getItem('openId')) {
  478. if (!this.getQueryParam('externalUserid')) {
  479. this.gerQwAuth(this.bId);
  480. } else {
  481. this.lightenShare()
  482. }
  483. } else {
  484. // 走授权操作
  485. this.getAuth();
  486. }
  487. },
  488. getAuth () {
  489. // 获取url上的code
  490. let code = this.getQueryParam('code')
  491. if (code) {
  492. // 判断业务id是否生产环境业务id
  493. fetch(this.httpUrl + `/p/insuite/p/isProdId?id=${this.bId}`)
  494. .then(res => {
  495. return res.json()
  496. }).then(result => {
  497. let { data, msg } = result
  498. if (typeof data === 'boolean' && data) {
  499. this.httpUrl = 'https://wlapi.wefanbot.com'
  500. } else {
  501. this.httpUrl = 'http://test.wefanbot.com:18993'
  502. }
  503. this.getInfoByh5Code(this.getQueryParam('code'))
  504. })
  505. } else {
  506. let redirect_uri = window.location.href
  507. // code 不存在,走微信网页授权逻辑
  508. let url = `https://open.weixin.qq.com/connect/oauth2/authorize?appId=wx99ec0d0828a4d2d3&redirect_uri=${redirect_uri}&scope=snsapi_userinfo&state=STATE#wechat_redirect`
  509. window.location.replace(url)
  510. }
  511. },
  512. getInfoByh5Code (code) {
  513. fetch(this.httpUrl + `/scrm/v1/mp-client/p/getInfoByh5Code?code=${code}&bId=${this.bId}`)
  514. .then(res => {
  515. return res.json()
  516. }).then(result => {
  517. let { data, code, msg } = result
  518. if (code === 1) {
  519. localStorage.setItem('openId', data.openId)
  520. this.ifH5Type()
  521. }
  522. })
  523. },
  524. // 企微授权
  525. gerQwAuth (bId) {
  526. let openId = this.getQueryParam('openId') || localStorage.getItem('openId')
  527. fetch(this.httpUrl + `/p/insuite/p/getOAUrl?openId=${openId}&bId=${bId}`)
  528. .then(res => {
  529. return res.json()
  530. }).then(result => {
  531. let { data, code, msg } = result
  532. if (code === 1) {
  533. window.location.replace(data)
  534. } else {
  535. this.$message({
  536. message: msg,
  537. type: 'warning'
  538. })
  539. }
  540. })
  541. },
  542. // 获取城市数据
  543. getCityLevel () {
  544. let url = ''
  545. if (this.toshopData.id == 115399319210021) {
  546. url = 'https://wl-1306604067.cos.ap-guangzhou.myqcloud.com/production/ct/103548289110001/1744104152989/five-province.json'
  547. } else {
  548. url = 'https://wl-1306604067.cos.ap-guangzhou.myqcloud.com/production/ct/103548289110001/1742009720857/four-province.json'
  549. }
  550. fetch(url)
  551. .then(res => {
  552. return res.json()
  553. }).then(result => {
  554. this.transformedData = this.transformData(result)
  555. })
  556. },
  557. // 省市数据做转换
  558. transformData (data) {
  559. return data.map(item => {
  560. // 创建一个新对象,避免直接修改原始对象
  561. const newItem = { ...item };
  562. // 重命名 text 为 label
  563. if (newItem.text) {
  564. newItem.label = newItem.text;
  565. newItem.value = newItem.text;
  566. delete newItem.text;
  567. }
  568. // 如果存在 children 数组,则递归处理每个子项
  569. if (newItem.children && Array.isArray(newItem.children)) {
  570. newItem.children = this.transformData(newItem.children);
  571. }
  572. return newItem;
  573. })
  574. },
  575. handleInfoCity (value) {
  576. this.province = value[0]
  577. this.city = value[1]
  578. // 清空经销商类型的数据
  579. this.toshopData.formProList.forEach(item => {
  580. if (item.type === 11) {
  581. item.value = ''
  582. }
  583. })
  584. this.storeList = []
  585. this.getStoreList()
  586. },
  587. handlechange (value) {
  588. this.toshopData.formProList.forEach(item => {
  589. if (item.type === 11) {
  590. item.value = value
  591. }
  592. })
  593. this.$forceUpdate()
  594. },
  595. getStoreList () {
  596. fetch(this.httpUrl + `/scrm/v1/wxcp-toshop-store/p/findListByPage?city=${this.city}&province=${this.province}`, {
  597. method: 'post',
  598. body: JSON.stringify({
  599. page: 1,
  600. pageCount: 10000,
  601. }),
  602. headers: {
  603. 'Content-Type': 'application/json'
  604. }
  605. }).then(res => {
  606. return res.json()
  607. }).then(result => {
  608. let { data, code, msg } = result
  609. if (code === 1) {
  610. this.storeList = data.records
  611. } else {
  612. this.$message({
  613. message: msg,
  614. type: 'warning'
  615. })
  616. }
  617. })
  618. },
  619. lightenShare () {
  620. let externalUserid = this.getQueryParam('externalUserid') || ''
  621. let openId = this.getQueryParam('openId') || localStorage.getItem('openId') || ''
  622. const headers = new Headers();
  623. headers.append('police', 110);
  624. fetch(this.httpUrl + `/scrm/v1/wxcp-toshop-share/p/lottery?clientId=${localStorage.getItem('bkClientId') || ''}&externalUserid=${externalUserid}&openId=${openId}&bId=${this.bId}`, {
  625. method: 'GET',
  626. headers: headers
  627. })
  628. .then(res => {
  629. return res.json()
  630. }).then(result => {
  631. let { data, code, msg } = result
  632. if (code === 1) {
  633. this.toshopData = data
  634. if (!this.isWeChatBrowser()) {
  635. localStorage.setItem('bkClientId', data.client.id)
  636. }
  637. this.getCityLevel()
  638. if (data.client.state === 1) {
  639. // 未提交表单
  640. this.step = 1
  641. } else if (data.client.state === 2) {
  642. // 已提交表单
  643. this.verificationCode = data.client.verificationCode
  644. if (data.client.formData) {
  645. let arr = JSON.parse(data.client.formData)
  646. const filteredItems = arr.filter(item => item.name.includes("门店"))
  647. if (filteredItems.length) {
  648. const names = filteredItems.map(item => item.value[0])
  649. this.storeName = names[0]
  650. }
  651. }
  652. this.step = 3
  653. } else if (data.client.state === 3) {
  654. // 已核销
  655. this.step = 4
  656. } else if (data.client.state === -1) {
  657. // 不符合资格
  658. this.step = 5
  659. }
  660. this.loadTime = Date.now() // 记录页面加载时间
  661. this.startInterval() // 启动定时任务
  662. } else {
  663. this.$message({
  664. message: msg,
  665. })
  666. }
  667. })
  668. },
  669. startInterval() {
  670. if (this.intervalId !== null) {
  671. clearInterval(this.intervalId); // 如果定时任务已经存在,先清除它
  672. }
  673. this.intervalId = setInterval(() => {
  674. const elapsedTime = Math.floor((Date.now() - this.loadTime) / 1000); // 计算停留时长(秒)
  675. this.sendDataToServer(this.toshopData.browseId, elapsedTime);
  676. }, 10000); // 每10秒调用一次
  677. },
  678. sendDataToServer(browseId, elapsedTime) {
  679. let openId = this.getQueryParam('openId') || localStorage.getItem('openId') || ''
  680. fetch(this.httpUrl + `/scrm/v1/wxcp-toshop-client-browse-history/p/updateBrowseDuration?openId=${openId}`, {
  681. method: 'post',
  682. body: JSON.stringify({
  683. id: browseId,
  684. duration: elapsedTime,
  685. }),
  686. headers: {
  687. 'Content-Type': 'application/json'
  688. }
  689. }).then(res => {
  690. return res.json()
  691. }).then(result => {
  692. let { data, code, msg } = result
  693. if (data) {
  694. } else {
  695. }
  696. })
  697. },
  698. clearIntervalTask() {
  699. if (this.intervalId !== null) {
  700. clearInterval(this.intervalId)
  701. this.intervalId = null // 清空定时任务的ID
  702. }
  703. },
  704. toSignUp () {
  705. if (this.step === 1) {
  706. this.step = 2
  707. } else {
  708. const isValid = this.toshopData.formProList.some(item => {
  709. if (item.isNeed && !item.value) {
  710. this.$message({
  711. message: '必填项不能为空',
  712. type: 'warning'
  713. })
  714. return true
  715. }
  716. if (this.containsAllChineseCharacters(item.name, '手机') && item.value.length !== 11) {
  717. this.$message({
  718. message: '请输入正确的手机号',
  719. type: 'warning'
  720. })
  721. return true
  722. }
  723. return false
  724. })
  725. if (isValid) return
  726. let cols = []
  727. cols = this.toshopData.formProList.map(item => {
  728. return {
  729. name: item.name,
  730. type: item.type,
  731. value: item.type === 10 ? [item.value.join('')] : [item.value],
  732. }
  733. })
  734. let openId = this.getQueryParam('openId') || localStorage.getItem('openId') || ''
  735. this.loading = true
  736. fetch(this.httpUrl + `/scrm/v1/wxcp-toshop-share/p/formData?clientId=${localStorage.getItem('bkClientId') || ''}&openId=${openId}`, {
  737. method: 'post',
  738. body: JSON.stringify({
  739. bid: this.bId,
  740. cols: cols,
  741. }),
  742. headers: {
  743. 'Content-Type': 'application/json'
  744. }
  745. }).then(res => {
  746. return res.json()
  747. }).then(result => {
  748. let { data, code, msg } = result
  749. if (data) {
  750. this.verificationCode = data.client.verificationCode
  751. if (data.client.state === 2) {
  752. // 已提交表单
  753. this.step = 3
  754. if (data.client.formData) {
  755. let arr = JSON.parse(data.client.formData)
  756. const filteredItems = arr.filter(item => item.name.includes("门店"))
  757. if (filteredItems.length) {
  758. const names = filteredItems.map(item => item.value[0])
  759. this.storeName = names[0]
  760. }
  761. }
  762. } else if (data.client.state === 3) {
  763. // 已核销
  764. this.step = 4
  765. } else if (data.client.state === -1) {
  766. // 不符合资格
  767. this.step = 5
  768. }
  769. } else {
  770. this.$message({
  771. message: msg,
  772. type: 'warning'
  773. })
  774. }
  775. }).finally(() => {
  776. this.loading = false
  777. })
  778. }
  779. },
  780. // 检查字符串中是否包含所有指定的中文字符
  781. containsAllChineseCharacters (str, chineseChars) {
  782. // 将要检查的字符拆分为数组
  783. const charsArray = chineseChars.split('')
  784. // 遍历每个字符并检查是否存在
  785. for (const char of charsArray) {
  786. if (!str.includes(char)) {
  787. return false
  788. }
  789. }
  790. return true
  791. },
  792. // 检测是否iOS端
  793. iosAgent () {
  794. return navigator.userAgent.match(/(iPhone|iPod|iPad);?/i);
  795. },
  796. // 复制文本函数,微信端,需要在用户触发 Click 事件里面才能执行成功
  797. handleCopy (message) {
  798. if (this.iosAgent()) {
  799. let inputObj = document.createElement("input");
  800. inputObj.value = message;
  801. document.body.appendChild(inputObj);
  802. inputObj.select();
  803. inputObj.setSelectionRange(0, inputObj.value.length);
  804. this.execCommand('Copy');
  805. document.body.removeChild(inputObj);
  806. } else {
  807. let domObj = document.createElement("span");
  808. domObj.innerHTML = message;
  809. document.body.appendChild(domObj);
  810. let selection = window.getSelection();
  811. let range = document.createRange();
  812. range.selectNodeContents(domObj);
  813. selection.removeAllRanges();
  814. selection.addRange(range);
  815. this.execCommand('Copy');
  816. document.body.removeChild(domObj);
  817. }
  818. },
  819. // 执行浏览器命令 Copy 顺便输出一下日志,如果在移动端推荐写个方法展示日志或者用alert(msg)也行。
  820. execCommand (action) {
  821. let is = document.execCommand(action);
  822. if (is) {
  823. this.$message({
  824. message: '复制成功',
  825. type: 'success'
  826. })
  827. } else {
  828. this.$message({
  829. message: '复制失败',
  830. type: 'error'
  831. })
  832. }
  833. },
  834. // 截取url中的数据
  835. getQueryParam (paramName) {
  836. // 获取当前URL的查询字符串部分
  837. const queryString = window.location.search;
  838. // 创建一个URLSearchParams对象
  839. const urlParams = new URLSearchParams(queryString);
  840. // 返回指定参数的值,如果不存在则返回null
  841. return urlParams.get(paramName);
  842. },
  843. // 判断当前是否为微信浏览器
  844. isWeChatBrowser() {
  845. const ua = navigator.userAgent.toLowerCase();
  846. return ua.includes('micromessenger');
  847. },
  848. }
  849. })
  850. </script>
  851. </html>