Pārlūkot izejas kodu

feat: 添加必要文件

Gaokun Wang 1 mēnesi atpakaļ
vecāks
revīzija
135765e4d4

+ 2 - 2
.stylelintrc.cjs

@@ -7,8 +7,8 @@ module.exports = {
     'stylelint-config-standard', // 配置 stylelint 拓展插件
     'stylelint-config-html/vue', // 配置 vue 中 template 样式格式化
     'stylelint-config-standard-scss', // 配置 stylelint scss 插件
-    'stylelint-config-recommended-vue/scss', // 配置 vue 中 scss 样式格式化
-    'stylelint-config-recess-order' // 配置 stylelint css 属性书写顺序插件,
+    'stylelint-config-recommended-vue/scss' // 配置 vue 中 scss 样式格式化
+    // 'stylelint-config-recess-order' // 配置 stylelint css 属性书写顺序插件,
   ],
   overrides: [
     // 扫描 .vue/html 文件中的 <style> 标签内的样式

+ 17 - 0
src/axios/config.ts

@@ -0,0 +1,17 @@
+import type { InternalAxiosRequestConfig, AxiosResponse } from 'axios'
+import { ResultEnum } from '@/enums/HttpEnum'
+const defaultRequestInterceptors = (config: InternalAxiosRequestConfig) => {
+  return config
+}
+
+const defaultResponseInterceptors = (response: AxiosResponse) => {
+  const { code } = response.data
+  if (response?.config?.responseType === 'blob') {
+    // 如果是文件流,直接过
+    return response
+  } else if (code === ResultEnum.SUCCESS) {
+    return response.data
+  }
+}
+
+export { defaultResponseInterceptors, defaultRequestInterceptors }

+ 36 - 0
src/axios/index.ts

@@ -0,0 +1,36 @@
+import service from './service'
+
+const request = (option: AxiosConfig) => {
+  const { url, method, params, data, headers, responseType } = option
+  return service.request({
+    url: url,
+    method,
+    params,
+    data: data,
+    responseType: responseType,
+    headers: {
+      ...headers
+    }
+  })
+}
+
+export default {
+  get: <T = any>(option: AxiosConfig) => {
+    return request({ method: 'get', ...option }) as Promise<ResultData<T>>
+  },
+  post: <T = any>(option: AxiosConfig) => {
+    return request({ method: 'post', ...option }) as Promise<ResultData<T>>
+  },
+  delete: <T = any>(option: AxiosConfig) => {
+    return request({ method: 'delete', ...option }) as Promise<ResultData<T>>
+  },
+  put: <T = any>(option: AxiosConfig) => {
+    return request({ method: 'put', ...option }) as Promise<ResultData<T>>
+  },
+  cancelRequest: (url: string | string[]) => {
+    return service.cancelRequest(url)
+  },
+  cancelAllRequest: () => {
+    return service.cancelAllRequest()
+  }
+}

+ 89 - 0
src/axios/service.ts

@@ -0,0 +1,89 @@
+import axios, { AxiosError, type AxiosInstance, type AxiosRequestConfig, type AxiosResponse, type InternalAxiosRequestConfig } from 'axios'
+import { ResultEnum } from '@/enums/HttpEnum'
+import { defaultRequestInterceptors, defaultResponseInterceptors } from './config'
+interface RequestInterceptors<T> {
+  // 请求拦截
+  requestInterceptors?: (config: InternalAxiosRequestConfig) => InternalAxiosRequestConfig
+  requestInterceptorsCatch?: (err: any) => any
+  // 响应拦截
+  responseInterceptors?: (config: T) => T
+  responseInterceptorsCatch?: (err: any) => any
+}
+
+interface RequestConfig<T = AxiosResponse> extends AxiosRequestConfig {
+  interceptors?: RequestInterceptors<T>
+}
+
+export const BASE_URL = import.meta.env.VITE_USE_MOCK ? import.meta.env.VITE_MOCK_API_PREFIX_PATH : import.meta.env.VITE_API_PREFIX_PATH
+
+const abortControllerMap: Map<string, AbortController> = new Map()
+
+const config = {
+  // 默认地址请求地址,可在 .env.** 文件中修改
+  baseURL: BASE_URL as string,
+  // 设置超时时间
+  timeout: ResultEnum.TIMEOUT as number,
+  // 跨域时候允许携带凭证
+  withCredentials: true
+}
+// instantiation
+const axiosInstance: AxiosInstance = axios.create(config)
+
+axiosInstance.interceptors.request.use((res: InternalAxiosRequestConfig) => {
+  const controller = new AbortController()
+  const url = res.url || ''
+  res.signal = controller.signal
+  abortControllerMap.set(url, controller)
+  return res
+})
+
+axiosInstance.interceptors.response.use(
+  (res: AxiosResponse) => {
+    const url = res.config.url || ''
+    abortControllerMap.delete(url)
+    return res
+  },
+  (error: AxiosError) => {
+    console.log('err: ' + error)
+    return Promise.reject(error)
+  }
+)
+// 默认请求/响应 处理
+axiosInstance.interceptors.request.use(defaultRequestInterceptors)
+axiosInstance.interceptors.response.use(defaultResponseInterceptors)
+
+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)
+    }
+  },
+
+  // 取消所有请求
+  cancelAllRequest() {
+    for (const [_, controller] of abortControllerMap) {
+      controller.abort()
+    }
+    abortControllerMap.clear()
+  }
+}
+export default service

