login.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. <template>
  2. <div class="full-screen flex flex-center bg flex-col">
  3. <div class="login white-bg radius" v-loading="loading">
  4. <div class="flex flex-center flex-child-average">
  5. <div class="flex left">
  6. <img
  7. src="https://wutong-1302848345.cos.ap-chengdu.myqcloud.com/wtzx/373e3ccd35be4ba2a72376050027612e.png"
  8. style="
  9. height: 560px;
  10. object-fit: contain;
  11. border-bottom-left-radius: 10px;
  12. border-top-left-radius: 10px;
  13. "
  14. />
  15. </div>
  16. <div class="right flex flex-col flex-child-average">
  17. <div class="flex flex-col flex-justify-between" style="height: 560px">
  18. <div
  19. class="flex flex-justify-end"
  20. style="margin-right: 3px; margin-top: 3px"
  21. >
  22. <div>
  23. <img
  24. v-if="qrCodeLogin"
  25. src="../assets/img/com.png"
  26. style="width: 80px"
  27. @click="qrCodeLogin = !qrCodeLogin"
  28. />
  29. <img
  30. v-else
  31. src="../assets/img/code.png"
  32. style="width: 80px"
  33. @click="qrCodeLogin = !qrCodeLogin"
  34. />
  35. </div>
  36. </div>
  37. <div
  38. v-if="qrCodeLogin"
  39. class="flex flex-center flex-col"
  40. style="height: 500px; margin-top: -20px"
  41. >
  42. <span class="font-24 black bold">欢迎来到梧桐树云平台👏</span>
  43. <div
  44. class="flex flex-col flex-center"
  45. style="height: 360px; width: 360px; margin-top: -20px"
  46. >
  47. <vue-qr
  48. :currentLevel="3"
  49. :logoCornerRadius="4"
  50. :logoScale="0.25"
  51. :logoSrc="logoSrc"
  52. :text="qrCodeText"
  53. size="260"
  54. />
  55. </div>
  56. <span
  57. class="mt-10 bold main-color font-16"
  58. style="margin-top: -20px"
  59. >打开微信扫描二维码登陆梧桐树云平台</span
  60. >
  61. </div>
  62. <div v-else class="flex flex-col flex-center" style="height: 500px">
  63. <span class="font-24 black bold">欢迎来到梧桐树云平台👏</span>
  64. <div
  65. class="flex flex-col flex-center mt-5"
  66. style="width: 450px; height: 400px"
  67. >
  68. <el-form ref="loginForm" :model="form" :rules="rules">
  69. <el-form-item prop="name">
  70. <el-input
  71. v-model="form.name"
  72. placeholder="用户帐号"
  73. prefix-icon="Avatar"
  74. size="large"
  75. />
  76. </el-form-item>
  77. <el-form-item prop="pass">
  78. <el-input
  79. v-model="form.pass"
  80. :type="flag ? 'text' : 'password'"
  81. placeholder="密码"
  82. prefix-icon="WalletFilled"
  83. size="large"
  84. >
  85. <template v-slot:suffix>
  86. <div class="pointer" @click="flag = !flag">
  87. <el-icon v-if="!flag">
  88. <Hide />
  89. </el-icon>
  90. <el-icon v-else>
  91. <View />
  92. </el-icon>
  93. </div>
  94. </template>
  95. </el-input>
  96. </el-form-item>
  97. <el-form-item prop="code">
  98. <el-input
  99. v-model="form.code"
  100. class="append"
  101. placeholder="验证码"
  102. prefix-icon="Refresh"
  103. size="large"
  104. @keyup.enter="submint"
  105. >
  106. <template v-slot:append>
  107. <img
  108. :src="code"
  109. class="pic"
  110. @click="init"
  111. style="
  112. height: 40px;
  113. background-color: red;
  114. background-blend-mode: lighten;
  115. "
  116. alt="code"
  117. />
  118. </template>
  119. </el-input>
  120. </el-form-item>
  121. <el-form-item>
  122. <div
  123. class="flex flex-align-center flex-justify-between full-width"
  124. >
  125. <div></div>
  126. <el-link :underline="false" class="font-12" type="primary"
  127. >忘记密码?</el-link
  128. >
  129. </div>
  130. </el-form-item>
  131. </el-form>
  132. <el-button
  133. size="large"
  134. style="width: 78%"
  135. type="primary"
  136. @click="submint"
  137. >登录</el-button
  138. >
  139. <div class="flex flex-col mt-10 flex-center">
  140. <span class="grey-6">由梧桐研究院提供技术支持</span>
  141. <span class="grey-6 mt-5">使用问题请咨询:13908866200</span>
  142. <el-button
  143. color="#558FF1"
  144. @click="
  145. download(
  146. 'https://wutong-1302848345.cos.ap-chengdu.myqcloud.com/wtzx/a53cc056c3914ae9884992dafe7a9679.pdf'
  147. )
  148. "
  149. style="width: 160px"
  150. plain
  151. class="mt-10 blockss"
  152. >
  153. 点击下载用户指南
  154. </el-button>
  155. <span class="grey-6 mt-5 font-12 mt-20"
  156. >为了获得最佳体验,您可以<span
  157. class="blue pointer"
  158. @click="
  159. download('https://www.google.cn/intl/zh-CN/chrome/')
  160. "
  161. >点击此处</span
  162. >获取Chrome 浏览器</span
  163. >
  164. </div>
  165. </div>
  166. </div>
  167. </div>
  168. </div>
  169. </div>
  170. </div>
  171. <div class="footer">
  172. <foolter />
  173. </div>
  174. </div>
  175. </template>
  176. <route>
  177. {
  178. meta: {
  179. layout: 'empty',
  180. },
  181. }
  182. </route>
  183. <script>
  184. import md5 from 'js-md5'
  185. import { useStore } from '@/store/user.js'
  186. import { removeToken, setToken } from '../utils/auth.js'
  187. import permissionStore from '@/store/permission.js'
  188. import VueQr from 'vue-qr/src/packages/vue-qr.vue'
  189. import foolter from '@/layout/foolter.vue'
  190. export default {
  191. name: 'login',
  192. components: { VueQr, foolter },
  193. watch: {
  194. qrCodeLogin: {
  195. handler(val) {
  196. if (val) {
  197. this.qrCode()
  198. this.checkLogin()
  199. }
  200. },
  201. immediate: true
  202. }
  203. },
  204. setup() {
  205. const user = useStore()
  206. const permission = permissionStore()
  207. return { user, permission }
  208. },
  209. data() {
  210. return {
  211. flag: false,
  212. form: {
  213. name: '',
  214. pass: ''
  215. },
  216. rules: {
  217. name: [
  218. { required: true, message: '请输入用户帐号', trigger: 'blur' }
  219. // { min: 11, max: 11, message: '请输入11位手机号', trigger: 'blur' }
  220. ],
  221. pass: [
  222. { required: true, message: '请输入密码', trigger: 'blur' },
  223. { min: 3, max: 12, message: '长度在 3 到 12 个字符', trigger: 'blur' }
  224. ],
  225. code: [
  226. { required: true, message: '请输入验证码', trigger: 'blur' },
  227. { min: 5, max: 5, message: '验证码不正确', trigger: 'blur' }
  228. ]
  229. },
  230. code: '',
  231. header: '',
  232. qrCodeLogin: false,
  233. time: null,
  234. qrCodeText: '',
  235. sessionId: '',
  236. logoSrc: new URL('../assets/img/logo.png', import.meta.url).href,
  237. dev: true,
  238. loading: false
  239. }
  240. },
  241. created() {
  242. this.permission.cleanPermission()
  243. // fixme prod 环境暂时开启账号登录功能
  244. // this.dev = window.location.href.indexOf('localhost') > -1 || window.location.href.indexOf('https://dev.wutongshucloud.com/') > -1 || window.location.href.indexOf('192.168.31') > -1
  245. this.dev =
  246. window.location.href.indexOf('localhost') > -1 ||
  247. window.location.href.indexOf('192.168.31') > -1
  248. removeToken()
  249. this.init()
  250. },
  251. unmounted() {
  252. clearInterval(this.time)
  253. },
  254. methods: {
  255. init() {
  256. const dev =
  257. window.location.href.indexOf('dash.wutongshucloud.com') > -1 ||
  258. window.location.href.indexOf('localhost') > -1
  259. sessionStorage.setItem('dev', dev)
  260. this.$api.login.captcha().then(res => {
  261. this.code = res.image
  262. this.header = res.key
  263. })
  264. const menu = { active: 0, subActive: 0 }
  265. localStorage.setItem('index', JSON.stringify(menu))
  266. localStorage.removeItem('data-type')
  267. },
  268. submint() {
  269. this.$refs.loginForm.validate(res => {
  270. if (res) {
  271. const params = {
  272. tenantId: '000000',
  273. username: this.form.name,
  274. password: md5(this.form.pass),
  275. grant_type: 'captcha',
  276. scope: 'all',
  277. type: 'account'
  278. }
  279. const header = {
  280. captchaKey: this.header,
  281. captchaCode: this.form.code
  282. }
  283. this.loading = true
  284. this.$api.login.login(params, header).then(res => {
  285. this.loading = false
  286. if (res.error_description) {
  287. this.$message.error(res.error_description)
  288. this.init()
  289. } else {
  290. setToken(res.access_token)
  291. this.user.setUserInfo({ name: res.real_name })
  292. this.getInfo()
  293. }
  294. })
  295. } else {
  296. return false
  297. }
  298. })
  299. },
  300. download(url) {
  301. window.open(
  302. url,
  303. '_blank' // <- This is what makes it open in a new window.
  304. )
  305. },
  306. loginAdmin() {
  307. this.form.name = '15587166921'
  308. this.form.pass = 'wtkj@123'
  309. },
  310. loginOther() {
  311. this.form.name = '15587160283'
  312. this.form.pass = 'wtkj@123'
  313. },
  314. getInfo() {
  315. this.$api.login.getUserInfo().then(res => {
  316. if (res.code === 200) {
  317. // 保存信息
  318. if (res.data.type === 3) {
  319. res.data.typeName = '机构'
  320. } else {
  321. res.data.typeName = '服务商'
  322. }
  323. this.user.setUserInfo(res.data)
  324. this.$router.replace('/')
  325. }
  326. })
  327. },
  328. checkLogin() {
  329. let count = 0
  330. this.time = setInterval(() => {
  331. count = count + 1
  332. if (this.qrCodeLogin === false) {
  333. clearInterval(this.time)
  334. }
  335. if (count === 60) {
  336. this.qrCode()
  337. count = 0
  338. }
  339. if (this.sessionId) {
  340. this.codeLogin()
  341. } else {
  342. this.codeLogin()
  343. }
  344. }, 1000)
  345. },
  346. qrCode() {
  347. this.$api.login.qrCode().then(res => {
  348. if (res.code === 200) {
  349. this.sessionId = res.data
  350. this.qrCodeText =
  351. 'https://prod.wutongshucloud.com/login?id=' + this.sessionId
  352. }
  353. })
  354. },
  355. codeLogin() {
  356. this.$api.login.qrCodeLogin({ sessionId: this.sessionId }).then(res => {
  357. if (res.code === 200) {
  358. const tmp = res.data
  359. if (Object.prototype.hasOwnProperty.call(tmp, 'phone')) {
  360. const params = {
  361. tenantId: '000000',
  362. phone: res.data.phone,
  363. openId: res.data.openId,
  364. grant_type: 'qrcode',
  365. scope: 'all',
  366. type: 'account'
  367. }
  368. this.$api.login.loginByCode(params).then(res => {
  369. if (res.error_description) {
  370. this.$message.error(res.error_description)
  371. } else {
  372. clearInterval(this.time)
  373. setToken(res.access_token)
  374. this.getInfo()
  375. this.$router.replace('/')
  376. }
  377. })
  378. }
  379. }
  380. })
  381. }
  382. }
  383. }
  384. </script>
  385. <style lang="scss" scoped>
  386. //noinspection ALL
  387. .bg {
  388. background-image: url('https://wutong-1302848345.cos.ap-chengdu.myqcloud.com/wtzx/7667edec62f44063a50c66e8654eaa87.png');
  389. .footer {
  390. position: fixed;
  391. bottom: 50px;
  392. color: white;
  393. }
  394. }
  395. .login {
  396. box-shadow: 5px 10px 10px 5px rgba(0, 0, 0, 0.28);
  397. .left {
  398. height: auto;
  399. .logo-main {
  400. width: 80%;
  401. }
  402. }
  403. .right {
  404. width: 560px;
  405. height: auto;
  406. .form {
  407. }
  408. }
  409. }
  410. .append {
  411. :deep(.el-input-group__append) {
  412. background-color: white;
  413. }
  414. .pic {
  415. border-top: #dddfe5 1px solid;
  416. border-bottom: #dddfe5 1px solid;
  417. }
  418. }
  419. </style>