signUp.html 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556
  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.0, maximum-scale=1.0, user-scalable=no">
  7. <title>活动</title>
  8. <!--引入 element-ui 的样式,-->
  9. <link rel="stylesheet"
  10. href="https://wl-1306604067.cos.ap-guangzhou.myqcloud.com/production/ct/103548289110001/1742018383195/element-ui.css">
  11. <!-- 必须先引入vue, 后使用element-ui -->
  12. <script
  13. src="https://wl-1306604067.cos.ap-guangzhou.myqcloud.com/production/ct/103548289110001/1742017957144/vue.js"></script>
  14. <!-- 引入element 的组件库-->
  15. <script
  16. src="https://wl-1306604067.cos.ap-guangzhou.myqcloud.com/production/ct/103548289110001/1742017747738/element-ui.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: 100%;
  30. box-sizing: border-box;
  31. background: #FAFAFA;
  32. }
  33. .page6 {
  34. width: 100vw;
  35. height: 100%;
  36. background: url('./img/signup_bg.png') no-repeat top;
  37. background-size: 100vw 210px;
  38. background-repeat: no-repeat;
  39. display: flex;
  40. justify-content: center;
  41. align-items: center;
  42. position: relative;
  43. }
  44. .page_title {
  45. font-weight: 800;
  46. font-size: 40px;
  47. color: #FFFFFF;
  48. position: fixed;
  49. top: 40px;
  50. left: 20px;
  51. }
  52. .form_content {
  53. width: 100%;
  54. height: calc(100vh - 180px);
  55. position: fixed;
  56. top: 180px;
  57. background: #FFFFFF;
  58. border-radius: 20px 20px 0px 0px;
  59. padding: 20px 20px 66px;
  60. overflow-y: auto;
  61. box-sizing: border-box;
  62. }
  63. .foot_btn {
  64. position: absolute;
  65. bottom: 14px;
  66. padding: 0 35px;
  67. width: 100%;
  68. box-sizing: border-box;
  69. }
  70. .signUp_btn {
  71. height: 52px;
  72. width: 100%;
  73. background: #1677FF;
  74. border-radius: 20px;
  75. font-weight: 500;
  76. font-size: 16px;
  77. color: #FFFFFF;
  78. text-align: center;
  79. }
  80. .el-form-item__label {
  81. padding-right: 0;
  82. font-weight: 500;
  83. font-size: 14px;
  84. color: #666666;
  85. }
  86. .el-input__inner {
  87. border: none;
  88. font-weight: 500;
  89. font-size: 14px;
  90. color: #222222;
  91. text-align: right;
  92. }
  93. .el-form-item {
  94. margin-bottom: 0;
  95. border-bottom: 1px solid #F9F9F9;
  96. padding: 10px 0;
  97. }
  98. .el-form-item__content .el-select {
  99. margin-left: 55px;
  100. }
  101. .el-form-item__content .el-cascader {
  102. margin-left: 55px;
  103. }
  104. .el-select-dropdown__item {
  105. white-space: normal;
  106. overflow: unset;
  107. height: auto;
  108. }
  109. .page6s {
  110. width: 100vw;
  111. height: 100vh;
  112. background: url('./img/signup_success.png') no-repeat center;
  113. background-size: 100vw 100vh;
  114. background-repeat: no-repeat;
  115. }
  116. .succ_tip {
  117. padding-top: 240px;
  118. font-weight: bold;
  119. font-size: 24px;
  120. color: #222222;
  121. line-height: 40px;
  122. text-align: center;
  123. width: 100%;
  124. word-break: keep-all;
  125. }
  126. .signup_page {
  127. width: 100vw;
  128. height: 100vh;
  129. background: url('./img/sign_up.png') no-repeat center;
  130. background-size: 100vw 100vh;
  131. background-repeat: no-repeat;
  132. }
  133. .signup_title {
  134. font-weight: bold;
  135. font-size: 24px;
  136. color: #FFFFFF;
  137. padding-top: 80px;
  138. text-align: center;
  139. line-height: 41px;
  140. }
  141. .fail_box {
  142. margin: 80px 20px 0;
  143. height: 287px;
  144. background: linear-gradient(#D5E6FF 50%, #FFFFFF 100%);
  145. border-radius: 20px;
  146. box-sizing: border-box;
  147. text-align: center;
  148. }
  149. .fail_img {
  150. width: 246px;
  151. height: 144px;
  152. margin-top: -20px;
  153. }
  154. .fail_title {
  155. font-weight: 500;
  156. font-size: 20px;
  157. color: #222222;
  158. line-height: 30px;
  159. padding: 20px 0;
  160. }
  161. .fail_tip {
  162. font-weight: 400;
  163. font-size: 16px;
  164. color: #666666;
  165. line-height: 30px;
  166. }
  167. </style>
  168. <body>
  169. <div id="box" class="box">
  170. <div class="page6" v-if="step === 1">
  171. <div class="page_title">核销领取礼品</div>
  172. <div class="form_content">
  173. <el-form ref="form" label-position="left" label-width="120px">
  174. <el-form-item label="核销码" required>
  175. <el-input v-model="verificationCode" placeholder="请输入"></el-input>
  176. </el-form-item>
  177. <el-form-item v-for="(item, index) in toshopData.formProList" :key="index" :label="item.name"
  178. :required="Boolean(item.isNeed)">
  179. <el-cascader v-if="item.type === 10" v-model="item.value" :options="transformedData"
  180. @change="handleInfoCity">
  181. </el-cascader>
  182. <el-select v-if="item.type === 11" v-model="item.value" placeholder="请选择" @change="handlechange">
  183. <el-option v-for="(sto, sindex) in storeList" :key="sindex" :label="sto.name" :value="sto.name">
  184. </el-option>
  185. </el-select>
  186. <el-input v-if="item.type === 0" v-model="item.value" placeholder="请输入"></el-input>
  187. <el-input v-if="item.type === 1" type="textarea" autosize v-model="item.value" placeholder="请输入"></el-input>
  188. <el-input v-if="item.type === 2" type="number" v-model="item.value" placeholder="请输入"></el-input>
  189. <el-select v-if="item.type === 3" v-model="item.value" placeholder="请选择">
  190. <el-option v-for="sto in item.formProTagReqs" :key="sto.proValue" :label="sto.proValue"
  191. :value="sto.proValue">
  192. </el-option>
  193. </el-select>
  194. <el-col :span="22" v-if="item.type === 5">
  195. <el-date-picker v-model="item.value" type="date" placeholder="选择日期" style="width: 100%;">
  196. </el-col>
  197. <el-col :span="22" v-if="item.type === 6">
  198. <el-time-picker v-model="item.value" placeholder="请选择"></el-time-picker>
  199. </el-col>
  200. <el-col :span="22" v-if="item.type === 7">
  201. <el-date-picker v-if="item.type === 7" v-model="item.value" type="datetime"
  202. placeholder="选择日期时间"></el-date-picker>
  203. </el-col>
  204. </el-form-item>
  205. </el-form>
  206. </div>
  207. <div class="foot_btn">
  208. <el-button class="signUp_btn" :loading="loading" @click="toSignUp">核销</el-button>
  209. </div>
  210. </div>
  211. <div class="page6s" v-else-if="step === 2">
  212. <div class="succ_tip">
  213. {{toshopData.verificationGuide}}
  214. </div>
  215. </div>
  216. <div class="signup_page" v-else-if="step === 3">
  217. <div class="signup_title">{{toshopData.name}}</div>
  218. <div class="fail_box">
  219. <img class="fail_img" src="./img/fail_img.png" />
  220. <div class="fail_title">{{toshopData.verificationFailGuide}}</div>
  221. <div class="fail_tip">{{toshopData.verificationFailGuide2}}</div>
  222. </div>
  223. </div>
  224. </div>
  225. </body>
  226. <script>
  227. new Vue({
  228. el: '#box',
  229. data () {
  230. return {
  231. httpUrl: '',
  232. bId: null,
  233. env: '',
  234. toshopData: {
  235. id: null,
  236. name: '',
  237. verificationGuide: '',
  238. verificationFailGuide: '',
  239. verificationFailGuide2: '',
  240. formProList: [],
  241. },
  242. step: 1,
  243. verificationCode: '',
  244. transformedData: [],
  245. storeList: [],
  246. province: '',
  247. city: '',
  248. loading: false,
  249. }
  250. },
  251. created () {
  252. var hrt = document.documentElement.clientHeight; //获取当前可视区域的高度存到hrt变量
  253. document.getElementById('box').style.height = hrt + 'px'//把获取到的高度赋值给根div
  254. this.bId = this.getQueryParam('bId')
  255. this.env = this.getQueryParam('env')
  256. if (!this.env || this.env === 'prod') {
  257. this.httpUrl = 'https://wlapi.wefanbot.com'
  258. } else {
  259. this.httpUrl = 'https://test.wefanbot.com:28993'
  260. }
  261. localStorage.removeItem('openId')
  262. this.ifH5Type()
  263. },
  264. methods: {
  265. ifH5Type () {
  266. if (this.getQueryParam('openId') || localStorage.getItem('openId')) {
  267. if (!this.getQueryParam('externalUserid')) {
  268. this.gerQwAuth(this.bId);
  269. } else {
  270. this.lightenShare()
  271. }
  272. } else {
  273. // 走授权操作
  274. this.getAuth();
  275. }
  276. },
  277. getAuth () {
  278. // 获取url上的code
  279. let code = this.getQueryParam('code')
  280. if (code) {
  281. // 判断业务id是否生产环境业务id
  282. fetch(this.httpUrl + `/p/insuite/p/isProdId?id=${this.bId}`)
  283. .then(res => {
  284. return res.json()
  285. }).then(result => {
  286. let { data, msg } = result
  287. if (typeof data === 'boolean' && data) {
  288. this.httpUrl = 'https://wlapi.wefanbot.com'
  289. } else {
  290. this.httpUrl = 'http://test.wefanbot.com:18993'
  291. }
  292. this.getInfoByh5Code(this.getQueryParam('code'))
  293. })
  294. } else {
  295. let redirect_uri = window.location.href
  296. // code 不存在,走微信网页授权逻辑
  297. let url = `https://open.weixin.qq.com/connect/oauth2/authorize?appId=wx99ec0d0828a4d2d3&redirect_uri=${redirect_uri}&scope=snsapi_userinfo&state=STATE#wechat_redirect`
  298. window.location.replace(url)
  299. }
  300. },
  301. getInfoByh5Code (code) {
  302. fetch(this.httpUrl + `/scrm/v1/mp-client/p/getInfoByh5Code?code=${code}&bId=${this.bId}`)
  303. .then(res => {
  304. return res.json()
  305. }).then(result => {
  306. let { data, code, msg } = result
  307. if (code === 1) {
  308. localStorage.setItem('openId', data.openId)
  309. this.ifH5Type()
  310. }
  311. })
  312. },
  313. // 企微授权
  314. gerQwAuth (bId) {
  315. let openId = this.getQueryParam('openId') || localStorage.getItem('openId')
  316. fetch(this.httpUrl + `/p/insuite/p/getOAUrl?openId=${openId}&bId=${bId}`)
  317. .then(res => {
  318. return res.json()
  319. }).then(result => {
  320. let { data, code, msg } = result
  321. if (code === 1) {
  322. window.location.replace(data)
  323. } else {
  324. this.$message({
  325. message: msg,
  326. type: 'warning'
  327. })
  328. }
  329. })
  330. },
  331. // 获取城市数据
  332. getCityLevel () {
  333. let url = ''
  334. if (this.toshopData.id == 115399319210021) {
  335. url = 'https://wl-1306604067.cos.ap-guangzhou.myqcloud.com/production/ct/103548289110001/1744104152989/five-province.json'
  336. } else {
  337. url = 'https://wl-1306604067.cos.ap-guangzhou.myqcloud.com/production/ct/103548289110001/1742009720857/four-province.json'
  338. }
  339. fetch(url)
  340. .then(res => {
  341. return res.json()
  342. }).then(result => {
  343. this.transformedData = this.transformData(result)
  344. })
  345. },
  346. // 省市数据做转换
  347. transformData (data) {
  348. return data.map(item => {
  349. // 创建一个新对象,避免直接修改原始对象
  350. const newItem = { ...item };
  351. // 重命名 text 为 label
  352. if (newItem.text) {
  353. newItem.label = newItem.text;
  354. newItem.value = newItem.text;
  355. delete newItem.text;
  356. }
  357. // 如果存在 children 数组,则递归处理每个子项
  358. if (newItem.children && Array.isArray(newItem.children)) {
  359. newItem.children = this.transformData(newItem.children);
  360. }
  361. return newItem;
  362. })
  363. },
  364. handleInfoCity (value) {
  365. this.province = value[0]
  366. this.city = value[1]
  367. // 清空经销商类型的数据
  368. this.toshopData.formProList.forEach(item => {
  369. if (item.type === 11) {
  370. item.value = ''
  371. }
  372. })
  373. this.storeList = []
  374. this.getStoreList()
  375. },
  376. handlechange (value) {
  377. this.toshopData.formProList.forEach(item => {
  378. if (item.type === 11) {
  379. item.value = value
  380. }
  381. })
  382. this.$forceUpdate()
  383. },
  384. getStoreList () {
  385. fetch(this.httpUrl + `/scrm/v1/wxcp-toshop-store/p/findListByPage?city=${this.city}&province=${this.province}`, {
  386. method: 'post',
  387. body: JSON.stringify({
  388. page: 1,
  389. pageCount: 10000,
  390. }),
  391. headers: {
  392. 'Content-Type': 'application/json'
  393. }
  394. }).then(res => {
  395. return res.json()
  396. }).then(result => {
  397. let { data, code, msg } = result
  398. if (code === 1) {
  399. this.storeList = data.records
  400. } else {
  401. this.$message({
  402. message: msg,
  403. type: 'warning'
  404. })
  405. }
  406. })
  407. },
  408. lightenShare () {
  409. let externalUserid = this.getQueryParam('externalUserid')
  410. let openId = this.getQueryParam('openId') || localStorage.getItem('openId')
  411. const headers = new Headers();
  412. headers.append('police', 110);
  413. fetch(this.httpUrl + `/scrm/v1/wxcp-toshop-verification/p/lottery?externalUserid=${externalUserid}&openId=${openId}&bId=${this.bId}`, {
  414. method: 'GET',
  415. headers: headers
  416. })
  417. .then(res => {
  418. return res.json()
  419. }).then(result => {
  420. let { data, code, msg } = result
  421. if (code === 1) {
  422. this.toshopData = data
  423. this.getCityLevel()
  424. } else {
  425. this.$message({
  426. message: msg,
  427. })
  428. }
  429. })
  430. },
  431. toSignUp () {
  432. if (!this.verificationCode) {
  433. this.$message({
  434. message: '核销码不能为空',
  435. type: 'warning'
  436. })
  437. return
  438. }
  439. const isValid = this.toshopData.formProList.some(item => {
  440. if (item.isNeed && !item.value) {
  441. this.$message({
  442. message: '必填项不能为空',
  443. type: 'warning'
  444. })
  445. return true
  446. }
  447. if (this.containsAllChineseCharacters(item.name, '手机') && item.value.length !== 11) {
  448. this.$message({
  449. message: '请输入正确的手机号',
  450. type: 'warning'
  451. })
  452. return true
  453. }
  454. return false
  455. })
  456. if (isValid) return
  457. let cols = []
  458. cols = this.toshopData.formProList.map(item => {
  459. return {
  460. name: item.name,
  461. type: item.type,
  462. value: item.type === 10 ? [item.value.join('')] : [item.value],
  463. }
  464. })
  465. let openId = this.getQueryParam('openId') || localStorage.getItem('openId')
  466. this.loading = true
  467. fetch(this.httpUrl + `/scrm/v1/wxcp-toshop-verification/p/formData?openId=${openId}`, {
  468. method: 'post',
  469. body: JSON.stringify({
  470. bid: this.bId,
  471. cols: cols,
  472. verificationCode: this.verificationCode
  473. }),
  474. headers: {
  475. 'Content-Type': 'application/json'
  476. }
  477. }).then(res => {
  478. return res.json()
  479. }).then(result => {
  480. let { data, code, msg } = result
  481. if (code === 1) {
  482. if (data.client.state === 3) {
  483. // 已核销(已提交核销表单)
  484. this.step = 2
  485. } else if (data.client.state === -1) {
  486. // 不符合资格
  487. this.step = 3
  488. }
  489. } else if (code === 2) {
  490. this.$message({
  491. message: '核销码无效',
  492. type: 'warning'
  493. })
  494. } else if (code === 3) {
  495. this.$message({
  496. message: msg,
  497. type: 'warning'
  498. })
  499. } else {
  500. this.$message({
  501. message: msg,
  502. type: 'warning'
  503. })
  504. }
  505. }).finally(() => {
  506. this.loading = false
  507. })
  508. },
  509. // 检查字符串中是否包含所有指定的中文字符
  510. containsAllChineseCharacters (str, chineseChars) {
  511. // 将要检查的字符拆分为数组
  512. const charsArray = chineseChars.split('')
  513. // 遍历每个字符并检查是否存在
  514. for (const char of charsArray) {
  515. if (!str.includes(char)) {
  516. return false
  517. }
  518. }
  519. return true
  520. },
  521. // 截取url中的数据
  522. getQueryParam (paramName) {
  523. // 获取当前URL的查询字符串部分
  524. const queryString = window.location.search;
  525. // 创建一个URLSearchParams对象
  526. const urlParams = new URLSearchParams(queryString);
  527. // 返回指定参数的值,如果不存在则返回null
  528. return urlParams.get(paramName);
  529. },
  530. }
  531. })
  532. </script>
  533. </html>