login.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  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/8471f31e2e0d4bf4a560887500d74aa0.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.2"
  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 mt-5"
  145. >开通账号及使用问题请咨询:15587166921</span
  146. >
  147. <el-button
  148. color="#558FF1"
  149. @click="
  150. download(
  151. 'https://wutong-1302848345.cos.ap-chengdu.myqcloud.com/wtzx/a53cc056c3914ae9884992dafe7a9679.pdf'
  152. )
  153. "
  154. style="width: 160px"
  155. plain
  156. class="mt-10 blockss"
  157. >
  158. 点击下载用户指南
  159. </el-button>
  160. <span class="grey-6 mt-5 font-12 mt-20"
  161. >为了获得最佳体验,您可以<span
  162. class="blue pointer"
  163. @click="
  164. download('https://www.google.cn/intl/zh-CN/chrome/')
  165. "
  166. >点击此处</span
  167. >获取Chrome 浏览器</span
  168. >
  169. </div>
  170. </div>
  171. </div>
  172. </div>
  173. </div>
  174. </div>
  175. </div>
  176. <div class="footer">
  177. <foolter />
  178. </div>
  179. </div>
  180. </template>
  181. <route>
  182. {
  183. meta: {
  184. layout: 'empty',
  185. },
  186. }
  187. </route>
  188. <script>
  189. import md5 from 'js-md5'
  190. import { useStore } from '@/store/user.js'
  191. import { removeToken, setToken } from '../utils/auth.js'
  192. import permissionStore from '@/store/permission.js'
  193. import VueQr from 'vue-qr/src/packages/vue-qr.vue'
  194. import foolter from '@/layout/foolter.vue'
  195. export default {
  196. name: 'login',
  197. components: { VueQr, foolter },
  198. watch: {
  199. qrCodeLogin: {
  200. handler(val) {
  201. if (val) {
  202. this.checkLogin()
  203. }
  204. },
  205. immediate: true
  206. },
  207. qrCodeText: {
  208. handler(val) {
  209. if (val.length === 0) {
  210. this.qrCode()
  211. }
  212. },
  213. immediate: true
  214. }
  215. },
  216. setup() {
  217. const user = useStore()
  218. const permission = permissionStore()
  219. return { user, permission }
  220. },
  221. data() {
  222. return {
  223. flag: false,
  224. form: {
  225. name: '',
  226. pass: ''
  227. },
  228. rules: {
  229. name: [
  230. { required: true, message: '请输入用户帐号', trigger: 'blur' }
  231. // { min: 11, max: 11, message: '请输入11位手机号', trigger: 'blur' }
  232. ],
  233. pass: [
  234. { required: true, message: '请输入密码', trigger: 'blur' },
  235. { min: 3, max: 16, message: '长度在 3 到 16 个字符', trigger: 'blur' }
  236. ],
  237. code: [
  238. { required: true, message: '请输入验证码', trigger: 'blur' },
  239. { min: 5, max: 5, message: '验证码不正确', trigger: 'blur' }
  240. ]
  241. },
  242. code: '',
  243. header: '',
  244. qrCodeLogin: false,
  245. time: null,
  246. qrCodeText: '',
  247. sessionId: '',
  248. logoSrc: new URL('../assets/img/logo.png', import.meta.url).href,
  249. dev: true,
  250. loading: false
  251. }
  252. },
  253. created() {
  254. this.permission.cleanPermission()
  255. // fixme prod 环境暂时开启账号登录功能
  256. removeToken()
  257. this.init()
  258. },
  259. unmounted() {
  260. clearInterval(this.time)
  261. },
  262. methods: {
  263. init() {
  264. this.dev =
  265. window.location.href.indexOf('https://test.wutongshucloud.com/') > -1 ||
  266. window.location.href.indexOf('192.168.31') > -1
  267. sessionStorage.setItem('dev', this.dev)
  268. this.$api.login.captcha().then(res => {
  269. this.code = res.image
  270. this.header = res.key
  271. })
  272. const menu = { active: 0, subActive: 0 }
  273. localStorage.setItem('index', JSON.stringify(menu))
  274. localStorage.removeItem('data-type')
  275. },
  276. submint() {
  277. this.$refs.loginForm.validate(res => {
  278. if (res) {
  279. const params = {
  280. tenantId: '000000',
  281. username: this.form.name,
  282. password: md5(this.form.pass),
  283. grant_type: 'captcha',
  284. scope: 'all',
  285. type: 'account'
  286. }
  287. const header = {
  288. captchaKey: this.header,
  289. captchaCode: this.form.code
  290. }
  291. this.loading = true
  292. this.$api.login.login(params, header).then(res => {
  293. this.loading = false
  294. if (res.error_description) {
  295. this.$message.error(res.error_description)
  296. this.init()
  297. } else {
  298. setToken(res.access_token)
  299. this.user.setUserInfo({ name: res.real_name })
  300. this.getInfo()
  301. this.menus()
  302. }
  303. })
  304. } else {
  305. return false
  306. }
  307. })
  308. },
  309. download(url) {
  310. window.open(
  311. url,
  312. '_blank' // <- This is what makes it open in a new window.
  313. )
  314. },
  315. getInfo() {
  316. this.$api.login.getUserInfo().then(res => {
  317. if (res.code === 200) {
  318. // 保存信息
  319. if (res.data.type === 3) {
  320. res.data.typeName = '机构'
  321. } else {
  322. res.data.typeName = '服务商'
  323. }
  324. this.user.setUserInfo(res.data)
  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.menus()
  376. }
  377. })
  378. }
  379. }
  380. })
  381. },
  382. menus() {
  383. this.$api.common.getMenus().then(res => {
  384. if (res.code === 200 && res.data.length > 0) {
  385. const first = res.data[0]
  386. if (first.children && first.children.length > 0) {
  387. this.$router.replace(first.children[0].path)
  388. localStorage.setItem(
  389. 'data-type',
  390. first.children[0].remark ? first.children[0].remark : 'project'
  391. )
  392. } else {
  393. this.$router.replace(first.path)
  394. localStorage.setItem(
  395. 'data-type',
  396. first.remark ? first.remark : 'project'
  397. )
  398. }
  399. }
  400. })
  401. },
  402. loginTest(type) {
  403. if (type === 1) {
  404. this.form.name = 'admin001'
  405. this.form.pass = 'admin123456'
  406. } else if (type === 2) {
  407. this.form.name = 'user001'
  408. this.form.pass = 'admin123456'
  409. }
  410. }
  411. }
  412. }
  413. </script>
  414. <style lang="scss" scoped>
  415. //noinspection ALL
  416. .bg {
  417. background-image: url('https://wutong-1302848345.cos.ap-chengdu.myqcloud.com/wtzx/7667edec62f44063a50c66e8654eaa87.png');
  418. background-size: cover;
  419. background-repeat: no-repeat;
  420. .footer {
  421. position: fixed;
  422. bottom: 10px;
  423. color: #eeeeee;
  424. }
  425. }
  426. .login {
  427. box-shadow: 5px 10px 10px 5px rgba(0, 0, 0, 0.28);
  428. .left {
  429. height: auto;
  430. .logo-main {
  431. width: 80%;
  432. }
  433. }
  434. .right {
  435. width: 560px;
  436. height: auto;
  437. }
  438. }
  439. .append {
  440. :deep(.el-input-group__append) {
  441. background-color: white;
  442. }
  443. .pic {
  444. border-top: #dddfe5 1px solid;
  445. border-bottom: #dddfe5 1px solid;
  446. }
  447. }
  448. </style>