index.vue 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981
  1. <template>
  2. <view class="login-wrapper" :style="colorStyle">
  3. <view class="login-top"></view>
  4. <view class="shading">
  5. <image :src="logoUrl" v-if="logoUrl" />
  6. <image src="../static/logo2.png" v-else />
  7. </view>
  8. <view class="whiteBg" v-if="formItem === 1">
  9. <view class="tips">
  10. <view class="tips-btn" :class="current == 1 ? 'on' : ''" @click="current = 1">
  11. <view>快速登录</view>
  12. <view :class="current == 1 ? 'line' : 'none'"></view>
  13. </view>
  14. <view class="tips-btn" :class="current == 0 ? 'on' : ''" @click="current = 0">
  15. <view>账号登录</view>
  16. <view :class="current == 0 ? 'line' : 'none'"></view>
  17. </view>
  18. </view>
  19. <view class="list" v-if="current !== 1">
  20. <form @submit.prevent="submit">
  21. <view class="item">
  22. <view class="acea-row row-middle">
  23. <image src="../static/phone_1.png" class="itemImg-add"></image>
  24. <input type="text" placeholder="输入手机号码" v-model="account" maxlength="11" required />
  25. </view>
  26. </view>
  27. <view class="item">
  28. <view class="acea-row row-middle">
  29. <image src="../static/code_1.png" class="item-img"></image>
  30. <input type="password" placeholder="填写登录密码" v-model="password" required />
  31. </view>
  32. </view>
  33. </form>
  34. <navigator class="forgetPwd" hover-class="none" url="/pages/users/retrievePassword/index">
  35. 忘记密码?
  36. </navigator>
  37. </view>
  38. <view class="list" v-if="current !== 0 || appLoginStatus || appleLoginStatus">
  39. <view class="item">
  40. <view class="acea-row row-middle">
  41. <image src="../static/phone_1.png" class="itemImg-add"></image>
  42. <input type="text" placeholder="输入手机号码" v-model="account" maxlength="11" />
  43. </view>
  44. </view>
  45. <view class="item">
  46. <view class="acea-row row-middle">
  47. <image src="../static/code_2.png" class="item-img"></image>
  48. <input type="text" placeholder="填写验证码" maxlength="6" class="codeIput" v-model="captcha" />
  49. <button class="code" :disabled="disabled" :class="disabled === true ? 'on' : ''" @click="code">
  50. {{ text }}
  51. </button>
  52. </view>
  53. </view>
  54. <view class="item" v-if="isShowCode">
  55. <view class="acea-row row-middle">
  56. <image src="../static/code_2.png" class="item-img"></image>
  57. <input type="text" placeholder="填写验证码" class="codeIput" v-model="codeVal" />
  58. <view class="code" @click="again"><img :src="codeUrl" /></view>
  59. </view>
  60. </view>
  61. </view>
  62. <view class="logon" @click="loginMobile" v-if="current !== 0">登录</view>
  63. <view class="logon" @click="submit" v-if="current === 0">登录</view>
  64. <!-- #ifdef APP-PLUS -->
  65. <view class="appLogin" v-if="!appLoginStatus && !appleLoginStatus">
  66. <view class="hds">
  67. <span class="line"></span>
  68. <p>其他方式登录</p>
  69. <span class="line"></span>
  70. </view>
  71. <view class="btn-wrapper">
  72. <view class="btn wx" @click="wxLogin">
  73. <span class="iconfont icon-s-weixindenglu1"></span>
  74. </view>
  75. <view class="btn pingguo" @click="appleLogin" v-if="appleShow">
  76. <view class="iconfont icon-s-pingguo"></view>
  77. </view>
  78. </view>
  79. </view>
  80. <!-- #endif -->
  81. <view class="protocol">
  82. <checkbox-group @change='ChangeIsDefault'>
  83. <checkbox :class="inAnimation?'trembling':''" @animationend='inAnimation=false'
  84. :checked="protocol ? true : false" />已阅读并同意 <text class="main-color"
  85. @click="privacy('user')">《用户协议》</text>
  86. 与<text class="main-color" @click="privacy('privacy ')">《隐私协议》</text>
  87. </checkbox-group>
  88. </view>
  89. </view>
  90. <view class="bottom"></view>
  91. </view>
  92. </template>
  93. <script>
  94. import dayjs from "@/plugin/dayjs/dayjs.min.js";
  95. import sendVerifyCode from "@/mixins/SendVerifyCode";
  96. import {
  97. loginH5,
  98. loginMobile,
  99. registerVerify,
  100. register,
  101. getCodeApi,
  102. getUserInfo,
  103. appleLogin
  104. } from "@/api/user";
  105. import attrs, {
  106. required,
  107. alpha_num,
  108. chs_phone
  109. } from "@/utils/validate";
  110. import {
  111. validatorDefaultCatch
  112. } from "@/utils/dialog";
  113. import {
  114. getLogo
  115. } from "@/api/public";
  116. // import cookie from "@/utils/store/cookie";
  117. import {
  118. VUE_APP_API_URL
  119. } from "@/utils";
  120. // #ifdef APP-PLUS
  121. import {
  122. wechatAppAuth
  123. } from '@/api/api.js'
  124. // #endif
  125. const BACK_URL = "login_back_url";
  126. import colors from '@/mixins/color.js';
  127. export default {
  128. name: "Login",
  129. mixins: [sendVerifyCode, colors],
  130. data: function() {
  131. return {
  132. inAnimation: false,
  133. protocol: false,
  134. navList: ["快速登录", "账号登录"],
  135. current: 1,
  136. account: "",
  137. password: "",
  138. captcha: "",
  139. formItem: 1,
  140. type: "login",
  141. logoUrl: "",
  142. keyCode: "",
  143. codeUrl: "",
  144. codeVal: "",
  145. isShowCode: false,
  146. appLoginStatus: false, // 微信登录强制绑定手机号码状态
  147. appUserInfo: null, // 微信登录保存的用户信息
  148. appleLoginStatus: false, // 苹果登录强制绑定手机号码状态
  149. appleUserInfo: null,
  150. appleShow: false, // 苹果登录版本必须要求ios13以上的
  151. keyLock: true
  152. };
  153. },
  154. watch: {
  155. formItem: function(nval, oVal) {
  156. if (nval == 1) {
  157. this.type = 'login'
  158. } else {
  159. this.type = 'register'
  160. }
  161. }
  162. },
  163. onLoad() {
  164. let self = this
  165. uni.getSystemInfo({
  166. success: (res) => {
  167. if (res.platform.toLowerCase() == 'ios' && this.getSystem(res.system)) {
  168. self.appleShow = true
  169. }
  170. }
  171. });
  172. },
  173. mounted: function() {
  174. // this.getCode();
  175. this.getLogoImage();
  176. },
  177. methods: {
  178. changeMsg() {
  179. this.inAnimation = true;
  180. },
  181. ChangeIsDefault(e) {
  182. this.$set(this, 'protocol', !this.protocol);
  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: '登录中'
  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: '获取用户信息失败',
  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: '提示',
  247. content: '请绑定手机号后,继续操作',
  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. self.$store.commit("UPDATE_USERINFO", data.userInfo);
  265. uni.reLaunch({
  266. url: backUrl
  267. });
  268. }
  269. }).catch(error => {
  270. uni.showModal({
  271. title: '提示',
  272. content: `错误信息${error}`,
  273. success: function(res) {
  274. if (res.confirm) {
  275. console.log('用户点击确定');
  276. } else if (res.cancel) {
  277. console.log('用户点击取消');
  278. }
  279. }
  280. });
  281. })
  282. },
  283. // App微信登录
  284. wxLogin() {
  285. if (!this.protocol) {
  286. this.inAnimation = true
  287. return this.$util.Tips({
  288. title: '请先阅读并同意协议'
  289. });
  290. }
  291. let self = this
  292. this.account = ''
  293. this.captcha = ''
  294. uni.showLoading({
  295. title: '登录中'
  296. })
  297. uni.login({
  298. provider: 'weixin',
  299. success: function(loginRes) {
  300. // 获取用户信息
  301. uni.getUserInfo({
  302. provider: 'weixin',
  303. success: function(infoRes) {
  304. self.appUserInfo = infoRes.userInfo
  305. self.wxLoginApi()
  306. },
  307. fail() {
  308. uni.showToast({
  309. title: '获取用户信息失败',
  310. icon: 'none',
  311. duration: 2000
  312. })
  313. },
  314. complete() {
  315. uni.hideLoading()
  316. }
  317. });
  318. },
  319. fail() {
  320. uni.showToast({
  321. title: '登录失败',
  322. icon: 'none',
  323. duration: 2000
  324. })
  325. }
  326. });
  327. },
  328. wxLoginApi() {
  329. let self = this
  330. wechatAppAuth({
  331. userInfo: self.appUserInfo,
  332. phone: this.account,
  333. code: this.captcha
  334. }).then(({
  335. data
  336. }) => {
  337. if (data.isbind) {
  338. uni.showModal({
  339. title: '提示',
  340. content: '请绑定手机号后,继续操作',
  341. showCancel: false,
  342. success: function(res) {
  343. if (res.confirm) {
  344. self.current = 1
  345. self.appLoginStatus = true
  346. }
  347. }
  348. });
  349. } else {
  350. self.$store.commit("LOGIN", {
  351. 'token': data.token,
  352. 'time': data.expires_time - self.$Cache.time()
  353. });
  354. let backUrl = self.$Cache.get(BACK_URL) || "/pages/index/index";
  355. self.$Cache.clear(BACK_URL);
  356. self.$store.commit("SETUID", data.userInfo.uid);
  357. self.$store.commit("UPDATE_USERINFO", data.userInfo);
  358. uni.reLaunch({
  359. url: backUrl
  360. });
  361. }
  362. }).catch(error => {
  363. uni.showModal({
  364. title: '提示',
  365. content: `错误信息${error}`,
  366. success: function(res) {
  367. if (res.confirm) {
  368. console.log('用户点击确定');
  369. } else if (res.cancel) {
  370. console.log('用户点击取消');
  371. }
  372. }
  373. });
  374. })
  375. },
  376. again() {
  377. this.codeUrl =
  378. VUE_APP_API_URL +
  379. "/sms_captcha?" +
  380. "key=" +
  381. this.keyCode +
  382. Date.parse(new Date());
  383. },
  384. code() {
  385. let that = this
  386. if (!that.protocol) {
  387. this.inAnimation = true
  388. return that.$util.Tips({
  389. title: '请先阅读并同意协议'
  390. });
  391. }
  392. if (!that.account) return that.$util.Tips({
  393. title: '请填写手机号码'
  394. });
  395. if (!/^1(3|4|5|7|8|9|6)\d{9}$/i.test(that.account)) return that.$util.Tips({
  396. title: '请输入正确的手机号码'
  397. });
  398. getCodeApi()
  399. .then(res => {
  400. that.keyCode = res.data.key;
  401. that.getCode();
  402. })
  403. .catch(res => {
  404. that.$util.Tips({
  405. title: res
  406. });
  407. });
  408. },
  409. async getLogoImage() {
  410. let that = this;
  411. getLogo(2).then(res => {
  412. that.logoUrl = res.data.logo_url;
  413. });
  414. },
  415. async loginMobile() {
  416. let that = this;
  417. if (!that.protocol) {
  418. this.inAnimation = true
  419. return that.$util.Tips({
  420. title: '请先阅读并同意协议'
  421. });
  422. }
  423. if (!that.account) return that.$util.Tips({
  424. title: '请填写手机号码'
  425. });
  426. if (!/^1(3|4|5|7|8|9|6)\d{9}$/i.test(that.account)) return that.$util.Tips({
  427. title: '请输入正确的手机号码'
  428. });
  429. if (!that.captcha) return that.$util.Tips({
  430. title: '请填写验证码'
  431. });
  432. if (!/^[\w\d]+$/i.test(that.captcha)) return that.$util.Tips({
  433. title: '请输入正确的验证码'
  434. });
  435. if (that.appLoginStatus) {
  436. that.wxLoginApi()
  437. } else if (that.appleLoginStatus) {
  438. that.appleLoginApi()
  439. } else {
  440. if (this.keyLock) {
  441. this.keyLock = !this.keyLock
  442. } else {
  443. return that.$util.Tips({
  444. title: '请勿重复点击'
  445. });
  446. }
  447. loginMobile({
  448. phone: that.account,
  449. captcha: that.captcha,
  450. spread: that.$Cache.get("spread")
  451. })
  452. .then(res => {
  453. let data = res.data;
  454. that.$store.commit("LOGIN", {
  455. 'token': data.token,
  456. 'time': data.expires_time - this.$Cache.time()
  457. });
  458. let backUrl = that.$Cache.get(BACK_URL) || "/pages/index/index";
  459. that.$Cache.clear(BACK_URL);
  460. getUserInfo().then(res => {
  461. this.keyLock = true
  462. that.$store.commit("SETUID", res.data.uid);
  463. that.$store.commit("UPDATE_USERINFO", res.data);
  464. if (backUrl.indexOf('/pages/users/login/index') !== -1) {
  465. backUrl = '/pages/index/index';
  466. }
  467. uni.reLaunch({
  468. url: backUrl
  469. });
  470. })
  471. })
  472. .catch(res => {
  473. this.keyLock = true
  474. that.$util.Tips({
  475. title: res
  476. });
  477. });
  478. }
  479. },
  480. async register() {
  481. let that = this;
  482. if (!that.account) return that.$util.Tips({
  483. title: '请填写手机号码'
  484. });
  485. if (!/^1(3|4|5|7|8|9|6)\d{9}$/i.test(that.account)) return that.$util.Tips({
  486. title: '请输入正确的手机号码'
  487. });
  488. if (!that.captcha) return that.$util.Tips({
  489. title: '请填写验证码'
  490. });
  491. if (!/^[\w\d]+$/i.test(that.captcha)) return that.$util.Tips({
  492. title: '请输入正确的验证码'
  493. });
  494. if (!that.password) return that.$util.Tips({
  495. title: '请填写密码'
  496. });
  497. if (/^([0-9]|[a-z]|[A-Z]){0,6}$/i.test(that.password)) return that.$util.Tips({
  498. title: '您输入的密码过于简单'
  499. });
  500. register({
  501. account: that.account,
  502. captcha: that.captcha,
  503. password: that.password,
  504. spread: that.$Cache.get("spread")
  505. })
  506. .then(res => {
  507. that.$util.Tips({
  508. title: res
  509. });
  510. that.formItem = 1;
  511. })
  512. .catch(res => {
  513. that.$util.Tips({
  514. title: res
  515. });
  516. });
  517. },
  518. async getCode() {
  519. let that = this;
  520. if (!that.account) return that.$util.Tips({
  521. title: '请填写手机号码'
  522. });
  523. if (!/^1(3|4|5|7|8|9|6)\d{9}$/i.test(that.account)) return that.$util.Tips({
  524. title: '请输入正确的手机号码'
  525. });
  526. if (that.formItem == 2) that.type = "register";
  527. await registerVerify({
  528. phone: that.account,
  529. type: that.type,
  530. key: that.keyCode,
  531. code: that.codeVal
  532. })
  533. .then(res => {
  534. that.$util.Tips({
  535. title: res.msg
  536. });
  537. that.sendCode();
  538. })
  539. .catch(res => {
  540. that.$util.Tips({
  541. title: res
  542. });
  543. });
  544. },
  545. navTap: function(index) {
  546. this.current = index;
  547. },
  548. async submit() {
  549. let that = this;
  550. if (!that.protocol) {
  551. this.inAnimation = true
  552. return that.$util.Tips({
  553. title: '请先阅读并同意协议'
  554. });
  555. }
  556. if (!that.account) return that.$util.Tips({
  557. title: '请填写账号'
  558. });
  559. if (!/^[\w\d]{5,16}$/i.test(that.account)) return that.$util.Tips({
  560. title: '请输入正确的账号'
  561. });
  562. if (!that.password) return that.$util.Tips({
  563. title: '请填写密码'
  564. });
  565. if (this.keyLock) {
  566. this.keyLock = !this.keyLock
  567. } else {
  568. return that.$util.Tips({
  569. title: '请勿重复点击'
  570. });
  571. }
  572. loginH5({
  573. account: that.account,
  574. password: that.password,
  575. spread: that.$Cache.get("spread")
  576. })
  577. .then(({
  578. data
  579. }) => {
  580. that.$store.commit("LOGIN", {
  581. 'token': data.token,
  582. 'time': data.expires_time - this.$Cache.time()
  583. });
  584. let backUrl = that.$Cache.get(BACK_URL) || "/pages/index/index";
  585. that.$Cache.clear(BACK_URL);
  586. getUserInfo().then(res => {
  587. this.keyLock = true
  588. that.$store.commit("SETUID", res.data.uid);
  589. that.$store.commit("UPDATE_USERINFO", res.data);
  590. uni.reLaunch({
  591. url: backUrl
  592. });
  593. }).catch(error => {
  594. this.keyLock = true
  595. })
  596. })
  597. .catch(e => {
  598. this.keyLock = true
  599. that.$util.Tips({
  600. title: e
  601. });
  602. });
  603. },
  604. privacy(type) {
  605. uni.navigateTo({
  606. url: "/pages/users/privacy/index?type=" + type
  607. })
  608. }
  609. }
  610. };
  611. </script>
  612. <style>
  613. page {}
  614. </style>
  615. <style lang="scss">
  616. .itemImg-add {
  617. width: 24rpx;
  618. height: 34rpx;
  619. }
  620. .item-img {
  621. width: 28rpx;
  622. height: 32rpx;
  623. }
  624. /deep/uni-checkbox .uni-checkbox-input{
  625. margin-top: -6rpx;
  626. }
  627. .appLogin {
  628. margin-top: 60rpx;
  629. .hds {
  630. display: flex;
  631. justify-content: center;
  632. align-items: center;
  633. font-size: 24rpx;
  634. color: #B4B4B4;
  635. .line {
  636. width: 68rpx;
  637. height: 1rpx;
  638. background: #CCCCCC;
  639. }
  640. p {
  641. margin: 0 20rpx;
  642. }
  643. }
  644. .btn-wrapper {
  645. display: flex;
  646. align-items: center;
  647. justify-content: center;
  648. margin-top: 30rpx;
  649. .btn {
  650. display: flex;
  651. align-items: center;
  652. justify-content: center;
  653. width: 68rpx;
  654. height: 68rpx;
  655. border-radius: 50%;
  656. }
  657. .apple-btn {
  658. display: flex;
  659. align-items: center;
  660. justify-content: center;
  661. width: 246rpx;
  662. height: 66rpx;
  663. margin-left: 30rpx;
  664. background: #EAEAEA;
  665. border-radius: 34rpx;
  666. font-size: 24rpx;
  667. .icon-s-pingguo {
  668. color: #333;
  669. margin-right: 10rpx;
  670. font-size: 34rpx;
  671. }
  672. }
  673. .iconfont {
  674. font-size: 40rpx;
  675. color: #fff;
  676. }
  677. .wx {
  678. background-color: #61C64F;
  679. }
  680. .mima {
  681. background-color: #28B3E9;
  682. }
  683. .yanzheng {
  684. background-color: #F89C23;
  685. }
  686. .pingguo {
  687. margin-left: 60rpx;
  688. background-color: #000;
  689. }
  690. }
  691. }
  692. .main-color {
  693. color: var(--view-theme);
  694. }
  695. .code img {
  696. width: 100%;
  697. height: 100%;
  698. }
  699. .acea-row.row-middle {
  700. input {
  701. margin-left: 20rpx;
  702. display: block;
  703. }
  704. }
  705. .login-wrapper {
  706. .login-top {
  707. height: 358rpx;
  708. background-color: var(--view-theme);
  709. background-image: url(../static/login.png);
  710. background-size: cover;
  711. background-repeat: no-repeat;
  712. image {
  713. width: 101%;
  714. height: 100%;
  715. }
  716. }
  717. .shading {
  718. display: flex;
  719. align-items: center;
  720. justify-content: center;
  721. width: 100%;
  722. margin-top: -230rpx;
  723. position: relative;
  724. image {
  725. width: 180rpx;
  726. height: 180rpx;
  727. top: 40rpx;
  728. }
  729. }
  730. .whiteBg {
  731. background-color: #fff;
  732. margin: -30rpx 56rpx 0rpx 56rpx;
  733. box-shadow: 0px 2px 14px 0px rgba(0, 0, 0, 0.08);
  734. border-radius: 8px;
  735. padding: 60rpx;
  736. .tips {
  737. display: flex;
  738. align-items: center;
  739. justify-content: center;
  740. height: 50rpx;
  741. margin: 40rpx;
  742. color: #999;
  743. .tips-btn {
  744. margin: 0 31rpx 0 48rpx;
  745. color: #999999;
  746. font-weight: bold;
  747. font-size: 32rpx;
  748. /* Safari 与 Chrome */
  749. .line {
  750. width: 80rpx;
  751. height: 6rpx;
  752. background: linear-gradient(135deg, var(--view-minorColor) 0%, var(--view-theme) 100%);
  753. border-radius: 2px;
  754. margin: 10rpx auto 0 auto;
  755. animation: myfirst .3s;
  756. -webkit-animation: myfirst .3s;
  757. }
  758. .none {
  759. width: 80rpx;
  760. background: #fff;
  761. height: 6rpx;
  762. }
  763. }
  764. @keyframes myfirst {
  765. 0% {
  766. width: 0rpx;
  767. }
  768. 100% {
  769. width: 80rpx;
  770. }
  771. }
  772. @-webkit-keyframes myfirst
  773. /* Safari 与 Chrome */
  774. {
  775. 0% {
  776. width: 0rpx;
  777. }
  778. 100% {
  779. width: 80rpx;
  780. }
  781. }
  782. .tips-btn.on {
  783. font-size: 36rpx;
  784. color: var(--view-theme);
  785. }
  786. }
  787. .list {
  788. border-radius: 16rpx;
  789. overflow: hidden;
  790. .forgetPwd {
  791. text-align: right;
  792. margin-top: 10rpx;
  793. color: #666666;
  794. font-size: 24rpx;
  795. }
  796. .item {
  797. border-bottom: 1px solid #F0F0F0;
  798. background: #fff;
  799. .row-middle {
  800. position: relative;
  801. padding: 16rpx 25rpx;
  802. input {
  803. flex: 1;
  804. font-size: 28rpx;
  805. height: 80rpx;
  806. }
  807. .code {
  808. position: absolute;
  809. right: 30rpx;
  810. top: 50%;
  811. color: var(--view-theme);
  812. font-size: 26rpx;
  813. transform: translateY(-50%);
  814. }
  815. }
  816. }
  817. }
  818. .logon {
  819. display: flex;
  820. align-items: center;
  821. justify-content: center;
  822. width: 100%;
  823. height: 86rpx;
  824. margin-top: 48rpx;
  825. background: linear-gradient(135deg, var(--view-minorColor) 0%, var(--view-theme) 100%);
  826. border-radius: 120rpx;
  827. color: #FFFFFF;
  828. font-size: 30rpx;
  829. }
  830. }
  831. .protocol {
  832. margin-top: 40rpx;
  833. color: #999999;
  834. font-size: 24rpx;
  835. }
  836. .trembling {
  837. animation: shake 0.6s;
  838. }
  839. @keyframes shake {
  840. 0%,
  841. 100% {
  842. -webkit-transform: translateX(0);
  843. }
  844. 10%,
  845. 30%,
  846. 50%,
  847. 70%,
  848. 90% {
  849. -webkit-transform: translateX(-5rpx);
  850. }
  851. 20%,
  852. 40%,
  853. 60%,
  854. 80% {
  855. -webkit-transform: translateX(5rpx);
  856. }
  857. }
  858. @-o-keyframes shake {
  859. /* Opera */
  860. 0%,
  861. 100% {
  862. -webkit-transform: translateX(0);
  863. }
  864. 10%,
  865. 30%,
  866. 50%,
  867. 70%,
  868. 90% {
  869. -webkit-transform: translateX(-5rpx);
  870. }
  871. 20%,
  872. 40%,
  873. 60%,
  874. 80% {
  875. -webkit-transform: translateX(5rpx);
  876. }
  877. }
  878. @-webkit-keyframes shake {
  879. /* Safari 和 Chrome */
  880. 0%,
  881. 100% {
  882. -webkit-transform: translateX(0);
  883. }
  884. 10%,
  885. 30%,
  886. 50%,
  887. 70%,
  888. 90% {
  889. -webkit-transform: translateX(-5rpx);
  890. }
  891. 20%,
  892. 40%,
  893. 60%,
  894. 80% {
  895. -webkit-transform: translateX(5rpx);
  896. }
  897. }
  898. @-moz-keyframes shake {
  899. /* Firefox */
  900. 0%,
  901. 100% {
  902. -moz-transform: translateX(0);
  903. }
  904. 10%,
  905. 30%,
  906. 50%,
  907. 70%,
  908. 90% {
  909. -moz-transform: translateX(-5rpx);
  910. }
  911. 20%,
  912. 40%,
  913. 60%,
  914. 80% {
  915. -moz-transform: translateX(5rpx);
  916. }
  917. }
  918. }
  919. </style>