From 5853953f7902246a7ee29f28bd519e596e9df292 Mon Sep 17 00:00:00 2001 From: ylweng Date: Fri, 5 Sep 2025 01:18:40 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=9E=84=E5=90=8E=E7=AB=AF=E6=9C=8D?= =?UTF-8?q?=E5=8A=A1=E6=9E=B6=E6=9E=84=E5=B9=B6=E4=BC=98=E5=8C=96=E5=89=8D?= =?UTF-8?q?=E7=AB=AF=E9=94=99=E8=AF=AF=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- admin-system/.env.development | 10 +- admin-system/.eslintrc-auto-import.json | 91 +++++++++ admin-system/package-lock.json | 6 +- admin-system/public/logo.svg | 4 + admin-system/src/layouts/index.vue | 4 +- admin-system/src/stores/user.ts | 17 +- admin-system/src/utils/request.ts | 68 ++++++- admin-system/src/views/login/index.vue | 2 +- admin-system/vite.config.ts | 2 +- backend/.env | 23 +++ backend/.env.development | 61 ------ backend/app.js | 20 +- backend/config/database.js | 105 ++++++----- backend/middleware/auth.js | 184 ------------------ backend/models/User.js | 122 ------------ backend/models/index.js | 140 ++++++++++++++ backend/package.json | 6 +- backend/routes/auth.js | 240 +++++++++++------------- backend/routes/users.js | 197 +++++++++---------- backend/scripts/initData.js | 78 -------- 20 files changed, 608 insertions(+), 772 deletions(-) create mode 100644 admin-system/.eslintrc-auto-import.json create mode 100644 admin-system/public/logo.svg create mode 100644 backend/.env delete mode 100644 backend/.env.development delete mode 100644 backend/middleware/auth.js delete mode 100644 backend/models/User.js create mode 100644 backend/models/index.js delete mode 100644 backend/scripts/initData.js 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 @@