Jelajahi Sumber

Merge remote-tracking branch 'origin/main'

zhanghao 3 bulan lalu
induk
melakukan
d0d5d6d4f2

+ 3 - 1
src/api/login.js

@@ -1,4 +1,5 @@
 import request from '@/utils/request'
+import { isPadDevice } from '@/utils/device'; // 设备检测工具函数
 
 // 登录方法
 export function login(username, password, code, uuid) {
@@ -8,8 +9,9 @@ export function login(username, password, code, uuid) {
     code,
     uuid
   }
+  const loginPath = isPadDevice() ? '/login' : 'zhhg_dp/doLogin';
   return request({
-    url: '/login',
+    url: loginPath,
     headers: {
       isToken: false
     },

+ 14 - 3
src/permission.js

@@ -5,10 +5,11 @@ import NProgress from 'nprogress'
 import 'nprogress/nprogress.css'
 import { getToken } from '@/utils/auth'
 import { isRelogin } from '@/utils/request'
+import { isPadDevice } from '@/utils/device'; // 设备检测工具函数
 
 NProgress.configure({ showSpinner: false })
 
-const whiteList = ['/login', '/auth-redirect', '/bind', '/register','/screen','/pad']
+const whiteList = ['/login','/loginPad','/user/doLogin', '/auth-redirect', '/bind', '/register','/screen','/pad']
 
 router.beforeEach((to, from, next) => {
   NProgress.start()
@@ -18,7 +19,11 @@ router.beforeEach((to, from, next) => {
     if (to.path === '/login') {
       next({ path: '/index' })
       NProgress.done()
-    } else {
+    }else if (to.path === '/loginPad') {
+      next({ path: '/pad' })
+      NProgress.done()
+    }
+     else {
       if (store.getters.roles.length === 0) {
         isRelogin.show = true
         // 判断当前用户是否已拉取完user_info信息
@@ -45,8 +50,14 @@ router.beforeEach((to, from, next) => {
       // 在免登录白名单,直接进入
       next()
     } else {
+      const loginPath = isPadDevice() ? 2 : 1;
       // next(`/login?redirect=${to.fullPath}`) // 否则全部重定向到登录页
-      next(`/screen`) // 否则全部重定向到登录页
+      if(loginPath==2){
+        next(`/login`) // 否则全部重定向到登录页
+      }else{
+        next(`/loginPad`) // 否则全部重定向到登录页
+      }
+    
       NProgress.done()
     }
   }

+ 5 - 0
src/router/index.js

@@ -57,6 +57,11 @@ export const constantRoutes = [
     hidden: true
   },
   {
+    path: '/loginPad',
+    component: () => import('@/views/loginPad'),
+    hidden: true
+  },
+  {
     path: '/register',
     component: () => import('@/views/register'),
     hidden: true

+ 1 - 1
src/store/index.js

@@ -22,4 +22,4 @@ const store = new Vuex.Store({
   getters
 })
 
-export default store
+export default store

+ 4 - 0
src/utils/device.js

@@ -0,0 +1,4 @@
+export function isPadDevice() {
+    const userAgent = navigator.userAgent || navigator.vendor || window.opera;
+    return /iPad|Tablet|Android|Mobile/i.test(userAgent) && !/Phone/i.test(userAgent);
+  }

+ 31 - 23
src/utils/jsencrypt.js

@@ -1,30 +1,38 @@
-import JSEncrypt from 'jsencrypt/bin/jsencrypt.min'
+import CryptoJS from 'crypto-js'
 
-// 密钥对生成 http://web.chacuo.net/netrsakeypair
+const KEY = CryptoJS.enc.Utf8.parse('X4RjV51wQxSxZHHQ')
+const IV = CryptoJS.enc.Utf8.parse('g49GarVwCTR6nBHQ')
 
-const publicKey = 'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdH\n' +
-  'nzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ=='
 
-const privateKey = 'MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAqhHyZfSsYourNxaY\n' +
-  '7Nt+PrgrxkiA50efORdI5U5lsW79MmFnusUA355oaSXcLhu5xxB38SMSyP2KvuKN\n' +
-  'PuH3owIDAQABAkAfoiLyL+Z4lf4Myxk6xUDgLaWGximj20CUf+5BKKnlrK+Ed8gA\n' +
-  'kM0HqoTt2UZwA5E2MzS4EI2gjfQhz5X28uqxAiEA3wNFxfrCZlSZHb0gn2zDpWow\n' +
-  'cSxQAgiCstxGUoOqlW8CIQDDOerGKH5OmCJ4Z21v+F25WaHYPxCFMvwxpcw99Ecv\n' +
-  'DQIgIdhDTIqD2jfYjPTY8Jj3EDGPbH2HHuffvflECt3Ek60CIQCFRlCkHpi7hthh\n' +
-  'YhovyloRYsM+IS9h/0BzlEAuO0ktMQIgSPT3aFAgJYwKpqRYKlLDVcflZFCKY7u3\n' +
-  'UP8iWi1Qw0Y='
-
-// 加密
-export function encrypt(txt) {
-  const encryptor = new JSEncrypt()
-  encryptor.setPublicKey(publicKey) // 设置公钥
-  return encryptor.encrypt(txt) // 对数据进行加密
+// 加密函数
+export function encryptData(data) {
+    const encrypted = CryptoJS.AES.encrypt(
+        data,
+        KEY,
+        {
+            iv: IV,
+            mode: CryptoJS.mode.CBC,
+            padding: CryptoJS.pad.Pkcs7
+        }
+    )
+    return encrypted.toString()
 }
 
-// 解密
-export function decrypt(txt) {
-  const encryptor = new JSEncrypt()
-  encryptor.setPrivateKey(privateKey) // 设置私钥
-  return encryptor.decrypt(txt) // 对数据进行解密
+// 解密函数
+export function decryptData(data) {
+    const decrypted = CryptoJS.AES.decrypt(
+        data,
+        KEY,
+        {
+            iv: IV,
+            mode: CryptoJS.mode.CBC,
+            padding: CryptoJS.pad.Pkcs7
+        }
+    )
+    return CryptoJS.enc.Utf8.stringify(decrypted)
 }
 
+export default {
+    encryptData,
+    decryptData
+}

+ 1 - 1
src/utils/request.js

@@ -190,4 +190,4 @@ export function download(url, params, filename) {
   })
 }
 
-export default service
+export default service

+ 2 - 2
src/utils/request2.js

@@ -16,7 +16,7 @@ axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
 // 创建axios实例
 const service = axios.create({
   // axios中请求配置有baseURL选项,表示请求URL公共部分
-  // baseURL: process.env.VUE_APP_BASE_API,
+  baseURL: process.env.VUE_APP_BASE_API,
   // 超时
   timeout: 60 * 60 * 1000
 })
@@ -190,4 +190,4 @@ export function download(url, params, filename) {
   })
 }
 
-export default service
+export default service

+ 1 - 1
src/views/login.vue

@@ -354,4 +354,4 @@ export default {
 .login-code-img {
   height: 38px;
 }
-</style>
+</style>

+ 332 - 0
src/views/loginPad.vue

@@ -0,0 +1,332 @@
+<template>
+    <div class="login">
+      <el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form">
+        <h3 class="title-pass">账号登录</h3>
+        <el-form-item prop="username">
+          <label class="custom-label">
+          <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>
+        </label>
+        </el-form-item>
+        <el-form-item prop="password">
+          <label class="custom-Pass">
+          <el-input
+            v-model="loginForm.password"
+            type="password"
+            auto-complete="off"
+            placeholder="密码"
+            @keyup.enter.native="handleLogin"
+          >
+            <!-- <svg-icon slot="prefix" icon-class="password" class="el-input__icon input-icon" /> -->
+          </el-input>
+        </label>
+        </el-form-item>
+        
+        <!-- <el-checkbox v-model="loginForm.rememberMe" style="margin:0px 0px 25px 0px;">记住密码</el-checkbox> -->
+        <el-form-item style="width:100%;">
+          <el-button
+            :loading="loading"
+            size="medium"
+            type="primary"
+            style="width:100%;"
+            @click.native.prevent="handleLogin"
+            class="login-submit"
+          >
+            <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 class="el-login-footer">
+  <!--      <span>Copyright © 2018-2022 All Rights Reserved.</span>-->
+      </div>
+    </div>
+  </template>
+  
+  <script>
+  import Cookies from "js-cookie";
+  import { encrypt, decrypt } from '@/utils/jsencrypt'
+  
+  export default {
+    name: "Login",
+    data() {
+      return {
+        codeUrl: "",
+        loginForm: {
+          username: "admin",
+          password: "admin123",
+          rememberMe: false,
+        
+          uuid: ""
+        },
+        loginRules: {
+          username: [
+            { required: true, trigger: "blur", message: "请输入您的账号" }
+          ],
+          password: [
+            { required: true, trigger: "blur", message: "请输入您的密码" }
+          ],
+        
+        },
+        loading: false,
+    
+        // 注册开关
+        register: false,
+        redirect: undefined
+      };
+    },
+    watch: {
+      $route: {
+        handler: function(route) {
+          this.redirect = route.query && route.query.redirect;
+        },
+        
+      }
+    },
+    created() {
+
+      this.getCookie();
+    },
+    methods: {
+ 
+      getCookie() {
+        const username = Cookies.get("username");
+        const password = Cookies.get("password");
+        const rememberMe = Cookies.get('rememberMe')
+        this.loginForm = {
+          username: username === undefined ? this.loginForm.username : username,
+          password: password === undefined ? this.loginForm.password : decrypt(password),
+          rememberMe: rememberMe === undefined ? false : Boolean(rememberMe)
+        };
+      },
+      handleLogin() {
+    this.$refs.loginForm.validate(valid => {
+      if (valid) {
+        this.loading = true;
+  
+        // 设置记住密码逻辑
+        if (this.loginForm.rememberMe) {
+          Cookies.set("username", this.loginForm.username, { expires: 30 });
+          Cookies.set("password", encrypt(this.loginForm.password), { expires: 30 });
+          Cookies.set('rememberMe', this.loginForm.rememberMe, { expires: 30 });
+        } else {
+          Cookies.remove("username");
+          Cookies.remove("password");
+          Cookies.remove('rememberMe');
+        }
+  
+        this.$store.dispatch("Login", this.loginForm)
+          .then(() => {
+            this.$router.push({ path: this.redirect || "/" }).catch(() => {});
+          })
+          .catch((error) => {
+            // 提取具体错误信息
+            let errorMsg;
+            if (error && error.msg) {
+              errorMsg = error.msg;
+            } else if (error && error.message) {
+              errorMsg = error.message;
+            } else {
+              errorMsg = '登录失败';
+            }
+            this.$message.error(errorMsg);
+            // // 刷新验证码
+            // if (this.captchaEnabled) {
+            //   try {
+            //     this.getCode();
+            //   } catch (e) {
+            //     console.error('刷新验证码失败:', e);
+            //   }
+            // }
+          })
+          .finally(() => {
+            this.loading = false;
+          });
+      }
+    });
+  }
+    }
+  };
+  </script>
+  
+  <style rel="stylesheet/scss" lang="scss">
+  .login {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    height: 100%;
+    background-image: url("../assets/images/login-background.png");
+    background-size: cover;
+  }
+  .title-pass {
+    margin: 0px auto 30px auto;
+      text-align: center;
+      font-family: FZZCHJW--GB1-0;
+      font-weight: 400;
+      font-size: 30px;
+      color: #A9FFFE;
+      letter-spacing: 4.21px;
+  }
+  
+  .login-form {
+    // border-radius: 6px;
+    // background: #ffffff;
+    width: 545px;
+    height: 505px;
+    padding: 100px 100px 20px 100px;
+    background-image: url("../assets/images/passwordBorder.png");
+    background-size: cover;
+    .el-input {
+      height: 38px;
+      input {
+        height: 38px;
+      }
+    }
+    .input-icon {
+      height: 39px;
+      width: 14px;
+      margin-left: 2px;
+    }
+  }
+  .login-tip {
+    font-size: 13px;
+    text-align: center;
+    color: #bfbfbf;
+  }
+  .login-code {
+    width: 33%;
+    height: 38px;
+    float: right;
+    img {
+      cursor: pointer;
+      vertical-align: middle;
+    }
+  }
+  .login-code-img {
+      height: 38px;
+      border: 2px #009998 solid;
+  }
+  .login-form .el-input input {
+      height: 38px;
+      background: #096C78;
+      border: 2px #009998 solid;
+      color: #A9FFFE;
+      opacity: 0.9;
+      padding-left: 35px;
+  }
+  .el-form-item.is-error .el-input__inner, .el-form-item.is-error .el-input__inner:focus, .el-form-item.is-error .el-textarea__inner, .el-form-item.is-error .el-textarea__inner:focus {
+      border-color: #009998;
+  }
+  .login-submit{
+      font-family: PingFangSC-SNaNpxibold;
+      font-weight: 600;
+      font-size: 18px;
+      color: #002230;
+      /* color: #FFFFFF; */
+      background-color: #1890ff;
+      /* border-color: #1890ff; */
+       opacity: 0.85;
+      background: #0DDBDA;
+      border: 1px solid #0FF9F7;
+      margin-top: 30px;
+  }
+  .login-submit:hover{
+    font-family: PingFangSC-SNaNpxibold;
+      font-weight: 600;
+      font-size: 18px;
+      color: #002230;
+      /* color: #FFFFFF; */
+      background-color: #1890ff;
+      /* border-color: #1890ff; */
+       opacity: 0.85;
+      background: #0DDBDA;
+      border: 1px solid #0FF9F7;
+      margin-top: 30px;
+  }
+  .login-submit:enabled {
+    font-family: PingFangSC-SNaNpxibold;
+      font-weight: 600;
+      font-size: 18px;
+      color: #002230;
+      /* color: #FFFFFF; */
+      background-color: #1890ff;
+      /* border-color: #1890ff; */
+       opacity: 0.85;
+      background: #0DDBDA;
+      border: 1px solid #0FF9F7;
+      margin-top: 30px;
+  }
+  .el-checkbox__input.is-checked + .el-checkbox__label {
+      color: #0FF9F7;
+  }
+  .el-checkbox__input.is-checked .el-checkbox__inner {
+      background-color: #0FF9F7;
+      border-color: #0FF9F7;
+  }
+  
+  .custom-label::before {
+    content: '';
+    position: absolute;
+    left: 10px;
+    top: 50%;
+    transform: translateY(-50%);
+    width: 18px;
+    height: 18px;
+    background-image: url("../assets/images/passWordUse.png"); /* 替换为你的图片路径 */
+    background-repeat: no-repeat;
+    background-size: cover;
+    z-index: 99;
+  }
+  .custom-Pass::before{
+    content: '';
+    position: absolute;
+    left: 10px;
+    top: 50%;
+    transform: translateY(-50%);
+    width: 18px;
+    height: 18px;
+    background-image: url("../assets/images/suoUse.png"); /* 替换为你的图片路径 */
+    background-repeat: no-repeat;
+    background-size: cover;
+    z-index: 99;
+  }
+  .custom-yzm::before{
+    content: '';
+    position: absolute;
+    left: 10px;
+    top: 50%;
+    transform: translateY(-50%);
+    width: 18px;
+    height: 18px;
+    background-image: url("../assets/images/yanzma.png"); /* 替换为你的图片路径 */
+    background-repeat: no-repeat;
+    background-size: cover;
+    z-index: 99;
+  }
+  .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;
+  }
+  .login-code-img {
+    height: 38px;
+  }
+  </style>