Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
水玉婷
ai-wechat
Commits
e34be04d
Commit
e34be04d
authored
Dec 04, 2025
by
水玉婷
Browse files
feat:401问题
parent
5b851fbb
Changes
6
Hide whitespace changes
Inline
Side-by-side
src/main.js
View file @
e34be04d
...
...
@@ -2,15 +2,25 @@ import { createApp } from 'vue'
import
App
from
'
./App.vue
'
import
router
from
'
./router
'
import
{
setRouter
}
from
'
./utils/router-manager
'
import
createFetchInterceptor
from
'
./utils/fetch-interceptor
'
import
{
initGlobalErrorHandler
,
handle401Error
,
is401Error
}
from
'
./utils/error-handler
'
const
app
=
createApp
(
App
)
app
.
use
(
router
)
// 设置全局路由实例
setRouter
(
router
)
// 启用fetch拦截器 - 自动处理401错误
createFetchInterceptor
()
// 全局错误处理 - 项目级别的401拦截机制
app
.
config
.
errorHandler
=
(
err
,
instance
,
info
)
=>
{
console
.
error
(
'
Vue全局错误捕获:
'
,
err
,
info
)
// 处理401错误
if
(
is401Error
(
err
))
{
console
.
log
(
'
Vue错误处理中检测到401,执行全局处理
'
)
handle401Error
()
}
}
// 初始化全局错误处理机制
initGlobalErrorHandler
()
app
.
mount
(
'
#app
'
)
\ No newline at end of file
src/utils/axios.js
View file @
e34be04d
...
...
@@ -44,18 +44,21 @@ instance.interceptors.response.use(
},
(
error
)
=>
{
if
(
error
.
response
)
{
const
{
status
}
=
error
.
response
const
{
status
,
data
}
=
error
.
response
// 处理401未授权错误
if
(
status
===
401
)
{
// 检查是否已经在跳转过程中,防止无限循环
if
(
isNavigatingToLogin
)
{
console
.
log
(
'
已在跳转登录页面中,避免重复跳转
'
)
return
Promise
.
reject
(
new
Error
(
'
正在跳转到登录页面
'
))
}
// 设置跳转标志
isNavigatingToLogin
=
true
console
.
log
(
'
检测到401错误,清除用户信息并跳转登录
'
)
// 清除本地存储的用户信息
localStorage
.
removeItem
(
'
wechat_user
'
)
...
...
@@ -65,13 +68,14 @@ instance.interceptors.response.use(
// 3秒后重置跳转标志,防止长时间锁定
setTimeout
(()
=>
{
isNavigatingToLogin
=
false
console
.
log
(
'
重置跳转标志
'
)
},
3000
)
return
Promise
.
reject
(
new
Error
(
'
未授权访问,请重新登录
'
))
}
// 其他错误处理
console
.
error
(
`请求失败:
${
status
}
`
,
error
.
response
.
data
)
console
.
error
(
`请求失败:
${
status
}
`
,
data
)
}
else
if
(
error
.
request
)
{
console
.
error
(
'
网络错误,请求未发送成功
'
,
error
)
}
else
{
...
...
src/utils/error-handler.js
0 → 100644
View file @
e34be04d
// 全局错误处理器 - 项目级别的401拦截机制
import
{
getRouter
}
from
'
./router-manager
'
// 防止重复跳转的标志
let
isHandling401
=
false
/**
* 处理401错误 - 项目级别拦截
*/
export
const
handle401Error
=
(
errorMessage
=
'
未授权访问,请重新登录
'
)
=>
{
// 检查是否已经在处理中,防止无限循环
if
(
isHandling401
)
{
console
.
log
(
'
已在处理401错误,避免重复操作
'
)
return
}
// 设置处理标志
isHandling401
=
true
console
.
log
(
'
执行全局401错误处理
'
)
// 清除本地存储的用户信息
localStorage
.
removeItem
(
'
wechat_user
'
)
// 获取路由实例
const
router
=
getRouter
()
// 跳转到登录页
if
(
router
)
{
// 使用replace而不是push,避免浏览器历史记录问题
router
.
replace
(
'
/login
'
)
}
else
{
// 备用方案:直接修改URL
if
(
window
.
location
.
hash
)
{
window
.
location
.
hash
=
'
/login
'
}
else
{
window
.
location
.
pathname
=
'
/login
'
}
}
// 3秒后重置处理标志
setTimeout
(()
=>
{
isHandling401
=
false
console
.
log
(
'
重置401处理标志
'
)
},
3000
)
// 抛出错误以便上层可以捕获
throw
new
Error
(
errorMessage
)
}
/**
* 检查是否为401错误
*/
export
const
is401Error
=
(
error
)
=>
{
if
(
!
error
)
return
false
// 检查axios错误
if
(
error
.
response
&&
error
.
response
.
status
===
401
)
{
return
true
}
// 检查fetch错误
if
(
error
.
status
===
401
)
{
return
true
}
// 检查错误消息
if
(
error
.
message
&&
(
error
.
message
.
includes
(
'
401
'
)
||
error
.
message
.
includes
(
'
未授权
'
)
||
error
.
message
.
includes
(
'
unauthorized
'
)
))
{
return
true
}
return
false
}
/**
* 全局错误拦截器
*/
export
const
setupGlobalErrorInterceptor
=
()
=>
{
// 拦截控制台错误
const
originalConsoleError
=
console
.
error
console
.
error
=
(...
args
)
=>
{
// 检查是否包含401相关错误
const
errorString
=
args
.
join
(
'
'
)
if
(
errorString
.
includes
(
'
401
'
)
||
errorString
.
includes
(
'
未授权
'
))
{
console
.
log
(
'
控制台检测到401错误:
'
,
errorString
)
}
originalConsoleError
.
apply
(
console
,
args
)
}
// 拦截未捕获的Promise错误
window
.
addEventListener
(
'
unhandledrejection
'
,
(
event
)
=>
{
const
error
=
event
.
reason
if
(
is401Error
(
error
))
{
console
.
log
(
'
未捕获的Promise错误中包含401:
'
,
error
)
event
.
preventDefault
()
// 阻止默认行为
handle401Error
()
}
})
// 拦截未捕获的JavaScript错误
window
.
addEventListener
(
'
error
'
,
(
event
)
=>
{
const
error
=
event
.
error
if
(
is401Error
(
error
))
{
console
.
log
(
'
未捕获的JavaScript错误中包含401:
'
,
error
)
event
.
preventDefault
()
// 阻止默认行为
handle401Error
()
}
})
}
/**
* 增强的fetch拦截器
*/
export
const
setupFetchInterceptor
=
()
=>
{
const
originalFetch
=
window
.
fetch
if
(
originalFetch
)
{
window
.
fetch
=
async
(...
args
)
=>
{
try
{
const
response
=
await
originalFetch
(...
args
)
// 检查401状态码
if
(
response
.
status
===
401
)
{
console
.
log
(
'
Fetch请求返回401,执行全局处理
'
)
handle401Error
()
}
return
response
}
catch
(
error
)
{
if
(
is401Error
(
error
))
{
handle401Error
()
}
throw
error
}
}
}
}
/**
* 初始化全局错误处理
*/
export
const
initGlobalErrorHandler
=
()
=>
{
setupGlobalErrorInterceptor
()
setupFetchInterceptor
()
console
.
log
(
'
全局错误处理机制已初始化
'
)
}
export
default
{
handle401Error
,
is401Error
,
setupGlobalErrorInterceptor
,
setupFetchInterceptor
,
initGlobalErrorHandler
}
\ No newline at end of file
src/utils/fetch-interceptor.js
deleted
100644 → 0
View file @
5b851fbb
// fetch拦截器 - 在外层处理401错误,保持组件通用性
import
{
navigateToLogin
}
from
'
./router-manager
'
// 防止重复跳转的标志
let
isNavigatingToLogin
=
false
// 获取用户token
const
getUserToken
=
()
=>
{
try
{
const
userData
=
localStorage
.
getItem
(
'
wechat_user
'
)
const
{
extMap
=
{}
}
=
JSON
.
parse
(
userData
||
'
{}
'
)
return
extMap
.
sessionId
||
''
}
catch
(
error
)
{
console
.
warn
(
'
解析用户信息失败
'
,
error
)
return
''
}
}
// 处理401错误
const
handle401Error
=
()
=>
{
// 检查是否已经在跳转过程中,防止无限循环
if
(
isNavigatingToLogin
)
{
throw
new
Error
(
'
正在跳转到登录页面
'
)
}
// 设置跳转标志
isNavigatingToLogin
=
true
// 清除本地存储的用户信息
localStorage
.
removeItem
(
'
wechat_user
'
)
// 使用全局路由管理器跳转
navigateToLogin
()
// 3秒后重置跳转标志,防止长时间锁定
setTimeout
(()
=>
{
isNavigatingToLogin
=
false
},
3000
)
throw
new
Error
(
'
未授权访问,请重新登录
'
)
}
// 创建fetch拦截器
const
createFetchInterceptor
=
()
=>
{
// 保存原始的fetch函数
const
originalFetch
=
window
.
fetch
// 拦截fetch请求
window
.
fetch
=
async
function
(
url
,
options
=
{})
{
// 设置默认请求头
const
defaultHeaders
=
{
'
Content-Type
'
:
'
application/json
'
,
}
// 添加认证信息
const
userToken
=
getUserToken
()
if
(
userToken
)
{
defaultHeaders
[
'
Token
'
]
=
userToken
defaultHeaders
[
'
x-session-id
'
]
=
userToken
defaultHeaders
[
'
x-app-code
'
]
=
import
.
meta
.
env
.
VITE_APP_CODE
||
''
}
// 合并请求头
const
headers
=
{
...
defaultHeaders
,
...
options
.
headers
}
const
config
=
{
...
options
,
headers
}
try
{
const
response
=
await
originalFetch
.
call
(
this
,
url
,
config
)
// 检查响应状态
if
(
response
.
status
===
401
)
{
handle401Error
()
}
return
response
}
catch
(
error
)
{
// 如果是401错误,已经处理过,直接抛出
if
(
error
.
message
.
includes
(
'
未授权访问
'
))
{
throw
error
}
// 其他网络错误
console
.
error
(
'
网络请求失败:
'
,
error
)
throw
error
}
}
// 返回取消拦截的方法
return
{
// 恢复原始fetch
restore
:
()
=>
{
window
.
fetch
=
originalFetch
},
// 获取当前拦截器状态
isIntercepted
:
()
=>
window
.
fetch
!==
originalFetch
}
}
// 导出拦截器创建函数
export
default
createFetchInterceptor
\ No newline at end of file
src/utils/wechat.js
View file @
e34be04d
// 引入axios
import
{
post
}
from
'
./axios.js
'
// 企业微信登录工具类 - 简化版本(直接从URL获取code)
class
WeChatLogin
{
constructor
()
{
...
...
@@ -50,14 +47,24 @@ class WeChatLogin {
}
}
// 获取用户信息 - 使用
axios
// 获取用户信息 - 使用
fetch
async
getUserInfo
(
code
)
{
try
{
const
response
=
await
post
(
'
/pedapi/pedService/wxcp/auth
'
,
{
authCode
:
code
const
response
=
await
fetch
(
'
/pedapi/pedService/wxcp/auth
'
,
{
method
:
'
POST
'
,
headers
:
{
'
Content-Type
'
:
'
application/json
'
},
body
:
JSON
.
stringify
({
authCode
:
code
})
})
const
result
=
response
.
data
if
(
!
response
.
ok
)
{
throw
new
Error
(
`HTTP error! status:
${
response
.
status
}
`
)
}
const
result
=
await
response
.
json
()
if
(
result
.
code
===
0
)
{
// 保存用户信息
...
...
src/views/Home.vue
View file @
e34be04d
...
...
@@ -32,6 +32,7 @@
const
userInfo
=
localStorage
.
getItem
(
'
wechat_user
'
)
const
{
extMap
=
{}}
=
JSON
.
parse
(
userInfo
||
'
{}
'
)
const
userToken
=
extMap
.
sessionId
;
console
.
log
(
'
userToken
'
,
userToken
)
// 使用环境变量代替硬编码
const
appCode
=
import
.
meta
.
env
.
VITE_APP_CODE
||
'
ped.qywx
'
;
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment