diff --git a/src/api/common.d.ts b/src/api/common.d.ts new file mode 100644 index 0000000..458347a --- /dev/null +++ b/src/api/common.d.ts @@ -0,0 +1,39 @@ +export type ID = number | string; +export type IDS = (number | string)[]; + +export interface BaseEntity { + createBy?: string; + createTime?: string; + updateBy?: string; + updateTime?: string; +} + +/** + * 分页查询参数 + * @param pageNum 当前页 + * @param pageSize 每页大小 + * @param orderByColumn 排序字段 + * @param isAsc 是否升序 + */ +export interface PageQuery { + isAsc?: string; + orderByColumn?: string; + pageNum?: number; + pageSize?: number; + [key: string]: any; +} + +export interface ApiResponse { + code?: number; + msg?: string; + + data?: T; + rows: T[]; + total?: number; + + token?: string; + + img?: string; + uuid?: string; + captchaOnOff?: boolean; +} diff --git a/src/api/request.ts b/src/api/request.ts index a960bbc..e0f3071 100644 --- a/src/api/request.ts +++ b/src/api/request.ts @@ -1,83 +1,91 @@ -import axios from 'axios'; -import router from '@/router'; -import { getToken } from '@/utils/auth'; -import { Modal, notification } from 'ant-design-vue'; -import type { AxiosRequestConfig } from "axios"; -import type { ApiResponse } from "@/api/common/model"; +import axios from "axios"; +import router from "@/router"; +import { getToken, removeToken } from "@/utils/auth"; +import { Modal, notification } from "ant-design-vue"; +import type { AxiosInstance, AxiosRequestConfig } from "axios"; +import type { ApiResponse } from "@/api/common"; const errCodeMap: { [key: string]: string } = { - '403': '当前操作没有权限', - '404': '访问资源不存在', - 'default': '系统未知错误,请反馈给管理员' + "403": "当前操作没有权限", + "404": "访问资源不存在", + default: "系统未知错误,请反馈给管理员", }; // 创建axios实例 -const service = axios.create({ +const service: AxiosInstance = axios.create({ baseURL: import.meta.env.VITE_APP_BASE_API, timeout: 10000, }); // 请求拦截器 service.interceptors.request.use( - config => { + (config) => { config.headers = config.headers || {}; - config.headers['Accept-Language'] = 'zh-CN'; + config.headers["Accept-Language"] = "zh-CN"; const token = getToken(); if (token) { - config.headers['Authorization'] = `Bearer ${token}`; + config.headers["Authorization"] = `Bearer ${token}`; } return config; }, - error => { + (error) => { return Promise.reject(error); } ); // 响应拦截器 service.interceptors.response.use( - response => { - // console.log(response); + (response) => { + if (response.config.responseType === "blob") { + return response.data; + } + const code = response.data.code || 200; const data = response.data; switch (code) { case 200: - return data ?? response; + return data; case 401: Modal.error({ - title: '系统提示', - content: '登录状态已过期,请重新登录', + title: "系统提示", + content: "登录状态已过期,请重新登录", onOk: () => { - router.push('/login') - } - }) + removeToken(); + router.replace("/login"); + }, + }); return Promise.reject(data); default: - const errMsg = errCodeMap[code] || data.msg || errCodeMap['default']; notification.error({ - message: '请求错误', - description: errMsg, + message: "请求错误", + description: errCodeMap[code] || data?.msg || errCodeMap.default, }); return Promise.reject(data); } }, - error => { - error.message = error.code === "ECONNABORTED" ? '请求超时,请稍后重试' : error.message; + (error) => { + if (!error.__handled) { + const message = + error.code === "ECONNABORTED" + ? "请求超时,请稍后重试" + : error.message || "网络异常"; + + notification.error({ + message: "网络错误", + description: message, + }); + + error.__handled = true; + } - // 网络/服务器错误统一处理 - notification.error({ - message: "网络错误", - description: error.message, - }); return Promise.reject(error); } ); -// 类型检查 function request(config: AxiosRequestConfig): Promise> { - return service(config) as unknown as Promise>; + return service(config) as Promise>; } export default request; -// export default service; \ No newline at end of file diff --git a/src/assets/styles/_base.scss b/src/assets/styles/_base.scss index 8ef6f45..fec7d34 100644 --- a/src/assets/styles/_base.scss +++ b/src/assets/styles/_base.scss @@ -12,3 +12,14 @@ background-color: #8B8B8B; border-radius: 32px; } + +.hide-scrollbar { + overflow: auto; + &::-webkit-scrollbar { + display: none; + } + /* 隐藏滚动条 - Firefox */ + scrollbar-width: none; + /* 隐藏滚动条 - IE/Edge */ + -ms-overflow-style: none; +} \ No newline at end of file diff --git a/src/store/auth.ts b/src/store/auth.ts index 8465fd9..8de8c8e 100644 --- a/src/store/auth.ts +++ b/src/store/auth.ts @@ -1,16 +1,16 @@ -import { defineStore } from 'pinia'; -import { ref } from 'vue'; -import { useRouter } from 'vue-router'; -import Cookies from 'js-cookie'; -import { message } from 'ant-design-vue'; +import Cookies from "js-cookie"; +import { defineStore } from "pinia"; +import { ref } from "vue"; +import { useRoute, useRouter } from "vue-router"; +import { message } from "ant-design-vue"; -import { useUserStore } from './user'; -import { login } from '@/api/system'; -import type { LoginInfo } from '@/api/system/model'; +import { useUserStore } from "./user"; +import { login, logout as logoutApi } from "@/api/system"; +import { TokenKey as TOKEN_KEY } from "@/utils/auth"; +import type { LoginInfo } from "@/api/system/model"; -const TOKEN_KEY = 'token'; - -export const useAuthStore = defineStore('auth', () => { +export const useAuthStore = defineStore("auth", () => { + const route = useRoute(); const router = useRouter(); const userStore = useUserStore(); @@ -34,12 +34,13 @@ export const useAuthStore = defineStore('auth', () => { if (res.code === 200) { setToken(res.token as string); await userStore.fetchUserInfo(); - message.success('登录成功'); - await router.push('/'); + message.success("登录成功"); + const redirect = route.query.redirect || "/"; + router.replace(redirect as string); return res; } else { // 抛出错误,让调用方处理 - throw new Error(res.msg || '登录失败'); + throw new Error(res.msg || "登录失败"); } } catch (error) { throw error; @@ -50,11 +51,11 @@ export const useAuthStore = defineStore('auth', () => { async function logout() { // 在实际应用中,这里可以调用后端的退出登录接口 - // await doLogoutApi(); + await logoutApi(); clearToken(); userStore.clearUserInfo(); - await router.push('/login'); - message.success('已成功退出'); + await router.push("/login"); + message.success("已成功退出"); } return { diff --git a/src/store/index.ts b/src/store/index.ts index a0032eb..c6c9473 100644 --- a/src/store/index.ts +++ b/src/store/index.ts @@ -1,2 +1,3 @@ export * from './auth'; export * from './user'; +export * from './pwo'; diff --git a/src/store/pwo.ts b/src/store/pwo.ts new file mode 100644 index 0000000..5d7886c --- /dev/null +++ b/src/store/pwo.ts @@ -0,0 +1,28 @@ +import { defineStore } from "pinia"; +import { ref, reactive } from "vue"; +import { message } from "ant-design-vue"; + +export const usePwoStore = defineStore("pwo", () => { + const code = ref(''); + const currentJob = ref({}); + + function setCode(traceOrderCode: string) { + code.value = traceOrderCode; + } + + function setCurrentJob(job: any) { + currentJob.value = job; + } + + function getCurrentJob() { + return currentJob.value; + } + + return { + code, + currentJob, + setCode, + setCurrentJob, + getCurrentJob, + } +}); diff --git a/src/utils/auth.ts b/src/utils/auth.ts index 1ddb068..48d05df 100644 --- a/src/utils/auth.ts +++ b/src/utils/auth.ts @@ -1,6 +1,6 @@ import Cookies from 'js-cookie'; -const TokenKey = 'Admin-Token' +export const TokenKey = 'Admin-Token' export function getToken() { return Cookies.get(TokenKey)