From 65cf44f21057a9b7be20e1f6f5fbe638976d18b6 Mon Sep 17 00:00:00 2001 From: 6448dfb631ba9538b4877fd6 <6448dfb631ba9538b4877fd6@devide> Date: Fri, 19 May 2023 08:49:00 +0000 Subject: [PATCH] Fri May 19 08:49:00 UTC 2023 inscode --- .inscode | 2 +- index.js | 35 +++++- vite-project/.gitignore | 24 ++++ vite-project/.vscode/extensions.json | 3 + vite-project/README.md | 18 +++ vite-project/index.html | 13 ++ vite-project/package.json | 27 ++++ vite-project/public/vite.svg | 1 + vite-project/src/App.vue | 10 ++ vite-project/src/api/user.ts | 16 +++ vite-project/src/assets/css/color-light.scss | 12 ++ vite-project/src/assets/css/dark/dark.scss | 9 ++ .../src/assets/css/element/element.scss | 5 + .../src/assets/css/element/index.scss | 8 ++ vite-project/src/assets/css/icon.css | 4 + vite-project/src/assets/css/index.scss | 9 ++ vite-project/src/assets/css/main.scss | 115 +++++++++++++++++ vite-project/src/assets/vue.svg | 1 + vite-project/src/components/HelloWorld.vue | 38 ++++++ vite-project/src/directive/adaptive.ts | 33 +++++ vite-project/src/directive/color.ts | 7 ++ vite-project/src/directive/index.ts | 12 ++ vite-project/src/directive/permiss.ts | 5 + vite-project/src/directive/watermark.ts | 42 +++++++ vite-project/src/layout/header/index.vue | 116 ++++++++++++++++++ .../layout/tags /user.ts | 39 ++++++ vite-project/src/main.ts | 37 ++++++ vite-project/src/router/index.ts | 67 ++++++++++ vite-project/src/style.css | 80 ++++++++++++ vite-project/src/types/index.d.ts | 9 ++ vite-project/src/utils/http/axios.ts | 79 ++++++++++++ vite-project/src/utils/http/errorHandler.ts | 28 +++++ vite-project/src/utils/index.js | 32 +++++ vite-project/src/vite-env.d.ts | 1 + vite-project/tsconfig.json | 20 +++ vite-project/tsconfig.node.json | 10 ++ vite-project/vite.config.ts | 7 ++ 37 files changed, 972 insertions(+), 2 deletions(-) create mode 100644 vite-project/.gitignore create mode 100644 vite-project/.vscode/extensions.json create mode 100644 vite-project/README.md create mode 100644 vite-project/index.html create mode 100644 vite-project/package.json create mode 100644 vite-project/public/vite.svg create mode 100644 vite-project/src/App.vue create mode 100644 vite-project/src/api/user.ts create mode 100644 vite-project/src/assets/css/color-light.scss create mode 100644 vite-project/src/assets/css/dark/dark.scss create mode 100644 vite-project/src/assets/css/element/element.scss create mode 100644 vite-project/src/assets/css/element/index.scss create mode 100644 vite-project/src/assets/css/icon.css create mode 100644 vite-project/src/assets/css/index.scss create mode 100644 vite-project/src/assets/css/main.scss create mode 100644 vite-project/src/assets/vue.svg create mode 100644 vite-project/src/components/HelloWorld.vue create mode 100644 vite-project/src/directive/adaptive.ts create mode 100644 vite-project/src/directive/color.ts create mode 100644 vite-project/src/directive/index.ts create mode 100644 vite-project/src/directive/permiss.ts create mode 100644 vite-project/src/directive/watermark.ts create mode 100644 vite-project/src/layout/header/index.vue create mode 100644 vite-project/src/layout/tags /user.ts create mode 100644 vite-project/src/main.ts create mode 100644 vite-project/src/router/index.ts create mode 100644 vite-project/src/style.css create mode 100644 vite-project/src/types/index.d.ts create mode 100644 vite-project/src/utils/http/axios.ts create mode 100644 vite-project/src/utils/http/errorHandler.ts create mode 100644 vite-project/src/utils/index.js create mode 100644 vite-project/src/vite-env.d.ts create mode 100644 vite-project/tsconfig.json create mode 100644 vite-project/tsconfig.node.json create mode 100644 vite-project/vite.config.ts diff --git a/.inscode b/.inscode index ecc8bdd..1bc302b 100644 --- a/.inscode +++ b/.inscode @@ -1,4 +1,4 @@ -run = "npm i && npm run dev" +run = "npm i && cd vite-project && npm run dev" [env] PATH = "/root/${PROJECT_DIR}/.config/npm/node_global/bin:/root/${PROJECT_DIR}/node_modules/.bin:${PATH}" diff --git a/index.js b/index.js index 2d7e683..2d9b913 100644 --- a/index.js +++ b/index.js @@ -1 +1,34 @@ -console.log("欢迎来到 InsCode"); \ No newline at end of file +console.log("欢迎来到 InsCode"); +/** + * 将 URL 中的查询参数转换成一个对象 + * @param {string} url 完整的 URL + * @returns {object} 包含查询参数的对象 + */ + export function param2Obj(url) { + // 从 URL 中取出查询参数部分,并进行 URL 解码 + const search = decodeURIComponent(url.split('?')[1]).replace(/\+/g, ' ') + + // 如果没有查询参数,返回一个空对象 + if (!search) { + return {} + } + // 初始化一个空对象,用于存储查询参数 + const obj = {} + // 将查询参数字符串按 & 符号分割成数组 + const searchArr = search.split('&') + // 遍历查询参数数组 + searchArr.forEach((v) => { + // 找到等号的位置 + const index = v.indexOf('=') + // 如果找到了等号 + if (index !== -1) { + // 取出参数名和参数值 + const name = v.substring(0, index) + const val = v.substring(index + 1, v.length) + // 将参数名和参数值存入对象中 + obj[name] = val + } + }) + // 返回包含查询参数的对象 + return obj + } \ No newline at end of file diff --git a/vite-project/.gitignore b/vite-project/.gitignore new file mode 100644 index 0000000..a547bf3 --- /dev/null +++ b/vite-project/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/vite-project/.vscode/extensions.json b/vite-project/.vscode/extensions.json new file mode 100644 index 0000000..c0a6e5a --- /dev/null +++ b/vite-project/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"] +} diff --git a/vite-project/README.md b/vite-project/README.md new file mode 100644 index 0000000..ef72fd5 --- /dev/null +++ b/vite-project/README.md @@ -0,0 +1,18 @@ +# Vue 3 + TypeScript + Vite + +This template should help get you started developing with Vue 3 and TypeScript in Vite. The template uses Vue 3 ` + + diff --git a/vite-project/package.json b/vite-project/package.json new file mode 100644 index 0000000..a09d80b --- /dev/null +++ b/vite-project/package.json @@ -0,0 +1,27 @@ +{ + "name": "vite-project", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vue-tsc && vite build", + "preview": "vite preview" + }, + "dependencies": { + "@element-plus/icons-vue": "^2.1.0", + "@vueuse/core": "^9.10.0", + "axios": "^0.27.2", + "element-plus": "^2.2.14", + "pinia": "^2.0.20", + "pinia-plugin-persistedstate": "^3.1.0", + "vue-router": "^4.1.3", + "vue": "^3.2.37" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^4.1.0", + "typescript": "^5.0.2", + "vite": "^4.3.2", + "vue-tsc": "^1.4.2" + } +} diff --git a/vite-project/public/vite.svg b/vite-project/public/vite.svg new file mode 100644 index 0000000..e7b8dfb --- /dev/null +++ b/vite-project/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/vite-project/src/App.vue b/vite-project/src/App.vue new file mode 100644 index 0000000..f76391c --- /dev/null +++ b/vite-project/src/App.vue @@ -0,0 +1,10 @@ + + + \ No newline at end of file diff --git a/vite-project/src/api/user.ts b/vite-project/src/api/user.ts new file mode 100644 index 0000000..9117443 --- /dev/null +++ b/vite-project/src/api/user.ts @@ -0,0 +1,16 @@ +import request from '~/utils/http/axios' + +export function login(data: {}) { + return request({ + url: '/login', + method: 'post', + data + }) +} +export function fetchUser(data: {}) { + return request({ + url: '/api/getUser', + method: 'get', + data + }) +} \ No newline at end of file diff --git a/vite-project/src/assets/css/color-light.scss b/vite-project/src/assets/css/color-light.scss new file mode 100644 index 0000000..da444bf --- /dev/null +++ b/vite-project/src/assets/css/color-light.scss @@ -0,0 +1,12 @@ +@import './variables.scss'; + +.tags-li { + &.active { + background-color: $primary-color; + color: #fff; + + .tags-li-title { + color: #fff; + } + } +} \ No newline at end of file diff --git a/vite-project/src/assets/css/dark/dark.scss b/vite-project/src/assets/css/dark/dark.scss new file mode 100644 index 0000000..1a40e85 --- /dev/null +++ b/vite-project/src/assets/css/dark/dark.scss @@ -0,0 +1,9 @@ +html.dark { + .main-content { + background-color: black; + } + + .tags { + background-color: black; + } +} \ No newline at end of file diff --git a/vite-project/src/assets/css/element/element.scss b/vite-project/src/assets/css/element/element.scss new file mode 100644 index 0000000..5b15294 --- /dev/null +++ b/vite-project/src/assets/css/element/element.scss @@ -0,0 +1,5 @@ +.card-header { + display: flex; + justify-content: space-between; + align-items: center; +} \ No newline at end of file diff --git a/vite-project/src/assets/css/element/index.scss b/vite-project/src/assets/css/element/index.scss new file mode 100644 index 0000000..cabe304 --- /dev/null +++ b/vite-project/src/assets/css/element/index.scss @@ -0,0 +1,8 @@ +@forward 'element-plus/theme-chalk/src/common/var.scss' with ($colors: ('primary': ('base': #0052d9), + 'success': ('base': #2ba471), + 'danger': ('base': #d54941)), + $menu: (('item-height': 50px))); + +// 如果只是按需导入,则可以忽略以下内容。 +// 如果你想导入所有样式: +@use 'element-plus/theme-chalk/src/index.scss' as *; \ No newline at end of file diff --git a/vite-project/src/assets/css/icon.css b/vite-project/src/assets/css/icon.css new file mode 100644 index 0000000..3ea036a --- /dev/null +++ b/vite-project/src/assets/css/icon.css @@ -0,0 +1,4 @@ +[class*=" el-icon-lx"], +[class^=el-icon-lx] { + font-family: lx-iconfont !important; +} \ No newline at end of file diff --git a/vite-project/src/assets/css/index.scss b/vite-project/src/assets/css/index.scss new file mode 100644 index 0000000..1785062 --- /dev/null +++ b/vite-project/src/assets/css/index.scss @@ -0,0 +1,9 @@ +@use './color-light.scss'; +@use './icon.css'; +@use './main.scss'; +@use './element/element.scss'; +@use './dark/dark.scss'; + +@tailwind base; +@tailwind components; +@tailwind utilities; \ No newline at end of file diff --git a/vite-project/src/assets/css/main.scss b/vite-project/src/assets/css/main.scss new file mode 100644 index 0000000..c7035cb --- /dev/null +++ b/vite-project/src/assets/css/main.scss @@ -0,0 +1,115 @@ +@import './variables.scss'; + +* { + margin: 0; + padding: 0; + + +} + +body { + font-family: 'PingFang SC', 'Helvetica Neue', Helvetica, 'microsoft yahei', arial, STHeiTi, + sans-serif; + font-size: 14px; + + svg { + display: inline-block; + } + + a { + color: var(--el-color-primary) + } + + a:hover { + text-decoration: underline; + } +} + + + +.main-content { + position: relative; + margin-left: 200px; + padding-top: 90px; + min-height: calc(100vh - 60px); + + -webkit-transition: left 0.3s ease-in-out; + transition: margin-left 0.3s ease-in-out; + border-left: 1px solid var(ç); + background: url(../images/bg.avif) no-repeat top center; + + &.content-collapse { + margin-left: 64px; + } +} + +.content { + width: auto; + overflow-y: auto; + + &.content-collapse { + left: 64px; + } +} + +.container { + padding: 16px; +} + + + + + + + +.move-enter-active { + animation: run-scale .1s ease-out 0s; +} + +.move-leave-active { + animation: run-scale .1s ease-in 0s reverse; +} + +.move-enter-from, +.move-leave-to { + opacity: 0; +} + +@keyframes run-scale { + 0% { + opacity: 0; + } + + 100% { + opacity: 1; + } +} + +/*BaseForm*/ + +.el-time-panel__content::after, +.el-time-panel__content::before { + margin-top: -7px; +} + +.el-time-spinner__wrapper .el-scrollbar__wrap:not(.el-scrollbar__wrap--hidden-default) { + padding-bottom: 0; +} + +[class*=' el-icon-'], +[class^='el-icon-'] { + speak: none; + font-style: normal; + font-weight: 400; + font-variant: normal; + text-transform: none; + line-height: 1; + vertical-align: baseline; + display: inline-block; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +[hidden] { + display: none !important; +} \ No newline at end of file diff --git a/vite-project/src/assets/vue.svg b/vite-project/src/assets/vue.svg new file mode 100644 index 0000000..770e9d3 --- /dev/null +++ b/vite-project/src/assets/vue.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/vite-project/src/components/HelloWorld.vue b/vite-project/src/components/HelloWorld.vue new file mode 100644 index 0000000..7b25f3f --- /dev/null +++ b/vite-project/src/components/HelloWorld.vue @@ -0,0 +1,38 @@ + + + + + diff --git a/vite-project/src/directive/adaptive.ts b/vite-project/src/directive/adaptive.ts new file mode 100644 index 0000000..47d9d34 --- /dev/null +++ b/vite-project/src/directive/adaptive.ts @@ -0,0 +1,33 @@ +import { DirectiveBinding } from 'vue' + +interface ExHTMLElement extends HTMLElement { + resizeListener: EventListener +} + +export default { + mounted: (el: ExHTMLElement, binding: DirectiveBinding) => { + el.resizeListener = () => { + setHeight(el, binding) + } + + setHeight(el, binding) + + window.addEventListener('resize', el.resizeListener) + }, + unmounted(el: ExHTMLElement) { + window.removeEventListener('resize', el.resizeListener) + }, + updated(el: ExHTMLElement, binding: DirectiveBinding) { + setHeight(el, binding) + } +} + +// set el-table height +function setHeight(el: ExHTMLElement, binding: DirectiveBinding) { + const top = el.offsetTop + const bottom = binding?.value?.bottom || 64 + const pageHeight = window.innerHeight + console.log(top, bottom, pageHeight) + el.style.height = pageHeight - top - bottom + 'px' + el.style.overflowY = 'auto' +} \ No newline at end of file diff --git a/vite-project/src/directive/color.ts b/vite-project/src/directive/color.ts new file mode 100644 index 0000000..096505f --- /dev/null +++ b/vite-project/src/directive/color.ts @@ -0,0 +1,7 @@ +import { DirectiveBinding } from 'vue' + +export default { + mounted(el: HTMLElement, binding: DirectiveBinding) { + el.style.color = binding.value + } +} \ No newline at end of file diff --git a/vite-project/src/directive/index.ts b/vite-project/src/directive/index.ts new file mode 100644 index 0000000..3b31e43 --- /dev/null +++ b/vite-project/src/directive/index.ts @@ -0,0 +1,12 @@ +import { App } from 'vue' +import color from './color' +import watermark from './watermark' +import adaptive from './adaptive' +import permiss from './permiss' + +export default (app: App) => { + app.directive('color', color) + app.directive('watermark', watermark) + app.directive('adaptive', adaptive) + app.directive('permiss', permiss) +} \ No newline at end of file diff --git a/vite-project/src/directive/permiss.ts b/vite-project/src/directive/permiss.ts new file mode 100644 index 0000000..664524b --- /dev/null +++ b/vite-project/src/directive/permiss.ts @@ -0,0 +1,5 @@ +import { DirectiveBinding } from 'vue' + +export default { + mounted(el: HTMLElement, binding: DirectiveBinding) { } +} \ No newline at end of file diff --git a/vite-project/src/directive/watermark.ts b/vite-project/src/directive/watermark.ts new file mode 100644 index 0000000..865aaf9 --- /dev/null +++ b/vite-project/src/directive/watermark.ts @@ -0,0 +1,42 @@ +import { DirectiveBinding } from 'vue' + +// 水印 +export default { + mounted(el: HTMLElement, binding: DirectiveBinding) { + let txt = 'hello world' + let style = {} + if (binding && binding.value) { + txt = binding.value.txt + style = binding.value.style + } + genWatermark(el, txt, style) + } +} + +interface CanvasTextStyle { + font?: string + color?: string +} + +function genWatermark(el: HTMLElement, txt: string, style?: CanvasTextStyle) { + const defaultStyle = { + font: '14px arial', + color: 'rgba(0,0,0,0.2)' + } + + let canvas = document.createElement('canvas') + let ctx = canvas.getContext('2d') + + ctx.translate(150, 75) + ctx.rotate((Math.PI / 180) * 25) + ctx.translate(-150, -75) + + ctx.font = style?.font || defaultStyle.font + ctx.fillStyle = style?.color || defaultStyle.color + ctx.textAlign = 'center' + ctx.textBaseline = 'middle' + + ctx.fillText(txt, canvas.width / 2, canvas.height / 2) + + el.style.backgroundImage = `url(${canvas.toDataURL('image/png')})` +} \ No newline at end of file diff --git a/vite-project/src/layout/header/index.vue b/vite-project/src/layout/header/index.vue new file mode 100644 index 0000000..130c789 --- /dev/null +++ b/vite-project/src/layout/header/index.vue @@ -0,0 +1,116 @@ + + + \ No newline at end of file diff --git a/vite-project/src/layout/tags /user.ts b/vite-project/src/layout/tags /user.ts new file mode 100644 index 0000000..80d185b --- /dev/null +++ b/vite-project/src/layout/tags /user.ts @@ -0,0 +1,39 @@ +import { defineStore } from 'pinia' +import { ref } from 'vue' +import { login } from '~/api/user' +import { UserInfo } from '~/types/index' + +export const useUserStore = defineStore( + 'user', + () => { + let username = ref('') + let userPermiss = ref([]) + + // 用户登录 + async function userLogin(param: UserInfo) { + const { username: name, permiss } = await login({ + username: param.username, + password: param.password + }) + console.log(permiss, name) + if (name) { + username.value = name + userPermiss.value = permiss + + return true + } + return false + } + + // 退出登录 + function userLogout() { + username.value = '' + userPermiss.value = [] + } + + return { username, userPermiss, userLogin, userLogout } + }, + { + persist: true + } +) \ No newline at end of file diff --git a/vite-project/src/main.ts b/vite-project/src/main.ts new file mode 100644 index 0000000..74308ef --- /dev/null +++ b/vite-project/src/main.ts @@ -0,0 +1,37 @@ +import { createApp } from 'vue' +import { createPinia } from 'pinia' +import piniaPluginPersistedstate from 'pinia-plugin-persistedstate' +const pinia = createPinia() + +pinia.use(piniaPluginPersistedstate) + +import App from './App.vue' +import router from './router' + +import './assets/css/index.scss' +import './assets/css/element/index.scss' +import 'element-plus/theme-chalk/dark/css-vars.css' + +const app = createApp(App) +app.use(pinia) +app.use(router) + +// 在 main.ts文件中设置svg-icon为全局组件 +import svgIcon from '~/components/svgIcon/index.vue' +app.component('svg-icon', svgIcon) +import 'iconify-icon' + +// 注册指令 +import directive from './directive' +directive(app) + +// 引入VForm 设计器需全局引入Element Plus +// import ElementPlus from 'element-plus' //引入element-plus库 +// import 'element-plus/dist/index.css' //引入element-plus样式 +// // 引入并全局注册VForm 3组件 +// import VForm3 from 'vform3-builds' //引入VForm 3库 +// import 'vform3-builds/dist/designer.style.css' //引入VForm3样式 +// app.use(ElementPlus) //全局注册element-plus +// app.use(VForm3) + +app.mount('#app') \ No newline at end of file diff --git a/vite-project/src/router/index.ts b/vite-project/src/router/index.ts new file mode 100644 index 0000000..9a90697 --- /dev/null +++ b/vite-project/src/router/index.ts @@ -0,0 +1,67 @@ +import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router' + +import { useUserStore } from '~/store/user' +import Home from '~/layout/index.vue' + +const modules = import.meta.glob('./modules/**/*.ts', { eager: true }) + +const routeModuleList: RouteRecordRaw[] = [] + +Object.values(modules).forEach((key: any) => { + const mod = key.default || [] + const modList = Array.isArray(mod) ? [...mod] : [mod] + routeModuleList.push(...modList) + routeModuleList.sort((a, b) => { + const orderA = a?.meta?.order || 0 + const orderB = b?.meta?.order || 0 + return orderA - orderB + }) +}) + +const routes: RouteRecordRaw[] = [ + { + path: '/', + name: 'Home', + component: Home, + redirect: '/dashboard/workbench', + children: [...routeModuleList] + }, + { + path: '/login', + name: 'Login', + meta: { + title: '登录' + }, + component: () => import(/* webpackChunkName: "login" */ '../views/login/login.vue') + }, + { + path: '/403', + name: '403', + meta: { + title: '没有权限' + }, + component: () => import(/* webpackChunkName: "403" */ '../views/403.vue') + } +] + +const router = createRouter({ + history: createWebHashHistory(), + routes +}) + +router.beforeEach((to, from, next) => { + const userStore = useUserStore() + document.title = `${to.meta.title} | mocha vue3 admin` + const role = userStore.username + + if (!role && to.path !== '/login') { + next('/login') + } else if (to.meta.permiss && !userStore.userPermiss.includes(to.meta.permiss)) { + // 如果没有权限,则进入403 + next('/403') + } else { + next() + } +}) + +export default router \ No newline at end of file diff --git a/vite-project/src/style.css b/vite-project/src/style.css new file mode 100644 index 0000000..7294765 --- /dev/null +++ b/vite-project/src/style.css @@ -0,0 +1,80 @@ +:root { + font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; + line-height: 1.5; + font-weight: 400; + + color-scheme: light dark; + color: rgba(255, 255, 255, 0.87); + background-color: #242424; + + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + -webkit-text-size-adjust: 100%; +} + +a { + font-weight: 500; + color: #646cff; + text-decoration: inherit; +} +a:hover { + color: #535bf2; +} + +body { + margin: 0; + display: flex; + place-items: center; + min-width: 320px; + min-height: 100vh; +} + +h1 { + font-size: 3.2em; + line-height: 1.1; +} + +button { + border-radius: 8px; + border: 1px solid transparent; + padding: 0.6em 1.2em; + font-size: 1em; + font-weight: 500; + font-family: inherit; + background-color: #1a1a1a; + cursor: pointer; + transition: border-color 0.25s; +} +button:hover { + border-color: #646cff; +} +button:focus, +button:focus-visible { + outline: 4px auto -webkit-focus-ring-color; +} + +.card { + padding: 2em; +} + +#app { + max-width: 1280px; + margin: 0 auto; + padding: 2rem; + text-align: center; +} + +@media (prefers-color-scheme: light) { + :root { + color: #213547; + background-color: #ffffff; + } + a:hover { + color: #747bff; + } + button { + background-color: #f9f9f9; + } +} diff --git a/vite-project/src/types/index.d.ts b/vite-project/src/types/index.d.ts new file mode 100644 index 0000000..f136f37 --- /dev/null +++ b/vite-project/src/types/index.d.ts @@ -0,0 +1,9 @@ +export interface SelectOptionItem { + value: string + label: string +} + +export interface UserInfo { + username: string + password?: string +} \ No newline at end of file diff --git a/vite-project/src/utils/http/axios.ts b/vite-project/src/utils/http/axios.ts new file mode 100644 index 0000000..f3ef7e1 --- /dev/null +++ b/vite-project/src/utils/http/axios.ts @@ -0,0 +1,79 @@ +import axios, { AxiosInstance, AxiosError, AxiosResponse, AxiosRequestConfig } from 'axios' +import { errorHandler, errorMsgHandler } from './errorHandler' + +import qs from 'qs' + +declare module 'axios' { + export interface AxiosRequestConfig { + isReturnNativeData?: boolean + errorMode?: string + repeatRequest?: boolean + } +} + +let pendingMap = new Map() + +function getRequestKey(config: AxiosRequestConfig) { + return (config.method || '') + config.url + '?' + qs.stringify(config?.data) +} + +function setPendingMap(config: AxiosRequestConfig) { + const controller = new AbortController() + config.signal = controller.signal + const key = getRequestKey(config) + if (pendingMap.has(key)) { + pendingMap.get(key).abort() + pendingMap.delete(key) + } else { + pendingMap.set(key, controller) + } +} + +const service: AxiosInstance = axios.create({ + timeout: 1000 * 30, + baseURL: import.meta.env.VITE_BASE_URL +}) + +service.interceptors.request.use( + (config) => { + if (!config.repeatRequest) { + setPendingMap(config) + } + return config + }, + (error: AxiosError) => { + console.log(error) + return Promise.reject() + } +) + +service.interceptors.response.use((response: AxiosResponse) => { + const config = response.config + const key = getRequestKey(config) + pendingMap.delete(key) + + if (response.status === 200) { + if (config?.isReturnNativeData) { + return response.data + } else { + const { result, code, message } = response.data + + if (code === 200) { + return result + } else { + errorHandler(message || errorMsgHandler(code), config.errorMode) + } + } + } else { + const errMsg = errorMsgHandler(response.status) + errorHandler(errMsg, config.errorMode) + Promise.reject() + } +}) + +// 错误处理 +service.interceptors.response.use(undefined, (e) => { + errorHandler(e.response.status) +}) + +export default service \ No newline at end of file diff --git a/vite-project/src/utils/http/errorHandler.ts b/vite-project/src/utils/http/errorHandler.ts new file mode 100644 index 0000000..929d779 --- /dev/null +++ b/vite-project/src/utils/http/errorHandler.ts @@ -0,0 +1,28 @@ +import { ElMessage, ElNotification } from 'element-plus' + +// 根据错误代码,获取对应文字 +const errorMsgHandler = (errStatus: number): string => { + if (errStatus === 500) return '服务器内部错误' + if ((errStatus = 400)) return '没有权限' + return '未知错误' +} + +// 根据mode,返回错误信息 +const errorHandler = (errMsg: string, mode: string = 'modal') => { + const msg = errMsg || '未知错误' + + if (mode === 'modal') { + ElMessage(msg + '|' + mode) + } + if (mode === 'toast') { + ElNotification({ + title: 'Error', + message: msg, + type: 'error' + }) + } + if (mode === 'hiden') { + } +} + +export { errorHandler, errorMsgHandler } \ No newline at end of file diff --git a/vite-project/src/utils/index.js b/vite-project/src/utils/index.js new file mode 100644 index 0000000..85fd341 --- /dev/null +++ b/vite-project/src/utils/index.js @@ -0,0 +1,32 @@ +/** + * 将 URL 中的查询参数转换成一个对象 + * @param {string} url 完整的 URL + * @returns {object} 包含查询参数的对象 + */ +export function param2Obj(url) { + // 从 URL 中取出查询参数部分,并进行 URL 解码 + const search = decodeURIComponent(url.split('?')[1]).replace(/\+/g, ' ') + // 如果没有查询参数,返回一个空对象 + if (!search) { + return {} + } + // 初始化一个空对象,用于存储查询参数 + const obj = {} + // 将查询参数字符串按 & 符号分割成数组 + const searchArr = search.split('&') + // 遍历查询参数数组 + searchArr.forEach((v) => { + // 找到等号的位置 + const index = v.indexOf('=') + // 如果找到了等号 + if (index !== -1) { + // 取出参数名和参数值 + const name = v.substring(0, index) + const val = v.substring(index + 1, v.length) + // 将参数名和参数值存入对象中 + obj[name] = val + } + }) + // 返回包含查询参数的对象 + return obj +} \ No newline at end of file diff --git a/vite-project/src/vite-env.d.ts b/vite-project/src/vite-env.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/vite-project/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/vite-project/tsconfig.json b/vite-project/tsconfig.json new file mode 100644 index 0000000..bc3776b --- /dev/null +++ b/vite-project/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "target": "ESNext", + "useDefineForClassFields": true, + "module": "ESNext", + "moduleResolution": "Node", + "strict": true, + "jsx": "preserve", + "sourceMap": true, + "resolveJsonModule": true, + "isolatedModules": true, + "esModuleInterop": true, + "lib": ["ESNext", "DOM"], + "skipLibCheck": true, + "baseUrl": ".", + "paths": { "~/*": ["src/*"] } + }, + "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.vue"], + "references": [{ "path": "./tsconfig.node.json" }] +} \ No newline at end of file diff --git a/vite-project/tsconfig.node.json b/vite-project/tsconfig.node.json new file mode 100644 index 0000000..cfa1ab5 --- /dev/null +++ b/vite-project/tsconfig.node.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "node", + "allowSyntheticDefaultImports": true + }, + "include": ["vite.config.ts"] +} diff --git a/vite-project/vite.config.ts b/vite-project/vite.config.ts new file mode 100644 index 0000000..05c1740 --- /dev/null +++ b/vite-project/vite.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [vue()], +}) -- GitLab