login.vue 13 KB

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