Browse Source

1、提交代理代码

qmj 4 months ago
parent
commit
62f5584f7a
6 changed files with 147 additions and 49 deletions
  1. 1 0
      .env.production
  2. 100 31
      src/layout/components/Navbar.vue
  3. 25 4
      src/permission.js
  4. 4 4
      src/store/modules/user.js
  5. 14 9
      src/views/login.vue
  6. 3 1
      vite.config.js

+ 1 - 0
.env.production

@@ -11,4 +11,5 @@ VITE_APP_BASE_API = '/prod-api'
 VITE_BUILD_COMPRESS = gzip
 
 //文件路径
+//VITE_APP_FILE_PATH='https://loanapi.waimai-paotui.com'
 VITE_APP_FILE_PATH='https://api.shoujida.com'

+ 100 - 31
src/layout/components/Navbar.vue

@@ -8,13 +8,13 @@
       <template v-if="appStore.device !== 'mobile'">
         <header-search id="header-search" class="right-menu-item" />
 
-        <el-tooltip content="源码地址" effect="dark" placement="bottom">
-          <ruo-yi-git id="ruoyi-git" class="right-menu-item hover-effect" />
-        </el-tooltip>
+<!--        <el-tooltip content="源码地址" effect="dark" placement="bottom">-->
+<!--          <ruo-yi-git id="ruoyi-git" class="right-menu-item hover-effect" />-->
+<!--        </el-tooltip>-->
 
-        <el-tooltip content="文档地址" effect="dark" placement="bottom">
-          <ruo-yi-doc id="ruoyi-doc" class="right-menu-item hover-effect" />
-        </el-tooltip>
+<!--        <el-tooltip content="文档地址" effect="dark" placement="bottom">-->
+<!--          <ruo-yi-doc id="ruoyi-doc" class="right-menu-item hover-effect" />-->
+<!--        </el-tooltip>-->
 
         <screenfull id="screenfull" class="right-menu-item hover-effect" />
 
@@ -25,26 +25,25 @@
           </div>
         </el-tooltip>
 
-        <el-tooltip content="布局大小" effect="dark" placement="bottom">
-          <size-select id="size-select" class="right-menu-item hover-effect" />
-        </el-tooltip>
+<!--        <el-tooltip content="布局大小" effect="dark" placement="bottom">-->
+<!--          <size-select id="size-select" class="right-menu-item hover-effect" />-->
+<!--        </el-tooltip>-->
+<!--        <div class="right-menu-item logout-wrapper">-->
+<!--          <span class="user-name">{{ userStore.name }}</span>-->
+<!--          <a @click="logout" class="logout-link">退出登录</a>-->
+<!--        </div>-->
       </template>
 
-      <el-dropdown @command="handleCommand" class="avatar-container right-menu-item hover-effect" trigger="hover">
+      <el-dropdown @command="handleCommand" class="avatar-container right-menu-item hover-effect" trigger="hover" placement="bottom-end">
         <div class="avatar-wrapper">
-          <img :src="userStore.avatar" class="user-avatar" />
-          <span class="user-nickname"> {{ userStore.nickName }} </span>
+          <div class="user-info">
+            <div class="user-name">{{ userStore.name }}</div>
+          </div>
         </div>
         <template #dropdown>
           <el-dropdown-menu>
-            <router-link to="/user/profile">
-              <el-dropdown-item>个人中心</el-dropdown-item>
-            </router-link>
-            <el-dropdown-item command="setLayout" v-if="settingsStore.showSettings">
-                <span>布局设置</span>
-              </el-dropdown-item>
-            <el-dropdown-item divided command="logout">
-              <span>退出登录</span>
+            <el-dropdown-item divided command="logout" class="logout-item">
+              <span class="logout-text">退出登录</span>
             </el-dropdown-item>
           </el-dropdown-menu>
         </template>
@@ -186,14 +185,68 @@ function toggleTheme() {
       }
     }
 
+    .logout-wrapper {
+      display: flex;
+      align-items: center;
+      gap: 8px;
+      padding: 0 12px;
+
+      .user-name {
+        font-size: 14px;
+        color: #5a5e66;
+        font-weight: 500;
+      }
+
+      .logout-link {
+        font-size: 14px;
+        color: #5a5e66;
+        text-decoration: none;
+        cursor: pointer;
+        transition: color 0.3s;
+
+        &:hover {
+          color: #409eff;
+        }
+      }
+    }
+
     .avatar-container {
       margin-right: 0px;
       padding-right: 0px;
+      min-width: 100px;
 
       .avatar-wrapper {
-        margin-top: 10px;
-        right: 8px;
-        position: relative;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        height: 100%;
+        padding: 0 16px;
+        cursor: pointer;
+        transition: background 0.3s;
+        line-height: 50px;
+
+        &:hover {
+          background: rgba(0, 0, 0, 0.025);
+        }
+
+        .user-info {
+          display: flex;
+          flex-direction: column;
+          align-items: center;
+          justify-content: center;
+          width: 100%;
+          height: 100%;
+
+          .user-name {
+            font-size: 14px;
+            color: #5a5e66;
+            font-weight: 500;
+            white-space: nowrap;
+            line-height: 50px;
+            text-align: center;
+            width: 100%;
+          }
+        }
 
         .user-avatar {
           cursor: pointer;
@@ -203,14 +256,6 @@ function toggleTheme() {
           border-radius: 50%;
         }
 
-        .user-nickname{
-          position: relative;
-          left: 0px;
-          bottom: 10px;
-          font-size: 14px;
-          font-weight: bold;
-        }
-
         i {
           cursor: pointer;
           position: absolute;
@@ -222,4 +267,28 @@ function toggleTheme() {
     }
   }
 }
+
+// 下拉菜单样式
+:deep(.el-dropdown-menu) {
+  .logout-item {
+    padding: 8px 20px;
+    text-align: center;
+    min-width: 120px;
+
+    .logout-text {
+      display: block;
+      color: #606266;
+      font-size: 14px;
+      transition: color 0.3s;
+    }
+
+    &:hover {
+      background-color: #f5f7fa;
+
+      .logout-text {
+        color: #409eff;
+      }
+    }
+  }
+}
 </style>

+ 25 - 4
src/permission.js

@@ -5,6 +5,7 @@ import { getToken } from '@/utils/auth'
 import { isPathMatch } from '@/utils/validate'
 import useSettingsStore from '@/store/modules/settings'
 import usePermissionStore from '@/store/modules/permission'
+import useUserStore from '@/store/modules/user'
 
 NProgress.configure({ showSpinner: false })
 
@@ -14,13 +15,28 @@ const isWhiteList = (path) => {
   return whiteList.some(pattern => isPathMatch(pattern, path))
 }
 
-router.beforeEach((to, from, next) => {
+router.beforeEach(async (to, from, next) => {
   NProgress.start()
   if (getToken()) {
     to.meta.title && useSettingsStore().setTitle(to.meta.title)
     /* has token*/
+    const userStore = useUserStore()
+    // 如果还没有用户信息,先获取用户信息
+    if (!userStore.name && userStore.token) {
+      try {
+        await userStore.getInfo()
+      } catch (error) {
+        console.error('获取用户信息失败:', error)
+        // 如果获取用户信息失败,清除token并跳转到登录页
+        await userStore.logOut()
+        next(`/login?redirect=${to.fullPath}`)
+        NProgress.done()
+        return
+      }
+    }
     if (to.path === '/login') {
-      next({ path: '/user/myuser' })
+      // 如果已经登录,跳转到首页
+      next({ path: '/user/myuser', replace: true })
       NProgress.done()
     } else if (isWhiteList(to.path)) {
       next()
@@ -29,13 +45,18 @@ router.beforeEach((to, from, next) => {
       const permissionStore = usePermissionStore()
       if (permissionStore.routes.length === 0) {
         // 菜单还未加载,先加载菜单
-        permissionStore.generateRoutes().then(accessRoutes => {
+        try {
+          const accessRoutes = await permissionStore.generateRoutes()
           // 动态添加路由
           accessRoutes.forEach(route => {
             router.addRoute(route) // 动态添加路由
           })
+          // 路由加载完成后,继续导航到目标路径
           next({ ...to, replace: true })
-        })
+        } catch (error) {
+          console.error('加载路由失败:', error)
+          next()
+        }
       } else {
         next()
       }

+ 4 - 4
src/store/modules/user.js

@@ -38,14 +38,14 @@ const useUserStore = defineStore(
       getInfo() {
         return new Promise((resolve, reject) => {
           getInfo().then(res => {
-            const user = res.user
+            const user = res.data.user
             let avatar = user.avatar || ""
             if (!isHttp(avatar)) {
               avatar = (isEmpty(avatar)) ? defAva : import.meta.env.VITE_APP_BASE_API + avatar
             }
-            if (res.roles && res.roles.length > 0) { // 验证返回的roles是否是一个非空数组
-              this.roles = res.roles
-              this.permissions = res.permissions
+            if (res.data.roles && res.data.roles.length > 0) { // 验证返回的roles是否是一个非空数组
+              this.roles = res.data.roles
+              this.permissions = res.data.permissions
             } else {
               this.roles = ['ROLE_DEFAULT']
             }

+ 14 - 9
src/views/login.vue

@@ -119,15 +119,20 @@ function handleLogin() {
       }
       // 调用action的登录方法
       userStore.login(loginForm.value).then(() => {
-        const query = route.query
-        const otherQueryParams = Object.keys(query).reduce((acc, cur) => {
-          if (cur !== "redirect") {
-            acc[cur] = query[cur]
-          }
-          return acc
-        }, {})
-        router.push({ path: "/user/myuser", query: otherQueryParams })
-      }).catch(() => {
+        // 登录成功后获取用户信息
+        return userStore.getInfo()
+      }).then(() => {
+        // 获取用户信息成功后,跳转到目标页面
+        // 路由守卫会自动处理路由加载
+        const redirectPath = route.query.redirect || '/user/myuser'
+        router.push(redirectPath).catch(() => {
+          // 如果跳转失败,可能是路由还未加载,等待一下再跳转
+          setTimeout(() => {
+            router.push(redirectPath)
+          }, 100)
+        })
+      }).catch((error) => {
+        console.error('登录失败:', error)
         loading.value = false
         // 重新获取验证码
         if (captchaEnabled.value) {

+ 3 - 1
vite.config.js

@@ -2,7 +2,9 @@ import { defineConfig, loadEnv } from 'vite'
 import path from 'path'
 import createVitePlugins from './vite/plugins'
 
-const baseUrl = 'http://localhost:8080' // 后端接口
+// const baseUrl = 'http://localhost:8080' // 后端接口
+// const baseUrl = 'https://loanagent.waimai-paotui.com' // 后端接口
+const baseUrl="https://agent.shoujida.com"
 
 // https://vitejs.dev/config/
 export default defineConfig(({ mode, command }) => {