diff --git a/admin-system/.env.development b/admin-system/.env.development index 3e9390d..de41971 100644 --- a/admin-system/.env.development +++ b/admin-system/.env.development @@ -5,19 +5,19 @@ NODE_ENV=development VITE_APP_TITLE=活牛采购智能数字化系统 - 管理后台 # API接口地址 -VITE_API_BASE_URL=http://localhost:3001/api +VITE_API_BASE_URL=http://localhost:3002/api # WebSocket地址 -VITE_WS_BASE_URL=ws://localhost:3001 +VITE_WS_BASE_URL=ws://localhost:3002 # 上传文件地址 -VITE_UPLOAD_URL=http://localhost:3001/api/upload +VITE_UPLOAD_URL=http://localhost:3002/api/upload # 静态资源地址 -VITE_STATIC_URL=http://localhost:3001/static +VITE_STATIC_URL=http://localhost:3002/static # 是否启用Mock数据 -VITE_USE_MOCK=true +VITE_USE_MOCK=false # 是否启用开发工具 VITE_DEV_TOOLS=true diff --git a/admin-system/.eslintrc-auto-import.json b/admin-system/.eslintrc-auto-import.json new file mode 100644 index 0000000..181d852 --- /dev/null +++ b/admin-system/.eslintrc-auto-import.json @@ -0,0 +1,91 @@ +{ + "globals": { + "Component": true, + "ComponentPublicInstance": true, + "ComputedRef": true, + "DirectiveBinding": true, + "EffectScope": true, + "ExtractDefaultPropTypes": true, + "ExtractPropTypes": true, + "ExtractPublicPropTypes": true, + "InjectionKey": true, + "MaybeRef": true, + "MaybeRefOrGetter": true, + "PropType": true, + "Ref": true, + "VNode": true, + "WritableComputedRef": true, + "acceptHMRUpdate": true, + "computed": true, + "createApp": true, + "createPinia": true, + "customRef": true, + "defineAsyncComponent": true, + "defineComponent": true, + "defineStore": true, + "effectScope": true, + "getActivePinia": true, + "getCurrentInstance": true, + "getCurrentScope": true, + "h": true, + "inject": true, + "isProxy": true, + "isReactive": true, + "isReadonly": true, + "isRef": true, + "mapActions": true, + "mapGetters": true, + "mapState": true, + "mapStores": true, + "mapWritableState": true, + "markRaw": true, + "nextTick": true, + "onActivated": true, + "onBeforeMount": true, + "onBeforeRouteLeave": true, + "onBeforeRouteUpdate": true, + "onBeforeUnmount": true, + "onBeforeUpdate": true, + "onDeactivated": true, + "onErrorCaptured": true, + "onMounted": true, + "onRenderTracked": true, + "onRenderTriggered": true, + "onScopeDispose": true, + "onServerPrefetch": true, + "onUnmounted": true, + "onUpdated": true, + "onWatcherCleanup": true, + "provide": true, + "reactive": true, + "readonly": true, + "ref": true, + "resolveComponent": true, + "setActivePinia": true, + "setMapStoreSuffix": true, + "shallowReactive": true, + "shallowReadonly": true, + "shallowRef": true, + "storeToRefs": true, + "toRaw": true, + "toRef": true, + "toRefs": true, + "toValue": true, + "triggerRef": true, + "unref": true, + "useAttrs": true, + "useCssModule": true, + "useCssVars": true, + "useId": true, + "useLink": true, + "useModel": true, + "useRoute": true, + "useRouter": true, + "useSlots": true, + "useTemplateRef": true, + "watch": true, + "watchEffect": true, + "watchPostEffect": true, + "watchSyncEffect": true + } +} diff --git a/admin-system/package-lock.json b/admin-system/package-lock.json index 95a994e..11fec03 100644 --- a/admin-system/package-lock.json +++ b/admin-system/package-lock.json @@ -1287,9 +1287,9 @@ } }, "node_modules/@types/node": { - "version": "20.19.12", - "resolved": "https://registry.npmmirror.com/@types/node/-/node-20.19.12.tgz", - "integrity": "sha512-lSOjyS6vdO2G2g2CWrETTV3Jz2zlCXHpu1rcubLKpz9oj+z/1CceHlj+yq53W+9zgb98nSov/wjEKYDNauD+Hw==", + "version": "20.19.13", + "resolved": "https://registry.npmmirror.com/@types/node/-/node-20.19.13.tgz", + "integrity": "sha512-yCAeZl7a0DxgNVteXFHt9+uyFbqXGy/ShC4BlcHkoE0AfGXYv/BUiplV72DjMYXHDBXFjhvr6DD1NiRVfB4j8g==", "dev": true, "license": "MIT", "dependencies": { diff --git a/admin-system/public/logo.svg b/admin-system/public/logo.svg new file mode 100644 index 0000000..30695eb --- /dev/null +++ b/admin-system/public/logo.svg @@ -0,0 +1,4 @@ + + + N + \ No newline at end of file diff --git a/admin-system/src/layouts/index.vue b/admin-system/src/layouts/index.vue index 7a70a37..f35e477 100644 --- a/admin-system/src/layouts/index.vue +++ b/admin-system/src/layouts/index.vue @@ -3,9 +3,9 @@
- + NiuMall - Logo + Logo
{ localStorage.setItem('token', access_token) localStorage.setItem('userInfo', JSON.stringify(user)) - ElMessage.success('登录成功') + ElMessage.success({ + message: '登录成功', + grouping: true, + duration: 3000 + }) return Promise.resolve() } catch (error: any) { - ElMessage.error(error.message || '登录失败') + // 错误信息已在request拦截器中统一处理 return Promise.reject(error) } } @@ -57,8 +61,13 @@ export const useUserStore = defineStore('user', () => { const logoutAction = async () => { try { await logout() - } catch (error) { - console.error('登出接口调用失败:', error) + ElMessage.success({ + message: '已退出登录', + grouping: true, + duration: 3000 + }) + } catch (error: any) { + // 错误信息已在request拦截器中统一处理 } finally { // 清除状态和本地存储 token.value = '' diff --git a/admin-system/src/utils/request.ts b/admin-system/src/utils/request.ts index ad56e03..5b76d0c 100644 --- a/admin-system/src/utils/request.ts +++ b/admin-system/src/utils/request.ts @@ -3,6 +3,19 @@ import type { AxiosResponse, AxiosError } from 'axios' import { ElMessage } from 'element-plus' import { useUserStore } from '@/stores/user' +// 错误代码映射表 +const ERROR_CODES: Record = { + 'AUTH_INVALID_CREDENTIALS': '用户名或密码错误', + 'AUTH_ACCOUNT_LOCKED': '账户已被锁定,请联系管理员', + 'AUTH_ACCOUNT_DISABLED': '账户已被禁用', + 'AUTH_TOKEN_EXPIRED': '登录已过期,请重新登录', + 'AUTH_INVALID_TOKEN': '无效的登录凭证', + 'NETWORK_ERROR': '网络错误,请检查网络连接', + 'TIMEOUT_ERROR': '请求超时,请稍后重试', + 'SERVER_ERROR': '服务器内部错误', + 'UNKNOWN_ERROR': '未知错误,请联系管理员' +} + // 创建axios实例 const request = axios.create({ baseURL: import.meta.env.VITE_API_BASE_URL || 'http://localhost:3000/api', @@ -36,8 +49,14 @@ request.interceptors.response.use( // 检查业务状态码 if (data.success === false) { - ElMessage.error(data.message || '请求失败') - return Promise.reject(new Error(data.message || '请求失败')) + const errorCode = data.code || 'UNKNOWN_ERROR' + const errorMsg = ERROR_CODES[errorCode] || data.message || '请求失败' + ElMessage.error({ + message: errorMsg, + grouping: true, + duration: 5000 + }) + return Promise.reject(new Error(errorMsg)) } return data @@ -47,30 +66,61 @@ request.interceptors.response.use( const { response } = error if (response) { + const errorCode = (response.data as any)?.code + const errorMsg = errorCode ? ERROR_CODES[errorCode] : undefined + switch (response.status) { case 401: - ElMessage.error('未授权,请重新登录') + ElMessage.error({ + message: errorMsg || '未授权,请重新登录', + grouping: true, + duration: 5000 + }) // 清除登录状态并跳转到登录页 const userStore = useUserStore() userStore.logoutAction() window.location.href = '/login' break case 403: - ElMessage.error('访问被拒绝,权限不足') + ElMessage.error({ + message: errorMsg || '访问被拒绝,权限不足', + grouping: true, + duration: 5000 + }) break case 404: - ElMessage.error('请求的资源不存在') + ElMessage.error({ + message: errorMsg || '请求的资源不存在', + grouping: true, + duration: 5000 + }) break case 500: - ElMessage.error('服务器内部错误') + ElMessage.error({ + message: errorMsg || '服务器内部错误', + grouping: true, + duration: 5000 + }) break default: - ElMessage.error(`请求失败: ${response.status}`) + ElMessage.error({ + message: errorMsg || `请求失败: ${response.status}`, + grouping: true, + duration: 5000 + }) } } else if (error.code === 'ECONNABORTED') { - ElMessage.error('请求超时,请稍后重试') + ElMessage.error({ + message: '请求超时,请稍后重试', + grouping: true, + duration: 5000 + }) } else { - ElMessage.error('网络错误,请检查网络连接') + ElMessage.error({ + message: '网络错误,请检查网络连接', + grouping: true, + duration: 5000 + }) } return Promise.reject(error) diff --git a/admin-system/src/views/login/index.vue b/admin-system/src/views/login/index.vue index 1896b20..5186173 100644 --- a/admin-system/src/views/login/index.vue +++ b/admin-system/src/views/login/index.vue @@ -3,7 +3,7 @@