user-login.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  1. <template>
  2. <el-form
  3. ref="loginForm"
  4. :rules="loginRules"
  5. :model="loginForm"
  6. class="login-form"
  7. status-icon
  8. label-width="80"
  9. @submit.native.prevent
  10. >
  11. <br/>
  12. <el-form-item label="账号" prop="username">
  13. <el-input
  14. v-model="loginForm.username"
  15. :placeholder="$t('login.username')"
  16. tabindex="1"
  17. auto-complete="on"
  18. prefix-icon="ibps-icon-user"
  19. @keyup.enter.native="handleLogin"
  20. style="width:75%;"
  21. />
  22. </el-form-item>
  23. <el-tooltip
  24. v-model="capsTooltip"
  25. :content="$t('login.capsTooltip')"
  26. placement="right"
  27. manual
  28. >
  29. <el-form-item label="密码" prop="password">
  30. <el-input
  31. v-model="loginForm.password"
  32. :type="passwordType"
  33. :placeholder="$t('login.password')"
  34. tabindex="2"
  35. auto-complete="on"
  36. prefix-icon="ibps-icon-lock"
  37. style="width: 75%;"
  38. @keyup.native="checkCapslock"
  39. @blur="capsTooltip = false"
  40. @keyup.enter.native="handleLogin"
  41. >
  42. <i
  43. slot="suffix"
  44. :class="passwordType === 'password' ? 'ibps-icon-eye-slash' : 'ibps-icon-eye'"
  45. class="el-input__icon"
  46. @click="showPassword"
  47. ></i>
  48. </el-input>
  49. </el-form-item>
  50. </el-tooltip>
  51. <el-form-item v-if="enabledValidCode" prop="captcha">
  52. <el-row :span="24">
  53. <el-col :span="15">
  54. <el-input
  55. v-model="loginForm.captcha"
  56. :maxlength="code.len"
  57. :placeholder="$t('login.code')"
  58. tabindex="3"
  59. auto-complete="on"
  60. prefix-icon="ibps-icon-qrcode"
  61. @keyup.enter.native="handleLogin"
  62. />
  63. </el-col>
  64. <el-col :span="9">
  65. <div class="login-code">
  66. <span v-if="code.type === 'text'" class="login-code-img" @click="refreshCode">{{ code.value}}</span>
  67. <img v-else :src="code.src" class="login-code-img" @click="refreshCode">
  68. </div>
  69. </el-col>
  70. </el-row>
  71. </el-form-item>
  72. <el-form-item prop="remember">
  73. <el-row :span="24">
  74. <el-col :span="14">
  75. <el-checkbox v-model="loginForm.remember">{{ $t('login.remember') }}</el-checkbox>
  76. </el-col>
  77. <el-col v-if="isRegOpen || isTenantOpen" :span="10">
  78. <el-button
  79. v-if="!isTenantOpen"
  80. type="text"
  81. class="forget"
  82. @click="forget"
  83. >{{ $t('login.forget') }}</el-button>
  84. <el-button
  85. v-if="isTenantOpen"
  86. type="text"
  87. class="forget"
  88. @click="tenantForget"
  89. >{{ $t('login.forget') }}</el-button>
  90. <el-divider v-if="isRegOpen" direction="vertical" />
  91. <el-button
  92. v-if="isRegOpen"
  93. type="text"
  94. class="register"
  95. @click="register"
  96. >{{ $t('login.register') }}</el-button>
  97. <el-divider v-if="isTenantOpen" direction="vertical" />
  98. <el-button
  99. v-if="isTenantOpen"
  100. type="text"
  101. class="register"
  102. @click="tenantRegister"
  103. >{{ $t('login.tenantRegister') }}</el-button>
  104. </el-col>
  105. </el-row>
  106. </el-form-item>
  107. <br/>
  108. <el-form-item>
  109. <el-button
  110. :loading="loading"
  111. type="primary"
  112. class="login-submit"
  113. @click.native.prevent="handleLogin"
  114. >{{ $t('login.logIn') }}</el-button>
  115. </el-form-item>
  116. </el-form>
  117. </template>
  118. <script>
  119. import { mapActions } from 'vuex'
  120. import Utils from '@/utils/util'
  121. import I18n from '@/utils/i18n'
  122. import { SZG_getServerCertificate, SZG_genRandom, SZG_signData } from '@/api/oauth2/ca'
  123. // import './xtxsync'
  124. const loginForm = process.env.NODE_ENV === 'development'
  125. ? {
  126. username: 'jinyuan',
  127. password: 'szjbd168',
  128. captcha: '',
  129. remember: true,
  130. requestId: ''
  131. } : {
  132. username: '',
  133. password: '',
  134. captcha: '',
  135. remember: true,
  136. requestId: ''
  137. }
  138. const validateUsername = (rule, value, callback) => {
  139. if (Utils.isEmpty(value)) {
  140. return callback(new Error(I18n.t('login.usernameCorrect')))
  141. }
  142. callback()
  143. }
  144. const validateMobile = (rule, value, callback) => {
  145. if (Utils.isEmpty(value)) {
  146. return callback(new Error(I18n.t('手机号不能为空')))
  147. } else {
  148. const isPhone = /^1(3|4|5|6|7|8|9)\d{9}$/
  149. if (value.length === 11) {
  150. if (!isPhone.test(value)) {
  151. return callback(new Error(I18n.t('请输入正确手机号')))
  152. } else {
  153. callback()
  154. }
  155. } else {
  156. if (!isPhone.test(value)) {
  157. return callback(new Error(I18n.t('请输入正确手机号')))
  158. } else {
  159. return callback(new Error(I18n.t('请输入正确手机号长度')))
  160. }
  161. }
  162. }
  163. }
  164. const validateCode = (rule, value, callback) => {
  165. callback()
  166. // if (this.code.value !== value) {
  167. // this.loginForm.captcha = ''
  168. // this.loadValidCode(false)
  169. // callback(new Error(I18n.t('login.codeCorrect')))
  170. // } else {
  171. // callback()
  172. // }
  173. }
  174. export default {
  175. name: 'login-form',
  176. data () {
  177. return {
  178. demoVar: '123',
  179. enabledValidCode: false,
  180. loginForm,
  181. isRegOpen: false,
  182. isTenantOpen: false,
  183. validateMobile: validateMobile,
  184. code: {
  185. src: '',
  186. value: '',
  187. len: 5,
  188. type: 'src'
  189. },
  190. loginRules: {
  191. username: [
  192. {
  193. required: true,
  194. trigger: 'blur',
  195. message: this.$t('login.usernameCorrect'),
  196. validator: validateUsername
  197. }
  198. ],
  199. password: [
  200. {
  201. required: true,
  202. message: this.$t('login.password'),
  203. trigger: 'blur'
  204. },
  205. {
  206. min: 1,
  207. message: this.$t('login.passwordCorrect'),
  208. trigger: 'blur'
  209. }
  210. ],
  211. captcha: [
  212. {
  213. required: true,
  214. message: this.$t('login.code'),
  215. trigger: 'blur'
  216. },
  217. {
  218. required: true,
  219. trigger: 'blur',
  220. validator: validateCode
  221. }
  222. ]
  223. },
  224. passwordType: 'password',
  225. capsTooltip: false,
  226. loading: false
  227. }
  228. },
  229. watch: {
  230. isRegOpen: {
  231. handler: function (val, oldVal) {
  232. if (val) {
  233. this.loginRules.username = [{
  234. required: true,
  235. trigger: 'blur',
  236. validator: validateMobile
  237. }]
  238. } else {
  239. this.loginRules.username = [{
  240. required: true,
  241. trigger: 'blur',
  242. validator: validateUsername
  243. }]
  244. }
  245. },
  246. immediate: true
  247. }
  248. },
  249. created () {
  250. this.initValidCode()
  251. this.loadValidCode(true)
  252. this.isRegisterOpen()
  253. },
  254. mounted () {
  255. // 注销退出清空验证码
  256. this.loginForm.captcha = ''
  257. // 注销退出清空请求ID
  258. this.loginForm.requestId = ''
  259. },
  260. methods: {
  261. ...mapActions({
  262. 'login': 'ibps/account/login',
  263. 'getCaptcha': 'ibps/account/getCaptcha',
  264. 'getRegisterOpen': 'ibps/account/getRegisterOpen',
  265. 'getRegisterTenantOpen': 'ibps/saas/getRegisterTenantOpen'
  266. }),
  267. initValidCode () {
  268. if (this.enabledValidCode) {
  269. this.loginRules.captcha[0]['required'] = true
  270. this.loginRules.captcha[1]['required'] = true
  271. } else {
  272. this.loginRules.captcha[0]['required'] = false
  273. this.loginRules.captcha[1]['required'] = false
  274. }
  275. },
  276. isRegisterOpen () {
  277. this.getRegisterOpen().then((data) => {
  278. this.isRegOpen = data.data
  279. }).catch((e) => { })
  280. this.getRegisterTenantOpen().then((data) => {
  281. this.isTenantOpen = data.data
  282. }).catch((e) => { })
  283. },
  284. // 获取验证码
  285. loadValidCode (isBackfill) {
  286. this.getCaptcha({ params: { requestId: this.loginForm.requestId } }).then((data) => {
  287. // 返回状态501,说明系统没有开启验证码
  288. if (data.state === 501) {
  289. this.enabledValidCode = false
  290. } else {
  291. this.enabledValidCode = true
  292. this.code.src = data.data
  293. this.loginForm.requestId = data.variables.requestId
  294. }
  295. this.initValidCode()
  296. if (isBackfill) {
  297. this.loginForm.code = this.code.value
  298. }
  299. }).catch((e) => {
  300. })
  301. },
  302. refreshCode () {
  303. this.loadValidCode()
  304. },
  305. checkCapslock ({ shiftKey, key } = {}) {
  306. if (key && key.length === 1) {
  307. if ((shiftKey && (key >= 'a' && key <= 'z')) || (!shiftKey && (key >= 'A' && key <= 'Z'))) {
  308. this.capsTooltip = true
  309. } else {
  310. this.capsTooltip = false
  311. }
  312. }
  313. if (key === 'CapsLock' && this.capsTooltip === true) {
  314. this.capsTooltip = false
  315. }
  316. },
  317. showPassword () {
  318. this.passwordType === '' ? (this.passwordType = 'password') : (this.passwordType = '')
  319. },
  320. forget () {
  321. this.$router.replace('/forget')
  322. },
  323. tenantForget () {
  324. this.$router.replace('/tenantForget')
  325. },
  326. register () {
  327. this.$router.replace('/register')
  328. },
  329. tenantRegister () {
  330. this.$router.replace('/tenantRegister')
  331. },
  332. handleLogin () {
  333. this.$refs.loginForm.validate(valid => {
  334. if (valid) {
  335. this.loading = true
  336. const loading = this.$loading({
  337. lock: true,
  338. text: this.$t('common.loading'),
  339. background: 'rgba(0, 0, 0, 0.7)'
  340. })
  341. this.login({
  342. form: this.loginForm
  343. }).then((data) => {
  344. localStorage.setItem('statistic', data.statistic)
  345. // 更新路由 尝试去获取 cookie 里保存的需要重定向的页面完整地址
  346. const redirect = this.$route.query.redirect
  347. if (redirect && redirect !== '/refresh') {
  348. if(data && (data.statistic === 'isMaster' ||data.statistic === 'isCharger')){
  349. // 重定向到开始路径
  350. this.$router.replace('/dashboard')
  351. } else {
  352. this.$router.replace('/')
  353. }
  354. } else {
  355. if(data && (data.statistic === 'isMaster' ||data.statistic === 'isCharger')){
  356. // 重定向到开始路径
  357. this.$router.replace('/dashboard')
  358. } else {
  359. this.$router.replace('/')
  360. }
  361. }
  362. // 延迟10秒关闭遮盖层
  363. setTimeout(() => {
  364. this.loading = false
  365. loading.close()
  366. }, 1000)
  367. }).catch((err) => {
  368. // 验证码错误自动清空&密码输入错误3次后触发验证码填写模块
  369. if (err && err.state === 6020104) {
  370. this.loginForm.captcha = ''
  371. this.enabledValidCode = true
  372. this.refreshCode()
  373. }
  374. // 有错误状态开启验证码需要刷新验证码
  375. if (err && err.state && this.enabledValidCode) {
  376. this.loginForm.captcha = ''
  377. this.refreshCode()
  378. }
  379. this.loading = false
  380. loading.close()
  381. })
  382. } else {
  383. this.$message.closeAll()
  384. this.$message({
  385. message: this.$t('common.dialog.saveError'),
  386. type: 'warning'
  387. })
  388. return false
  389. }
  390. })
  391. },
  392. // ca认证
  393. caAuth () {
  394. SZG_getServerCertificate().then(res1 => {
  395. let data1 = res1.variables && res1.variables.data
  396. console.log(data1)
  397. SZG_genRandom().then(res2 => {
  398. let data2 = res2.variables && res2.variables.data
  399. console.log(data2)
  400. if (data2) {
  401. SZG_signData({ inData: data2 }).then(res3 => {
  402. let data3 = res3.variables && res3.variables.data
  403. console.log(res3, data3)
  404. })
  405. }
  406. })
  407. }).catch(err => {
  408. console.log('获取服务器证书失败!')
  409. })
  410. // 获取用户列表,并截取用户姓名显示到登录框中
  411. this.loginForm.username = xtxsync.SOF_GetUserList()
  412. },
  413. // 验签
  414. caVerify () {
  415. xtxsync.SOF_VerifySignedData()
  416. }
  417. }
  418. }
  419. </script>
  420. <style scoped>
  421. .el-form-item {
  422. margin-bottom: 6px !important;
  423. }
  424. </style>