- 后端与前端新增 keyAction 参数,支持按键按下/抬起独立事件,保持向下兼容 - 前端控制栏支持 pointerdown/pointerup 长按,新增键盘捕获输入框,映射浏览器按键到 Android KeyEvent - 重构顶栏布局:用户区右置并添加在线指示器、状态文本省略,优化窄屏响应式表现 - 控制栏录制按钮组防拆行,分辨率/帧率选择器自适应收缩,全局样式增强 - 修复 AdminAuthFilter 中 doFilter 被异常捕获导致误返回 401 的问题 - 移除管理后台中用户 admin 角色及相关 UI 与 API - 更新信令前端环境代理地址,修正路由名称大小写
79 lines
2.5 KiB
TypeScript
79 lines
2.5 KiB
TypeScript
import axios from 'axios';
|
||
import { ElMessage } from 'element-plus';
|
||
import router from '@/router';
|
||
|
||
/**
|
||
* 请求基地址。
|
||
*
|
||
* 开发态(vite dev)强制使用相对路径 '',即请求 /api/**,
|
||
* 由 Vite dev server 代理转发到后端(见 vite.config.ts 的 server.proxy,
|
||
* 目标取自 VITE_API_TARGET)。这样浏览器侧始终同源,从根本上避免:
|
||
* - 跨域被拦截;
|
||
* - .env 里写死的后端 IP(如 192.168.5.224)在当前网络/主机下不可达,
|
||
* 或用 localhost 打开页面时该 IP 解析不到,浏览器直接抛 "Failed to fetch"。
|
||
*
|
||
* 生产构建下才使用 VITE_API_BASE;若未配置则同样走相对路径,
|
||
* 由部署侧(Nginx 等)反向代理 /api。
|
||
*/
|
||
const BASE_URL = import.meta.env.DEV ? '' : import.meta.env.VITE_API_BASE || '';
|
||
|
||
const request = axios.create({
|
||
baseURL: BASE_URL,
|
||
timeout: 15000,
|
||
});
|
||
|
||
request.interceptors.request.use((config) => {
|
||
const token = localStorage.getItem('admin_token');
|
||
if (token) {
|
||
config.headers['Authorization'] = `Bearer ${token}`;
|
||
}
|
||
return config;
|
||
});
|
||
|
||
/**
|
||
* 统一响应拦截:除 401 外所有异常都给出错误提示。
|
||
* 401 表示令牌失效/未登录,清除本地令牌并跳转登录页。
|
||
*/
|
||
request.interceptors.response.use(
|
||
(resp) => resp.data,
|
||
(error) => {
|
||
const status = error.response?.status;
|
||
if (status === 401) {
|
||
localStorage.removeItem('admin_token');
|
||
ElMessage.error('登录已失效,请重新登录');
|
||
if (router.currentRoute.value.name !== 'login') {
|
||
router.replace({ name: 'login' });
|
||
}
|
||
} else {
|
||
ElMessage.error(error.response?.data?.message || error.message || '请求失败');
|
||
}
|
||
return Promise.reject(error);
|
||
},
|
||
);
|
||
|
||
/**
|
||
* 不携带任何鉴权头的请求实例,专用于登录等公开接口,
|
||
* 避免把本地可能过期/失效的令牌误带上去造成 401 / 鉴权混乱。
|
||
* 公开接口的 401 表示账号或密码错误,直接提示,不跳转(已在登录页)。
|
||
*/
|
||
export const publicRequest = axios.create({
|
||
baseURL: BASE_URL,
|
||
timeout: 15000,
|
||
});
|
||
|
||
publicRequest.interceptors.response.use(
|
||
(resp) => resp.data,
|
||
(error) => {
|
||
const status = error.response?.status;
|
||
if (status === 401) {
|
||
ElMessage.error('登录失败,请检查账号或密码');
|
||
} else {
|
||
ElMessage.error(error.response?.data?.message || error.message || '请求失败');
|
||
}
|
||
return Promise.reject(error);
|
||
},
|
||
);
|
||
|
||
export default request;
|
||
|