register.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665
  1. <template>
  2. <view class="login-wrapper" :style="colorStyle">
  3. <view class="shading">
  4. <image :src="logoUrl" />
  5. </view>
  6. <view class="whiteBg">
  7. <view class="list" v-if="current !== 1">
  8. <form @submit.prevent="submit">
  9. <view class="item">
  10. <view class="acea-row row-middle">
  11. <image src="../static/phone_1.png" style="width: 24rpx; height: 34rpx;"></image>
  12. <input type="text" :placeholder="$t(`输入手机号码`)" v-model="account" maxlength="11" required />
  13. </view>
  14. </view>
  15. <view class="item">
  16. <view class="acea-row row-middle">
  17. <image src="../static/code_1.png" style="width: 28rpx; height: 32rpx;"></image>
  18. <input type="password" :placeholder="$t(`填写登录密码`)" v-model="password" required />
  19. </view>
  20. </view>
  21. </form>
  22. <!-- <navigator class="forgetPwd" hover-class="none" url="/pages/users/retrievePassword/index">
  23. <span class="iconfont icon-wenti"></span>忘记密码
  24. </navigator> -->
  25. </view>
  26. <view class="list" v-if="current !== 0 || appLoginStatus || appleLoginStatus">
  27. <view class="item">
  28. <view class="acea-row row-middle">
  29. <image src="../static/phone_1.png" style="width: 24rpx; height: 34rpx;"></image>
  30. <input type="text" :placeholder="$t(`输入手机号码`)" v-model="account" :maxlength="11" />
  31. </view>
  32. </view>
  33. <view class="item">
  34. <view class="acea-row row-middle">
  35. <image src="../static/code_2.png" style="width: 28rpx; height: 32rpx;"></image>
  36. <input type="text" :placeholder="$t(`填写邀请码`)" class="codeIput"
  37. v-model="spread" />
  38. </view>
  39. </view>
  40. <view class="item">
  41. <view class="acea-row row-middle">
  42. <image src="../static/code_2.png" style="width: 28rpx; height: 32rpx;"></image>
  43. <input type="text" :placeholder="$t(`填写验证码`)" :maxlength="6" class="codeIput"
  44. v-model="captcha" />
  45. <button class="code" :disabled="disabled" :class="disabled === true ? 'on' : ''" @click="code">
  46. {{ text }}
  47. </button>
  48. </view>
  49. </view>
  50. <view class="item" v-if="isShowCode">
  51. <view class="acea-row row-middle">
  52. <image src="../static/code_2.png" style="width: 28rpx; height: 32rpx;"></image>
  53. <input type="text" :placeholder="$t(`填写验证码`)" class="codeIput" v-model="codeVal" />
  54. <view class="code" @click="again"><img :src="codeUrl" /></view>
  55. </view>
  56. </view>
  57. </view>
  58. <view class="logon" @click="loginMobile" v-if="current !== 0">{{$t(`注册`)}}</view>
  59. <view class="logon" @click="submit" v-if="current === 0">{{$t(`登录`)}}</view>
  60. <view class="tips">
  61. <!-- <view v-if="current==0" @click="current = 1">{{$t(`快速登录`)}}</view> -->
  62. <!-- <view v-if="current==1" @click="current = 0">{{$t(`账号登录`)}}</view> -->
  63. </view>
  64. <!-- TODO -->
  65. <view class="choose">
  66. <!-- <view class="reg" @click="forget">忘记密码</view>
  67. <view class="xian">|</view> -->
  68. <view class="zhuce" @click="zhuce">账号登录</view>
  69. </view>
  70. <view class="protocol">
  71. <checkbox-group @change='ChangeIsDefault'>
  72. <checkbox :class="inAnimation?'trembling':''" @animationend='inAnimation=false'
  73. :checked="protocol ? true : false" />{{$t(`已阅读并同意`)}} <text class="main-color"
  74. @click="privacy(4)">{{$t(`《用户协议》`)}}</text>
  75. {{$t(`与`)}}<text class="main-color" @click="privacy(3)">{{$t(`《隐私协议》`)}}</text>
  76. </checkbox-group>
  77. </view>
  78. </view>
  79. <!-- <view class="bottom">
  80. <view class="ver" v-if="copyRight">{{copyRight}}</view>
  81. <view v-else class="ver">© 2014-2023
  82. <a href="https://www.crmeb.com">www.crmeb.com</a>
  83. </view>
  84. </view> -->
  85. <Verify @success="success" :captchaType="captchaType" :imgSize="{ width: '330px', height: '155px' }"
  86. ref="verify"></Verify>
  87. </view>
  88. </template>
  89. <script>
  90. import dayjs from "@/plugin/dayjs/dayjs.min.js";
  91. import sendVerifyCode from "@/mixins/SendVerifyCode";
  92. import {
  93. loginH5,
  94. loginMobile,
  95. registerVerify,
  96. register,
  97. getCodeApi,
  98. getUserInfo,
  99. appleLogin
  100. } from "@/api/user";
  101. import attrs, {
  102. required,
  103. alpha_num,
  104. chs_phone
  105. } from "@/utils/validate";
  106. import {
  107. getLogo
  108. } from "@/api/public";
  109. // import cookie from "@/utils/store/cookie";
  110. import {
  111. VUE_APP_API_URL
  112. } from "@/utils";
  113. // #ifdef APP-PLUS
  114. import {
  115. wechatAppAuth
  116. } from '@/api/api.js'
  117. // #endif
  118. const BACK_URL = "login_back_url";
  119. import colors from '@/mixins/color.js';
  120. import Verify from '../components/verify/index.vue';
  121. export default {
  122. name: "Login",
  123. components: {
  124. Verify
  125. },
  126. mixins: [sendVerifyCode, colors],
  127. data: function() {
  128. return {
  129. copyRight: '',
  130. inAnimation: false,
  131. protocol: false,
  132. current: 1,
  133. spread:'',
  134. account: "",
  135. password: "",
  136. captcha: "",
  137. formItem: 2,
  138. type: "login",
  139. logoUrl: "",
  140. keyCode: "",
  141. codeUrl: "",
  142. codeVal: "",
  143. isShowCode: false,
  144. appLoginStatus: false, // 微信登录强制绑定手机号码状态
  145. appUserInfo: null, // 微信登录保存的用户信息
  146. appleLoginStatus: false, // 苹果登录强制绑定手机号码状态
  147. appleUserInfo: null,
  148. appleShow: false, // 苹果登录版本必须要求ios13以上的
  149. keyLock: true
  150. };
  151. },
  152. watch: {
  153. formItem: function(nval, oVal) {
  154. if (nval == 1) {
  155. this.type = 'login'
  156. } else {
  157. this.type = 'register'
  158. }
  159. }
  160. },
  161. onLoad() {
  162. let self = this
  163. if (uni.getStorageSync('copyRight').copyrightContext) {
  164. this.copyRight = uni.getStorageSync('copyRight').copyrightContext
  165. }
  166. self.spread = self.$Cache.get("spread");
  167. },
  168. mounted: function() {
  169. this.getLogoImage();
  170. },
  171. methods: {
  172. ChangeIsDefault(e) {
  173. this.$set(this, 'protocol', !this.protocol);
  174. },
  175. privacy(type) {
  176. uni.navigateTo({
  177. url: "/pages/users/privacy/index?type=" + type
  178. })
  179. },
  180. zhuce() {
  181. uni.navigateTo({
  182. url: "/pages/users/login/index"
  183. })
  184. },
  185. again() {
  186. this.codeUrl =
  187. VUE_APP_API_URL +
  188. "/sms_captcha?" +
  189. "key=" +
  190. this.keyCode +
  191. Date.parse(new Date());
  192. },
  193. success(data) {
  194. this.$refs.verify.hide()
  195. getCodeApi()
  196. .then(res => {
  197. this.keyCode = res.data.key;
  198. this.getCode(data);
  199. })
  200. .catch(res => {
  201. this.$util.Tips({
  202. title: res
  203. });
  204. });
  205. },
  206. code() {
  207. let that = this
  208. if (!that.protocol) {
  209. this.inAnimation = true
  210. return that.$util.Tips({
  211. title: '请先阅读并同意协议'
  212. });
  213. }
  214. if (!that.account) return that.$util.Tips({
  215. title: that.$t(`请填写手机号码`)
  216. });
  217. if (!/^1(3|4|5|7|8|9|6)\d{9}$/i.test(that.account)) return that.$util.Tips({
  218. title: that.$t(`请输入正确的手机号码`)
  219. });
  220. this.$refs.verify.show()
  221. },
  222. async getLogoImage() {
  223. let that = this;
  224. getLogo(2).then(res => {
  225. that.logoUrl = res.data.logo_url;
  226. });
  227. },
  228. async loginMobile() {
  229. let that = this;
  230. if (!that.protocol) {
  231. this.inAnimation = true
  232. return that.$util.Tips({
  233. title: '请先阅读并同意协议'
  234. });
  235. }
  236. if (!that.account) return that.$util.Tips({
  237. title: that.$t(`请填写手机号码`)
  238. });
  239. if (!/^1(3|4|5|7|8|9|6)\d{9}$/i.test(that.account)) return that.$util.Tips({
  240. title: that.$t(`请输入正确的手机号码`)
  241. });
  242. if (!that.captcha) return that.$util.Tips({
  243. title: that.$t(`请填写验证码`)
  244. });
  245. if (!that.spread) return that.$util.Tips({
  246. title: that.$t(`请填写邀请码/手机号`)
  247. });
  248. if (!/^[\w\d]+$/i.test(that.captcha)) return that.$util.Tips({
  249. title: that.$t(`请输入正确的验证码`)
  250. });
  251. if (this.keyLock) {
  252. this.keyLock = !this.keyLock
  253. } else {
  254. return that.$util.Tips({
  255. title: that.$t(`请勿重复点击`)
  256. });
  257. }
  258. loginMobile({
  259. phone: that.account,
  260. captcha: that.captcha,
  261. spread: that.spread
  262. })
  263. .then(res => {
  264. let data = res.data;
  265. that.$store.commit("LOGIN", {
  266. 'token': data.token,
  267. 'time': data.expires_time - this.$Cache.time()
  268. });
  269. let backUrl = that.$Cache.get(BACK_URL) || "/pages/index/index";
  270. that.$Cache.clear(BACK_URL);
  271. getUserInfo().then(res => {
  272. this.keyLock = true
  273. that.$store.commit("SETUID", res.data.uid);
  274. if (backUrl.indexOf('/pages/users/login/index') !== -1) {
  275. backUrl = '/pages/index/index';
  276. }
  277. uni.reLaunch({
  278. url: backUrl
  279. });
  280. })
  281. })
  282. .catch(res => {
  283. this.keyLock = true
  284. that.$util.Tips({
  285. title: res
  286. });
  287. });
  288. },
  289. async register() {
  290. let that = this;
  291. if (!that.protocol) {
  292. this.inAnimation = true
  293. return that.$util.Tips({
  294. title: '请先阅读并同意协议'
  295. });
  296. }
  297. if (!that.account) return that.$util.Tips({
  298. title: that.$t(`请填写手机号码`)
  299. });
  300. if (!/^1(3|4|5|7|8|9|6)\d{9}$/i.test(that.account)) return that.$util.Tips({
  301. title: that.$t(`请输入正确的手机号码`)
  302. });
  303. if (!that.captcha) return that.$util.Tips({
  304. title: that.$t(`请填写验证码`)
  305. });
  306. if (!/^[\w\d]+$/i.test(that.captcha)) return that.$util.Tips({
  307. title: that.$t(`请输入正确的验证码`)
  308. });
  309. if (!that.password) return that.$util.Tips({
  310. title: that.$t(`请填写密码`)
  311. });
  312. if (/^([0-9]|[a-z]|[A-Z]){0,6}$/i.test(that.password)) return that.$util.Tips({
  313. title: that.$t(`您输入的密码过于简单`)
  314. });
  315. register({
  316. account: that.account,
  317. captcha: that.captcha,
  318. password: that.password,
  319. spread: that.$Cache.get("spread")
  320. })
  321. .then(res => {
  322. that.$util.Tips({
  323. title: res
  324. });
  325. that.formItem = 1;
  326. })
  327. .catch(res => {
  328. that.$util.Tips({
  329. title: res
  330. });
  331. });
  332. },
  333. async getCode(data) {
  334. let that = this;
  335. if (!that.protocol) {
  336. this.inAnimation = true
  337. return that.$util.Tips({
  338. title: '请先阅读并同意协议'
  339. });
  340. }
  341. if (!that.account) return that.$util.Tips({
  342. title: that.$t(`请填写手机号码`)
  343. });
  344. if (!/^1(3|4|5|7|8|9|6)\d{9}$/i.test(that.account)) return that.$util.Tips({
  345. title: that.$t(`请输入正确的手机号码`)
  346. });
  347. if (that.formItem == 2) that.type = "register";
  348. await registerVerify({
  349. phone: that.account,
  350. type: that.type,
  351. key: that.keyCode,
  352. captchaType: this.captchaType,
  353. captchaVerification: data.captchaVerification
  354. })
  355. .then(res => {
  356. this.sendCode()
  357. that.$util.Tips({
  358. title: res.msg
  359. });
  360. })
  361. .catch(res => {
  362. that.$util.Tips({
  363. title: res
  364. });
  365. });
  366. },
  367. navTap: function(index) {
  368. this.current = index;
  369. },
  370. async submit() {
  371. let that = this;
  372. if (!that.protocol) {
  373. this.inAnimation = true
  374. return that.$util.Tips({
  375. title: '请先阅读并同意协议'
  376. });
  377. }
  378. if (!that.account) return that.$util.Tips({
  379. title: that.$t(`请填写账号`)
  380. });
  381. if (!/^[\w\d]{5,16}$/i.test(that.account)) return that.$util.Tips({
  382. title: that.$t(`请输入正确的账号`)
  383. });
  384. if (!that.password) return that.$util.Tips({
  385. title: that.$t(`请填写密码`)
  386. });
  387. if (this.keyLock) {
  388. this.keyLock = !this.keyLock
  389. } else {
  390. return that.$util.Tips({
  391. title: that.$t(`请勿重复点击`)
  392. });
  393. }
  394. loginH5({
  395. account: that.account,
  396. password: that.password,
  397. spread: that.$Cache.get("spread")
  398. })
  399. .then(({
  400. data
  401. }) => {
  402. that.$store.commit("LOGIN", {
  403. 'token': data.token,
  404. 'time': data.expires_time - this.$Cache.time()
  405. });
  406. let backUrl = that.$Cache.get(BACK_URL) || "/pages/index/index";
  407. that.$Cache.clear(BACK_URL);
  408. getUserInfo().then(res => {
  409. this.keyLock = true
  410. that.$store.commit("SETUID", res.data.uid);
  411. uni.reLaunch({
  412. url: backUrl
  413. });
  414. }).catch(error => {
  415. this.keyLock = true
  416. })
  417. })
  418. .catch(e => {
  419. this.keyLock = true
  420. that.$util.Tips({
  421. title: e
  422. });
  423. });
  424. }
  425. }
  426. };
  427. </script>
  428. <style>
  429. page {
  430. background: #fff;
  431. }
  432. </style>
  433. <style lang="scss">
  434. .appLogin {
  435. margin-top: 60rpx;
  436. .hds {
  437. display: flex;
  438. justify-content: center;
  439. align-items: center;
  440. font-size: 24rpx;
  441. color: #B4B4B4;
  442. .line {
  443. width: 68rpx;
  444. height: 1rpx;
  445. background: #CCCCCC;
  446. }
  447. p {
  448. margin: 0 20rpx;
  449. }
  450. }
  451. .btn-wrapper {
  452. display: flex;
  453. align-items: center;
  454. justify-content: center;
  455. margin-top: 30rpx;
  456. .btn {
  457. display: flex;
  458. align-items: center;
  459. justify-content: center;
  460. width: 68rpx;
  461. height: 68rpx;
  462. border-radius: 50%;
  463. }
  464. .apple-btn {
  465. display: flex;
  466. align-items: center;
  467. justify-content: center;
  468. width: 68rpx;
  469. height: 68rpx;
  470. border-radius: 50%;
  471. background: #000;
  472. .icon-s-pingguo {
  473. color: #fff;
  474. font-size: 44rpx;
  475. }
  476. }
  477. .iconfont {
  478. font-size: 40rpx;
  479. color: #fff;
  480. }
  481. .wx {
  482. margin-right: 30rpx;
  483. background-color: #61C64F;
  484. }
  485. .mima {
  486. margin-right: 30rpx;
  487. background-color: #28B3E9;
  488. }
  489. .yanzheng {
  490. margin-right: 30rpx;
  491. background-color: #F89C23;
  492. }
  493. }
  494. }
  495. .code img {
  496. width: 100%;
  497. height: 100%;
  498. }
  499. .acea-row.row-middle {
  500. input {
  501. margin-left: 20rpx;
  502. display: block;
  503. }
  504. }
  505. .login-wrapper {
  506. padding: 30rpx;
  507. .shading {
  508. display: flex;
  509. align-items: center;
  510. justify-content: center;
  511. width: 100%;
  512. /* #ifdef APP-VUE */
  513. margin-top: 50rpx;
  514. /* #endif */
  515. /* #ifndef APP-VUE */
  516. margin-top: 200rpx;
  517. /* #endif */
  518. image {
  519. width: 240rpx;
  520. height: 240rpx;
  521. }
  522. }
  523. .whiteBg {
  524. margin-top: 100rpx;
  525. .list {
  526. border-radius: 16rpx;
  527. overflow: hidden;
  528. .item {
  529. border-bottom: 1px solid #F0F0F0;
  530. background: #fff;
  531. .row-middle {
  532. position: relative;
  533. padding: 16rpx 45rpx;
  534. input {
  535. flex: 1;
  536. font-size: 28rpx;
  537. height: 80rpx;
  538. }
  539. .code {
  540. position: absolute;
  541. right: 30rpx;
  542. top: 50%;
  543. color: var(--view-theme);
  544. font-size: 26rpx;
  545. transform: translateY(-50%);
  546. }
  547. }
  548. }
  549. }
  550. .logon {
  551. display: flex;
  552. align-items: center;
  553. justify-content: center;
  554. width: 100%;
  555. height: 86rpx;
  556. margin-top: 80rpx;
  557. background-color: var(--view-theme);
  558. border-radius: 120rpx;
  559. color: #FFFFFF;
  560. font-size: 30rpx;
  561. }
  562. .tips {
  563. margin: 30rpx;
  564. text-align: center;
  565. color: #999;
  566. }
  567. }
  568. }
  569. .protocol {
  570. margin-top: 40rpx;
  571. color: #999999;
  572. font-size: 24rpx;
  573. text-align: center;
  574. bottom: 20rpx;
  575. }
  576. .bottom {
  577. position: fixed;
  578. bottom: 30rpx;
  579. left: 0;
  580. display: flex;
  581. width: 100%;
  582. justify-content: center;
  583. color: #999999;
  584. .ver {
  585. font-size: 20rpx;
  586. }
  587. .ver-msg {
  588. margin-left: 10rpx;
  589. }
  590. a {
  591. color: #999999;
  592. margin-left: 10rpx;
  593. text-decoration: none;
  594. }
  595. }
  596. .trembling {
  597. animation: shake 0.6s;
  598. }
  599. .main-color {
  600. color: var(--view-theme);
  601. }
  602. .choose {
  603. display: flex;
  604. justify-content: center;
  605. .reg {
  606. font-size: 28rpx;
  607. font-weight: 500;
  608. color: #ff8d3a;
  609. }
  610. .xian {
  611. color: #FF4C4C;
  612. padding-left: 10rpx;
  613. }
  614. .zhuce {
  615. font-size: 28rpx;
  616. font-weight: 500;
  617. color: #FF4C4C;
  618. padding-left: 10rpx;
  619. }
  620. }
  621. </style>