diff --git a/.env.development b/.env.development index 1efe8bf..5fb1b59 100644 --- a/.env.development +++ b/.env.development @@ -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/' diff --git a/src/utils/request.ts b/src/utils/request.ts index f13d23d..7443fd5 100644 --- a/src/utils/request.ts +++ b/src/utils/request.ts @@ -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 }; diff --git a/src/views/assets/category/component/editCategory.vue b/src/views/assets/category/component/editCategory.vue index e1c5acb..6f009b1 100644 --- a/src/views/assets/category/component/editCategory.vue +++ b/src/views/assets/category/component/editCategory.vue @@ -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'); }) diff --git a/src/views/customerService/account/component/editAccount.vue b/src/views/customerService/account/component/editAccount.vue index 7dccdbd..e17982b 100644 --- a/src/views/customerService/account/component/editAccount.vue +++ b/src/views/customerService/account/component/editAccount.vue @@ -175,7 +175,7 @@ const onSubmit = async () => { emit('refresh'); } catch (error) { console.error('操作失败:', error); - ElMessage.error(state.formData.id ? '修改失败' : '添加失败'); + // 错误已由请求拦截器统一处理 } finally { state.loading = false; } diff --git a/src/views/customerService/account/component/promptConfig.vue b/src/views/customerService/account/component/promptConfig.vue index af69cf9..1fa0eaa 100644 --- a/src/views/customerService/account/component/promptConfig.vue +++ b/src/views/customerService/account/component/promptConfig.vue @@ -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; } diff --git a/src/views/customerService/account/index.vue b/src/views/customerService/account/index.vue index c05f7b7..57485d0 100644 --- a/src/views/customerService/account/index.vue +++ b/src/views/customerService/account/index.vue @@ -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; diff --git a/src/views/customerService/product/component/editRole.vue b/src/views/customerService/product/component/editRole.vue index 06c913e..f77a082 100644 --- a/src/views/customerService/product/component/editRole.vue +++ b/src/views/customerService/product/component/editRole.vue @@ -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; } diff --git a/src/views/customerService/product/component/exportDialog.vue b/src/views/customerService/product/component/exportDialog.vue index e440edb..b473acc 100644 --- a/src/views/customerService/product/component/exportDialog.vue +++ b/src/views/customerService/product/component/exportDialog.vue @@ -74,7 +74,7 @@ const handleExport = async () => { isShowDialog.value = false; } catch (error: any) { console.error('导出失败:', error); - ElMessage.error(`导出失败:${error.message || '未知错误'}`); + // 错误已由请求拦截器统一处理 } finally { loading.value = false; } diff --git a/src/views/customerService/product/component/importDialog.vue b/src/views/customerService/product/component/importDialog.vue index 1d2109e..dd69461 100644 --- a/src/views/customerService/product/component/importDialog.vue +++ b/src/views/customerService/product/component/importDialog.vue @@ -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('文件上传失败'); + // 错误已由请求拦截器统一处理 // 手动上传模式下不会执行到这里 }; diff --git a/src/views/customerService/product/index.vue b/src/views/customerService/product/index.vue index 35ab69a..8b9d0ed 100644 --- a/src/views/customerService/product/index.vue +++ b/src/views/customerService/product/index.vue @@ -173,7 +173,7 @@ const getProductList = async () => { } } catch (error) { console.error('获取产品列表失败:', error); - ElMessage.error('获取产品列表失败'); + // 错误已由请求拦截器统一处理,此处不再重复提示 } finally { tableData.loading = false; } diff --git a/src/views/customerService/report/component/exportDialog.vue b/src/views/customerService/report/component/exportDialog.vue index fcba1be..03cfd7d 100644 --- a/src/views/customerService/report/component/exportDialog.vue +++ b/src/views/customerService/report/component/exportDialog.vue @@ -74,7 +74,7 @@ const handleExport = async () => { isShowDialog.value = false; } catch (error: any) { console.error('导出失败:', error); - ElMessage.error(`导出失败:${error.message || '未知错误'}`); + // 错误已由请求拦截器统一处理 } finally { loading.value = false; } diff --git a/src/views/customerService/report/index.vue b/src/views/customerService/report/index.vue index a27b439..ee8ccab 100644 --- a/src/views/customerService/report/index.vue +++ b/src/views/customerService/report/index.vue @@ -201,7 +201,7 @@ const dataList = async () => { tableData.total = res.data.total; } catch (error) { console.error('获取数据失败:', error); - ElMessage.error('获取数据失败'); + // 错误已由请求拦截器统一处理 } finally { tableData.loading = false; } diff --git a/src/views/customerService/script/component/editRole.vue b/src/views/customerService/script/component/editRole.vue index b0f66cd..02a96cf 100644 --- a/src/views/customerService/script/component/editRole.vue +++ b/src/views/customerService/script/component/editRole.vue @@ -162,7 +162,7 @@ const onSubmit = async () => { emit('refresh'); } catch (error) { console.error('提交失败:', error); - ElMessage.error('操作失败'); + // 错误已由请求拦截器统一处理 } finally { state.loading = false; } diff --git a/src/views/customerService/script/index.vue b/src/views/customerService/script/index.vue index d4dc424..7d7e0df 100644 --- a/src/views/customerService/script/index.vue +++ b/src/views/customerService/script/index.vue @@ -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('删除失败'); + // 错误已由请求拦截器统一处理 } } };