loginMobile.vue 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634
  1. <template>
  2. <div class="mobile-content"
  3. v-bind:style="{background: `url(${loginStyle.bgUrlMobile}) no-repeat center center`}"
  4. v-bind:class="{'mobile-background-null': !loginStyle.bgUrlMobile}">
  5. <div class="mobile-opacity" v-bind:class="{'mobile-opacity-active': loginStyle.bgUrlMobile}">
  6. <template>
  7. <header-mobile/>
  8. </template>
  9. <div class="login">
  10. <div v-if="loginWay === 0">
  11. <div class="login-way" v-if="activeTab === 0">
  12. <div class="page-part">
  13. <mt-field auto-complete="off" placeholder="手机号/邮箱" v-model="login.username" @blur.native.capture="codeCount"></mt-field>
  14. </div>
  15. <div class="page-part">
  16. <mt-field placeholder="密码" v-model="login.password" type="password"></mt-field>
  17. <template>
  18. <div class="handle">
  19. <span class="fast-login" @click="activeTab = 1">短信快捷登录</span>
  20. <span class="pwd" @click="forgetPwd">忘记密码?</span>
  21. </div>
  22. </template>
  23. </div>
  24. <template v-if="showCheckCode">
  25. <div class="page-part">
  26. <mt-field placeholder="验证码" v-model="login.captcha">
  27. <img :src="imgSrc" height="45px" width="100px" @click="getCode">
  28. </mt-field>
  29. </div>
  30. </template>
  31. <div class="page-part">
  32. <mt-button size="large" type="primary" @click="checkLogin(true)">登录</mt-button>
  33. </div>
  34. </div>
  35. <div class="login-way" v-if="activeTab === 1">
  36. <div class="page-part">
  37. <mt-field auto-complete="off"
  38. placeholder="请输入手机号"
  39. v-model="fastLogin.mobile"
  40. :state="state.mobile"></mt-field>
  41. </div>
  42. <div class="page-part">
  43. <mt-field auto-complete="off"
  44. placeholder="短信验证码"
  45. v-model="fastLogin.code">
  46. <span class="token" @click="getCheckCode" v-text="tokenText">获取验证码</span>
  47. </mt-field>
  48. <template>
  49. <div class="handle">
  50. <span class="pwd" @click="activeTab = 0">用户名密码登录</span>
  51. </div>
  52. </template>
  53. </div>
  54. <div class="page-part">
  55. <mt-button size="large" type="primary" @click="fastToLogin(true)">登录</mt-button>
  56. </div>
  57. </div>
  58. <div class="login-btn">
  59. <p>还没有优软云账号?</p>
  60. <mt-button size="large" plain type="primary" @click="jump">立即注册</mt-button>
  61. </div>
  62. </div>
  63. <div v-if="loginWay === 1">
  64. <div class="user-info">
  65. <div class="img"><img :src="bhImg || '/images/all/icon_mall_index.png'" alt=""></div>
  66. <div class="user-name">{{bhName}}</div>
  67. </div>
  68. <div class="page-part">
  69. <mt-field auto-complete="off" placeholder="请输入账号" v-model="bhLogin.username"></mt-field>
  70. </div>
  71. <div class="page-part">
  72. <mt-field placeholder="请输入密码" v-model="bhLogin.password" type="password"></mt-field>
  73. </div>
  74. <div class="page-part">
  75. <mt-button size="large" type="primary" @click="bhBind">确&nbsp;&nbsp;&nbsp;定</mt-button>
  76. </div>
  77. <div class="login-btn">
  78. <p>还没有优软云账号?</p>
  79. <mt-button size="large" plain type="primary"><a :href="`/register/enterpriseRegistration${this.$store.state.option.fullPath}&tk=${bhToken}`" class="go">创建新账号</a></mt-button>
  80. </div>
  81. </div>
  82. <mt-popup v-model="popupVisible" position="right" class="mint-popup" :modal="false">
  83. <ul style="height:100vh;overflow-y:auto">
  84. <li class="listitem itemgreen">选择您要登录的公司:</li>
  85. <li v-for="item in enterprise" class="listitem" @click="selectEnterprise(false, item.id)">{{ item.name }}</li>
  86. </ul>
  87. </mt-popup>
  88. </div>
  89. </div>
  90. </div>
  91. </template>
  92. <script>
  93. function getCodeD (appId) {
  94. let paramse = {
  95. appId: appId
  96. }
  97. return new Promise((resolve, reject) => {
  98. if (window.cordova) {
  99. window.MrJsBridge.call((returnValue) => {
  100. resolve(returnValue)
  101. }, (error) => {
  102. console.log(error)
  103. reject(error)
  104. }, 'getCode', paramse)
  105. }
  106. })
  107. }
  108. import HeaderMobile from '~components/mobile/headerMobile.vue'
  109. export default {
  110. name: 'loginMobile',
  111. components: {
  112. HeaderMobile
  113. },
  114. data () {
  115. return {
  116. loading: false,
  117. popupVisible: false,
  118. imgSrc: '',
  119. showCheckCode: false,
  120. login: {
  121. username: '',
  122. password: '',
  123. spaceUU: '',
  124. captcha: ''
  125. },
  126. bhLogin: {
  127. username: '',
  128. password: ''
  129. },
  130. fastLogin: {
  131. mobile: '',
  132. code: ''
  133. },
  134. state: {
  135. mobile: 'error'
  136. },
  137. appId: '',
  138. returnUrl: '',
  139. baseUrl: '',
  140. bhCode: '',
  141. bhToken: '',
  142. bhImg: '',
  143. bhName: '',
  144. tokenCode: '',
  145. tokenTime: 60,
  146. tokenText: '获取验证码',
  147. loginWay: 0,
  148. activeTab: 0
  149. }
  150. },
  151. mounted () {
  152. this.$nextTick(() => {
  153. this.getUrl()
  154. // 碧合应用授权认证
  155. window.document.addEventListener('deviceready', function () {
  156. window.addEventListener('js_bridge_called', function () {
  157. })
  158. })
  159. let appId = 'a9f624cbbdb947049f5638880b0ecbb2'
  160. getCodeD(appId).then((data) => {
  161. // 成功回调 code
  162. alert(data)
  163. this.bhCode = data
  164. this.bhToLogin()
  165. }).catch((error) => {
  166. console.log(error)
  167. })
  168. })
  169. },
  170. computed: {
  171. enterprise () {
  172. return this.$store.state.login.chooseRegisterEnterprise.choose.data
  173. },
  174. loginStyle () {
  175. return this.$store.state.login.loginStyle.data.content ? this.$store.state.login.loginStyle.data.content : ''
  176. }
  177. },
  178. methods: {
  179. selectEnterprise (flag, type) {
  180. this.login.spaceUU = type
  181. this.popupVisible = flag
  182. if (this.$route.query.type) {
  183. this.bhToLogin()
  184. } else {
  185. if (this.activeTab === 0) {
  186. this.toLogin(flag)
  187. }
  188. if (this.activeTab === 1) {
  189. this.fastToLogin(flag)
  190. }
  191. }
  192. },
  193. // 弹窗处理
  194. downToast (type) {
  195. this.$toast({
  196. message: type,
  197. iconClass: 'el-icon-warning'
  198. })
  199. },
  200. // 忘记密码
  201. forgetPwd () {
  202. window.location.href = `/reset/forgetPasswordValidationAccount${this.$store.state.option.fullPath}`
  203. },
  204. jump () {
  205. window.location.href = `/register/enterpriseRegistration${this.$store.state.option.fullPath}`
  206. },
  207. getUrl () {
  208. this.appId = this.$store.state.option.appId
  209. this.returnUrl = this.$store.state.option.returnUrl
  210. this.baseUrl = this.$store.state.option.baseUrl
  211. },
  212. getCode () {
  213. this.imgSrc = '/sso/login/checkCode?timestamp=' + (new Date()).valueOf()
  214. },
  215. checkLogin (flag) {
  216. if (!this.login.username) {
  217. this.$toast({message: '请填写账号', iconClass: 'el-icon-warning'})
  218. } else if (!this.login.password) {
  219. this.$toast({message: '请填写密码', iconClass: 'el-icon-warning'})
  220. } else {
  221. this.toLogin(flag)
  222. }
  223. },
  224. codeCount () {
  225. this.$http.get(`/sso/login/getPwdErrorCount`, {params: {username: this.login.username}})
  226. .then(response => {
  227. if (response.data.success) {
  228. let count = response.data.content || ''
  229. if (count >= 3 && count < 5) {
  230. this.showCheckCode = true
  231. this.getCode()
  232. this.$toast({
  233. message: '当前已输错密码' + count + '次,若达到5次今日将无法登陆',
  234. iconClass: 'el-icon-warning'
  235. })
  236. } else if (count === 5) {
  237. this.$toast({
  238. message: '密码错误次数已达上限,今日无法登陆',
  239. iconClass: 'el-icon-warning'
  240. })
  241. }
  242. } else {
  243. this.$toast({
  244. message: response.data.errMsg,
  245. iconClass: 'el-icon-warning'
  246. })
  247. }
  248. }).catch(err => {
  249. this.$toast({
  250. message: err.errMsg,
  251. iconClass: 'el-icon-warning'
  252. })
  253. })
  254. },
  255. toLogin (flag) {
  256. this.$indicator.open('登录中...')
  257. let param = new FormData()
  258. param.append('username', this.login.username)
  259. param.append('password', this.login.password)
  260. param.append('captcha', this.login.captcha)
  261. param.append('appId', this.appId)
  262. param.append('returnUrl', this.returnUrl)
  263. param.append('baseUrl', this.baseUrl)
  264. param.append('spaceUU', this.login.spaceUU)
  265. let config = {
  266. headers: {'Content-Type': 'multipart/form-data'}
  267. }
  268. this.$http.post('/sso/login', param, config)
  269. .then(response => {
  270. this.$indicator.close()
  271. if (response.data.success) {
  272. // 弹框用户选择企业
  273. if (response.data.content.spaces) {
  274. this.$store.commit('login/chooseRegisterEnterprise/GET_ENTERPRISE_SUCCESS', response.data.content.spaces)
  275. this.popupVisible = flag
  276. } else if (response.data.content.loginUrls) {
  277. // 遍历登录url循环让各个应用登录
  278. let param = response.data.content.data
  279. let a = ''
  280. for (let n in param) {
  281. a += (n + '=' + encodeURIComponent(param[n]) + '&')
  282. }
  283. let params = a.substr(0, a.length - 1)
  284. this.$indicator.open('跳转中...')
  285. if (response.data.content.currentUrl) {
  286. this.$jsonp(`${response.data.content.currentUrl}?${params}`, {
  287. name: 'successCallback',
  288. timeout: 5000
  289. }, (err, data) => {
  290. if (err) {
  291. this.$indicator.close()
  292. this.$toast({
  293. message: '登录超时,请重试',
  294. iconClass: 'el-icon-error'
  295. })
  296. this.login.spaceUU = ''
  297. throw err
  298. } else {
  299. this.loginOther(response, params)
  300. }
  301. })
  302. } else {
  303. this.loginOther(response, params, 3000)
  304. }
  305. }
  306. } else {
  307. this.login.password = ''
  308. this.$toast({
  309. message: response.data.errMsg,
  310. iconClass: 'el-icon-error'
  311. })
  312. let count = response.data.errorCount
  313. if (count >= 3 && count < 5) {
  314. this.showCheckCode = true
  315. this.getCode()
  316. let _this = this
  317. setTimeout(function () {
  318. _this.getCode()
  319. }, 100)
  320. this.$toast({
  321. message: '当前已输错密码' + count + '次,若达到5次今日将无法登陆',
  322. iconClass: 'el-icon-warning'
  323. })
  324. }
  325. }
  326. }).catch(err => {
  327. this.$toast({
  328. message: err.errMsg,
  329. iconClass: 'el-icon-error'
  330. })
  331. })
  332. },
  333. getJsonp: function (url, timeout = 500) {
  334. return new Promise((resolve, reject) => {
  335. this.$jsonp(url, {
  336. name: 'successCallback',
  337. timeout: timeout
  338. }, function (err, data) {
  339. if (err) {
  340. reject(err)
  341. throw err
  342. } else {
  343. resolve(data)
  344. }
  345. })
  346. })
  347. },
  348. crossAfter (url) {
  349. try {
  350. window.location.href = url
  351. } catch (err) {
  352. console.log(err)
  353. }
  354. },
  355. loginOther (response, a, timeout) {
  356. const crossAfter = this.crossAfter
  357. let promises = []
  358. for (let i in response.data.content.loginUrls) {
  359. if (response.data.content.currentUrl !== response.data.content.loginUrls[i]) {
  360. promises.push(this.getJsonp(`${response.data.content.loginUrls[i]}?${a}`))
  361. }
  362. }
  363. Promise.all(promises).then(() => {
  364. crossAfter(response.data.content.returnUrl || 'http://www.ubtob.com', timeout)
  365. }).catch(() => {
  366. crossAfter(response.data.content.returnUrl || 'http://www.ubtob.com', timeout)
  367. })
  368. },
  369. // 碧合绑定账号
  370. bhBind () {
  371. this.$indicator.open('绑定中请稍后...')
  372. if (!this.bhLogin.username) {
  373. this.$indicator.close()
  374. this.downToast('请填写账号')
  375. } else if (!this.bhLogin.password) {
  376. this.$indicator.close()
  377. this.downToast('请填写密码')
  378. } else {
  379. let param = new FormData()
  380. param.append('_operate', 'account')
  381. param.append('t', this.bhToken)
  382. param.append('username', this.bhLogin.username)
  383. param.append('password', this.bhLogin.password)
  384. let config = {
  385. headers: {'Content-Type': 'multipart/form-data'}
  386. }
  387. this.$http.post('/foreign/addAccount', param, config)
  388. .then(response => {
  389. this.$indicator.close()
  390. if (response.data.success) {
  391. this.bhToLogin()
  392. } else {
  393. return Promise.reject(response.data)
  394. }
  395. }).catch(err => {
  396. this.$indicator.close()
  397. this.$toast({
  398. message: err.errMsg,
  399. iconClass: 'el-icon-error'
  400. })
  401. })
  402. }
  403. },
  404. // 判断是否绑定、选择账套
  405. bhToLogin () {
  406. this.$indicator.open('加载中...')
  407. if (this.$route.query.type) {
  408. let param = new FormData()
  409. param.append('code', this.bhCode || '')
  410. param.append('type', 'bh')
  411. param.append('appId', this.$route.query.appId ? this.$route.query.appId : '')
  412. param.append('returnUrl', this.$route.query.returnURL ? this.$route.query.returnURL : '')
  413. param.append('baseUrl', this.$route.query.baseUrl ? this.$route.query.baseUrl : '')
  414. param.append('spaceUU', this.login.spaceUU ? this.login.spaceUU : '')
  415. let config = {
  416. headers: {'Content-Type': 'multipart/form-data'}
  417. }
  418. this.$http.post('/sso/login/foreignLogin', param, config)
  419. .then(response => {
  420. this.$indicator.close()
  421. if (response.data.success) {
  422. if (!response.data.content.hasRegister && response.data.content.token) {
  423. this.loginWay = 1
  424. this.bhToken = response.data.content.token
  425. this.$http.get(`/foreign/userInfo/${this.bhToken}`, {params: {token: this.bhToken}})
  426. .then(response => {
  427. if (response.data.success) {
  428. this.bhImg = response.data.content.foreignUserImg
  429. this.bhName = response.data.content.foreignUserName
  430. } else {
  431. return Promise.reject(response.data)
  432. }
  433. }).catch(err => {
  434. this.$toast({
  435. message: err.errMsg,
  436. iconClass: 'el-icon-error'
  437. })
  438. })
  439. } else if (response.data.content.spaces) {
  440. // 弹框让用户选择企业
  441. this.$store.commit('login/chooseRegisterEnterprise/GET_ENTERPRISE_SUCCESS', response.data.content.spaces)
  442. this.popupVisible = true
  443. this.$indicator.open('跳转中...')
  444. } else if (response.data.content.loginUrls) {
  445. // 遍历登录url循环让各应用登录(需要跨域)
  446. let param = response.data.content.data
  447. let a = ''
  448. for (let n in param) {
  449. a += (n + '=' + encodeURIComponent(param[n]) + '&')
  450. }
  451. let params = a.substr(0, a.length - 1)
  452. this.$indicator.open('加载中...')
  453. if (response.data.content.currentUrl) {
  454. this.$jsonp(`${response.data.content.currentUrl}?${params}`, {
  455. name: 'successCallback',
  456. timeout: 3000
  457. }, (err, data) => {
  458. if (err) {
  459. this.$toast({
  460. message: '登录超时,请重试',
  461. iconClass: 'el-icon-error'
  462. })
  463. this.$indicator.close()
  464. throw err
  465. } else {
  466. this.loginOther(response, params)
  467. }
  468. })
  469. } else {
  470. this.loginOther(response, params, 3000)
  471. }
  472. }
  473. } else {
  474. this.$toast({
  475. message: response.data,
  476. iconClass: 'el-icon-error'
  477. })
  478. }
  479. }).catch(err => {
  480. this.$indicator.close()
  481. let _this = this
  482. setTimeout(function () {
  483. _this.getCode()
  484. }, 100)
  485. this.$toast({
  486. message: err.errMsg,
  487. iconClass: 'el-icon-error'
  488. })
  489. })
  490. }
  491. },
  492. // 验证手机号
  493. validateMobile () {
  494. let reg = /^1[0-9]{10}$/
  495. if (!this.fastLogin.mobile) {
  496. this.downToast('请先填写手机号')
  497. this.state.mobile = 'error'
  498. } else {
  499. if (!reg.test(this.fastLogin.mobile)) {
  500. this.downToast('请填写正确的手机号')
  501. this.state.mobile = 'warning'
  502. } else {
  503. this.state.mobile = 'success'
  504. }
  505. }
  506. },
  507. // 短信获取验证码
  508. getCheckCode () {
  509. if (this.tokenTime > 0 && this.tokenTime < 60) {
  510. this.downToast('请稍后再点击,我在倒计时')
  511. } else {
  512. this.validateMobile()
  513. if (this.state.mobile === 'success') {
  514. this.$indicator.open('获取中...')
  515. let _this = this
  516. this.$http.get('/sso/login/sendSmsCode', {params: {mobile: this.fastLogin.mobile}})
  517. .then(response => {
  518. this.$indicator.close()
  519. if (response.data.success) {
  520. this.tokenCode = response.data.content.token
  521. this.$toast({
  522. message: '验证码已经发送到您的手机,请注意查收',
  523. iconClass: 'el-icon-success'
  524. })
  525. this.tokenText = '已发送(' + this.tokenTime + 'S)'
  526. let setTime = setInterval(() => {
  527. _this.tokenTime--
  528. this.tokenText = '已发送(' + this.tokenTime + 'S)'
  529. if (this.tokenTime <= 0) {
  530. clearInterval(setTime)
  531. _this.tokenText = '获取验证码'
  532. _this.tokenTime = 60
  533. }
  534. }, 1000)
  535. } else {
  536. this.state.mobile = 'error'
  537. this.downToast(response.data.errMsg)
  538. }
  539. }).catch((err) => {
  540. this.$indicator.close()
  541. this.downToast(err.errMsg)
  542. })
  543. }
  544. }
  545. },
  546. // 短信快捷登录
  547. fastToLogin (flag) {
  548. if (this.fastLogin.mobile === '') {
  549. this.downToast('手机号不能为空')
  550. } else if (this.fastLogin.code === '') {
  551. this.downToast('验证码不能为空')
  552. } else {
  553. this.$indicator.open('登录中...')
  554. let param = new FormData()
  555. param.append('mobile', this.fastLogin.mobile)
  556. param.append('code', this.fastLogin.code)
  557. param.append('appId', this.$route.query.appId ? this.$route.query.appId : '')
  558. param.append('token', this.tokenCode)
  559. param.append('spaceUU', this.login.spaceUU ? this.login.spaceUU : '')
  560. param.append('returnUrl', this.returnUrl ? this.returnUrl : '')
  561. param.append('baseUrl', this.baseUrl ? this.baseUrl : '')
  562. let config = {
  563. headers: {'Content-Type': 'multipart/form-data'}
  564. }
  565. this.$http.post('/sso/login/sms', param, config)
  566. .then(response => {
  567. this.$indicator.close()
  568. if (response.data.success) {
  569. // 弹框用户选择企业
  570. if (response.data.content.spaces) {
  571. this.$store.commit('login/chooseRegisterEnterprise/GET_ENTERPRISE_SUCCESS', response.data.content.spaces)
  572. this.popupVisible = flag
  573. } else if (response.data.content.loginUrls) {
  574. // 遍历登录url循环让各个应用登录
  575. let param = response.data.content.data
  576. let a = ''
  577. for (let n in param) {
  578. a += (n + '=' + encodeURIComponent(param[n]) + '&')
  579. }
  580. let params = a.substr(0, a.length - 1)
  581. this.$indicator.open('跳转中...')
  582. if (response.data.content.currentUrl) {
  583. this.$jsonp(`${response.data.content.currentUrl}?${params}`, {
  584. name: 'successCallback',
  585. timeout: 5000
  586. }, (err, data) => {
  587. if (err) {
  588. this.$indicator.close()
  589. this.$toast({
  590. message: '登录超时,请重试',
  591. iconClass: 'el-icon-error'
  592. })
  593. this.login.spaceUU = ''
  594. throw err
  595. } else {
  596. this.loginOther(response, params)
  597. }
  598. })
  599. } else {
  600. this.loginOther(response, params, 3000)
  601. }
  602. }
  603. } else {
  604. this.login.password = ''
  605. this.$toast({
  606. message: response.data.errMsg,
  607. iconClass: 'el-icon-error'
  608. })
  609. let count = response.data.errorCount
  610. if (count >= 3 && count < 5) {
  611. this.showCheckCode = true
  612. this.getCode()
  613. let _this = this
  614. setTimeout(function () {
  615. _this.getCode()
  616. }, 100)
  617. this.$toast({
  618. message: '当前已输错密码' + count + '次,若达到5次今日将无法登陆',
  619. iconClass: 'el-icon-warning'
  620. })
  621. }
  622. }
  623. }).catch(err => {
  624. this.$toast({
  625. message: err.errMsg,
  626. iconClass: 'el-icon-error'
  627. })
  628. })
  629. }
  630. }
  631. }
  632. }
  633. </script>