wangtao 2 years ago
parent
commit
dd838facf8

+ 1 - 1
.env.development

@@ -1,7 +1,7 @@
 ENV = 'development'
 
 # 接口地址
-VUE_APP_BASE_API  = 'http://localhost:1537'
+VUE_APP_BASE_API  = 'http://172.16.120.49/wyxtapi/'
 VUE_APP_WS_API = 'ws://localhost:1537'
 
 # 是否启用 babel-plugin-dynamic-import-node插件

+ 2 - 2
.env.production

@@ -3,8 +3,8 @@ ENV = 'production'
 # 如果使用 Nginx 代理后端接口,那么此处需要改为 '/',文件查看 Docker 部署篇,Nginx 配置
 # 接口地址,注意协议,如果你没有配置 ssl,需要将 https 改为 http
 # VUE_APP_BASE_API  = 'http://114.55.24.6:8083'
-VUE_APP_BASE_API  = 'http://10.21.39.6:8088'
+VUE_APP_BASE_API  = 'http://172.16.120.49/wyxtapi/'
 
 # 如果接口是 http 形式, wss 需要改为 ws
 # VUE_APP_WS_API = 'ws://114.55.24.6:8083'
-VUE_APP_WS_API = 'ws://10.21.39.6:8088'
+VUE_APP_WS_API = 'ws://10.21.39.6:8088'

+ 1 - 0
.gitignore

@@ -4,6 +4,7 @@ dist/
 npm-debug.log*
 yarn-debug.log*
 yarn-error.log*
+.history/
 **/*.log
 
 tests/**/coverage/

+ 114 - 114
package.json

