feat(auth): 实现自动登录功能并优化API请求配置

- 在App.vue中添加onMounted钩子自动执行autoLogin函数
- 新增auth.js工具模块实现自动登录逻辑
- 配置API请求优先从localStorage获取Token
- 添加对localStorage和Cookie中Token的兼容性处理
- 集成echarts-china-map依赖包
- 移除测试用硬编码Token和调试日志
- 统一API基础路径为/api
- 添加Docker部署配置文件和nginx反向代理设置
This commit is contained in:
2026-06-11 14:32:28 +08:00
parent 6114d989bc
commit ab43fa2457
8 changed files with 131 additions and 32 deletions

11
.dockerignore Normal file
View File

@@ -0,0 +1,11 @@
node_modules
.git
.gitignore
.idea
*.md
deploy.sh
.env
src
public
scripts
node_modules

16
Dockerfile Normal file
View File

@@ -0,0 +1,16 @@
# ============================================
# Docker 部署 - 数据大屏管理系统
# 使用 Nginx 托管前端 + 反向代理 API
# ============================================
FROM nginx:alpine
# 将构建好的前端静态文件复制到 Nginx
COPY dist/ /usr/share/nginx/html/
# 替换 Nginx 配置
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 18800
CMD ["nginx", "-g", "daemon off;"]

20
nginx.conf Normal file
View File

@@ -0,0 +1,20 @@
server {
listen 18800;
server_name localhost;
# 前端静态文件
location / {
root /usr/share/nginx/html;
index index.html;
try_files $uri $uri/ /index.html; # Vue Router 历史模式支持
}
# API 反向代理到真实后端
location /api/ {
proxy_pass http://140.143.206.120/prod-api/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}

View File

@@ -12,6 +12,7 @@
"axios": "^1.6.7",
"cors": "^2.8.6",
"echarts": "^5.6.0",
"echarts-china-map": "^1.0.4",
"element-plus": "^2.6.1",
"express": "^5.2.1",
"mysql2": "^3.22.3",

View File

@@ -3,6 +3,12 @@
</template>
<script setup>
import { onMounted } from 'vue'
import { autoLogin } from '@/utils/auth'
onMounted(() => {
autoLogin()
})
</script>
<style scoped>

View File

@@ -1,6 +1,6 @@
import axios from 'axios'
const baseURL = process.env.VUE_APP_API_BASE_URL || '/api'
const baseURL = '/api'
const service = axios.create({
baseURL,
@@ -10,31 +10,27 @@ const service = axios.create({
}
})
// 从 Cookies 获取 Token与 klp-ui 保持一致
// Token 获取顺序localStorage自动登录 > Cookie主系统登录
const getToken = () => {
// 1. 优先取自动登录存的 token
const localToken = localStorage.getItem('Admin-Token')
if (localToken) return localToken
// 2. 其次从 Cookie 取(主系统登录)
const name = 'Admin-Token'
const value = `; ${document.cookie}`
const parts = value.split(`; ${name}=`)
if (parts.length === 2) return parts.pop().split(';').shift()
return null
}
service.interceptors.request.use(
config => {
let token = getToken()
// ========== 测试用:临时硬编码 Token ==========
// 如果没有从 Cookies 获取到 Token使用测试 Token
if (!token) {
token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpblR5cGUiOiJsb2dpbiIsImxvZ2luSWQiOiJzeXNfdXNlcjoxIiwicm5TdHIiOiJGM2w5Nm5ncGV4ZDA4d1BUYWlvVmFreWhCUDdlc2gyeCIsInVzZXJJZCI6MX0.aP06S-5aJtukzMjmYW3d5zK3v10TOKcdNpROniv5lr8'
}
// ========== 测试用结束 ==========
console.log('请求URL:', config.url)
console.log('使用的Token:', token ? '已设置' : '未设置')
const token = getToken()
if (token) {
// 尝试两种格式Bearer 和 直接使用Token
config.headers['Authorization'] = token // 直接使用Token不带Bearer前缀
config.headers['Authorization'] = token
}
return config
},
@@ -45,8 +41,6 @@ service.interceptors.request.use(
service.interceptors.response.use(
response => {
console.log('响应数据:', response.data)
let res = response.data
// 如果响应数据为空

57
src/utils/auth.js Normal file
View File

@@ -0,0 +1,57 @@
/**
* 自动登录模块
* 应用启动时用账号密码获取 Token存到 localStorage
* 后续所有 API 请求从 localStorage 取 Token
*/
const LOGIN_URL = '/api/login'
const STORAGE_KEY = 'Admin-Token'
/**
* 调用登录接口获取 Token
*/
export async function autoLogin() {
// 如果已有 Token跳过
const existing = localStorage.getItem(STORAGE_KEY)
if (existing) {
console.log('[Auth] 已有 Token跳过自动登录')
return existing
}
console.log('[Auth] 正在自动登录获取 Token...')
try {
const response = await fetch(LOGIN_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
username: 'admin',
password: 'FAD888888'
})
})
const data = await response.json()
// 兼容多种返回格式
const token = data.token || data.data?.token || data.data
if (token) {
localStorage.setItem(STORAGE_KEY, token)
console.log('[Auth] Token 获取成功')
return token
} else {
console.warn('[Auth] 登录接口返回中未找到 token:', data)
return null
}
} catch (err) {
console.error('[Auth] 自动登录失败:', err.message)
return null
}
}
/**
* 清除 Token登出时调用
*/
export function clearToken() {
localStorage.removeItem(STORAGE_KEY)
}

View File

@@ -1,39 +1,33 @@
import axios from 'axios'
// klp-oa线上API地址测试环境
const baseURL = 'http://140.143.206.120:8080'
// 走 Nginx 代理,同域名请求
const baseURL = '/api'
const service = axios.create({
baseURL: baseURL,
timeout: 30000
})
// 从 Cookies 获取 Token与 klp-ui 保持一致
// Token 获取顺序localStorage自动登录 > Cookie主系统登录
const getToken = () => {
// 1. 优先取自动登录存的 token
const localToken = localStorage.getItem('Admin-Token')
if (localToken) return localToken
// 2. 其次从 Cookie 取(主系统登录)
const name = 'Admin-Token'
const value = `; ${document.cookie}`
const parts = value.split(`; ${name}=`)
if (parts.length === 2) return parts.pop().split(';').shift()
return null
}
service.interceptors.request.use(
config => {
// 携带Token
let token = getToken()
// ========== 测试用:临时硬编码 Token ==========
// 如果没有从 Cookies 获取到 Token使用测试 Token
if (!token) {
token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpblR5cGUiOiJsb2dpbiIsImxvZ2luSWQiOiJzeXNfdXNlcjoxIiwicm5TdHIiOiJGM2w5Nm5ncGV4ZDA4d1BUYWlvVmFreWhCUDdlc2gyeCIsInVzZXJJZCI6MX0.aP06S-5aJtukzMjmYW3d5zK3v10TOKcdNpROniv5lr8'
}
// ========== 测试用结束 ==========
console.log('请求URL:', config.url)
console.log('使用的Token:', token ? '已设置' : '未设置')
const token = getToken()
if (token) {
// 直接使用Token不带Bearer前缀
config.headers['Authorization'] = "Bearer " + token
}
return config