index.vue 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. <template>
  2. <div class="simple-login">
  3. <van-overlay :show="show" @click="show = false">
  4. <div class="wrapper flex justify-center items-center" @click.stop>
  5. <div class="block flex items-center flex-col py-6">
  6. <div class="close" @click="onClose"></div>
  7. <div class="title pb-6">登录</div>
  8. <div class="forlogoutm">
  9. <div class="form-item mb-4">
  10. <input
  11. type="text"
  12. placeholder="手机号"
  13. v-model="formData.mobile"
  14. />
  15. </div>
  16. <div class="form-item mb-4 code">
  17. <input
  18. type="text"
  19. placeholder="验证码"
  20. class="code"
  21. v-model="formData.verifyCode"
  22. />
  23. <span class="send" @click="onSend">{{ sendCodeBtnText }}</span>
  24. </div>
  25. <div class="submit" @click="onSubmit">登录</div>
  26. </div>
  27. </div>
  28. </div>
  29. </van-overlay>
  30. </div>
  31. </template>
  32. <script>
  33. import { mapGetters } from 'vuex'
  34. import { isMobile } from '@/utils/validator'
  35. export default {
  36. name: 'simple-login',
  37. data() {
  38. return {
  39. show: false,
  40. sendStatus: 0,
  41. formData: {
  42. appId: '',
  43. mobile: '',
  44. verifyCode: '',
  45. },
  46. timer: null,
  47. }
  48. },
  49. computed: {
  50. ...mapGetters(['loginVisiable', 'appId']),
  51. sendCodeBtnText() {
  52. return this.sendStatus === 0
  53. ? '发送验证码'
  54. : `再次发送${this.sendStatus}s`
  55. },
  56. },
  57. watch: {
  58. loginVisiable() {
  59. this.show = this.loginVisiable
  60. },
  61. },
  62. methods: {
  63. async onSubmit() {
  64. try {
  65. this.formData.appId = this.appId
  66. const res = await this.$http.api.customLogin(this.formData)
  67. this.$store.dispatch('user/login', res.data)
  68. this.$store.commit('app/HIDE_LOGIN')
  69. } catch (error) {
  70. console.log(error)
  71. }
  72. },
  73. onClose() {
  74. this.$store.commit('app/HIDE_LOGIN')
  75. },
  76. async onSend() {
  77. if (this.sendStatus > 0) return
  78. // 验证手机号是否合法
  79. if (!isMobile(this.formData.mobile)) {
  80. this.$toast('请输入正确的手机号')
  81. return
  82. }
  83. try {
  84. // 发送验证码
  85. const res = await this.$http.api.sendVerifyCode({
  86. mobile: this.formData.mobile,
  87. appId: this.appId,
  88. type: 1,
  89. })
  90. this.$toast('验证码已发送')
  91. // 开启倒计时
  92. this.countdown()
  93. } catch (error) {
  94. console.log(error)
  95. }
  96. },
  97. countdown() {
  98. this.sendStatus = 30
  99. this.timer = setInterval(() => {
  100. if (this.sendStatus === 0) {
  101. clearInterval(this.timer)
  102. return
  103. }
  104. this.sendStatus--
  105. }, 1000)
  106. },
  107. },
  108. }
  109. </script>
  110. <style scoped lang="scss">
  111. @media screen and (min-width: 768px) {
  112. .wrapper {
  113. height: 100vh;
  114. .block {
  115. position: relative;
  116. width: 400px;
  117. background: #fff;
  118. .close {
  119. position: absolute;
  120. right: 16px;
  121. top: 16px;
  122. width: 24px;
  123. height: 24px;
  124. background: url(https://static.caimei365.com/www/authentic/h5/icon-close.png)
  125. center no-repeat;
  126. background-size: 24px 24px;
  127. cursor: pointer;
  128. }
  129. .title {
  130. font-size: 24px;
  131. color: #101010;
  132. }
  133. .form-item {
  134. position: relative;
  135. width: 326px;
  136. input {
  137. width: 326px;
  138. display: block;
  139. padding: 14px 16px;
  140. font-size: 14px;
  141. border: 1px solid #d8d8d8;
  142. box-sizing: border-box;
  143. &.code {
  144. width: 225px;
  145. }
  146. }
  147. .send {
  148. position: absolute;
  149. right: 0;
  150. top: 50%;
  151. transform: translateY(-50%);
  152. font-size: 16px;
  153. color: #bc1724;
  154. cursor: pointer;
  155. }
  156. }
  157. .submit {
  158. width: 326px;
  159. height: 46px;
  160. background: #bc1724;
  161. font-size: 16px;
  162. color: #fff;
  163. text-align: center;
  164. line-height: 46px;
  165. transition: all 0.4s;
  166. cursor: pointer;
  167. &:hover {
  168. background-color: #960915;
  169. }
  170. }
  171. }
  172. }
  173. }
  174. @media screen and (max-width: 768px) {
  175. .wrapper {
  176. height: 100vh;
  177. .block {
  178. position: relative;
  179. width: 76vw;
  180. background: #fff;
  181. .close {
  182. position: absolute;
  183. right: 2.4vw;
  184. top: 2.4vw;
  185. width: 5.6vw;
  186. height: 5.6vw;
  187. background: url(https://static.caimei365.com/www/authentic/h5/icon-close.png)
  188. center no-repeat;
  189. background-size: 4.8vw 4.8vw;
  190. cursor: pointer;
  191. }
  192. .title {
  193. font-size: 4.8vw;
  194. color: #101010;
  195. }
  196. .form-item {
  197. position: relative;
  198. width: 62vw;
  199. input {
  200. width: 62vw;
  201. display: block;
  202. padding: 1.8vw 2.4vw;
  203. font-size: 14px;
  204. border: 0.1vw solid #d8d8d8;
  205. box-sizing: border-box;
  206. &.code {
  207. width: 42.8vw;
  208. }
  209. }
  210. .send {
  211. position: absolute;
  212. right: 0;
  213. top: 50%;
  214. transform: translateY(-50%);
  215. font-size: 3.2vw;
  216. color: #bc1724;
  217. cursor: pointer;
  218. }
  219. }
  220. .submit {
  221. width: 62vw;
  222. height: 8.8vw;
  223. background: #bc1724;
  224. font-size: 3.2vw;
  225. color: #fff;
  226. text-align: center;
  227. line-height: 8.8vw;
  228. transition: all 0.4s;
  229. &:hover {
  230. background-color: #b60c1a;
  231. }
  232. }
  233. }
  234. }
  235. }
  236. </style>