index.vue 14 KB

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