login.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441
  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/ec3e8c5dd656476582ca7a4724fdafd6.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 v-if="!dev">
  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 v-if="dev" class="flex flex-center full-width">
  126. <el-button type="primary" plain @click="loginTest(1)"
  127. >测试管理员001
  128. </el-button>
  129. <el-button type="primary" plain @click="loginTest(2)"
  130. >测试用户001
  131. </el-button>
  132. </div>
  133. </div>
  134. </el-form-item>
  135. </el-form>
  136. <el-button
  137. size="large"
  138. style="width: 78%"
  139. type="primary"
  140. @click="submint"
  141. >登录
  142. </el-button>
  143. <div class="flex flex-col mt-10 flex-center">
  144. <span class="grey-6">由梧桐研究院提供技术支持</span>
  145. <span class="grey-6 mt-5">使用问题请咨询:15587166921</span>
  146. <el-button
  147. color="#558FF1"
  148. @click="
  149. download(
  150. 'https://wutong-1302848345.cos.ap-chengdu.myqcloud.com/wtzx/a53cc056c3914ae9884992dafe7a9679.pdf'
  151. )
  152. "
  153. style="width: 160px"
  154. plain
  155. class="mt-10 blockss"
  156. >
  157. 点击下载用户指南
  158. </el-button>
  159. <span class="grey-6 mt-5 font-12 mt-20"
  160. >为了获得最佳体验,您可以<span
  161. class="blue pointer"
  162. @click="
  163. download('https://www.google.cn/intl/zh-CN/chrome/')
  164. "
  165. >点击此处</span
  166. >获取Chrome 浏览器</span
  167. >
  168. </div>
  169. </div>
  170. </div>
  171. </div>
  172. </div>
  173. </div>
  174. </div>
  175. <div class="footer">
  176. <foolter />
  177. </div>
  178. </div>
  179. </template>
  180. <route>
  181. {
  182. meta: {
  183. layout: 'empty',
  184. },
  185. }
  186. </route>
  187. <script>
  188. import md5 from 'js-md5'
  189. import { useStore } from '@/store/user.js'
  190. import { removeToken, setToken } from '../utils/auth.js'
  191. import permissionStore from '@/store/permission.js'
  192. import VueQr from 'vue-qr/src/packages/vue-qr.vue'
  193. import foolter from '@/layout/foolter.vue'
  194. export default {
  195. name: 'login',
  196. components: { VueQr, foolter },
  197. watch: {
  198. qrCodeLogin: {
  199. handler(val) {
  200. if (val) {
  201. this.checkLogin()
  202. }
  203. },
  204. immediate: true
  205. },
  206. qrCodeText: {
  207. handler(val) {
  208. if (val.length === 0) {
  209. this.qrCode()
  210. }
  211. },
  212. immediate: true
  213. }
  214. },
  215. setup() {
  216. const user = useStore()
  217. const permission = permissionStore()
  218. return { user, permission }
  219. },
  220. data() {
  221. return {
  222. flag: false,
  223. form: {
  224. name: '',
  225. pass: ''
  226. },
  227. rules: {
  228. name: [
  229. { required: true, message: '请输入用户帐号', trigger: 'blur' }
  230. // { min: 11, max: 11, message: '请输入11位手机号', trigger: 'blur' }
  231. ],
  232. pass: [
  233. { required: true, message: '请输入密码', trigger: 'blur' },
  234. { min: 3, max: 16, message: '长度在 3 到 16 个字符', trigger: 'blur' }
  235. ],
  236. code: [
  237. { required: true, message: '请输入验证码', trigger: 'blur' },
  238. { min: 5, max: 5, message: '验证码不正确', trigger: 'blur' }
  239. ]
  240. },
  241. code: '',
  242. header: '',
  243. qrCodeLogin: false,
  244. time: null,
  245. qrCodeText: '',
  246. sessionId: '',
  247. logoSrc: new URL('../assets/img/logo.png', import.meta.url).href,
  248. dev: true,
  249. loading: false
  250. }
  251. },
  252. created() {
  253. this.permission.cleanPermission()
  254. // fixme prod 环境暂时开启账号登录功能
  255. removeToken()
  256. this.init()
  257. },
  258. unmounted() {
  259. clearInterval(this.time)
  260. },
  261. methods: {
  262. init() {
  263. this.dev =
  264. window.location.href.indexOf('https://test.wutongshucloud.com/') > -1 ||
  265. window.location.href.indexOf('192.168.31') > -1
  266. sessionStorage.setItem('dev', this.dev)
  267. this.$api.login.captcha().then(res => {
  268. this.code = res.image
  269. this.header = res.key
  270. })
  271. const menu = { active: 0, subActive: 0 }
  272. localStorage.setItem('index', JSON.stringify(menu))
  273. localStorage.removeItem('data-type')
  274. },
  275. submint() {
  276. this.$refs.loginForm.validate(res => {
  277. if (res) {
  278. const params = {
  279. tenantId: '000000',
  280. username: this.form.name,
  281. password: md5(this.form.pass),
  282. grant_type: 'captcha',
  283. scope: 'all',
  284. type: 'account'
  285. }
  286. const header = {
  287. captchaKey: this.header,
  288. captchaCode: this.form.code
  289. }
  290. this.loading = true
  291. this.$api.login.login(params, header).then(res => {
  292. this.loading = false
  293. if (res.error_description) {
  294. this.$message.error(res.error_description)
  295. this.init()
  296. } else {
  297. setToken(res.access_token)
  298. this.user.setUserInfo({ name: res.real_name })
  299. this.getInfo()
  300. }
  301. })
  302. } else {
  303. return false
  304. }
  305. })
  306. },
  307. download(url) {
  308. window.open(
  309. url,
  310. '_blank' // <- This is what makes it open in a new window.
  311. )
  312. },
  313. getInfo() {
  314. this.$api.login.getUserInfo().then(res => {
  315. if (res.code === 200) {
  316. // 保存信息
  317. if (res.data.type === 3) {
  318. res.data.typeName = '机构'
  319. } else {
  320. res.data.typeName = '服务商'
  321. }
  322. this.user.setUserInfo(res.data)
  323. this.$router.replace('/')
  324. }
  325. })
  326. },
  327. checkLogin() {
  328. let count = 0
  329. this.time = setInterval(() => {
  330. count = count + 1
  331. if (this.qrCodeLogin === false) {
  332. clearInterval(this.time)
  333. }
  334. if (count === 60) {
  335. this.qrCode()
  336. count = 0
  337. }
  338. if (this.sessionId) {
  339. this.codeLogin()
  340. } else {
  341. this.codeLogin()
  342. }
  343. }, 1000)
  344. },
  345. qrCode() {
  346. this.$api.login.qrCode().then(res => {
  347. if (res.code === 200) {
  348. this.sessionId = res.data
  349. this.qrCodeText =
  350. 'https://prod.wutongshucloud.com/login?id=' + this.sessionId
  351. }
  352. })
  353. },
  354. codeLogin() {
  355. this.$api.login.qrCodeLogin({ sessionId: this.sessionId }).then(res => {
  356. if (res.code === 200) {
  357. const tmp = res.data
  358. if (Object.prototype.hasOwnProperty.call(tmp, 'phone')) {
  359. const params = {
  360. tenantId: '000000',
  361. phone: res.data.phone,
  362. openId: res.data.openId,
  363. grant_type: 'qrcode',
  364. scope: 'all',
  365. type: 'account'
  366. }
  367. this.$api.login.loginByCode(params).then(res => {
  368. if (res.error_description) {
  369. this.$message.error(res.error_description)
  370. } else {
  371. clearInterval(this.time)
  372. setToken(res.access_token)
  373. this.getInfo()
  374. this.$router.replace('/')
  375. }
  376. })
  377. }
  378. }
  379. })
  380. },
  381. loginTest(type) {
  382. if (type === 1) {
  383. this.form.name = 'admin001'
  384. this.form.pass = 'admin123456'
  385. } else if (type === 2) {
  386. this.form.name = 'user001'
  387. this.form.pass = 'admin123456'
  388. }
  389. }
  390. }
  391. }
  392. </script>
  393. <style lang="scss" scoped>
  394. //noinspection ALL
  395. .bg {
  396. background-image: url('https://wutong-1302848345.cos.ap-chengdu.myqcloud.com/wtzx/7667edec62f44063a50c66e8654eaa87.png');
  397. background-size: cover;
  398. background-repeat: no-repeat;
  399. .footer {
  400. position: fixed;
  401. bottom: 10px;
  402. color: #eeeeee;
  403. }
  404. }
  405. .login {
  406. box-shadow: 5px 10px 10px 5px rgba(0, 0, 0, 0.28);
  407. .left {
  408. height: auto;
  409. .logo-main {
  410. width: 80%;
  411. }
  412. }
  413. .right {
  414. width: 560px;
  415. height: auto;
  416. }
  417. }
  418. .append {
  419. :deep(.el-input-group__append) {
  420. background-color: white;
  421. }
  422. .pic {
  423. border-top: #dddfe5 1px solid;
  424. border-bottom: #dddfe5 1px solid;
  425. }
  426. }
  427. </style>