+ 42 - 0
src/enums/HttpEnum.ts

@@ -0,0 +1,42 @@
+/**
+ * @description:请求配置
+ */
+export enum ResultEnum {
+  SUCCESS = 200,
+  ERROR = 500,
+  OVERDUE = 401,
+  TIMEOUT = 30000,
+  TYPE = 'success'
+}
+
+/**
+ * @description:请求方法
+ */
+export enum RequestEnum {
+  GET = 'GET',
+  POST = 'POST',
+  PATCH = 'PATCH',
+  PUT = 'PUT',
+  DELETE = 'DELETE'
+}
+
+/**
+ * @description:mock 响应
+ */
+export enum ResponseEnum {
+  TIMEOUT = 10
+}
+
+/**
+ * @description:常用的 contentTyp 类型
+ */
+export enum ContentTypeEnum {
+  // json
+  JSON = 'application/json;charset=UTF-8',
+  // text
+  TEXT = 'text/plain;charset=UTF-8',
+  // form-data 一般配合qs
+  FORM_URLENCODED = 'application/x-www-form-urlencoded;charset=UTF-8',
+  // form-data 上传
+  FORM_DATA = 'multipart/form-data;charset=UTF-8'
+}

+ 4 - 0
src/layouts/container/AppClassic/index.vue

@@ -0,0 +1,4 @@
+<template>
+  <div>test</div>
+</template>
+<script lang="tsx" setup></script>

+ 4 - 0
src/layouts/container/AppTransverse/index.vue

@@ -0,0 +1,4 @@
+<template>
+  <div></div>
+</template>
+<script lang="tsx" setup></script>

+ 13 - 0
src/layouts/index.vue

@@ -0,0 +1,13 @@
+<template>
+  <div class="wh-full">
+    <component :is="LayoutComponents['classic']" />
+  </div>
+</template>
+
+<script setup lang="ts" name="Layout">
+import AppClassic from './container/AppClassic/index.vue'
+
+const LayoutComponents: Record<LayoutType, Component> = {
+  classic: AppClassic
+}
+</script>

+ 10 - 4
src/main.ts

@@ -1,7 +1,13 @@
 import { createApp } from 'vue'
-import './style.css'
-
-import '@/assets/styles/index.scss'
 import App from './App.vue'
 
-createApp(App).mount('#app')
+import setupAppUse from '../plugins/app-use'
+
+import '@/assets/styles/index.scss'
+// 创建实例
+const setupAll = async () => {
+  const app = createApp(App)
+  app.use(setupAppUse)
+  app.mount('#app')
+}
+setupAll()

+ 0 - 79
src/style.css

@@ -1,79 +0,0 @@
-:root {
-  font-family: 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;
-}
-
-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;
-  }
-}

+ 2 - 0
src/types/auto-components.d.ts

@@ -8,6 +8,8 @@ export {}
 /* prettier-ignore */
 declare module 'vue' {
   export interface GlobalComponents {
+    AppClassic: typeof import('./../layouts/container/AppClassic/index.vue')['default']
+    AppTransverse: typeof import('./../layouts/container/AppTransverse/index.vue')['default']
     HelloWorld: typeof import('./../components/HelloWorld.vue')['default']
     RouterLink: typeof import('vue-router')['RouterLink']
     RouterView: typeof import('vue-router')['RouterView']

+ 1 - 1
env.d.ts → src/types/env.d.ts

@@ -3,7 +3,7 @@
 declare module '*.vue' {
   import { DefineComponent } from 'vue'
 
-  const component: DefineComponent<{}, {}, any>
+  const component: DefineComponent<object, object, any>
   export default component
 }
 

+ 0 - 0
src/views/home/index.vue


+ 6 - 3
tsconfig.app.json

@@ -7,9 +7,12 @@
     "strict": true,
     "noUnusedLocals": true,
     "noUnusedParameters": true,
-    "erasableSyntaxOnly": true,
     "noFallthroughCasesInSwitch": true,
-    "noUncheckedSideEffectImports": true
+    "noUncheckedSideEffectImports": true,
+    "baseUrl": "./",
+    "paths": {
+      "@/*": ["src/*"]
+    }
   },
-  "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue", "src/types/*.d.ts"]
+  "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"]
 }

+ 0 - 1
tsconfig.node.json

@@ -17,7 +17,6 @@
     "strict": true,
     "noUnusedLocals": true,
     "noUnusedParameters": true,
-    "erasableSyntaxOnly": true,
     "noFallthroughCasesInSwitch": true,
     "noUncheckedSideEffectImports": true
   },

+ 1 - 1
vite.config.ts

@@ -34,7 +34,7 @@ export default defineConfig(({ mode, command }: ConfigEnv): UserConfig => {
       }
     },
     optimizeDeps: {
-      include: ['vue', 'vue-router', 'pinia', 'vue-i18n', 'axios', '@vueuse/core']
+      include: ['vue', 'vue-router', 'pinia', 'axios', '@vueuse/core', 'element-plus', '@element-plus/icons-vue']
     }
   }
 })