user-login.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. <template>
  2. <el-form ref="loginForm" :rules="loginRules" :model="loginForm" class="login-form" status-icon label-width="80" @submit.native.prevent>
  3. </br>
  4. </br>
  5. <el-form-item label="账号" style="font-weight: 1000;font-family: arial black;" prop="username" >
  6. <el-input v-model="loginForm.username" :placeholder="$t('login.username')" tabindex="1" auto-complete="on" prefix-icon="ibps-icon-user" @keyup.enter.native="handleLogin"
  7. style="width:100%;"/>
  8. </el-form-item>
  9. <el-tooltip v-model="capsTooltip" :content="$t('login.capsTooltip')" placement="right" manual>
  10. <el-form-item label="密码" style="font-weight: 1000;font-family: arial black;" prop="password">
  11. <el-input
  12. v-model="loginForm.password"
  13. :type="passwordType"
  14. :placeholder="$t('login.password')"
  15. tabindex="2"
  16. auto-complete="on"
  17. prefix-icon="ibps-icon-lock"
  18. @keyup.native="checkCapslock"
  19. @blur="capsTooltip = false"
  20. style="width: 100%;"
  21. @keyup.enter.native="handleLogin"
  22. >
  23. <i slot="suffix" :class="passwordType==='password'?'ibps-icon-eye-slash':'ibps-icon-eye'" class=" el-input__icon" @click="showPassword" />
  24. </el-input>
  25. </el-form-item>
  26. </el-tooltip>
  27. <el-form-item v-if="enabledValidCode" prop="captcha">
  28. <el-row :span="24">
  29. <el-col :span="15">
  30. <el-input v-model="loginForm.captcha" :maxlength="code.len" :placeholder="$t('login.code')" tabindex="3" auto-complete="on" prefix-icon="ibps-icon-qrcode" @keyup.enter.native="handleLogin" />
  31. </el-col>
  32. <el-col :span="9">
  33. <div class="login-code">
  34. <span v-if="code.type === 'text'" class="login-code-img" @click="refreshCode">{{ code.value }}</span>
  35. <img v-else :src="code.src" class="login-code-img" @click="refreshCode">
  36. </div>
  37. </el-col>
  38. </el-row>
  39. </el-form-item>
  40. <el-form-item prop="remember" class="remember">
  41. <el-row :span="24">
  42. <el-col :span="14">
  43. <el-checkbox class="remember" v-model="loginForm.remember" >{{ $t('login.remember') }}</el-checkbox>
  44. </el-col>
  45. <el-col v-if="isRegOpen || isTenantOpen" :span="10">
  46. <el-button v-if="!isTenantOpen" type="text" class="forget" @click="forget">{{ $t('login.forget') }}</el-button>
  47. <el-button v-if="isTenantOpen" type="text" class="forget" @click="tenantForget">{{ $t('login.forget') }}</el-button>
  48. <el-divider v-if="isRegOpen" direction="vertical" />
  49. <el-button v-if="isRegOpen" type="text" class="register" @click="register">{{ $t('login.register') }}</el-button>
  50. <el-divider v-if="isTenantOpen" direction="vertical" />
  51. <el-button v-if="isTenantOpen" type="text" class="register" @click="tenantRegister">{{ $t('login.tenantRegister') }}</el-button>
  52. </el-col>
  53. </el-row>
  54. </el-form-item>
  55. </br>
  56. <el-form-item>
  57. <el-button :loading="loading" type="primary" class="login-submit" @click.native.prevent="handleLogin">{{ $t('login.logIn') }}</el-button>
  58. </el-form-item>
  59. </el-form>
  60. </template>
  61. <script>
  62. import { mapActions } from 'vuex'
  63. import Utils from '@/utils/util'
  64. import I18n from '@/utils/i18n'
  65. const loginForm = process.env.NODE_ENV === 'development'
  66. ? {
  67. username: 'admin',
  68. password: '1',
  69. captcha: '',
  70. remember: true,
  71. requestId: ''
  72. } : {
  73. username: '',
  74. password: '',
  75. captcha: '',
  76. remember: true,
  77. requestId: ''
  78. }
  79. const validateUsername = (rule, value, callback) => {
  80. if (Utils.isEmpty(value)) {
  81. return callback(new Error(I18n.t('login.usernameCorrect')))
  82. }
  83. callback()
  84. }
  85. const validateMobile = (rule, value, callback) => {
  86. if (Utils.isEmpty(value)) {
  87. return callback(new Error(I18n.t('手机号不能为空')))
  88. } else {
  89. const isPhone = /^1(3|4|5|6|7|8|9)\d{9}$/
  90. if (value.length === 11) {
  91. if (!isPhone.test(value)) {
  92. return callback(new Error(I18n.t('请输入正确手机号')))
  93. } else {
  94. callback()
  95. }
  96. } else {
  97. if (!isPhone.test(value)) {
  98. return callback(new Error(I18n.t('请输入正确手机号')))
  99. } else {
  100. return callback(new Error(I18n.t('请输入正确手机号长度')))
  101. }
  102. }
  103. }
  104. }
  105. const validateCode = (rule, value, callback) => {
  106. callback()
  107. // if (this.code.value !== value) {
  108. // this.loginForm.captcha = ''
  109. // this.loadValidCode(false)
  110. // callback(new Error(I18n.t('login.codeCorrect')))
  111. // } else {
  112. // callback()
  113. // }
  114. }
  115. export default {
  116. name: 'login-form',
  117. data() {
  118. return {
  119. demoVar:'123',
  120. enabledValidCode: false,
  121. loginForm,
  122. isRegOpen: false,
  123. isTenantOpen: false,
  124. validateMobile: validateMobile,
  125. code: {
  126. src: '',
  127. value: '',
  128. len: 5,
  129. type: 'src'
  130. },
  131. loginRules: {
  132. username: [
  133. { required: true, trigger: 'blur', message: this.$t('login.usernameCorrect'), validator: validateUsername }
  134. ],
  135. password: [
  136. { required: true, message: this.$t('login.password'), trigger: 'blur' },
  137. { min: 1, message: this.$t('login.passwordCorrect'), trigger: 'blur' }
  138. ],
  139. captcha: [
  140. { required: true, message: this.$t('login.code'), trigger: 'blur' },
  141. { required: true, trigger: 'blur', validator: validateCode }
  142. ]
  143. },
  144. passwordType: 'password',
  145. capsTooltip: false,
  146. loading: false
  147. }
  148. },
  149. watch: {
  150. isRegOpen: {
  151. handler: function(val, oldVal) {
  152. if (val) {
  153. this.loginRules.username = [{ required: true, trigger: 'blur', validator: validateMobile }]
  154. } else {
  155. this.loginRules.username = [{ required: true, trigger: 'blur', validator: validateUsername }]
  156. }
  157. },
  158. immediate: true
  159. }
  160. },
  161. created() {
  162. this.initValidCode()
  163. this.loadValidCode(true)
  164. this.isRegisterOpen()
  165. },
  166. mounted() {
  167. // 注销退出清空验证码
  168. this.loginForm.captcha = ''
  169. // 注销退出清空请求ID
  170. this.loginForm.requestId = ''
  171. },
  172. methods: {
  173. ...mapActions({
  174. 'login': 'ibps/account/login',
  175. 'getCaptcha': 'ibps/account/getCaptcha',
  176. 'getRegisterOpen': 'ibps/account/getRegisterOpen',
  177. 'getRegisterTenantOpen': 'ibps/saas/getRegisterTenantOpen'
  178. }),
  179. initValidCode() {
  180. if (this.enabledValidCode) {
  181. this.loginRules.captcha[0]['required'] = true
  182. this.loginRules.captcha[1]['required'] = true
  183. } else {
  184. this.loginRules.captcha[0]['required'] = false
  185. this.loginRules.captcha[1]['required'] = false
  186. }
  187. },
  188. isRegisterOpen() {
  189. this.getRegisterOpen().then((data) => {
  190. this.isRegOpen = data.data
  191. }).catch((e) => {})
  192. this.getRegisterTenantOpen().then((data) => {
  193. this.isTenantOpen = data.data
  194. }).catch((e) => {})
  195. },
  196. // 获取验证码
  197. loadValidCode(isBackfill) {
  198. this.getCaptcha({ params: { requestId: this.loginForm.requestId }}).then((data) => {
  199. // 返回状态501,说明系统没有开启验证码
  200. if (data.state === 501) {
  201. this.enabledValidCode = false
  202. } else {
  203. this.enabledValidCode = true
  204. this.code.src = data.data
  205. this.loginForm.requestId = data.variables.requestId
  206. }
  207. this.initValidCode()
  208. if (isBackfill) {
  209. this.loginForm.code = this.code.value
  210. }
  211. }).catch((e) => {
  212. })
  213. },
  214. refreshCode() {
  215. this.loadValidCode()
  216. },
  217. checkCapslock({ shiftKey, key } = {}) {
  218. if (key && key.length === 1) {
  219. if ((shiftKey && (key >= 'a' && key <= 'z')) || (!shiftKey && (key >= 'A' && key <= 'Z'))) {
  220. this.capsTooltip = true
  221. } else {
  222. this.capsTooltip = false
  223. }
  224. }
  225. if (key === 'CapsLock' && this.capsTooltip === true) {
  226. this.capsTooltip = false
  227. }
  228. },
  229. showPassword() {
  230. this.passwordType === ''
  231. ? (this.passwordType = 'password')
  232. : (this.passwordType = '')
  233. },
  234. forget() {
  235. this.$router.replace('/forget')
  236. },
  237. tenantForget() {
  238. this.$router.replace('/tenantForget')
  239. },
  240. register() {
  241. this.$router.replace('/register')
  242. },
  243. tenantRegister() {
  244. this.$router.replace('/tenantRegister')
  245. },
  246. handleLogin() {
  247. this.$refs.loginForm.validate(valid => {
  248. if (valid) {
  249. this.loading = true
  250. const loading = this.$loading({
  251. lock: true,
  252. text: this.$t('common.loading'),
  253. background: 'rgba(0, 0, 0, 0.7)'
  254. })
  255. this.login({
  256. form: this.loginForm
  257. }).then((data) => {
  258. localStorage.setItem('statistic', data.statistic)
  259. // 更新路由 尝试去获取 cookie 里保存的需要重定向的页面完整地址
  260. const redirect = this.$route.query.redirect
  261. if (redirect && redirect !== '/refresh') {
  262. if(data && (data.statistic === "isMaster"||data.statistic === "isCharger" )){
  263. // 重定向到开始路径
  264. this.$router.replace('/dashboard')
  265. } else {
  266. this.$router.replace('/')
  267. }
  268. } else {
  269. if(data && (data.statistic === "isMaster"||data.statistic === "isCharger" )){
  270. // 重定向到开始路径
  271. this.$router.replace('/dashboard')
  272. } else {
  273. this.$router.replace('/')
  274. }
  275. }
  276. // 延迟10秒关闭遮盖层
  277. setTimeout(() => {
  278. this.loading = false
  279. loading.close()
  280. }, 1000)
  281. }).catch((err) => {
  282. // 验证码错误自动清空&密码输入错误3次后触发验证码填写模块
  283. if (err && err.state === 6020104) {
  284. this.loginForm.captcha = ''
  285. this.enabledValidCode = true
  286. this.refreshCode()
  287. }
  288. // 有错误状态开启验证码需要刷新验证码
  289. if (err && err.state && this.enabledValidCode) {
  290. this.loginForm.captcha = ''
  291. this.refreshCode()
  292. }
  293. this.loading = false
  294. loading.close()
  295. })
  296. } else {
  297. this.$message.closeAll()
  298. this.$message({
  299. message: this.$t('common.dialog.saveError'),
  300. type: 'warning'
  301. })
  302. return false
  303. }
  304. })
  305. }
  306. }
  307. }
  308. </script>
  309. <style scoped>
  310. ::v-deep .remember .el-checkbox__input.is-checked .el-checkbox__inner, .remember .el-checkbox__input.is-indeterminate .el-checkbox__inner{
  311. background-color: rgb(180,35,41);
  312. border-color:rgb(180,35,41);
  313. }
  314. ::v-deep .remember .el-checkbox__input.is-checked+.el-checkbox__label {
  315. color: rgb(180,35,41);
  316. }
  317. ::v-deep .login-submit {
  318. background-color: rgb(180,35,41);
  319. }
  320. ::v-deep .login-submit:hover {
  321. background-color: rgb(180,35,41);
  322. }
  323. ::v-deep .el-button--primary {
  324. border-color: rgb(180,35,41);
  325. }
  326. </style>