index.vue 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795
  1. <template>
  2. <view class="login-wrapper" :style="colorStyle">
  3. <view class="shading">
  4. <image :src="logoUrl" v-if="logoUrl" />
  5. <image src="../static/logo2.png" v-else />
  6. </view>
  7. <view class="whiteBg" v-if="formItem === 1">
  8. <view class="list" v-if="current !== 1">
  9. <form @submit.prevent="submit">
  10. <view class="item">
  11. <view class="acea-row row-middle">
  12. <image src="../static/phone_1.png" style="width: 24rpx; height: 34rpx;"></image>
  13. <input type="text" :placeholder="$t(`输入手机号码`)" v-model="account" maxlength="11" required />
  14. </view>
  15. </view>
  16. <view class="item">
  17. <view class="acea-row row-middle">
  18. <image src="../static/code_1.png" style="width: 28rpx; height: 32rpx;"></image>
  19. <input type="password" :placeholder="$t(`填写登录密码`)" v-model="password" required />
  20. </view>
  21. </view>
  22. </form>
  23. <!-- <navigator class="forgetPwd" hover-class="none" url="/pages/users/retrievePassword/index">
  24. <span class="iconfont icon-wenti"></span>忘记密码
  25. </navigator> -->
  26. </view>
  27. <view class="list" v-if="current !== 0 || appLoginStatus || appleLoginStatus">
  28. <view class="item">
  29. <view class="acea-row row-middle">
  30. <image src="../static/phone_1.png" style="width: 24rpx; height: 34rpx;"></image>
  31. <input type="text" :placeholder="$t(`输入手机号码`)" v-model="account" maxlength="11" />
  32. </view>
  33. </view>
  34. <view class="item">
  35. <view class="acea-row row-middle">
  36. <image src="../static/code_2.png" style="width: 28rpx; height: 32rpx;"></image>
  37. <input type="text" :placeholder="$t(`填写验证码`)" maxlength="6" class="codeIput" v-model="captcha" />
  38. <button class="code" :disabled="disabled" :class="disabled === true ? 'on' : ''" @click="code">
  39. {{ text }}
  40. </button>
  41. </view>
  42. </view>
  43. <view class="item" v-if="isShowCode">
  44. <view class="acea-row row-middle">
  45. <image src="../static/code_2.png" style="width: 28rpx; height: 32rpx;"></image>
  46. <input type="text" :placeholder="$t(`填写验证码`)" class="codeIput" v-model="codeVal" />
  47. <view class="code" @click="again"><img :src="codeUrl" /></view>
  48. </view>
  49. </view>
  50. </view>
  51. <view class="logon" @click="loginMobile" v-if="current !== 0">{{$t(`登录`)}}</view>
  52. <view class="logon" @click="submit" v-if="current === 0">{{$t(`登录`)}}</view>
  53. <!-- #ifndef APP-PLUS -->
  54. <view class="tips">
  55. <view v-if="current==0" @click="current = 1">{{$t(`快速登录`)}}</view>
  56. <view v-if="current==1" @click="current = 0">{{$t(`账号登录`)}}</view>
  57. </view>
  58. <!-- #endif -->
  59. <!-- #ifdef APP-PLUS -->
  60. <view class="appLogin" v-if="!appLoginStatus && !appleLoginStatus">
  61. <view class="hds">
  62. <span class="line"></span>
  63. <p>{{$t(`其他方式登录`)}}</p>
  64. <span class="line"></span>
  65. </view>
  66. <view class="btn-wrapper">
  67. <view class="btn wx" @click="wxLogin">
  68. <span class="iconfont icon-s-weixindenglu1"></span>
  69. </view>
  70. <view class="btn mima" v-if="current == 1" @click="current =0">
  71. <span class="iconfont icon-s-mimadenglu1"></span>
  72. </view>
  73. <view class="btn yanzheng" v-if="current == 0" @click="current =1">
  74. <span class="iconfont icon-s-yanzhengmadenglu1"></span>
  75. </view>
  76. <view class="apple-btn" @click="appleLogin" v-if="appleShow">
  77. <view class="iconfont icon-s-pingguo"></view>
  78. </view>
  79. </view>
  80. </view>
  81. <!-- #endif -->
  82. <view class="protocol">
  83. <checkbox-group @change='ChangeIsDefault'>
  84. <checkbox :class="inAnimation?'trembling':''" @animationend='inAnimation=false'
  85. :checked="protocol ? true : false" />{{$t(`已阅读并同意`)}} <text class="main-color"
  86. @click="privacy(4)">{{$t(`《用户协议》`)}}</text>
  87. {{$t(`与`)}}<text class="main-color" @click="privacy(3)">{{$t(`《隐私协议》`)}}</text>
  88. </checkbox-group>
  89. </view>
  90. </view>
  91. <view class="bottom"></view>
  92. </view>
  93. </template>
  94. <script>
  95. import dayjs from "@/plugin/dayjs/dayjs.min.js";
  96. import sendVerifyCode from "@/mixins/SendVerifyCode";
  97. import {
  98. loginH5,
  99. loginMobile,
  100. registerVerify,
  101. register,
  102. getCodeApi,
  103. getUserInfo,
  104. appleLogin
  105. } from "@/api/user";
  106. import attrs, {
  107. required,
  108. alpha_num,
  109. chs_phone
  110. } from "@/utils/validate";
  111. import {
  112. getLogo
  113. } from "@/api/public";
  114. // import cookie from "@/utils/store/cookie";
  115. import {
  116. VUE_APP_API_URL
  117. } from "@/utils";
  118. // #ifdef APP-PLUS
  119. import {
  120. wechatAppAuth
  121. } from '@/api/api.js'
  122. // #endif
  123. const BACK_URL = "login_back_url";
  124. import colors from '@/mixins/color.js';
  125. export default {
  126. name: "Login",
  127. mixins: [sendVerifyCode, colors],
  128. data: function() {
  129. return {
  130. inAnimation: false,
  131. protocol: false,
  132. navList: [this.$t(`快速登录`),this.$t(`账号登录`)],
  133. current: 1,
  134. account: "",
  135. password: "",
  136. captcha: "",
  137. formItem: 1,
  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. uni.getSystemInfo({
  164. success: (res) => {
  165. if (res.platform.toLowerCase() == 'ios' && this.getSystem(res.system)) {
  166. self.appleShow = true
  167. }
  168. }
  169. });
  170. },
  171. mounted: function() {
  172. // this.getCode();
  173. this.getLogoImage();
  174. },
  175. methods: {
  176. ChangeIsDefault(e) {
  177. this.$set(this, 'protocol', !this.protocol);
  178. },
  179. privacy(type) {
  180. uni.navigateTo({
  181. url: "/pages/users/privacy/index?type=" + type
  182. })
  183. },
  184. // IOS 版本号判断
  185. getSystem(system) {
  186. let str
  187. system.toLowerCase().indexOf('ios') === -1 ? str = system : str = system.split(' ')[1]
  188. if (str.indexOf('.'))
  189. return str.split('.')[0] >= 13
  190. return str >= 13
  191. },
  192. // 苹果登录
  193. appleLogin() {
  194. let self = this
  195. this.account = ''
  196. this.captcha = ''
  197. if (!self.protocol) {
  198. this.inAnimation = true
  199. return self.$util.Tips({
  200. title: '请先阅读并同意协议'
  201. });
  202. }
  203. uni.showLoading({
  204. title: this.$t(`登录中`)
  205. })
  206. uni.login({
  207. provider: 'apple',
  208. timeout: 10000,
  209. success(loginRes) {
  210. uni.getUserInfo({
  211. provider: 'apple',
  212. success: function(infoRes) {
  213. self.appleUserInfo = infoRes.userInfo
  214. self.appleLoginApi()
  215. },
  216. fail() {
  217. uni.showToast({
  218. title: self.$t(`获取用户信息失败`),
  219. icon: 'none',
  220. duration: 2000
  221. })
  222. },
  223. complete() {
  224. uni.hideLoading()
  225. }
  226. });
  227. },
  228. fail(error) {
  229. console.log(error)
  230. }
  231. })
  232. },
  233. // 苹果登录Api
  234. appleLoginApi() {
  235. let self = this
  236. appleLogin({
  237. openId: self.appleUserInfo.openId,
  238. email: self.appleUserInfo.email || '',
  239. phone: this.account,
  240. captcha: this.captcha
  241. }).then(({
  242. data
  243. }) => {
  244. if (data.isbind) {
  245. uni.showModal({
  246. title: self.$t(`提示`),
  247. content: self.$t(`请绑定手机号后,继续操作`),
  248. showCancel: false,
  249. success: function(res) {
  250. if (res.confirm) {
  251. self.current = 1
  252. self.appleLoginStatus = true
  253. }
  254. }
  255. });
  256. } else {
  257. self.$store.commit("LOGIN", {
  258. 'token': data.token,
  259. 'time': data.expires_time - self.$Cache.time()
  260. });
  261. let backUrl = self.$Cache.get(BACK_URL) || "/pages/index/index";
  262. self.$Cache.clear(BACK_URL);
  263. self.$store.commit("SETUID", data.userInfo.uid);
  264. uni.reLaunch({
  265. url: backUrl
  266. });
  267. }
  268. }).catch(error => {
  269. uni.showModal({
  270. title: self.$t(`提示`),
  271. content: self.$t(`错误信息`) + `${error}`,
  272. success: function(res) {
  273. if (res.confirm) {
  274. console.log(self.$t(`用户点击确定`));
  275. } else if (res.cancel) {
  276. console.log(self.$t(`用户点击取消`));
  277. }
  278. }
  279. });
  280. })
  281. },
  282. // App微信登录
  283. wxLogin() {
  284. let self = this
  285. this.account = ''
  286. this.captcha = ''
  287. if (!self.protocol) {
  288. this.inAnimation = true
  289. return self.$util.Tips({
  290. title: '请先阅读并同意协议'
  291. });
  292. }
  293. uni.showLoading({
  294. title: self.$t(`登录中`)
  295. })
  296. uni.login({
  297. provider: 'weixin',
  298. success: function(loginRes) {
  299. // 获取用户信息
  300. uni.getUserInfo({
  301. provider: 'weixin',
  302. success: function(infoRes) {
  303. self.appUserInfo = infoRes.userInfo
  304. self.wxLoginApi()
  305. },
  306. fail() {
  307. uni.showToast({
  308. title: self.$t(`获取用户信息失败`),
  309. icon: 'none',
  310. duration: 2000
  311. })
  312. },
  313. complete() {
  314. uni.hideLoading()
  315. }
  316. });
  317. },
  318. fail() {
  319. uni.showToast({
  320. title: self.$t(`登录失败`),
  321. icon: 'none',
  322. duration: 2000
  323. })
  324. }
  325. });
  326. },
  327. wxLoginApi() {
  328. let self = this
  329. wechatAppAuth({
  330. userInfo: self.appUserInfo,
  331. phone: this.account,
  332. code: this.captcha
  333. }).then(({
  334. data
  335. }) => {
  336. if (data.isbind) {
  337. uni.showModal({
  338. title: self.$t(`提示`),
  339. content: self.$t(`请绑定手机号后,继续操作`),
  340. showCancel: false,
  341. success: function(res) {
  342. if (res.confirm) {
  343. self.current = 1
  344. self.appLoginStatus = true
  345. }
  346. }
  347. });
  348. } else {
  349. self.$store.commit("LOGIN", {
  350. 'token': data.token,
  351. 'time': data.expires_time - self.$Cache.time()
  352. });
  353. let backUrl = self.$Cache.get(BACK_URL) || "/pages/index/index";
  354. self.$Cache.clear(BACK_URL);
  355. self.$store.commit("SETUID", data.userInfo.uid);
  356. uni.reLaunch({
  357. url: backUrl
  358. });
  359. }
  360. }).catch(error => {
  361. uni.showModal({
  362. title: self.$t(`提示`),
  363. content: self.$t(`错误信息`) + `${error}`,
  364. success: function(res) {
  365. if (res.confirm) {
  366. console.log(self.$t(`用户点击确定`));
  367. } else if (res.cancel) {
  368. console.log(self.$t(`用户点击取消`));
  369. }
  370. }
  371. });
  372. })
  373. },
  374. again() {
  375. this.codeUrl =
  376. VUE_APP_API_URL +
  377. "/sms_captcha?" +
  378. "key=" +
  379. this.keyCode +
  380. Date.parse(new Date());
  381. },
  382. code() {
  383. let that = this
  384. if (!that.protocol) {
  385. this.inAnimation = true
  386. return that.$util.Tips({
  387. title: '请先阅读并同意协议'
  388. });
  389. }
  390. getCodeApi()
  391. .then(res => {
  392. that.keyCode = res.data.key;
  393. that.getCode();
  394. })
  395. .catch(res => {
  396. that.$util.Tips({
  397. title: res
  398. });
  399. });
  400. },
  401. async getLogoImage() {
  402. let that = this;
  403. getLogo(2).then(res => {
  404. that.logoUrl = res.data.logo_url;
  405. });
  406. },
  407. async loginMobile() {
  408. let that = this;
  409. if (!that.protocol) {
  410. this.inAnimation = true
  411. return that.$util.Tips({
  412. title: '请先阅读并同意协议'
  413. });
  414. }
  415. if (!that.account) return that.$util.Tips({
  416. title: that.$t(`请填写手机号码`)
  417. });
  418. if (!/^1(3|4|5|7|8|9|6)\d{9}$/i.test(that.account)) return that.$util.Tips({
  419. title: that.$t(`请输入正确的手机号码`)
  420. });
  421. if (!that.captcha) return that.$util.Tips({
  422. title: that.$t(`请填写验证码`)
  423. });
  424. if (!/^[\w\d]+$/i.test(that.captcha)) return that.$util.Tips({
  425. title: that.$t(`请输入正确的验证码`)
  426. });
  427. if (that.appLoginStatus) {
  428. that.wxLoginApi()
  429. } else if (that.appleLoginStatus) {
  430. that.appleLoginApi()
  431. } else {
  432. if (this.keyLock) {
  433. this.keyLock = !this.keyLock
  434. } else {
  435. return that.$util.Tips({
  436. title: that.$t(`请勿重复点击`)
  437. });
  438. }
  439. loginMobile({
  440. phone: that.account,
  441. captcha: that.captcha,
  442. spread: that.$Cache.get("spread")
  443. })
  444. .then(res => {
  445. let data = res.data;
  446. that.$store.commit("LOGIN", {
  447. 'token': data.token,
  448. 'time': data.expires_time - this.$Cache.time()
  449. });
  450. let backUrl = that.$Cache.get(BACK_URL) || "/pages/index/index";
  451. that.$Cache.clear(BACK_URL);
  452. getUserInfo().then(res => {
  453. this.keyLock = true
  454. that.$store.commit("SETUID", res.data.uid);
  455. if (backUrl.indexOf('/pages/users/login/index') !== -1) {
  456. backUrl = '/pages/index/index';
  457. }
  458. uni.reLaunch({
  459. url: backUrl
  460. });
  461. })
  462. })
  463. .catch(res => {
  464. this.keyLock = true
  465. that.$util.Tips({
  466. title: res
  467. });
  468. });
  469. }
  470. },
  471. async register() {
  472. let that = this;
  473. if (!that.protocol) {
  474. this.inAnimation = true
  475. return that.$util.Tips({
  476. title: '请先阅读并同意协议'
  477. });
  478. }
  479. if (!that.account) return that.$util.Tips({
  480. title: that.$t(`请填写手机号码`)
  481. });
  482. if (!/^1(3|4|5|7|8|9|6)\d{9}$/i.test(that.account)) return that.$util.Tips({
  483. title: that.$t(`请输入正确的手机号码`)
  484. });
  485. if (!that.captcha) return that.$util.Tips({
  486. title: that.$t(`请填写验证码`)
  487. });
  488. if (!/^[\w\d]+$/i.test(that.captcha)) return that.$util.Tips({
  489. title: that.$t(`请输入正确的验证码`)
  490. });
  491. if (!that.password) return that.$util.Tips({
  492. title: that.$t(`请填写密码`)
  493. });
  494. if (/^([0-9]|[a-z]|[A-Z]){0,6}$/i.test(that.password)) return that.$util.Tips({
  495. title: that.$t(`您输入的密码过于简单`)
  496. });
  497. register({
  498. account: that.account,
  499. captcha: that.captcha,
  500. password: that.password,
  501. spread: that.$Cache.get("spread")
  502. })
  503. .then(res => {
  504. that.$util.Tips({
  505. title: res
  506. });
  507. that.formItem = 1;
  508. })
  509. .catch(res => {
  510. that.$util.Tips({
  511. title: res
  512. });
  513. });
  514. },
  515. async getCode() {
  516. let that = this;
  517. if (!that.protocol) {
  518. this.inAnimation = true
  519. return that.$util.Tips({
  520. title: '请先阅读并同意协议'
  521. });
  522. }
  523. if (!that.account) return that.$util.Tips({
  524. title: that.$t(`请填写手机号码`)
  525. });
  526. if (!/^1(3|4|5|7|8|9|6)\d{9}$/i.test(that.account)) return that.$util.Tips({
  527. title: that.$t(`请输入正确的手机号码`)
  528. });
  529. if (that.formItem == 2) that.type = "register";
  530. await registerVerify({
  531. phone: that.account,
  532. type: that.type,
  533. key: that.keyCode,
  534. code: that.codeVal
  535. })
  536. .then(res => {
  537. that.$util.Tips({
  538. title: res.msg
  539. });
  540. that.sendCode();
  541. })
  542. .catch(res => {
  543. that.$util.Tips({
  544. title: res
  545. });
  546. });
  547. },
  548. navTap: function(index) {
  549. this.current = index;
  550. },
  551. async submit() {
  552. let that = this;
  553. if (!that.protocol) {
  554. this.inAnimation = true
  555. return that.$util.Tips({
  556. title: '请先阅读并同意协议'
  557. });
  558. }
  559. if (!that.account) return that.$util.Tips({
  560. title: that.$t(`请填写账号`)
  561. });
  562. if (!/^[\w\d]{5,16}$/i.test(that.account)) return that.$util.Tips({
  563. title: that.$t(`请输入正确的账号`)
  564. });
  565. if (!that.password) return that.$util.Tips({
  566. title: that.$t(`请填写密码`)
  567. });
  568. if (this.keyLock) {
  569. this.keyLock = !this.keyLock
  570. } else {
  571. return that.$util.Tips({
  572. title: that.$t(`请勿重复点击`)
  573. });
  574. }
  575. loginH5({
  576. account: that.account,
  577. password: that.password,
  578. spread: that.$Cache.get("spread")
  579. })
  580. .then(({
  581. data
  582. }) => {
  583. that.$store.commit("LOGIN", {
  584. 'token': data.token,
  585. 'time': data.expires_time - this.$Cache.time()
  586. });
  587. let backUrl = that.$Cache.get(BACK_URL) || "/pages/index/index";
  588. that.$Cache.clear(BACK_URL);
  589. getUserInfo().then(res => {
  590. this.keyLock = true
  591. that.$store.commit("SETUID", res.data.uid);
  592. uni.reLaunch({
  593. url: backUrl
  594. });
  595. }).catch(error => {
  596. this.keyLock = true
  597. })
  598. })
  599. .catch(e => {
  600. this.keyLock = true
  601. that.$util.Tips({
  602. title: e
  603. });
  604. });
  605. }
  606. }
  607. };
  608. </script>
  609. <style>
  610. page {
  611. background: #fff;
  612. }
  613. </style>
  614. <style lang="scss">
  615. .appLogin {
  616. margin-top: 60rpx;
  617. .hds {
  618. display: flex;
  619. justify-content: center;
  620. align-items: center;
  621. font-size: 24rpx;
  622. color: #B4B4B4;
  623. .line {
  624. width: 68rpx;
  625. height: 1rpx;
  626. background: #CCCCCC;
  627. }
  628. p {
  629. margin: 0 20rpx;
  630. }
  631. }
  632. .btn-wrapper {
  633. display: flex;
  634. align-items: center;
  635. justify-content: center;
  636. margin-top: 30rpx;
  637. .btn {
  638. display: flex;
  639. align-items: center;
  640. justify-content: center;
  641. width: 68rpx;
  642. height: 68rpx;
  643. border-radius: 50%;
  644. }
  645. .apple-btn {
  646. display: flex;
  647. align-items: center;
  648. justify-content: center;
  649. width: 68rpx;
  650. height: 68rpx;
  651. border-radius: 50%;
  652. background: #000;
  653. .icon-s-pingguo {
  654. color: #fff;
  655. font-size: 44rpx;
  656. }
  657. }
  658. .iconfont {
  659. font-size: 40rpx;
  660. color: #fff;
  661. }
  662. .wx {
  663. margin-right: 30rpx;
  664. background-color: #61C64F;
  665. }
  666. .mima {
  667. margin-right: 30rpx;
  668. background-color: #28B3E9;
  669. }
  670. .yanzheng {
  671. margin-right: 30rpx;
  672. background-color: #F89C23;
  673. }
  674. }
  675. }
  676. .code img {
  677. width: 100%;
  678. height: 100%;
  679. }
  680. .acea-row.row-middle {
  681. input {
  682. margin-left: 20rpx;
  683. display: block;
  684. }
  685. }
  686. .login-wrapper {
  687. padding: 30rpx;
  688. .shading {
  689. display: flex;
  690. align-items: center;
  691. justify-content: center;
  692. width: 100%;
  693. /* #ifdef APP-VUE */
  694. margin-top: 50rpx;
  695. /* #endif */
  696. /* #ifndef APP-VUE */
  697. margin-top: 200rpx;
  698. /* #endif */
  699. image {
  700. width: 240rpx;
  701. height: 240rpx;
  702. }
  703. }
  704. .whiteBg {
  705. margin-top: 100rpx;
  706. .list {
  707. border-radius: 16rpx;
  708. overflow: hidden;
  709. .item {
  710. border-bottom: 1px solid #F0F0F0;
  711. background: #fff;
  712. .row-middle {
  713. position: relative;
  714. padding: 16rpx 45rpx;
  715. input {
  716. flex: 1;
  717. font-size: 28rpx;
  718. height: 80rpx;
  719. }
  720. .code {
  721. position: absolute;
  722. right: 30rpx;
  723. top: 50%;
  724. color: var(--view-theme);
  725. font-size: 26rpx;
  726. transform: translateY(-50%);
  727. }
  728. }
  729. }
  730. }
  731. .logon {
  732. display: flex;
  733. align-items: center;
  734. justify-content: center;
  735. width: 100%;
  736. height: 86rpx;
  737. margin-top: 80rpx;
  738. background-color: var(--view-theme);
  739. border-radius: 120rpx;
  740. color: #FFFFFF;
  741. font-size: 30rpx;
  742. }
  743. .tips {
  744. margin: 30rpx;
  745. text-align: center;
  746. color: #999;
  747. }
  748. }
  749. }
  750. .protocol {
  751. margin-top: 40rpx;
  752. color: #999999;
  753. font-size: 24rpx;
  754. text-align: center;
  755. bottom: 20rpx;
  756. }
  757. .trembling {
  758. animation: shake 0.6s;
  759. }
  760. .main-color {
  761. color: var(--view-theme);
  762. }
  763. </style>