Reg.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730
  1. <template>
  2. <div class="inner_box">
  3. <div id="udb_reg_phone_password">
  4. <div class="udb_phone_code_box">
  5. <div class="title">
  6. 注册
  7. <Back />
  8. </div>
  9. <div class="reg_input_box">
  10. <!-- 账密输入 -->
  11. <div class="phone_code">
  12. <div class="phone_code_input">
  13. <!-- 账号名 -->
  14. <div class="phone_code_tel" @keyup.enter="checkPassport">
  15. <i class="red">*</i>
  16. <div
  17. v-if="canPassport"
  18. class="bind_send"
  19. @click="checkPassport"
  20. >
  21. 验证账号
  22. </div>
  23. <div v-else class="bind_send gray">验证中</div>
  24. <input
  25. class="phone_code_input_captcha"
  26. placeholder="请输入账号名"
  27. v-model="passport"
  28. type="text"
  29. compositionstart="compositionstartInput"
  30. @input="passportKeyup"
  31. />
  32. </div>
  33. <!-- 手机号 -->
  34. <!-- <div class="phone_code_tel">
  35. <i class="red">*</i>
  36. <input
  37. class="phone_code_input_username"
  38. type="tel"
  39. maxlength="11"
  40. placeholder="请输入手机号"
  41. oninput="value=value.replace(/[^\d]/g,'')"
  42. v-model="phoneNumber"
  43. />
  44. </div> -->
  45. <!-- 验证码 -->
  46. <!-- <div class="phone_code_captcha">
  47. <i class="red">*</i>
  48. <div
  49. class="bind_send"
  50. :class="{ gray: canVerif }"
  51. @click="sendPhoneNumber"
  52. >
  53. {{ verifText }}
  54. </div>
  55. <input
  56. class="phone_code_input_captcha"
  57. placeholder="请输入验证码"
  58. v-model="captcha"
  59. maxlength="4"
  60. />
  61. </div> -->
  62. <!-- 密码 -->
  63. <div class="reg_password">
  64. <i class="red">*</i>
  65. <input
  66. class="reg_input_password"
  67. type="password"
  68. placeholder="请输入密码"
  69. password="true"
  70. maxlength="20"
  71. oninput="value=value.replace(/[\u4E00-\u9FA5]|[\uFE30-\uFFA0]|\s+|[^\w\u4e00-\u9fa5\/\-]|[/|]/ig,'');"
  72. v-model="password"
  73. />
  74. </div>
  75. <!-- 确认密码 -->
  76. <div class="reg_password2">
  77. <i class="red">*</i>
  78. <input
  79. class="reg_input_password2"
  80. type="password"
  81. placeholder="请再次输入密码"
  82. password="true"
  83. maxlength="20"
  84. oninput="value=value.replace(/[\u4E00-\u9FA5]|[\uFE30-\uFFA0]|\s+|[^\w\u4e00-\u9fa5\/\-]|[/|]/ig,'');"
  85. v-model="passwordAgin"
  86. />
  87. </div>
  88. </div>
  89. </div>
  90. <!-- 阅读协议 -->
  91. <!-- <div class="reg_phone_protocol">
  92. <input
  93. class="reg_phone_protocol_checkbox"
  94. type="checkbox"
  95. id="is_phone_read"
  96. checked
  97. v-model="ischeckRegPhone"
  98. />
  99. <label
  100. for="is_phone_read"
  101. :class="{ red: !ischeckRegPhone }"
  102. class="reg_phone_protocol_text"
  103. >
  104. 阅读并同意
  105. </label>
  106. <span @click="onAgreement" class="agreement">用户协议</span>
  107. </div> -->
  108. <div v-if="canReg" class="bind_phone_true" @click="bindTrue">
  109. 注册
  110. </div>
  111. <div v-else class="bind_phone_true gray">注册中</div>
  112. <!-- 底部跳其他页面 -->
  113. <div class="other" @click="onLogin">返回登录</div>
  114. </div>
  115. </div>
  116. </div>
  117. </div>
  118. </template>
  119. <script>
  120. import { mapState } from "vuex";
  121. import Back from "@/components/Inner/Back"; // 返回按钮
  122. export default {
  123. name: "RegPhonePwd",
  124. components: {
  125. Back,
  126. },
  127. inject: ["checkCode", "routeLink"],
  128. data() {
  129. return {
  130. passport: "", // 账号名
  131. phoneNumber: "", // 手机号
  132. captcha: "", // 验证码
  133. password: "", // 密码
  134. passwordAgin: "", // 确认密码
  135. ischeckRegPhone: true, // 阅读并同意
  136. verifText: "获取验证码", // 获取验证码按钮文本
  137. canVerif: false, // 获取验证码按钮是否可以点击
  138. countDownTimer: null, // 验证码倒计时
  139. canSms: true, // 是否可以请求验证码接口
  140. canReg: true, // 是否可以注册
  141. canPassport: true, // 是否可以验证
  142. accountList: [], // 账密列表
  143. accountLocal: [], // 本地存储的账密
  144. checkPassportInput: false, // 是否校验过账号
  145. };
  146. },
  147. computed: {
  148. ...mapState(["query"]),
  149. },
  150. watch: {},
  151. created() {},
  152. mounted() {
  153. // 初始化操作
  154. this.init();
  155. },
  156. destroyed() {
  157. clearInterval(this.countDownTimer);
  158. },
  159. methods: {
  160. // ios中文输入
  161. compositionstartInput() {
  162. this.passport = "";
  163. },
  164. // 账号 输入
  165. passportKeyup() {
  166. this.passport = this.passport.replace(
  167. /[\u4E00-\u9FA5]|[\uFE30-\uFFA0]|\s+|[^\w\u4e00-\u9fa5\/\-]|[/|]/gi,
  168. ""
  169. );
  170. this.checkPassportInput = false;
  171. },
  172. // 初始化操作
  173. init() {
  174. // 初始化账密列表内容
  175. this.initAccountList();
  176. },
  177. // 验证账号
  178. checkPassport() {
  179. const { passport } = this;
  180. const regpassport = /^[a-zA-Z][a-zA-Z0-9_]{3,31}$/.test(passport);
  181. if (!regpassport) {
  182. this.$toast.text("账号需用字母开头, 且长度大于4位");
  183. return;
  184. }
  185. if (passport == "admin" || passport == "root") {
  186. this.$toast.text("此账号已被注册");
  187. return;
  188. }
  189. this.passportExists();
  190. },
  191. // 验证账号
  192. passportExists() {
  193. if (!this.canPassport) {
  194. return;
  195. }
  196. this.canPassport = false;
  197. const { passport } = this;
  198. this.$api
  199. .passportExists({
  200. passport,
  201. })
  202. .then((res) => {
  203. this.checkCode(res);
  204. this.canPassport = true;
  205. const { code, data, msg } = res.data;
  206. // 错误
  207. if (code) {
  208. return;
  209. }
  210. if (data) {
  211. this.$toast.text("此账号已被注册");
  212. return;
  213. }
  214. this.checkPassportInput = true;
  215. this.$toast.text("此账号可用");
  216. });
  217. },
  218. // 获取验证码
  219. sendPhoneNumber() {
  220. if (!this.canSms) {
  221. return;
  222. }
  223. const { phoneNumber } = this;
  224. // 1. 验证手机号格式
  225. this.canVerif = this.$utils.checkVerification(phoneNumber);
  226. if (!this.canVerif) {
  227. this.$toast.text("手机号格式不正确");
  228. return;
  229. }
  230. // 3. 请求接口 发送验证码
  231. this.$api
  232. .sendSms({
  233. mobile: phoneNumber,
  234. reason: "regist",
  235. })
  236. .then((res) => {
  237. this.checkCode(res);
  238. const { code, data, msg } = res.data;
  239. // 错误
  240. if (code) {
  241. this.canVerif = false;
  242. return;
  243. }
  244. // 2. 验证码倒计时
  245. this.countDown();
  246. });
  247. },
  248. // 用户协议
  249. onAgreement() {},
  250. // 倒计时
  251. countDown() {
  252. this.canSms = false;
  253. let count = 60;
  254. this.verifText = count + "s";
  255. this.countDownTimer = setInterval(() => {
  256. count--;
  257. this.verifText = count + "s";
  258. // 倒计时结束
  259. if (count === 0) {
  260. this.canVerif = false;
  261. this.verifText = "获取验证码";
  262. this.canSms = true;
  263. clearInterval(this.countDownTimer);
  264. }
  265. }, 1000);
  266. },
  267. // 注册
  268. bindTrue() {
  269. const {
  270. phoneNumber,
  271. captcha,
  272. password,
  273. passwordAgin,
  274. ischeckRegPhone,
  275. passport,
  276. checkPassportInput,
  277. } = this;
  278. // 0. 校验账号是否为空
  279. if (!passport) {
  280. this.$toast.text("账号不能为空");
  281. return;
  282. }
  283. // 是否验证过账号
  284. if (!checkPassportInput) {
  285. this.$toast.text("请先验证账号是否可用");
  286. return;
  287. }
  288. // 1. 验证手机号格式
  289. // const telCheck = this.$utils.checkVerification(phoneNumber);
  290. // if (!telCheck) {
  291. // this.$toast.text("手机号格式不准确");
  292. // return;
  293. // }
  294. // 2. 验证验证码是否为空
  295. // if (!captcha) {
  296. // this.$toast.text("验证码不能为空");
  297. // return;
  298. // }
  299. // 3. 验证密码
  300. if (!password) {
  301. this.$toast.text("密码不能为空");
  302. return;
  303. }
  304. if (password !== passwordAgin) {
  305. this.$toast.text("两次密码不一致");
  306. return;
  307. }
  308. // 4. 阅读协议
  309. if (!ischeckRegPhone) {
  310. this.$toast.text("请阅读与同意协议");
  311. return;
  312. }
  313. // 5. 校验账号
  314. const regpassport = /^[a-zA-Z][a-zA-Z0-9_]{3,31}$/.test(passport);
  315. if (!regpassport) {
  316. this.$toast.text("账号需用字母开头, 且长度大于4位");
  317. return;
  318. }
  319. if (passport == "admin" || passport == "root") {
  320. this.$toast.text("此账号已被注册");
  321. return;
  322. }
  323. // 是否验证过账号
  324. if (!checkPassportInput) {
  325. this.passportExists().then(() => {
  326. if (this.checkPassportInput) {
  327. this.onRegister();
  328. }
  329. });
  330. return;
  331. }
  332. // 6. 注册
  333. this.onRegister();
  334. },
  335. // 返回登录
  336. onLogin() {
  337. this.routeLink("Login");
  338. },
  339. // 注册接口
  340. onRegister() {
  341. if (!this.canReg) {
  342. return;
  343. }
  344. this.canReg = false;
  345. const { phoneNumber, captcha, password, passport } = this;
  346. const promoCode = this.$utils.getQueryString("promoCode");
  347. const { appid } = this.$CONFIG;
  348. const registObj = {
  349. passport,
  350. // mobile: phoneNumber,
  351. // smsCode: captcha,
  352. password,
  353. promoCode,
  354. appId: appid,
  355. };
  356. this.$api.regist(registObj).then((res) => {
  357. this.checkCode(res);
  358. this.canReg = true;
  359. const { code, msg } = res.data;
  360. // 错误
  361. if (code) {
  362. return;
  363. }
  364. this.$toast.text(msg);
  365. // 记住密码
  366. this.rememberFun(passport, password);
  367. // 成功 去登录
  368. this.onLogin();
  369. });
  370. },
  371. // 初始化账密列表
  372. initAccountList() {
  373. // const accountLocal = JSON.parse(localStorage.getItem("jhremember"));
  374. let accountLocal = this.$utils.readStorage("", "jhremember");
  375. accountLocal = accountLocal && JSON.parse(accountLocal);
  376. accountLocal &&
  377. accountLocal.length &&
  378. accountLocal.map((ele) => {
  379. const _account = ele.split("&&")[0];
  380. const _pwd = ele.split("&&")[1];
  381. const account = this.$utils.decrypt(_account);
  382. const pwd = this.$utils.decrypt(_pwd);
  383. this.accountList.push({
  384. account,
  385. pwd,
  386. });
  387. });
  388. },
  389. // 记住密码
  390. rememberFun(account, password) {
  391. this.$utils.rememberFun(account, password);
  392. },
  393. },
  394. };
  395. </script>
  396. <style lang="less">
  397. #udb_reg_phone_password {
  398. input {
  399. outline: none;
  400. }
  401. .udb_phone_code_box {
  402. width: 700 / @rem;
  403. height: 550 / @rem;
  404. position: absolute;
  405. top: 50%;
  406. left: 50%;
  407. margin-left: -350 / @rem;
  408. margin-top: -275 / @rem;
  409. font-size: 32 / @rem;
  410. background-color: #fff;
  411. box-sizing: border-box;
  412. border-radius: 5px;
  413. overflow: hidden;
  414. .title {
  415. height: 100 / @rem;
  416. line-height: 100 / @rem;
  417. background-color: #3faeed;
  418. color: #fff;
  419. font-size: 36 / @rem;
  420. }
  421. .reg_input_box {
  422. padding: 0 / @rem 30 / @rem;
  423. .other {
  424. margin-top: 20 / @rem;
  425. float: left;
  426. color: #3faeed;
  427. font-size: 28 / @rem;
  428. }
  429. }
  430. .reg_phone_protocol_text {
  431. display: inline-block;
  432. }
  433. .red {
  434. line-height: 70 / @rem;
  435. color: #e43633;
  436. float: left;
  437. }
  438. .agreement {
  439. color: #e65c1c;
  440. border-bottom: 1 / @rem solid #e65c1c;
  441. margin-left: -2 / @rem;
  442. }
  443. .reg_phone_protocol {
  444. font-size: 32 / @rem;
  445. margin-top: 20 / @rem;
  446. }
  447. .reg_phone_protocol_checkbox {
  448. vertical-align: middle;
  449. -webkit-appearance: checkbox;
  450. }
  451. .phone_code_input {
  452. width: 100%;
  453. margin-top: 25 / @rem;
  454. }
  455. .phone_code_tel,
  456. .phone_code_captcha {
  457. width: 100%;
  458. height: 70 / @rem;
  459. position: relative;
  460. margin-top: 20 / @rem;
  461. }
  462. .phone_code_tel {
  463. margin-top: 20 / @rem;
  464. }
  465. .icon-shouji1,
  466. .icon-mima {
  467. width: 50 / @rem;
  468. height: 70 / @rem;
  469. line-height: 70 / @rem;
  470. position: absolute;
  471. left: 0;
  472. z-index: 5;
  473. }
  474. .phone_code_input_username,
  475. .phone_code_input_captcha {
  476. width: 94.5%;
  477. height: 75 / @rem;
  478. padding-left: 20 / @rem;
  479. float: right;
  480. font-size: 32 / @rem;
  481. border: 1 / @rem solid #d6d6d6;
  482. box-sizing: border-box;
  483. }
  484. .phone_code_input_captcha {
  485. width: 60%;
  486. margin-right: 30 / @rem;
  487. }
  488. input::-webkit-input-placeholder {
  489. color: #888;
  490. }
  491. .phone_code_protocol {
  492. width: 100%;
  493. font-size: 32 / @rem;
  494. margin: auto;
  495. margin-top: 50 / @rem;
  496. height: 40 / @rem;
  497. line-height: 40 / @rem;
  498. }
  499. .phone_code_protocol_checkbox {
  500. position: relative;
  501. top: 2 / @rem;
  502. }
  503. .phone_code_protocol_text {
  504. display: inline-block;
  505. }
  506. .phone_code_check,
  507. .bind_captcha_check {
  508. font-size: 32 / @rem;
  509. color: #e43633;
  510. position: absolute;
  511. }
  512. .bind_send {
  513. width: 30%;
  514. height: 75 / @rem;
  515. line-height: 70 / @rem;
  516. float: right;
  517. color: #ffffff;
  518. font-size: 32 / @rem;
  519. border-radius: 10 / @rem;
  520. background-color: #3faeed;
  521. }
  522. .bind_phone_true {
  523. width: 80%;
  524. height: 90 / @rem;
  525. line-height: 90 / @rem;
  526. margin: 20 / @rem auto 0;
  527. border-radius: 15 / @rem;
  528. background-color: #3faeed;
  529. color: #ffffff;
  530. box-sizing: border-box;
  531. font-size: 32 / @rem;
  532. }
  533. .gray {
  534. background-color: #888;
  535. }
  536. .reg_password,
  537. .reg_password2 {
  538. width: 100%;
  539. height: 70 / @rem;
  540. margin-top: 20 / @rem;
  541. position: relative;
  542. }
  543. .reg_input_password {
  544. width: 94.5%;
  545. height: 70 / @rem;
  546. padding-left: 20 / @rem;
  547. float: right;
  548. font-size: 32 / @rem;
  549. box-sizing: border-box;
  550. border: 1 / @rem solid #d6d6d6;
  551. }
  552. .reg_input_password2 {
  553. width: 94.5%;
  554. height: 70 / @rem;
  555. padding-left: 20 / @rem;
  556. float: right;
  557. z-index: 4;
  558. font-size: 32 / @rem;
  559. box-sizing: border-box;
  560. border: 1 / @rem solid #d6d6d6;
  561. outline: none;
  562. }
  563. .icon-mima {
  564. position: absolute;
  565. left: 0;
  566. width: 50 / @rem;
  567. z-index: 5;
  568. height: 70 / @rem;
  569. line-height: 70 / @rem;
  570. }
  571. .login_password_check,
  572. .login_passwordAgin_check {
  573. font-size: 32 / @rem;
  574. color: #e43633;
  575. position: absolute;
  576. }
  577. .is_hide_password,
  578. .is_hide_pwd_agin {
  579. display: none;
  580. }
  581. }
  582. }
  583. // 横屏
  584. @media screen and (orientation: landscape),
  585. /**竖屏 */ all and (orientation: portrait) and (min-width: 600px) and (min-height: 800px),
  586. /**ipad */ all and (min-device-aspect-ratio: 3/4) and (max-device-aspect-ratio: 4/3),
  587. all and (device-aspect-ratio: 4/3) {
  588. #udb_reg_phone_password {
  589. .udb_phone_code_box {
  590. width: 350 / @rem;
  591. height: 300 / @rem;
  592. margin-left: -175 / @rem;
  593. margin-top: -150 / @rem;
  594. font-size: 16 / @rem;
  595. overflow-y: auto;
  596. .title {
  597. height: 50 / @rem;
  598. line-height: 50 / @rem;
  599. font-size: 18 / @rem;
  600. }
  601. .reg_input_box {
  602. padding: 0 / @rem 15 / @rem;
  603. .other {
  604. margin-top: 5 / @rem;
  605. font-size: 14 / @rem;
  606. }
  607. }
  608. .red {
  609. line-height: 35 / @rem;
  610. }
  611. .agreement {
  612. margin-left: -1 / @rem;
  613. }
  614. .reg_phone_protocol {
  615. font-size: 16 / @rem;
  616. margin-top: 5 / @rem;
  617. }
  618. .phone_code_input {
  619. margin-top: 15 / @rem;
  620. }
  621. .phone_code_tel,
  622. .phone_code_captcha {
  623. height: 40 / @rem;
  624. margin-top: 10 / @rem;
  625. }
  626. .phone_code_tel {
  627. margin-top: 5 / @rem;
  628. }
  629. .phone_code_input_username,
  630. .phone_code_input_captcha {
  631. height: 40 / @rem;
  632. padding-left: 10 / @rem;
  633. font-size: 16 / @rem;
  634. }
  635. .phone_code_input_captcha {
  636. width: 55.15%;
  637. }
  638. .phone_code_protocol {
  639. height: 20 / @rem;
  640. line-height: 20 / @rem;
  641. margin-top: 5 / @rem;
  642. font-size: 16 / @rem;
  643. }
  644. .phone_code_protocol_checkbox {
  645. top: 1 / @rem;
  646. }
  647. .phone_code_check,
  648. .bind_captcha_check {
  649. font-size: 16 / @rem;
  650. }
  651. .bind_send {
  652. height: 40 / @rem;
  653. line-height: 40 / @rem;
  654. font-size: 16 / @rem;
  655. border-radius: 5 / @rem;
  656. }
  657. .bind_phone_true {
  658. height: 40 / @rem;
  659. line-height: 40 / @rem;
  660. margin: 15 / @rem auto 0;
  661. border-radius: 7 / @rem;
  662. font-size: 16 / @rem;
  663. }
  664. .reg_password,
  665. .reg_password2 {
  666. height: 40 / @rem;
  667. margin-top: 15 / @rem;
  668. }
  669. .reg_input_password {
  670. height: 40 / @rem;
  671. padding-left: 10 / @rem;
  672. font-size: 16 / @rem;
  673. }
  674. .reg_input_password2 {
  675. height: 40 / @rem;
  676. padding-left: 10 / @rem;
  677. font-size: 16 / @rem;
  678. }
  679. .login_password_check,
  680. .login_passwordAgin_check {
  681. font-size: 16 / @rem;
  682. }
  683. }
  684. }
  685. }
  686. // ipad 横屏
  687. @media /** 伪竖屏*/all and (orientation: portrait) and (min-width: 600px) and (min-height: 800px),
  688. /**ipad伪横屏 */ all and (orientation: landscape) and (min-width: 800px) and (min-height: 600px),
  689. all and (min-device-aspect-ratio: 3/4) and (max-device-aspect-ratio: 4/3),
  690. all and (device-aspect-ratio: 4/3) {
  691. #udb_reg_phone_password {
  692. .udb_phone_code_box {
  693. height: 300 / @rem;
  694. }
  695. }
  696. }
  697. </style>