Login.vue 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. <template>
  2. <div class="main">
  3. <a-form class="user-layout-login" ref="formLogin" :autoFormCreate="(form)=>{this.form = form}" id="formLogin">
  4. <a-tabs
  5. :activeKey="customActiveKey"
  6. :tabBarStyle="{ textAlign: 'center', borderBottom: 'unset' }"
  7. @change="handleTabClick">
  8. <a-tab-pane key="tab1" tab="账号密码登陆">
  9. <a-form-item
  10. fieldDecoratorId="username"
  11. :fieldDecoratorOptions="{rules: [{ required: true, message: '请输入帐户名或邮箱' }, { validator: this.handleUsernameOrEmail }], validateTrigger: 'change'}">
  12. <a-input size="large" type="text" placeholder="请输入帐户名 / jeecg">
  13. <a-icon slot="prefix" type="user" :style="{ color: 'rgba(0,0,0,.25)' }"/>
  14. </a-input>
  15. </a-form-item>
  16. <a-form-item
  17. fieldDecoratorId="password"
  18. :fieldDecoratorOptions="{rules: [{ required: true, message: '请输入密码' }], validateTrigger: 'blur'}">
  19. <a-input size="large" type="password" autocomplete="false" placeholder="密码 / 123456">
  20. <a-icon slot="prefix" type="lock" :style="{ color: 'rgba(0,0,0,.25)' }"/>
  21. </a-input>
  22. </a-form-item>
  23. </a-tab-pane>
  24. <a-tab-pane key="tab2" tab="手机号登陆">
  25. <a-form-item
  26. fieldDecoratorId="mobile"
  27. :fieldDecoratorOptions="{rules: [{ required: true, pattern: /^1[34578]\d{9}$/, message: '请输入正确的手机号' }], validateTrigger: 'change'}">
  28. <a-input size="large" type="text" placeholder="手机号">
  29. <a-icon slot="prefix" type="mobile" :style="{ color: 'rgba(0,0,0,.25)' }"/>
  30. </a-input>
  31. </a-form-item>
  32. <a-row :gutter="16">
  33. <a-col class="gutter-row" :span="16">
  34. <a-form-item
  35. fieldDecoratorId="captcha"
  36. :fieldDecoratorOptions="{rules: [{ required: true, message: '请输入验证码' }], validateTrigger: 'blur'}">
  37. <a-input size="large" type="text" placeholder="验证码">
  38. <a-icon slot="prefix" type="mail" :style="{ color: 'rgba(0,0,0,.25)' }"/>
  39. </a-input>
  40. </a-form-item>
  41. </a-col>
  42. <a-col class="gutter-row" :span="8">
  43. <a-button
  44. class="getCaptcha"
  45. tabindex="-1"
  46. :disabled="state.smsSendBtn"
  47. @click.stop.prevent="getCaptcha"
  48. v-text="!state.smsSendBtn && '获取验证码' || (state.time+' s')"></a-button>
  49. </a-col>
  50. </a-row>
  51. </a-tab-pane>
  52. </a-tabs>
  53. <a-form-item>
  54. <a-checkbox v-model="formLogin.rememberMe">自动登陆</a-checkbox>
  55. <router-link :to="{ name: 'recover', params: { user: 'aaa'} }" class="forge-password" style="float: right;">
  56. 忘记密码
  57. </router-link>
  58. </a-form-item>
  59. <a-form-item style="margin-top:24px">
  60. <a-button
  61. size="large"
  62. type="primary"
  63. htmlType="submit"
  64. class="login-button"
  65. :loading="loginBtn"
  66. @click.stop.prevent="handleSubmit"
  67. :disabled="loginBtn">确定
  68. </a-button>
  69. </a-form-item>
  70. <div class="user-login-other">
  71. <span>其他登陆方式</span>
  72. <a><a-icon class="item-icon" type="alipay-circle"></a-icon></a>
  73. <a><a-icon class="item-icon" type="taobao-circle"></a-icon></a>
  74. <a><a-icon class="item-icon" type="weibo-circle"></a-icon></a>
  75. <router-link class="register" :to="{ name: 'register' }">
  76. 注册账户
  77. </router-link>
  78. </div>
  79. </a-form>
  80. <two-step-captcha
  81. v-if="requiredTwoStepCaptcha"
  82. :visible="stepCaptchaVisible"
  83. @success="stepCaptchaSuccess"
  84. @cancel="stepCaptchaCancel"></two-step-captcha>
  85. </div>
  86. </template>
  87. <script>
  88. //import md5 from "md5"
  89. import api from '@/api'
  90. import TwoStepCaptcha from '@/components/tools/TwoStepCaptcha'
  91. import { mapActions } from "vuex"
  92. import { timeFix } from "@/utils/util"
  93. import Vue from 'vue'
  94. import { ACCESS_TOKEN } from "@/store/mutation-types"
  95. export default {
  96. components: {
  97. TwoStepCaptcha
  98. },
  99. data () {
  100. return {
  101. customActiveKey: "tab1",
  102. loginBtn: false,
  103. // login type: 0 email, 1 username, 2 telephone
  104. loginType: 0,
  105. requiredTwoStepCaptcha: false,
  106. stepCaptchaVisible: false,
  107. form: null,
  108. state: {
  109. time: 60,
  110. smsSendBtn: false,
  111. },
  112. formLogin: {
  113. username: "",
  114. password: "",
  115. captcha: "",
  116. mobile: "",
  117. rememberMe: true
  118. },
  119. }
  120. },
  121. created () {
  122. Vue.ls.remove(ACCESS_TOKEN)
  123. // update-begin- --- author:scott ------ date:20190225 ---- for:暂时注释,未实现登录验证码功能
  124. // this.$http.get('/auth/2step-code')
  125. // .then(res => {
  126. // this.requiredTwoStepCaptcha = res.result.stepCode
  127. // }).catch(err => {
  128. // console.log('2step-code:', err)
  129. // })
  130. // update-end- --- author:scott ------ date:20190225 ---- for:暂时注释,未实现登录验证码功能
  131. // this.requiredTwoStepCaptcha = true
  132. },
  133. methods: {
  134. ...mapActions([ "Login", "Logout" ]),
  135. // handler
  136. handleUsernameOrEmail (rule, value, callback) {
  137. const regex = /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((\.[a-zA-Z0-9_-]{2,3}){1,2})$/;
  138. if (regex.test(value)) {
  139. this.loginType = 0
  140. } else {
  141. this.loginType = 1
  142. }
  143. callback()
  144. },
  145. handleTabClick (key) {
  146. this.customActiveKey = key
  147. // this.form.resetFields()
  148. },
  149. handleSubmit () {
  150. let that = this
  151. let flag = false
  152. let loginParams = {
  153. remember_me: that.formLogin.rememberMe
  154. };
  155. // 使用账户密码登陆
  156. if (that.customActiveKey === 'tab1') {
  157. that.form.validateFields([ 'username', 'password' ], { force: true }, (err, values) => {
  158. if (!err) {
  159. flag = true
  160. loginParams[!that.loginType ? 'email' : 'username'] = values.username
  161. //loginParams.password = md5(values.password)
  162. loginParams.password = values.password
  163. }
  164. })
  165. // 使用手机号登陆
  166. } else {
  167. that.form.validateFields([ 'mobile', 'captcha' ], { force: true }, (err, values) => {
  168. if (!err) {
  169. flag = true
  170. loginParams = Object.assign(loginParams, values)
  171. }
  172. })
  173. }
  174. if (!flag) return
  175. that.loginBtn = true
  176. that.Login(loginParams).then(() => {
  177. if (that.requiredTwoStepCaptcha) {
  178. that.stepCaptchaVisible = true
  179. } else {
  180. that.loginSuccess()
  181. }
  182. }).catch((err) => {
  183. that.requestFailed(err);
  184. })
  185. },
  186. getCaptcha (e) {
  187. e.preventDefault()
  188. let that = this
  189. this.form.validateFields([ 'mobile' ], { force: true },
  190. (err) => {
  191. if (!err) {
  192. this.state.smsSendBtn = true;
  193. let interval = window.setInterval(() => {
  194. if (that.state.time-- <= 0) {
  195. that.state.time = 60;
  196. that.state.smsSendBtn = false;
  197. window.clearInterval(interval);
  198. }
  199. }, 1000);
  200. const hide = this.$message.loading('验证码发送中..', 0);
  201. this.$http.post(api.SendSms, { mobile: that.formLogin.mobile })
  202. .then(res => {
  203. setTimeout(hide, 2500);
  204. this.$notification[ 'success' ]({
  205. message: '提示',
  206. description: '验证码获取成功,您的验证码为:' + res.result.captcha,
  207. duration: 8
  208. })
  209. })
  210. .catch(err => {
  211. setTimeout(hide, 1);
  212. clearInterval(interval);
  213. that.state.time = 60;
  214. that.state.smsSendBtn = false;
  215. this.requestFailed(err);
  216. });
  217. }
  218. }
  219. );
  220. },
  221. stepCaptchaSuccess () {
  222. this.loginSuccess()
  223. },
  224. stepCaptchaCancel () {
  225. this.Logout().then(() => {
  226. this.loginBtn = false
  227. this.stepCaptchaVisible = false
  228. })
  229. },
  230. loginSuccess () {
  231. this.loginBtn = false
  232. this.$router.push({ name: "dashboard" })
  233. this.$notification.success({
  234. message: '欢迎',
  235. description: `${timeFix()},欢迎回来`,
  236. });
  237. },
  238. requestFailed (err) {
  239. this.$notification[ 'error' ]({
  240. message: '登录失败',
  241. description: ((err.response || {}).data || {}).message || err.message || "请求出现错误,请稍后再试",
  242. duration: 4,
  243. });
  244. this.loginBtn = false;
  245. },
  246. }
  247. }
  248. </script>
  249. <style lang="scss" scoped>
  250. .user-layout-login {
  251. label {
  252. font-size: 14px;
  253. }
  254. .getCaptcha {
  255. display: block;
  256. width: 100%;
  257. height: 40px;
  258. }
  259. .forge-password {
  260. font-size: 14px;
  261. }
  262. button.login-button {
  263. padding: 0 15px;
  264. font-size: 16px;
  265. height: 40px;
  266. width: 100%;
  267. }
  268. .user-login-other {
  269. text-align: left;
  270. margin-top: 24px;
  271. line-height: 22px;
  272. .item-icon {
  273. font-size: 24px;
  274. color: rgba(0,0,0,.2);
  275. margin-left: 16px;
  276. vertical-align: middle;
  277. cursor: pointer;
  278. transition: color .3s;
  279. &:hover {
  280. color: #1890ff;
  281. }
  282. }
  283. .register {
  284. float: right;
  285. }
  286. }
  287. }
  288. </style>