李金
7 months ago
15 changed files with 646 additions and 486 deletions
-
1package.json
-
12src/components/switch/index.tsx
-
5src/locales/lang/zh-CN.ts
-
54src/pages/system/menus/index.tsx
-
112src/pages/system/menus/store.ts
-
10src/pages/system/menus/style.ts
-
413src/pages/system/roles/index.tsx
-
90src/pages/system/roles/store.ts
-
177src/request.ts
-
8src/service/base.ts
-
35src/types/roles.d.ts
-
158src/utils/index.ts
-
8src/vite-env.d.ts
-
47vite.config.ts
@ -0,0 +1,12 @@ |
|||||
|
import { convertToBool } from '@/utils' |
||||
|
import { Switch as AntSwitch, SwitchProps } from 'antd' |
||||
|
|
||||
|
|
||||
|
export const Switch = ({ value, ...props }: SwitchProps) => { |
||||
|
console.log(value, props) |
||||
|
return ( |
||||
|
<AntSwitch {...props} value={convertToBool(value)}/> |
||||
|
) |
||||
|
} |
||||
|
|
||||
|
export default Switch |
@ -1,99 +1,140 @@ |
|||||
import { getToken, setToken } from '@/store/system.ts' |
import { getToken, setToken } from '@/store/system.ts' |
||||
|
import { IApiResult } from '@/types' |
||||
|
import { Record } from '@icon-park/react' |
||||
import { message } from 'antd' |
import { message } from 'antd' |
||||
import axios, { AxiosRequestConfig, AxiosResponse } from 'axios' |
|
||||
|
import axios, { |
||||
|
AxiosRequestConfig, |
||||
|
AxiosInstance, AxiosResponse, |
||||
|
} from 'axios' |
||||
|
|
||||
|
|
||||
export type { AxiosRequestConfig } |
export type { AxiosRequestConfig } |
||||
|
type FetchMethod = <T = any, D = any>(url: string, data?: D, config?: AxiosRequestConfig<D>) => Promise<IApiResult<T>> |
||||
|
|
||||
|
interface RequestMethods extends Pick<AxiosInstance, 'get' | 'post' | 'put' | 'delete' | 'request' | 'postForm' | 'patch' | 'patchForm' | 'putForm' | 'options'> { |
||||
|
} |
||||
|
|
||||
export const request = axios.create({ |
|
||||
baseURL: '/api/v1', |
|
||||
// timeout: 1000,
|
|
||||
headers: { |
|
||||
'Content-Type': 'application/json', |
|
||||
}, |
|
||||
|
|
||||
|
const axiosInstance = axios.create({ |
||||
|
baseURL: '/api/v1', |
||||
|
// timeout: 1000,
|
||||
|
headers: { |
||||
|
'Content-Type': 'application/json', |
||||
|
}, |
||||
}) |
}) |
||||
|
|
||||
//拦截request,添加token
|
//拦截request,添加token
|
||||
request.interceptors.request.use((config) => { |
|
||||
|
axiosInstance.interceptors.request.use((config) => { |
||||
|
|
||||
const token = getToken() |
|
||||
if (token) { |
|
||||
config.headers.Authorization = `Bearer ${token}` |
|
||||
} |
|
||||
|
const token = getToken() |
||||
|
if (token) { |
||||
|
config.headers.Authorization = `Bearer ${token}` |
||||
|
} |
||||
|
|
||||
return config |
|
||||
|
return config |
||||
}, (error) => { |
}, (error) => { |
||||
console.log('error', error) |
|
||||
return Promise.reject(error) |
|
||||
|
console.log('error', error) |
||||
|
return Promise.reject(error) |
||||
}) |
}) |
||||
|
|
||||
|
|
||||
//拦截response,返回data
|
//拦截response,返回data
|
||||
request.interceptors.response.use((response: AxiosResponse) => { |
|
||||
|
axiosInstance.interceptors.response.use( |
||||
|
(response) => { |
||||
// console.log('response', response.data)
|
// console.log('response', response.data)
|
||||
|
|
||||
message.destroy() |
message.destroy() |
||||
|
|
||||
switch (response.data.code) { |
|
||||
case 200: |
|
||||
//login
|
|
||||
if (response.config.url?.includes('/sys/login')) { |
|
||||
setToken(response.data.data.token) |
|
||||
} |
|
||||
return response.data |
|
||||
case 401: |
|
||||
setToken('') |
|
||||
if (window.location.pathname === '/login') { |
|
||||
return |
|
||||
} |
|
||||
|
|
||||
|
|
||||
// 401: 未登录
|
|
||||
message.error('登录失败,跳转重新登录') |
|
||||
// eslint-disable-next-line no-case-declarations
|
|
||||
const search = new URLSearchParams(window.location.search) |
|
||||
// eslint-disable-next-line no-case-declarations
|
|
||||
let redirect = window.location.pathname |
|
||||
if (search.toString() !== '') { |
|
||||
redirect = window.location.pathname + '?=' + search.toString() |
|
||||
} |
|
||||
window.location.href = `/login?redirect=${encodeURIComponent(redirect)}` |
|
||||
return |
|
||||
default: |
|
||||
message.error(response.data.message) |
|
||||
return Promise.reject(response) |
|
||||
|
const result = response.data as IApiResult |
||||
|
|
||||
|
switch (result.code) { |
||||
|
case 200: |
||||
|
//login
|
||||
|
if (response.config.url?.includes('/sys/login')) { |
||||
|
setToken(result.data.token) |
||||
|
} |
||||
|
return response |
||||
|
case 401: |
||||
|
setToken('') |
||||
|
if (window.location.pathname === '/login') { |
||||
|
return Promise.reject(new Error('to login')) |
||||
|
} |
||||
|
|
||||
|
|
||||
|
// 401: 未登录
|
||||
|
message.error('登录失败,跳转重新登录') |
||||
|
// eslint-disable-next-line no-case-declarations
|
||||
|
const search = new URLSearchParams(window.location.search) |
||||
|
// eslint-disable-next-line no-case-declarations
|
||||
|
let redirect = window.location.pathname |
||||
|
if (search.toString() !== '') { |
||||
|
redirect = window.location.pathname + '?=' + search.toString() |
||||
|
} |
||||
|
window.location.href = `/login?redirect=${encodeURIComponent(redirect)}` |
||||
|
return Promise.reject(new Error('to login')) |
||||
|
default: |
||||
|
message.error(result.message ?? '请求失败') |
||||
|
return Promise.reject(response) |
||||
} |
} |
||||
|
|
||||
}, (error) => { |
|
||||
|
}, (error) => { |
||||
// console.log('error', error)
|
// console.log('error', error)
|
||||
const { response } = error |
const { response } = error |
||||
if (response) { |
if (response) { |
||||
switch (response.status) { |
|
||||
case 401: |
|
||||
if (window.location.pathname === '/login') { |
|
||||
return |
|
||||
} |
|
||||
|
|
||||
setToken('') |
|
||||
// 401: 未登录
|
|
||||
message.error('登录失败,跳转重新登录') |
|
||||
// eslint-disable-next-line no-case-declarations
|
|
||||
const search = new URLSearchParams(window.location.search) |
|
||||
// eslint-disable-next-line no-case-declarations
|
|
||||
let redirect = window.location.pathname |
|
||||
if (search.toString() !== '') { |
|
||||
redirect = window.location.pathname + '?=' + search.toString() |
|
||||
} |
|
||||
window.location.href = `/login?redirect=${encodeURIComponent(redirect)}` |
|
||||
return |
|
||||
default: |
|
||||
message.error(response.data.message) |
|
||||
return Promise.reject(response) |
|
||||
} |
|
||||
|
switch (response.status) { |
||||
|
case 401: |
||||
|
if (window.location.pathname === '/login') { |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
setToken('') |
||||
|
// 401: 未登录
|
||||
|
message.error('登录失败,跳转重新登录') |
||||
|
// eslint-disable-next-line no-case-declarations
|
||||
|
const search = new URLSearchParams(window.location.search) |
||||
|
// eslint-disable-next-line no-case-declarations
|
||||
|
let redirect = window.location.pathname |
||||
|
if (search.toString() !== '') { |
||||
|
redirect = window.location.pathname + '?=' + search.toString() |
||||
|
} |
||||
|
window.location.href = `/login?redirect=${encodeURIComponent(redirect)}` |
||||
|
return |
||||
|
default: |
||||
|
message.error(response.data.message) |
||||
|
return Promise.reject(response) |
||||
|
} |
||||
} |
} |
||||
|
|
||||
return Promise.reject(error) |
return Promise.reject(error) |
||||
}) |
|
||||
|
}) |
||||
|
|
||||
|
|
||||
|
export const createFetchMethods = () => { |
||||
|
const methods = {} |
||||
|
|
||||
|
for (const method of Object.keys(axiosInstance)) { |
||||
|
methods[method] = <T = any, D = any>(url: string, data?: D, config?: AxiosRequestConfig<D>) => { |
||||
|
if (config && data) { |
||||
|
config = { |
||||
|
...config, |
||||
|
data, |
||||
|
} |
||||
|
} |
||||
|
return axiosInstance[method](url, config) |
||||
|
.then((response: AxiosResponse<IApiResult<T>>) => { |
||||
|
if (response.data.code !== 200) { |
||||
|
throw new Error(response.data.message) |
||||
|
} |
||||
|
return response.data as IApiResult<T> |
||||
|
}) |
||||
|
.catch((err) => { |
||||
|
throw err |
||||
|
}) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return methods as Record<keyof RequestMethods, FetchMethod> |
||||
|
} |
||||
|
|
||||
|
export const request = createFetchMethods() |
||||
export default request |
export default request |
@ -1 +1,9 @@ |
|||||
/// <reference types="vite/client" />
|
/// <reference types="vite/client" />
|
||||
|
interface ImportMetaEnv { |
||||
|
readonly API_URL: string |
||||
|
// 更多环境变量...
|
||||
|
} |
||||
|
|
||||
|
interface ImportMeta { |
||||
|
readonly env: ImportMetaEnv |
||||
|
} |
@ -1,36 +1,43 @@ |
|||||
import { defineConfig } from 'vite' |
|
||||
|
import { defineConfig, loadEnv } from 'vite' |
||||
import react from '@vitejs/plugin-react' |
import react from '@vitejs/plugin-react' |
||||
import { viteMockServe } from 'vite-plugin-mock' |
import { viteMockServe } from 'vite-plugin-mock' |
||||
|
|
||||
//import { TanStackRouterVite } from '@tanstack/router-vite-plugin'
|
//import { TanStackRouterVite } from '@tanstack/router-vite-plugin'
|
||||
|
|
||||
|
|
||||
// https://vitejs.dev/config/
|
// https://vitejs.dev/config/
|
||||
export default defineConfig({ |
|
||||
|
export default defineConfig(({ mode }) => { |
||||
|
|
||||
|
// 根据当前工作目录中的 `mode` 加载 .env 文件
|
||||
|
// 设置第三个参数为 '' 来加载所有环境变量,而不管是否有 `VITE_` 前缀。
|
||||
|
const env = loadEnv(mode, process.cwd(), '') |
||||
|
return { |
||||
//定义别名的路径
|
//定义别名的路径
|
||||
resolve: { |
resolve: { |
||||
alias: { |
|
||||
'@': '/src', |
|
||||
}, |
|
||||
|
alias: { |
||||
|
'@': '/src', |
||||
|
}, |
||||
}, |
}, |
||||
server: { |
server: { |
||||
proxy: { |
|
||||
'/api': { |
|
||||
target: 'http://47.113.117.106:8000', |
|
||||
changeOrigin: true, |
|
||||
rewrite: (path) => path |
|
||||
} |
|
||||
|
proxy: { |
||||
|
'/api': { |
||||
|
target: env.API_URL, |
||||
|
changeOrigin: true, |
||||
|
rewrite: (path) => path |
||||
} |
} |
||||
|
} |
||||
}, |
}, |
||||
plugins: [ |
plugins: [ |
||||
react(), |
|
||||
viteMockServe({ |
|
||||
// 是否启用 mock 功能(默认值:process.env.NODE_ENV !== 'production')
|
|
||||
enable: false, |
|
||||
|
react(), |
||||
|
viteMockServe({ |
||||
|
// 是否启用 mock 功能(默认值:process.env.NODE_ENV !== 'production')
|
||||
|
enable: false, |
||||
|
|
||||
// mock 文件的根路径,默认值:'mocks'
|
|
||||
mockPath: 'mock', |
|
||||
logger: true, |
|
||||
}), |
|
||||
//TanStackRouterVite(),
|
|
||||
|
// mock 文件的根路径,默认值:'mocks'
|
||||
|
mockPath: 'mock', |
||||
|
logger: true, |
||||
|
}), |
||||
|
//TanStackRouterVite(),
|
||||
], |
], |
||||
|
} |
||||
}) |
}) |
Write
Preview
Loading…
Cancel
Save
Reference in new issue