# Jing-Admin **Repository Path**: whale_8/jing-admin ## Basic Information - **Project Name**: Jing-Admin - **Description**: No description available - **Primary Language**: JavaScript - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2025-09-08 - **Last Updated**: 2026-01-12 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # vue-project This template should help get you started developing with Vue 3 in Vite. ## Recommended IDE Setup [VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur). ## Type Support for `.vue` Imports in TS TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) to make the TypeScript language service aware of `.vue` types. ## Customize configuration See [Vite Configuration Reference](https://vite.dev/config/). ## Project Setup ```sh pnpm install ``` ### Compile and Hot-Reload for Development ```sh pnpm dev ``` ### Type-Check, Compile and Minify for Production ```sh pnpm build ``` ### Lint with [ESLint](https://eslint.org/) ```sh pnpm lint ``` ### 配置环境 vite.config.js ``` import { ViteEjsPlugin } from 'vite-plugin-ejs' const root = process.cwd() // 获取根路径 //判断环境 const isBuild = command === 'build' let actualMode = mode if (!actualMode) { actualMode = isBuild ? 'production' : 'development' } const env = loadEnv(actualMode, root) plugins: [ vue(), vueDevTools(), ViteEjsPlugin({ title: env.VITE_APP_TITLE, }), ], ``` index.html ``` <%= title %> ``` ### 添加element-plus ```shell pnpm install element-plus ``` ### main.ts 中引入 ``` import ElementPlus from 'element-plus' import 'element-plus/dist/index.css' app.use(ElementPlus) ``` ### 添加 animate.css 动画库 ```shell npm install animate.css --save ``` main.ts ``` import 'animate.css' ``` ### 添加axios ```shell pnpm i axios ``` #### 创建axios 文件夹 添加index.ts 文件 ``` import service from './service' import { CONTENT_TYPE } from '@/constants' // 调用service请求 const request = (option: AxiosConfig) => { const { url, method, params, data, headers, responseType } = option const userStore = useUserStoreWithOut() return service.request({ url:url, method, params, data: data, responseType: responseType, headers: { 'Content-Type': CONTENT_TYPE, [userStore.getTokenKey ?? 'Authorization']: userStore.getToken ?? '', ...headers, } }) } // 封装请求方法 export default { get: (option: AxiosConfig) => { return request({ method: 'get', ...option }) as Promise> }, post: (option: AxiosConfig) => { return request({ method: 'post', ...option }) as Promise> }, delete: (option: AxiosConfig) => { return request({ method: 'delete', ...option }) as Promise> }, put: (option: AxiosConfig) => { return request({ method: 'put', ...option }) as Promise> }, cancelRequest: (url: string | string[]) => { return service.cancelRequest(url) }, cancelAllRequest: () => { return service.cancelAllRequest() } } ``` #### 创建 service.ts ``` import axios, { AxiosError } from 'axios' import type { InternalAxiosRequestConfig, AxiosResponse } from 'axios' import type {RequestConfig}from './types' import { ElMessage } from 'element-plus' import { REQUEST_TIMEOUT } from '@/constants' import { defaultRequestInterceptors, defaultResponseInterceptors } from '@/axios/config.ts' export const PATH_URL = import.meta.env.VITE_API_BASE_PATH const abortControllerMap: Map = new Map() // 创建 const axiosInstance = axios.create({ timeout: REQUEST_TIMEOUT, baseURL: PATH_URL, }) //拦截器 axiosInstance.interceptors.request.use( (config: InternalAxiosRequestConfig): InternalAxiosRequestConfig => { const controller = new AbortController() //中止控制器 const url = config?.url || '' config.signal = controller.signal // 绑定 abortControllerMap.set(url, controller) //添加到map中 return config }, ) // 响应拦截器 axiosInstance.interceptors.response.use( (res: AxiosResponse) => { const url = res.config.url || '' // 成功后再map中删除url abortControllerMap.delete(url) // 这里不能做任何处理,否则后面的 interceptors 拿不到完整的上下文了 return res }, (error: AxiosError) => { //返回错误信息 console.log('err: ' + error) ElMessage.error(error.message) return Promise.reject(error) }, ) // use axiosInstance.interceptors.request.use(defaultRequestInterceptors) axiosInstance.interceptors.response.use(defaultResponseInterceptors) //创建service 封装请求 \取消请求 \ 取消全部请求 const service = { request: (config: RequestConfig) => { return new Promise((resolve, reject) => { if (config.interceptors?.requestInterceptors) { config = config.interceptors.requestInterceptors(config as any) } axiosInstance .request(config) .then((res) => { resolve(res) }) .catch((err: any) => { reject(err) }) }) }, cancelRequest: (url: string | string[]) => { const urlList = Array.isArray(url) ? url : [url] for (const _url of urlList) { abortControllerMap.get(_url)?.abort() //取消 abortControllerMap.delete(_url) // 删除 } }, cancelAllRequests: () => { for (const [_, controller] of abortControllerMap) { controller.abort() //取消 } abortControllerMap.clear() }, } export default service ``` #### 创建config.ts ``` import type { AxiosResponse, InternalAxiosRequestConfig } from './types' import { ElMessage } from 'element-plus' import qs from 'qs' import { SUCCESS_CODE, TRANSFORM_REQUEST_DATA } from '@/constants' import { objToFormData } from '@/utils' // 请求拦截器 const defaultRequestInterceptors = (config: InternalAxiosRequestConfig) => { if(config.method === 'post' && config.headers['Content-Type'] === 'application/x-www-form-urlencoded') { // 内容类型(Content-Type),主要用于处理表单数据。 键值对(key-value pairs) 的形式 config.data = qs.stringify(config.data) }else if ( TRANSFORM_REQUEST_DATA && config.method === 'post' && config.headers['Content-Type'] === 'multipart/form-data' && !(config.data instanceof FormData) ){ // 文件传输 config.data = objToFormData(config.data) } if (config.method === 'get' && config.params) { let url = config.url as string url += '?' const keys = Object.keys(config.params) for (const key of keys) { if (config.params[key] !== void 0 && config.params[key] !== null) { url += `${key}=${encodeURIComponent(config.params[key])}&` } } url = url.substring(0, url.length - 1) config.params = {} config.url = url } return config } // 响应拦截器 const defaultResponseInterceptors = (response: AxiosResponse) => { if (response?.config?.responseType === 'blob') { return response } else if (response?.data.code === SUCCESS_CODE){ return response.data }else { ElMessage.error(response?.data?.message) //退出登录 if (response?.data?.code === 401) { // const userStore = useUserStoreWithOut() //userStore.logout() } } } export { defaultResponseInterceptors, defaultRequestInterceptors } ``` #### 使用 ``` import request from '@/axios' export const loginApi = (data: UserType): Promise> => { return request.post({ url: '/mock/user/login', data }) } ``` ### mock ```shell import { viteMockServe } from 'vite-plugin-mock' // vite.config.ts viteMockServe({ ignore: /^\_/, mockPath: 'mock', }) ``` ### pinia 添加持久化 pinia-plugin-persistedstate index.ts ``` import type { App } from 'vue' import { createPinia } from 'pinia' import piniaPluginPersistedstate from 'pinia-plugin-persistedstate' const store = createPinia() store.use(piniaPluginPersistedstate) export const setupStore = (app: App) => { app.use(store) } export { store } ``` main.ts ``` // 引入状态管理 import { setupStore } from '@/stores' app.use(setupStore) ```