新增错误消息防抖机制,优化错误提示显示并清理冗余代码
This commit is contained in:
@@ -3,7 +3,6 @@ ENV = 'development'
|
||||
|
||||
# 本地环境接口地址
|
||||
VITE_API_URL = 'http://192.168.3.200:8808/'
|
||||
# VITE_API_URL = 'http://localhost:8808/'
|
||||
# VITE_API_URL = 'http://192.168.3.11:8808/'
|
||||
|
||||
|
||||
|
||||
@@ -6,6 +6,22 @@ import qs from 'qs';
|
||||
// 标记是否正在处理 token 过期,避免重复弹窗
|
||||
let isHandlingTokenExpired = false;
|
||||
|
||||
// 错误消息防抖:防止短时间内显示多个错误消息
|
||||
let lastErrorTime = 0;
|
||||
const ERROR_MESSAGE_INTERVAL = 2000; // 2秒内只显示一个错误
|
||||
|
||||
const showErrorMessage = (message: string) => {
|
||||
const now = Date.now();
|
||||
|
||||
// 2秒内只显示一个错误消息(不管内容是否相同)
|
||||
if (now - lastErrorTime < ERROR_MESSAGE_INTERVAL) {
|
||||
return; // 跳过
|
||||
}
|
||||
|
||||
lastErrorTime = now;
|
||||
ElMessage.error(message);
|
||||
};
|
||||
|
||||
// 配置新建第一个 axios 实例(原来的主服务)
|
||||
const service: AxiosInstance = axios.create({
|
||||
baseURL: import.meta.env.VITE_API_URL,
|
||||
@@ -20,9 +36,6 @@ const service: AxiosInstance = axios.create({
|
||||
|
||||
// 配置新建第二个 axios 实例(新功能服务)
|
||||
const newService: AxiosInstance = axios.create({
|
||||
// baseURL: 'http://192.168.3.95:8000/',
|
||||
// baseURL: 'http://192.168.3.49:8000/',
|
||||
// baseURL: 'http://localhost:8000/',
|
||||
baseURL: 'http://192.168.3.200:8000/',
|
||||
// baseURL: 'http://192.168.3.11:8000/',
|
||||
timeout: 50000,
|
||||
@@ -118,7 +131,7 @@ const responseInterceptor = (response: AxiosResponse) => {
|
||||
// 业务逻辑错误处理
|
||||
if (code !== undefined && code !== 0 && code !== 200) {
|
||||
const errorMsg = message || `请求失败(${code})`;
|
||||
ElMessage.error(errorMsg);
|
||||
showErrorMessage(errorMsg);
|
||||
return Promise.reject(new Error(errorMsg));
|
||||
}
|
||||
|
||||
@@ -130,7 +143,7 @@ const responseErrorHandler = (error: any) => {
|
||||
console.error('API请求错误:', error);
|
||||
|
||||
if (error.code === 'ECONNABORTED' && error.message.includes('timeout')) {
|
||||
ElMessage.error('请求超时,请检查网络连接');
|
||||
showErrorMessage('请求超时,请检查网络连接');
|
||||
return Promise.reject(new Error('请求超时'));
|
||||
}
|
||||
|
||||
@@ -144,7 +157,8 @@ const responseErrorHandler = (error: any) => {
|
||||
}
|
||||
|
||||
const httpStatus = error.response.status;
|
||||
const message = error.response.data?.message || error.response.statusText;
|
||||
// 优先使用返回数据中的 message 字段
|
||||
const responseMessage = error.response.data?.message;
|
||||
|
||||
// 处理 HTTP 错误状态
|
||||
switch (httpStatus) {
|
||||
@@ -152,23 +166,23 @@ const responseErrorHandler = (error: any) => {
|
||||
handleTokenExpired();
|
||||
break;
|
||||
case 403:
|
||||
ElMessage.error('没有权限访问该资源');
|
||||
showErrorMessage(responseMessage || '没有权限访问该资源');
|
||||
break;
|
||||
case 404:
|
||||
ElMessage.error('请求的资源不存在');
|
||||
showErrorMessage(responseMessage || '请求的资源不存在');
|
||||
break;
|
||||
case 500:
|
||||
ElMessage.error('服务器内部错误');
|
||||
showErrorMessage(responseMessage || '服务器内部错误');
|
||||
break;
|
||||
case 502:
|
||||
ElMessage.error('网关错误');
|
||||
showErrorMessage(responseMessage || '网关错误');
|
||||
break;
|
||||
case 503:
|
||||
ElMessage.error('服务不可用');
|
||||
showErrorMessage(responseMessage || '服务不可用');
|
||||
break;
|
||||
default:
|
||||
if (httpStatus >= 400) {
|
||||
ElMessage.error(message || `请求失败(${httpStatus})`);
|
||||
showErrorMessage(responseMessage || `请求失败(${httpStatus})`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,4 +198,4 @@ newService.interceptors.response.use(responseInterceptor, responseErrorHandler);
|
||||
|
||||
// 导出
|
||||
export default service;
|
||||
export { newService };
|
||||
export { newService, showErrorMessage };
|
||||
|
||||
@@ -212,7 +212,6 @@ const fetchDictTypeOptions = () => {
|
||||
dictLoading.value = true;
|
||||
getDicts('assets')
|
||||
.then((res: any) => {
|
||||
console.log('字典接口返回数据:', res);
|
||||
const list = res.data?.list ?? [];
|
||||
// 提取所有字典类型信息
|
||||
dictTypeOptions.value = list
|
||||
@@ -220,11 +219,10 @@ const fetchDictTypeOptions = () => {
|
||||
.filter((info: DictInfo) => info && info.name);
|
||||
// 保存完整的字典数据列表(包含info和values)
|
||||
dictValueOptions.value = list;
|
||||
console.log('字典类型选项:', dictTypeOptions.value);
|
||||
console.log('字典值选项:', dictValueOptions.value);
|
||||
|
||||
})
|
||||
.catch((err: any) => {
|
||||
console.error('获取字典数据失败:', err);
|
||||
|
||||
dictTypeOptions.value = [];
|
||||
dictValueOptions.value = [];
|
||||
})
|
||||
@@ -415,8 +413,6 @@ const onSubmit = () => {
|
||||
updateCategory(submitData)
|
||||
.then(() => {
|
||||
ElMessage.success('修改成功');
|
||||
console.log(submitData,'111');
|
||||
|
||||
closeDialog();
|
||||
emit('getCategoryList');
|
||||
})
|
||||
|
||||
@@ -175,7 +175,7 @@ const onSubmit = async () => {
|
||||
emit('refresh');
|
||||
} catch (error) {
|
||||
console.error('操作失败:', error);
|
||||
ElMessage.error(state.formData.id ? '修改失败' : '添加失败');
|
||||
// 错误已由请求拦截器统一处理
|
||||
} finally {
|
||||
state.loading = false;
|
||||
}
|
||||
|
||||
@@ -144,10 +144,11 @@ const onSubmit = async () => {
|
||||
closeDialog();
|
||||
emit('refresh');
|
||||
} else {
|
||||
ElMessage.error(res.message || '配置失败');
|
||||
// 错误已由请求拦截器统一处理
|
||||
}
|
||||
} catch (error: any) {
|
||||
ElMessage.error(error.message || '配置失败');
|
||||
console.error('配置失败:', error);
|
||||
// 错误已由请求拦截器统一处理
|
||||
} finally {
|
||||
state.loading = false;
|
||||
}
|
||||
|
||||
@@ -179,7 +179,7 @@ const getList = async () => {
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取客服账号列表失败:', error);
|
||||
ElMessage.error('获取数据失败');
|
||||
// 错误已由请求拦截器统一处理
|
||||
tableData.data = [];
|
||||
tableData.total = 0;
|
||||
} finally {
|
||||
@@ -273,7 +273,7 @@ const handleStatusChange = async (row: TableDataItem) => {
|
||||
return;
|
||||
}
|
||||
console.error('状态切换失败:', error);
|
||||
ElMessage.error('状态切换失败');
|
||||
// 错误已由请求拦截器统一处理
|
||||
} finally {
|
||||
setTimeout(() => {
|
||||
row.statusLoading = false;
|
||||
|
||||
@@ -115,7 +115,7 @@ const openDialog = async (row?: ProductFormData) => {
|
||||
state.isShowDialog = true;
|
||||
} catch (error) {
|
||||
console.error('打开对话框失败:', error);
|
||||
ElMessage.error('初始化数据失败');
|
||||
// 错误已由请求拦截器统一处理
|
||||
}
|
||||
};
|
||||
|
||||
@@ -155,7 +155,7 @@ const onCancel = () => {
|
||||
*/
|
||||
const onSubmit = async () => {
|
||||
if (!formRef.value) {
|
||||
ElMessage.error('表单引用不存在');
|
||||
console.error('表单引用不存在');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -189,7 +189,7 @@ const onSubmit = async () => {
|
||||
emit('refresh');
|
||||
} catch (error) {
|
||||
console.error('提交失败:', error);
|
||||
ElMessage.error(state.formData.id === 0 ? '添加失败' : '修改失败');
|
||||
// 错误已由请求拦截器统一处理
|
||||
} finally {
|
||||
state.loading = false;
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ const handleExport = async () => {
|
||||
isShowDialog.value = false;
|
||||
} catch (error: any) {
|
||||
console.error('导出失败:', error);
|
||||
ElMessage.error(`导出失败:${error.message || '未知错误'}`);
|
||||
// 错误已由请求拦截器统一处理
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
|
||||
@@ -288,7 +288,7 @@ const handleCustomUpload = async (file: File) => {
|
||||
success: false,
|
||||
message: error.message || '导入失败',
|
||||
};
|
||||
ElMessage.error(`导入失败:${error.message || '未知错误'}`);
|
||||
// 错误已由请求拦截器统一处理
|
||||
}
|
||||
};
|
||||
|
||||
@@ -324,7 +324,8 @@ const handleDownloadTemplate = async () => {
|
||||
saveAs(zipBlob, filename);
|
||||
ElMessage.success(`模板下载成功!`);
|
||||
} catch (error: any) {
|
||||
ElMessage.error(`模板下载失败:${error.message || '未知错误'}`);
|
||||
console.error('模板下载失败:', error);
|
||||
// 错误已由请求拦截器统一处理
|
||||
} finally {
|
||||
downloadLoading.value = false;
|
||||
}
|
||||
@@ -343,7 +344,7 @@ const handleUploadSuccess = (response: any, file: UploadFile, fileList: UploadFi
|
||||
*/
|
||||
const handleUploadError = (error: Error, file: UploadFile, fileList: UploadFiles) => {
|
||||
console.error('上传失败回调', error);
|
||||
ElMessage.error('文件上传失败');
|
||||
// 错误已由请求拦截器统一处理
|
||||
// 手动上传模式下不会执行到这里
|
||||
};
|
||||
|
||||
|
||||
@@ -173,7 +173,7 @@ const getProductList = async () => {
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取产品列表失败:', error);
|
||||
ElMessage.error('获取产品列表失败');
|
||||
// 错误已由请求拦截器统一处理,此处不再重复提示
|
||||
} finally {
|
||||
tableData.loading = false;
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ const handleExport = async () => {
|
||||
isShowDialog.value = false;
|
||||
} catch (error: any) {
|
||||
console.error('导出失败:', error);
|
||||
ElMessage.error(`导出失败:${error.message || '未知错误'}`);
|
||||
// 错误已由请求拦截器统一处理
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
|
||||
@@ -201,7 +201,7 @@ const dataList = async () => {
|
||||
tableData.total = res.data.total;
|
||||
} catch (error) {
|
||||
console.error('获取数据失败:', error);
|
||||
ElMessage.error('获取数据失败');
|
||||
// 错误已由请求拦截器统一处理
|
||||
} finally {
|
||||
tableData.loading = false;
|
||||
}
|
||||
|
||||
@@ -162,7 +162,7 @@ const onSubmit = async () => {
|
||||
emit('refresh');
|
||||
} catch (error) {
|
||||
console.error('提交失败:', error);
|
||||
ElMessage.error('操作失败');
|
||||
// 错误已由请求拦截器统一处理
|
||||
} finally {
|
||||
state.loading = false;
|
||||
}
|
||||
|
||||
@@ -197,7 +197,7 @@ const loadTableData = async () => {
|
||||
tableData.total = total;
|
||||
} catch (error) {
|
||||
console.error('加载数据失败:', error);
|
||||
ElMessage.error('数据加载失败');
|
||||
// 错误已由请求拦截器统一处理
|
||||
tableData.data = [];
|
||||
tableData.total = 0;
|
||||
} finally {
|
||||
@@ -238,7 +238,7 @@ const handleDelete = async (row: ScriptItem) => {
|
||||
} catch (error) {
|
||||
if (error !== 'cancel') {
|
||||
console.error('删除失败:', error);
|
||||
ElMessage.error('删除失败');
|
||||
// 错误已由请求拦截器统一处理
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user