@@ -1,117 +1,117 @@
 {
-  "name": "eladmin-web",
-  "version": "2.6.0",
-  "description": "EL-ADMIN 前端源码",
-  "author": "Zheng Jie",
-  "license": "Apache-2.0",
-  "scripts": {
-    "dev": "vue-cli-service serve",
-    "build:prod": "vue-cli-service build",
-    "build:stage": "vue-cli-service build --mode staging",
-    "preview": "node build/index.js --preview",
-    "lint": "eslint --ext .js,.vue src",
-    "test:unit": "jest --clearCache && vue-cli-service test:unit",
-    "svgo": "svgo -f src/assets/icons/svg --config=src/assets/icons/svgo.yml",
-    "new": "plop"
-  },
-  "husky": {
-    "hooks": {
-      "pre-commit": "lint-staged"
-    }
-  },
-  "lint-staged": {
-    "src/**/*.{js,vue}": [
-      "eslint --fix",
-      "git add"
+    "name": "eladmin-web",
+    "version": "2.6.0",
+    "description": "EL-ADMIN 前端源码",
+    "author": "Zheng Jie",
+    "license": "Apache-2.0",
+    "scripts": {
+        "dev": "vue-cli-service serve",
+        "build:prod": "vue-cli-service build",
+        "build:stage": "vue-cli-service build --mode staging",
+        "preview": "node build/index.js --preview",
+        "lint": "eslint --ext .js,.vue src",
+        "test:unit": "jest --clearCache && vue-cli-service test:unit",
+        "svgo": "svgo -f src/assets/icons/svg --config=src/assets/icons/svgo.yml",
+        "new": "plop"
+    },
+    "husky": {
+        "hooks": {
+            "pre-commit": "lint-staged"
+        }
+    },
+    "lint-staged": {
+        "src/**/*.{js,vue}": [
+            "eslint --fix",
+            "git add"
+        ]
+    },
+    "repository": {
+        "type": "git",
+        "url": "https://github.com/elunez/eladmin-web.git"
+    },
+    "bugs": {
+        "url": "https://github.com/elunez/eladmin/issues"
+    },
+    "dependencies": {
+        "@riophae/vue-treeselect": "0.4.0",
+        "axios": "^0.21.4",
+        "clipboard": "2.0.4",
+        "codemirror": "^5.49.2",
+        "connect": "3.6.6",
+        "core-js": "^2.6.12",
+        "echarts": "^4.2.1",
+        "echarts-gl": "^1.1.1",
+        "echarts-wordcloud": "^1.1.3",
+        "element-ui": "^2.13.2",
+        "file-saver": "1.3.8",
+        "fuse.js": "3.4.4",
+        "highlight.js": "^10.6.0",
+        "js-beautify": "^1.10.2",
+        "js-cookie": "2.2.0",
+        "jsencrypt": "^3.0.0-rc.1",
+        "jszip": "^3.7.1",
+        "mavon-editor": "^2.9.0",
+        "normalize.css": "7.0.0",
+        "nprogress": "0.2.0",
+        "path-to-regexp": "2.4.0",
+        "qs": "^6.9.1",
+        "screenfull": "4.2.0",
+        "sortablejs": "1.8.4",
+        "vue": "2.6.10",
+        "vue-count-to": "1.0.13",
+        "vue-cropper": "0.4.9",
+        "vue-echarts": "^5.0.0-beta.0",
+        "vue-highlightjs": "^1.3.3",
+        "vue-image-crop-upload": "^2.5.0",
+        "vue-router": "3.0.2",
+        "vue-splitpane": "1.0.4",
+        "vuedraggable": "2.20.0",
+        "vuex": "3.1.0",
+        "wangeditor": "^3.1.1",
+        "xlsx": "^0.17.2"
+    },
+    "devDependencies": {
+        "@babel/core": "7.0.0",
+        "@babel/parser": "^7.7.4",
+        "@babel/register": "7.0.0",
+        "@vue/babel-plugin-transform-vue-jsx": "^1.2.1",
+        "@vue/cli-plugin-babel": "3.5.3",
+        "@vue/cli-plugin-eslint": "^3.9.1",
+        "@vue/cli-plugin-unit-jest": "3.5.3",
+        "@vue/cli-service": "3.5.3",
+        "@vue/test-utils": "1.0.0-beta.29",
+        "autoprefixer": "^9.5.1",
+        "babel-core": "7.0.0-bridge.0",
+        "babel-eslint": "10.0.1",
+        "babel-jest": "23.6.0",
+        "babel-plugin-dynamic-import-node": "2.3.0",
+        "babel-plugin-transform-remove-console": "^6.9.4",
+        "chalk": "2.4.2",
+        "chokidar": "2.1.5",
+        "connect": "3.6.6",
+        "eslint": "5.15.3",
+        "eslint-plugin-vue": "5.2.2",
+        "html-webpack-plugin": "3.2.0",
+        "http-proxy-middleware": "^0.19.1",
+        "husky": "1.3.1",
+        "lint-staged": "8.1.5",
+        "plop": "^2.7.4",
+        "runjs": "^4.3.2",
+        "sass": "^1.26.10",
+        "sass-loader": "^7.1.0",
+        "script-ext-html-webpack-plugin": "2.1.3",
+        "script-loader": "0.7.2",
+        "serve-static": "^1.13.2",
+        "svg-sprite-loader": "4.1.3",
+        "svgo": "1.2.0",
+        "vue-template-compiler": "2.6.10"
+    },
+    "engines": {
+        "node": ">=8.9",
+        "npm": ">= 3.0.0"
+    },
+    "browserslist": [
+        "> 1%",
+        "last 2 versions"
     ]
-  },
-  "repository": {
-    "type": "git",
-    "url": "https://github.com/elunez/eladmin-web.git"
-  },
-  "bugs": {
-    "url": "https://github.com/elunez/eladmin/issues"
-  },
-  "dependencies": {
-    "@riophae/vue-treeselect": "0.4.0",
-    "axios": "^0.21.4",
-    "clipboard": "2.0.4",
-    "codemirror": "^5.49.2",
-    "connect": "3.6.6",
-    "core-js": "^2.6.12",
-    "echarts": "^4.2.1",
-    "echarts-gl": "^1.1.1",
-    "echarts-wordcloud": "^1.1.3",
-    "element-ui": "^2.13.2",
-    "file-saver": "1.3.8",
-    "fuse.js": "3.4.4",
-    "highlight.js": "^10.6.0",
-    "js-beautify": "^1.10.2",
-    "js-cookie": "2.2.0",
-    "jsencrypt": "^3.0.0-rc.1",
-    "jszip": "^3.7.1",
-    "mavon-editor": "^2.9.0",
-    "normalize.css": "7.0.0",
-    "nprogress": "0.2.0",
-    "path-to-regexp": "2.4.0",
-    "qs": "^6.9.1",
-    "screenfull": "4.2.0",
-    "sortablejs": "1.8.4",
-    "vue": "2.6.10",
-    "vue-count-to": "1.0.13",
-    "vue-cropper": "0.4.9",
-    "vue-echarts": "^5.0.0-beta.0",
-    "vue-highlightjs": "^1.3.3",
-    "vue-image-crop-upload": "^2.5.0",
-    "vue-router": "3.0.2",
-    "vue-splitpane": "1.0.4",
-    "vuedraggable": "2.20.0",
-    "vuex": "3.1.0",
-    "wangeditor": "^3.1.1",
-    "xlsx": "^0.17.2"
-  },
-  "devDependencies": {
-    "@babel/core": "7.0.0",
-    "@babel/parser": "^7.7.4",
-    "@babel/register": "7.0.0",
-    "@vue/babel-plugin-transform-vue-jsx": "^1.2.1",
-    "@vue/cli-plugin-babel": "3.5.3",
-    "@vue/cli-plugin-eslint": "^3.9.1",
-    "@vue/cli-plugin-unit-jest": "3.5.3",
-    "@vue/cli-service": "3.5.3",
-    "@vue/test-utils": "1.0.0-beta.29",
-    "autoprefixer": "^9.5.1",
-    "babel-core": "7.0.0-bridge.0",
-    "babel-eslint": "10.0.1",
-    "babel-jest": "23.6.0",
-    "babel-plugin-dynamic-import-node": "2.3.0",
-    "babel-plugin-transform-remove-console": "^6.9.4",
-    "chalk": "2.4.2",
-    "chokidar": "2.1.5",
-    "connect": "3.6.6",
-    "eslint": "5.15.3",
-    "eslint-plugin-vue": "5.2.2",
-    "html-webpack-plugin": "3.2.0",
-    "http-proxy-middleware": "^0.19.1",
-    "husky": "1.3.1",
-    "lint-staged": "8.1.5",
-    "plop": "^2.7.4",
-    "runjs": "^4.3.2",
-    "sass": "^1.26.10",
-    "sass-loader": "^7.1.0",
-    "script-ext-html-webpack-plugin": "2.1.3",
-    "script-loader": "0.7.2",
-    "serve-static": "^1.13.2",
-    "svg-sprite-loader": "4.1.3",
-    "svgo": "1.2.0",
-    "vue-template-compiler": "2.6.10"
-  },
-  "engines": {
-    "node": ">=8.9",
-    "npm": ">= 3.0.0"
-  },
-  "browserslist": [
-    "> 1%",
-    "last 2 versions"
-  ]
 }

BIN
public/favicon.ico


+ 12 - 7
public/index.html

@@ -1,15 +1,20 @@
 <!DOCTYPE html>
 <html>
-  <head>
+
+<head>
     <meta charset="utf-8">
     <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
     <meta name="renderer" content="webkit">
     <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
-    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
-    <title><%= webpackConfig.name %></title>
-  </head>
-  <body>
+    <link rel="icon" href="/favicon.png">
+    <title>
+        <%= webpackConfig.name %>
+    </title>
+</head>
+
+<body>
     <div id="app"></div>
     <!-- built files will be auto injected -->
-  </body>
-</html>
+</body>
+
+</html>

+ 37 - 0
public/jsencrypt.js

@@ -0,0 +1,37 @@
+import JSEncrypt from 'jsencrypt/bin/jsencrypt.min'
+
+// 密钥对生成 http://web.chacuo.net/netrsakeypair
+
+const publicKey = `MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCxPWP0HTBE9vEeM34Qx03U8oVm
+C6xIqWPRuI5t8J0zEDQudAgXKPjy8E0Q3cX800UNBTx2gUfRRNrONqALKDnJ1SE6
+qCUDeXOez8sa95GQ9d4BX7pSjZLrPfnCBTBtb5LGkY5zmlmtpG2AV9eJr+kQqhs/
+r0c4njwaDjVG4kF3ZQIDAQAB`
+
+const privateKey = `MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBALE9Y/QdMET28R4z
+fhDHTdTyhWYLrEipY9G4jm3wnTMQNC50CBco+PLwTRDdxfzTRQ0FPHaBR9FE2s42
+oAsoOcnVITqoJQN5c57Pyxr3kZD13gFfulKNkus9+cIFMG1vksaRjnOaWa2kbYBX
+14mv6RCqGz+vRziePBoONUbiQXdlAgMBAAECgYBjSDdAXEVYrFdeiouYjHwdyAhP
+pERKo5BFvzMRhJIaM353cwnBJ3NkapVQ2Fn6iMIKTB+VZk+7eu1yTAkUluDfLowd
+REZS4ipOBY5UuNnjbXmSOoUQw6vRnox0X4x6S1vd4FBHgpVe1VkiE7Nz5U7Clyd5
+yw2P1lHwMyB/guAH4QJBAN3dGkMASj0jm23maHOfehp/zlACB8HpMKuV4z/bEg45
+nC9Hw5NloUHrXdzEXP1+S46MCH2THflxDVYtnZTRLO0CQQDMgp3Jrn7kkKtNceZF
+R08hLbVmfNlatgONgFJ5JnR+GTQ6o2gwM6SLyoBkfAIiEDpr6c6nBXTU09GOYxBk
++h1ZAkB32pXxVBrG5JF20V3j+GcyIZEGz9H5A0xzpUlambIrVRv2vsH8wo5W2hue
+w8Woe629mBCOJgevVU9rGsFiP44RAkEApbTYAQjAjJakFpZJjKzg8vNEXoye2R9N
+9aOaL8v27A2kAjdRPm050IL+UW0hlVQs4i+KYE7NgX03+PVP3WHD0QJBANLo4PRw
+7Y+dLPAzuazsD3/5SYaSh+KSD/+tVbc6CFvLyfFUKp/a4PzzvGaLo/Ky/ffOY5k0
+hmavbHCKcg+r+hg=`
+
+// 加密
+export function encrypt(txt) {
+    const encryptor = new JSEncrypt()
+    encryptor.setPublicKey(publicKey) // 设置公钥
+    return encryptor.encrypt(txt) // 对数据进行加密
+}
+
+// 解密
+export function decrypt(txt) {
+    const encryptor = new JSEncrypt()
+    encryptor.setPrivateKey(privateKey) // 设置私钥
+    return encryptor.decrypt(txt) // 对数据进行解密
+}

+ 12 - 5
src/api/login.js

@@ -2,17 +2,24 @@ import request from '@/utils/request'
 
 export function login(username, password, code, uuid) {
   return request({
-    url: 'auth/login',
+    url: 'auth/login3',
     method: 'post',
     data: {
       username,
-      password,
-      code,
-      uuid
+      password
+      // code,
+      // uuid
     }
   })
 }
-
+// 登录方法(SaaS)
+export function loginSaaS(data) {
+  return request({
+    url: 'auth/login3',
+    method: 'post',
+    data
+  })
+}
 export function loginSSO(username, password) {
   return request({
     url: 'auth/login2',

BIN
src/assets/images/bg.png


BIN
src/assets/logo/logo-b.png


BIN
src/assets/logo/logo.png


+ 7 - 2
src/layout/components/Sidebar/Logo.vue

@@ -2,11 +2,11 @@
   <div class="sidebar-logo-container" :class="{'collapse':collapse}">
     <transition name="sidebarLogoFade">
       <router-link v-if="collapse" key="collapse" class="sidebar-logo-link" to="/">
-        <img v-if="logo" :src="logo" class="sidebar-logo">
+        <img v-if="logo" src="@/assets/logo/logo.png" class="sidebar-logo">
         <!-- <h1 v-else class="sidebar-title">{{ title }} </h1> -->
       </router-link>
       <router-link v-else key="expand" class="sidebar-logo-link" to="/">
-        <img v-if="logo" :src="logo" class="sidebar-logo">
+        <img v-if="logo" src="@/assets/logo/logo.png" class="sidebar-logo">
         <!-- <h1 class="sidebar-title">{{ title }} </h1> -->
       </router-link>
     </transition>
@@ -62,6 +62,11 @@ export default {
       vertical-align: middle;
       margin-right: 6px;
     }
+    & .sidebar-logo2{
+      width:40px;
+      height:auto;
+      margin:20px auto;
+    }
 
     & .sidebar-title {
       display: inline-block;

+ 53 - 31
src/router/index.js

@@ -2,53 +2,75 @@ import router from './routers'
 import store from '@/store'
 import Config from '@/settings'
 import NProgress from 'nprogress' // progress bar
-import 'nprogress/nprogress.css'// progress bar style
+import 'nprogress/nprogress.css' // progress bar style
 import { getToken } from '@/utils/auth' // getToken from cookie
 import { buildMenus } from '@/api/system/menu'
 import { filterAsyncRouter } from '@/store/modules/permission'
+import { decrypt } from '@/utils/jsencrypt'
+NProgress.configure({ showSpinner: false }) // NProgress Configuration
 
-NProgress.configure({ showSpinner: false })// NProgress Configuration
-
-const whiteList = ['/login', '/sso']// no redirect whitelist
+const whiteList = ['/login', '/sso'] // no redirect whitelist
 
 router.beforeEach((to, from, next) => {
   if (to.meta.title) {
     document.title = to.meta.title + ' - ' + Config.title
   }
   NProgress.start()
-  if (getToken()) {
-    // 已登录且要跳转的页面是登录页
-    if (to.path === '/login') {
-      next({ path: '/' })
-      NProgress.done()
-    } else {
-      if (store.getters.roles.length === 0) { // 判断当前用户是否已拉取完user_info信息
-        store.dispatch('GetInfo').then(() => { // 拉取user_info
-          // 动态路由,拉取菜单
+  const url = window.location.hash
+  if (url.indexOf('userNameSaaS') > 0 && url.indexOf('passWordSaaS') > 0) {
+    if (store.getters.roles.length === 0) {
+      const params = {
+        username: undefined,
+        password: undefined
+      }
+      const data = url.split('login?userNameSaaS=')[1].split('&passWordSaaS=')
+      params.username = decrypt(decodeURIComponent(data[0]))
+      params.password = decrypt(decodeURIComponent(data[1]))
+      store.dispatch('Login', params).then((res) => {
+        store.dispatch('GetInfo').then(() => {
           loadMenus(next, to)
-        }).catch(() => {
-          store.dispatch('LogOut').then(() => {
-            location.reload() // 为了重新实例化vue-router对象 避免bug
-          })
         })
-      // 登录时未拉取 菜单,在此处拉取
-      } else if (store.getters.loadMenus) {
-        // 修改成false,防止死循环
-        store.dispatch('updateLoadMenus')
-        loadMenus(next, to)
-      } else {
+      }).catch(() => {
         next()
-      }
+      })
+    } else {
+      next()
     }
   } else {
-    /* has no token*/
-    if (whiteList.indexOf(to.path) !== -1) { // 在免登录白名单,直接进入
-      next()
-    } else if (to.path === '/sso') {
-      next()
+    if (getToken()) {
+      // 已登录且要跳转的页面是登录页
+      if (to.path === '/login') {
+        next({ path: '/' })
+        NProgress.done()
+      } else {
+        if (store.getters.roles.length === 0) { // 判断当前用户是否已拉取完user_info信息
+          store.dispatch('GetInfo').then(() => { // 拉取user_info
+            // 动态路由,拉取菜单
+            loadMenus(next, to)
+          }).catch(() => {
+            store.dispatch('LogOut').then(() => {
+              location.reload() // 为了重新实例化vue-router对象 避免bug
+            })
+          })
+          // 登录时未拉取 菜单,在此处拉取
+        } else if (store.getters.loadMenus) {
+          // 修改成false,防止死循环
+          store.dispatch('updateLoadMenus')
+          loadMenus(next, to)
+        } else {
+          next()
+        }
+      }
     } else {
-      next(`/login?redirect=${to.fullPath}`) // 否则全部重定向到登录页
-      NProgress.done()
+      /* has no token*/
+      if (whiteList.indexOf(to.path) !== -1) { // 在免登录白名单,直接进入
+        next()
+      } else if (to.path === '/sso') {
+        next()
+      } else {
+        next(`/login?redirect=${to.fullPath}`) // 否则全部重定向到登录页
+        NProgress.done()
+      }
     }
   }
 })

+ 14 - 1
src/store/modules/user.js

@@ -1,4 +1,4 @@
-import { login, loginSSO, getInfo, logout } from '@/api/login'
+import { login, loginSSO, getInfo, loginSaaS, logout } from '@/api/login'
 import { getToken, setToken, removeToken } from '@/utils/auth'
 
 const user = {
@@ -42,6 +42,19 @@ const user = {
         })
       })
     },
+    // 登录SaaS
+    LoginSaaS({ commit }, userInfo) {
+      return new Promise((resolve, reject) => {
+        loginSaaS({ username: userInfo.username, password: userInfo.password }).then(res => {
+          console.log(res)
+          setToken(res.data)
+          commit('SET_TOKEN', res.data)
+          resolve()
+        }).catch(error => {
+          reject(error)
+        })
+      })
+    },
     // 单点登录
     LoginSSO({ commit }, userInfo) {
       console.log(userInfo)

+ 37 - 0
src/utils/jsencrypt.js

@@ -0,0 +1,37 @@
+import JSEncrypt from 'jsencrypt/bin/jsencrypt.min'
+
+// 密钥对生成 http://web.chacuo.net/netrsakeypair
+
+const publicKey = `MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCxPWP0HTBE9vEeM34Qx03U8oVm
+C6xIqWPRuI5t8J0zEDQudAgXKPjy8E0Q3cX800UNBTx2gUfRRNrONqALKDnJ1SE6
+qCUDeXOez8sa95GQ9d4BX7pSjZLrPfnCBTBtb5LGkY5zmlmtpG2AV9eJr+kQqhs/
+r0c4njwaDjVG4kF3ZQIDAQAB`
+
+const privateKey = `MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBALE9Y/QdMET28R4z
+fhDHTdTyhWYLrEipY9G4jm3wnTMQNC50CBco+PLwTRDdxfzTRQ0FPHaBR9FE2s42
+oAsoOcnVITqoJQN5c57Pyxr3kZD13gFfulKNkus9+cIFMG1vksaRjnOaWa2kbYBX
+14mv6RCqGz+vRziePBoONUbiQXdlAgMBAAECgYBjSDdAXEVYrFdeiouYjHwdyAhP
+pERKo5BFvzMRhJIaM353cwnBJ3NkapVQ2Fn6iMIKTB+VZk+7eu1yTAkUluDfLowd
+REZS4ipOBY5UuNnjbXmSOoUQw6vRnox0X4x6S1vd4FBHgpVe1VkiE7Nz5U7Clyd5
+yw2P1lHwMyB/guAH4QJBAN3dGkMASj0jm23maHOfehp/zlACB8HpMKuV4z/bEg45
+nC9Hw5NloUHrXdzEXP1+S46MCH2THflxDVYtnZTRLO0CQQDMgp3Jrn7kkKtNceZF
+R08hLbVmfNlatgONgFJ5JnR+GTQ6o2gwM6SLyoBkfAIiEDpr6c6nBXTU09GOYxBk
++h1ZAkB32pXxVBrG5JF20V3j+GcyIZEGz9H5A0xzpUlambIrVRv2vsH8wo5W2hue
+w8Woe629mBCOJgevVU9rGsFiP44RAkEApbTYAQjAjJakFpZJjKzg8vNEXoye2R9N
+9aOaL8v27A2kAjdRPm050IL+UW0hlVQs4i+KYE7NgX03+PVP3WHD0QJBANLo4PRw
+7Y+dLPAzuazsD3/5SYaSh+KSD/+tVbc6CFvLyfFUKp/a4PzzvGaLo/Ky/ffOY5k0
+hmavbHCKcg+r+hg=`
+
+// 加密
+export function encrypt(txt) {
+  const encryptor = new JSEncrypt()
+  encryptor.setPublicKey(publicKey) // 设置公钥
+  return encryptor.encrypt(txt) // 对数据进行加密
+}
+
+// 解密
+export function decrypt(txt) {
+  const encryptor = new JSEncrypt()
+  encryptor.setPrivateKey(privateKey) // 设置私钥
+  return encryptor.decrypt(txt) // 对数据进行解密
+}

+ 245 - 136
src/views/login.vue

@@ -1,74 +1,116 @@
 <template>
-  <div class="login" :style="'background-image:url('+ Background +');'">
-    <el-form ref="loginForm" :model="loginForm" :rules="loginRules" label-position="left" label-width="0px" class="login-form">
-      <h3 class="title">
-        <span class="CN">用户登录</span>
-        <span class="EN">LOGIN</span>
-      </h3>
+  <div class="login">
+    <div v-if="erp" class="bg"><img src="@/assets/images/bg.png" alt="" style="width:100%;height:100%;"></div>
+    <div v-if="erp" class="logo">
+      <img src="@/assets/logo/logo-b.png" alt="">
+      <span class="logo_txt">智慧文印管理系统</span>
+    </div>
+    <el-form v-if="erp" ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form">
+      <h3 class="title">用户登录 <span>LOGIN</span></h3>
       <el-form-item prop="username">
-        <el-input v-model="loginForm.username" type="text" auto-complete="off" placeholder="请输入用户名">
+        <el-input v-model="loginForm.username" type="text" auto-complete="off" placeholder="账号">
           <svg-icon slot="prefix" icon-class="user" class="el-input__icon input-icon" />
         </el-input>
       </el-form-item>
       <el-form-item prop="password">
-        <el-input v-model="loginForm.password" show-password type="password" auto-complete="off" placeholder="请输入密码" @keyup.enter.native="handleLogin">
+        <el-input
+          v-model="loginForm.password"
+          :type="passwordtxt"
+          auto-complete="off"
+          placeholder="密码"
+          @keyup.enter.native="handleLogin"
+        >
           <svg-icon slot="prefix" icon-class="password" class="el-input__icon input-icon" />
+          <svg-icon v-show="passwordtxt =='password'" slot="prefix" icon-class="eye" class="el-input__icon input-icon" style="position:absolute;right:-340px" @click="eyeTab" />
+          <svg-icon v-show="passwordtxt =='text'" slot="prefix" icon-class="eye-open" class="el-input__icon input-icon" style="position:absolute;right:-340px" @click="eyeTab" />
         </el-input>
+
       </el-form-item>
-      <el-form-item prop="code">
-        <el-input v-model="loginForm.code" auto-complete="off" placeholder="请输入验证码" style="width: 63%" @keyup.enter.native="handleLogin">
+      <el-form-item v-if="captchaOnOff" prop="code">
+        <el-input
+          v-model="loginForm.code"
+          auto-complete="off"
+          placeholder="验证码"
+          style="width: 63%"
+          @keyup.enter.native="handleLogin"
+        >
           <svg-icon slot="prefix" icon-class="validCode" class="el-input__icon input-icon" />
         </el-input>
         <div class="login-code">
-          <img :src="codeUrl">
-          <i class="el-icon-refresh" @click="getCode" />
+          <img :src="codeUrl" class="login-code-img" @click="getCode">
         </div>
       </el-form-item>
-      <el-checkbox v-model="loginForm.rememberMe" style="margin:0 0 25px 0;">
-        记住我
-      </el-checkbox>
+      <el-checkbox v-model="loginForm.rememberMe" style="margin:0px 0px 25px 0px;" @change="memory">记住密码</el-checkbox>
       <el-form-item style="width:100%;">
-        <el-button :loading="loading" size="medium" type="primary" style="width:100%;" @click.native.prevent="handleLogin">
+        <el-button
+          :loading="loading"
+          size="medium"
+          type="primary"
+          style="width:100%;"
+          @click.native.prevent="handleLogin"
+        >
           <span v-if="!loading">登 录</span>
           <span v-else>登 录 中...</span>
         </el-button>
+        <!-- <div style="float: right;" v-if="register">
+          <router-link class="link-type" :to="'/register'">立即注册</router-link>
+        </div> -->
       </el-form-item>
     </el-form>
     <!--  底部  -->
-    <div v-if="$store.state.settings.showFooter" id="el-login-footer">
-      <span v-html="$store.state.settings.footerTxt" />
-      <span> ⋅ </span>
-      <a href="https://beian.miit.gov.cn/#/Integrated/index" target="_blank">{{ $store.state.settings.caseNumber }}</a>
+    <div v-if="erp" class="el-login-footer">
+      <!-- <span>Copyright © 2018-2021 yongtian.vip All Rights Reserved.</span> -->
+    </div>
+    <div v-if="ERPloading" id="loader-wrapper">
+      <div id="loader" />
+      <div class="loader-section section-left" />
+      <div class="loader-section section-right" />
+      <div class="load_title">正在加载系统资源,请耐心等待</div>
     </div>
   </div>
 </template>
 
 <script>
-import { encrypt } from '@/utils/rsaEncrypt'
-import Config from '@/settings'
+import bgImg from '@/assets/images/bg.png'
+import logoImg from '@/assets/logo/logo-b.png'
 import { getCodeImg } from '@/api/login'
 import Cookies from 'js-cookie'
-import Background from '@/assets/images/login_bg.png'
+import { decrypt, encrypt } from '@/utils/jsencrypt'
+
 export default {
   name: 'Login',
   data() {
     return {
-      Background: Background,
+      erp: false,
+      ERPloading: true,
+      passwordtxt: 'password',
+      bg: bgImg,
+      logo: logoImg,
       codeUrl: '',
-      cookiePass: '',
+      cookiePassword: '',
       loginForm: {
-        username: 'admin',
-        password: '123456',
+        username: '',
+        password: '',
+        // username: "admin",
+        // password: "admin123",
         rememberMe: false,
         code: '',
         uuid: ''
       },
       loginRules: {
-        username: [{ required: true, trigger: 'blur', message: '用户名不能为空' }],
-        password: [{ required: true, trigger: 'blur', message: '密码不能为空' }],
-        code: [{ required: true, trigger: 'change', message: '验证码不能为空' }]
+        username: [
+          { required: true, trigger: 'blur', message: '请输入您的账号' }
+        ],
+        password: [
+          { required: true, trigger: 'blur', message: '请输入您的密码' }
+        ],
+        code: [{ required: true, trigger: 'change', message: '请输入验证码' }]
       },
       loading: false,
+      // 验证码开关
+      captchaOnOff: false,
+      // 注册开关
+      register: false,
       redirect: undefined
     }
   },
@@ -81,146 +123,213 @@ export default {
     }
   },
   created() {
-    // 获取验证码
-    this.getCode()
-    // 获取用户名密码等Cookie
-    this.getCookie()
-    // token 过期提示
-    this.point()
+    this.getUrl()
   },
   methods: {
+    getUrl() {
+      const url = this.$route.query
+      if (url.username && url.password) {
+        const data = { username: url.username, password: url.password }
+        data.password = encrypt(encodeuricomponent(this.loginForm.password))
+        this.handleLoginERP(data)
+      } else if (url.userNameSaaS && url.passWordSaaS) {
+        const data = {
+          username: decrypt(decodeURIComponent(url.userNameSaaS)),
+          password: decrypt(decodeURIComponent(url.passWordSaaS))
+        }
+        Cookies.set('username20220719', data.username, { expires: 30 })
+        Cookies.set('password20220719', url.passWordSaaS, { expires: 30 })
+        this.handleLoginSaaS(data)
+      } else {
+        this.getCode()
+        this.getCookie()
+      }
+    },
+    eyeTab() {
+      if (this.passwordtxt == 'password') {
+        this.passwordtxt = 'text'
+      } else {
+        this.passwordtxt = 'password'
+      }
+    },
     getCode() {
       getCodeImg().then(res => {
+        this.captchaOnOff = true
         this.codeUrl = res.img
         this.loginForm.uuid = res.uuid
+        this.erp = true
+        setTimeout(() => {
+          this.ERPloading = false
+        },)
       })
     },
     getCookie() {
-      const username = Cookies.get('username')
-      let password = Cookies.get('password')
-      const rememberMe = Cookies.get('rememberMe')
-      // 保存cookie里面的加密后的密码
-      this.cookiePass = password === undefined ? '' : password
-      password = password === undefined ? this.loginForm.password : password
+      const username = Cookies.get('username20220719')
+      const password = Cookies.get('password20220719')
+      const rememberMe = Cookies.get('rememberMe20220719')
       this.loginForm = {
         username: username === undefined ? this.loginForm.username : username,
-        password: password,
-        rememberMe: rememberMe === undefined ? false : Boolean(rememberMe),
-        code: ''
+        password: password === undefined ? this.loginForm.password : decrypt(password),
+        rememberMe: rememberMe === undefined ? false : Boolean(rememberMe)
       }
     },
     handleLogin() {
       this.$refs.loginForm.validate(valid => {
-        const user = {
-          username: this.loginForm.username,
-          password: this.loginForm.password,
-          rememberMe: this.loginForm.rememberMe,
-          code: this.loginForm.code,
-          uuid: this.loginForm.uuid
-        }
-        if (user.password !== this.cookiePass) {
-          user.password = encrypt(user.password)
-        }
         if (valid) {
           this.loading = true
-          if (user.rememberMe) {
-            Cookies.set('username', user.username, { expires: Config.passCookieExpires })
-            Cookies.set('password', user.password, { expires: Config.passCookieExpires })
-            Cookies.set('rememberMe', user.rememberMe, { expires: Config.passCookieExpires })
-          } else {
-            Cookies.remove('username')
-            Cookies.remove('password')
-            Cookies.remove('rememberMe')
-          }
-          this.$store.dispatch('Login', user).then(() => {
-            this.loading = false
-            this.$router.push({ path: this.redirect || '/' })
+          this.$store.dispatch('Login', this.loginForm).then((res) => {
+            this.$router.push({ path: '/dashboard' }).catch(() => {})
           }).catch(() => {
             this.loading = false
-            this.getCode()
+            if (this.captchaOnOff) {
+              this.getCode()
+            }
           })
-        } else {
-          console.log('error submit!!')
-          return false
         }
       })
     },
-    point() {
-      const point = Cookies.get('point') !== undefined
-      if (point) {
-        this.$notify({
-          title: '提示',
-          message: '当前登录状态已过期,请重新登录!',
-          type: 'warning',
-          duration: 5000
-        })
-        Cookies.remove('point')
+    memory() {
+      if (this.loginForm.rememberMe) {
+        Cookies.set('username20220719', this.loginForm.username, { expires: 30 })
+        Cookies.set('password20220719', encrypt(encodeuricomponent(this.loginForm.password)), { expires: 30 })
+        Cookies.set('rememberMe20220719', this.loginForm.rememberMe, { expires: 30 })
+      } else {
+        Cookies.remove('username20220719')
+        Cookies.remove('password20220719')
+        Cookies.remove('rememberMe20220719')
       }
+    },
+    handleLoginERP(data) { // erp登录
+      this.$store.dispatch('LoginERP', data).then((res) => {
+        this.$router.push({ path: '/dashboard' }).catch(() => {})
+      }).catch((err) => {
+        location.href = '/dashboard'
+      })
+    },
+    handleLoginSaaS(data) { // SaaS登录
+      this.$store.dispatch('Login', data).then((res) => {
+        this.$router.push({ path: '/dashboard' })
+      }).catch((err) => {
+        location.href = ''
+      })
     }
   }
 }
 </script>
 
-<style rel="stylesheet/scss" lang="scss">
-  .login {
-    display: flex;
-    justify-content: center;
-    align-items: center;
-    height: 100%;
-    background-size: cover;
+<style  lang="scss" scoped>
+.bg{
+  width:100%;
+  height:100%;
+  overflow: hidden;
+  position: fixed;
+  top:0;
+  left:0;
+  z-index: -1;
+  .bgimg{
+    width:100%;
+    height:100%;
+    position: absolute;
+    top:0;
+    left:0;
+    z-index: -1;
   }
-  .title {
-    margin: 0 auto 30px auto;
-    text-align: left;
-    color: #707070;
-    .CN {
-      color: #474747;
-    }
-    .EN {
-      color: #d4d4d4;
-      margin-left: 10px;
-    }
+}
+.logo{
+  width:100%;
+  position: fixed;
+  top:0;
+  img{
+    width:152px;
+    margin:10px 2rem 0 20px;
+    vertical-align: middle;
+  }
+  .logo_txt{
+    font-size: 1.5rem;
+    color:#fff;
+    vertical-align: middle;
+    letter-spacing: 4px;
+  }
+}
+.login {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  height: 100%;
+  // background-image: url("../assets/images/login-background.jpg");
+  background-size: cover;
+}
+.title {
+  margin: 0px auto 30px auto;
+  text-align: left;
+  color: #000000;
+  font-size: 20px;
+  span{
+    margin-left:10px;
+    opacity: 0.25;
   }
+}
 
-  .login-form {
-    border-radius: 6px;
-    background: #ffffff;
-    width: 335px;
-    padding: 25px 25px 5px 25px;
-    .el-input {
-      height: 38px;
-      input {
-        height: 38px;
-      }
-    }
-    .input-icon{
-      height: 39px;width: 14px;margin-left: 2px;
+.login-form {
+  border-radius: 6px;
+  background: #ffffff;
+  width: 456px;
+  padding: 63px 35px;
+  .el-input {
+    height: 40px;
+    font-size: 16px !important;
+    input {
+      height: 40px;
     }
   }
-  .login-tip {
-    font-size: 13px;
-    text-align: center;
-    color: #bfbfbf;
+  .input-icon {
+    height: 39px;
+    width: 14px;
+    margin-left: 2px;
   }
-  .login-code {
-    width: 33%;
-    height: 38px;
-    float: right;
-    display: inline-flex;
-    justify-content: center;
-    align-items: center;
-    img{
-      vertical-align:middle;
-      width: 80%;
-      height: 38px;
-      padding: 5px;
-      border: 1px solid rgb(217,217,217);
-      border-radius: 3px;
-    }
-    i {
-      color: rgb(135,135,135);
-      margin-left: 5px;
-      cursor: pointer;
-    }
+}
+.login-tip {
+  font-size: 13px;
+  text-align: center;
+  color: #bfbfbf;
+}
+.login-code {
+  width: 33%;
+  height: 36px;
+  float: right;
+  img {
+    cursor: pointer;
+    vertical-align: middle;
+    width:100%;
+    height: 36px;
+    margin-top:-1px;
   }
+}
+.el-login-footer {
+  height: 40px;
+  line-height: 40px;
+  position: fixed;
+  bottom: 0;
+  width: 100%;
+  text-align: center;
+  color: #fff;
+  font-family: Arial;
+  font-size: 12px;
+  letter-spacing: 1px;
+}
+::v-deep .el-input__inner{
+  height:36px !important;
+  line-height: 36px !important;
+}
+</style>
+<style>
+html,
+body,
+#app {
+    height: 100%;
+    margin: 0px;
+    padding: 0px;
+    background-color: transparent !important;
+
+}
 </style>

+ 116 - 117
vue.config.js

@@ -3,7 +3,7 @@ const path = require('path')
 const defaultSettings = require('./src/settings.js')
 
 function resolve(dir) {
-  return path.join(__dirname, dir)
+    return path.join(__dirname, dir)
 }
 
 const name = defaultSettings.title // 网址标题
@@ -11,127 +11,126 @@ const port = 8013 // 端口配置
 
 // All configuration item explanations can be find in https://cli.vuejs.org/config/
 module.exports = {
-  // hash 模式下可使用
-  // publicPath: process.env.NODE_ENV === 'development' ? '/' : './',
-  publicPath: '/',
-  outputDir: 'dist',
-  assetsDir: 'static',
-  lintOnSave: process.env.NODE_ENV === 'development',
-  productionSourceMap: false,
-  devServer: {
-    port: port,
-    open: true,
-    overlay: {
-      warnings: false,
-      errors: true
-    },
-    proxy: {
-      '/api': {
-        target: process.env.VUE_APP_BASE_API,
-        changeOrigin: true,
-        pathRewrite: {
-          '^/api': 'api'
+    // hash 模式下可使用
+    publicPath: './',
+    outputDir: 'dist',
+    assetsDir: 'static',
+    lintOnSave: process.env.NODE_ENV === 'development',
+    productionSourceMap: false,
+    devServer: {
+        port: port,
+        open: true,
+        overlay: {
+            warnings: false,
+            errors: true
+        },
+        proxy: {
+            '/api': {
+                target: process.env.VUE_APP_BASE_API,
+                changeOrigin: true,
+                pathRewrite: {
+                    '^/api': 'api'
+                }
+            },
+            '/auth': {
+                target: process.env.VUE_APP_BASE_API,
+                changeOrigin: true,
+                pathRewrite: {
+                    '^/auth': 'auth'
+                }
+            }
         }
-      },
-      '/auth': {
-        target: process.env.VUE_APP_BASE_API,
-        changeOrigin: true,
-        pathRewrite: {
-          '^/auth': 'auth'
+    },
+    configureWebpack: {
+        // provide the app's title in webpack's name field, so that
+        // it can be accessed in index.html to inject the correct title.
+        name: name,
+        resolve: {
+            alias: {
+                '@': resolve('src'),
+                '@crud': resolve('src/components/Crud')
+            }
         }
-      }
-    }
-  },
-  configureWebpack: {
-    // provide the app's title in webpack's name field, so that
-    // it can be accessed in index.html to inject the correct title.
-    name: name,
-    resolve: {
-      alias: {
-        '@': resolve('src'),
-        '@crud': resolve('src/components/Crud')
-      }
-    }
-  },
-  chainWebpack(config) {
-    config.plugins.delete('preload') // TODO: need test
-    config.plugins.delete('prefetch') // TODO: need test
+    },
+    chainWebpack(config) {
+        config.plugins.delete('preload') // TODO: need test
+        config.plugins.delete('prefetch') // TODO: need test
 
-    // set svg-sprite-loader
-    config.module
-      .rule('svg')
-      .exclude.add(resolve('src/assets/icons'))
-      .end()
-    config.module
-      .rule('icons')
-      .test(/\.svg$/)
-      .include.add(resolve('src/assets/icons'))
-      .end()
-      .use('svg-sprite-loader')
-      .loader('svg-sprite-loader')
-      .options({
-        symbolId: 'icon-[name]'
-      })
-      .end()
+        // set svg-sprite-loader
+        config.module
+            .rule('svg')
+            .exclude.add(resolve('src/assets/icons'))
+            .end()
+        config.module
+            .rule('icons')
+            .test(/\.svg$/)
+            .include.add(resolve('src/assets/icons'))
+            .end()
+            .use('svg-sprite-loader')
+            .loader('svg-sprite-loader')
+            .options({
+                symbolId: 'icon-[name]'
+            })
+            .end()
 
-    // set preserveWhitespace
-    config.module
-      .rule('vue')
-      .use('vue-loader')
-      .loader('vue-loader')
-      .tap(options => {
-        options.compilerOptions.preserveWhitespace = true
-        return options
-      })
-      .end()
+        // set preserveWhitespace
+        config.module
+            .rule('vue')
+            .use('vue-loader')
+            .loader('vue-loader')
+            .tap(options => {
+                options.compilerOptions.preserveWhitespace = true
+                return options
+            })
+            .end()
 
-    config
-      // https://webpack.js.org/configuration/devtool/#development
-      .when(process.env.NODE_ENV === 'development',
-        config => config.devtool('cheap-source-map')
-      )
+        config
+        // https://webpack.js.org/configuration/devtool/#development
+            .when(process.env.NODE_ENV === 'development',
+            config => config.devtool('cheap-source-map')
+        )
 
-    config
-      .when(process.env.NODE_ENV !== 'development',
-        config => {
-          config
-            .plugin('ScriptExtHtmlWebpackPlugin')
-            .after('html')
-            .use('script-ext-html-webpack-plugin', [{
-            // `runtime` must same as runtimeChunk name. default is `runtime`
-              inline: /runtime\..*\.js$/
-            }])
-            .end()
-          config
-            .optimization.splitChunks({
-              chunks: 'all',
-              cacheGroups: {
-                libs: {
-                  name: 'chunk-libs',
-                  test: /[\\/]node_modules[\\/]/,
-                  priority: 10,
-                  chunks: 'initial' // only package third parties that are initially dependent
-                },
-                elementUI: {
-                  name: 'chunk-elementUI', // split elementUI into a single package
-                  priority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or app
-                  test: /[\\/]node_modules[\\/]_?element-ui(.*)/ // in order to adapt to cnpm
-                },
-                commons: {
-                  name: 'chunk-commons',
-                  test: resolve('src/components'), // can customize your rules
-                  minChunks: 3, //  minimum common number
-                  priority: 5,
-                  reuseExistingChunk: true
+        config
+            .when(process.env.NODE_ENV !== 'development',
+                config => {
+                    config
+                        .plugin('ScriptExtHtmlWebpackPlugin')
+                        .after('html')
+                        .use('script-ext-html-webpack-plugin', [{
+                            // `runtime` must same as runtimeChunk name. default is `runtime`
+                            inline: /runtime\..*\.js$/
+                        }])
+                        .end()
+                    config
+                        .optimization.splitChunks({
+                            chunks: 'all',
+                            cacheGroups: {
+                                libs: {
+                                    name: 'chunk-libs',
+                                    test: /[\\/]node_modules[\\/]/,
+                                    priority: 10,
+                                    chunks: 'initial' // only package third parties that are initially dependent
+                                },
+                                elementUI: {
+                                    name: 'chunk-elementUI', // split elementUI into a single package
+                                    priority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or app
+                                    test: /[\\/]node_modules[\\/]_?element-ui(.*)/ // in order to adapt to cnpm
+                                },
+                                commons: {
+                                    name: 'chunk-commons',
+                                    test: resolve('src/components'), // can customize your rules
+                                    minChunks: 3, //  minimum common number
+                                    priority: 5,
+                                    reuseExistingChunk: true
+                                }
+                            }
+                        })
+                    config.optimization.runtimeChunk('single')
                 }
-              }
-            })
-          config.optimization.runtimeChunk('single')
-        }
-      )
-  },
-  transpileDependencies: [
-    'vue-echarts',
-    'resize-detector'
-  ]
+            )
+    },
+    transpileDependencies: [
+        'vue-echarts',
+        'resize-detector'
+    ]
 }