├── src ├── types.ts ├── assets │ ├── styles │ │ ├── variables.scss │ │ ├── index.scss │ │ ├── dark.scss │ │ ├── markdown.scss │ │ └── nprogress.scss │ └── svg │ │ └── vitecamp.svg ├── utils │ ├── dark.ts │ └── format.ts ├── store │ ├── index.ts │ └── theme.ts ├── router │ ├── route.common.ts │ ├── route.async.ts │ ├── route.exception.ts │ └── index.ts ├── api │ ├── modules │ │ └── login.ts │ ├── code.ts │ └── http.ts ├── views │ ├── example │ │ └── MarkdownPage.vue │ ├── exception │ │ ├── 401.vue │ │ └── 404.vue │ └── home │ │ └── index.vue ├── App.vue ├── main.ts ├── components │ ├── ZhProcess.md │ ├── EnProcess.md │ └── TheFooter.vue ├── env.d.ts ├── components.d.ts └── auto-imports.d.ts ├── .env.development ├── .env.production ├── .husky ├── .gitignore ├── pre-commit └── commit-msg ├── .gitattributes ├── .npmrc ├── .gitignore ├── .prettierignore ├── .eslintignore ├── .env ├── .commitlintrc.js ├── .vscode ├── settings.json └── extensions.json ├── index.html ├── locales ├── zh-CN.json └── en.json ├── prettier.config.js ├── .editorconfig ├── tsconfig.json ├── .eslintrc.js ├── LICENSE ├── windi.config.ts ├── vite.config.ts ├── package.json ├── public └── favicon.svg ├── presets └── presets.ts ├── README.zh-CN.md ├── README.md └── .eslintrc-auto-import.json /src/types.ts: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.env.development: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.env.production: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.husky/.gitignore: -------------------------------------------------------------------------------- 1 | _ 2 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf -------------------------------------------------------------------------------- /src/assets/styles/variables.scss: -------------------------------------------------------------------------------- 1 | $theme-color: #2080F0FF 2 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | shamefully-hoist=true 2 | strict-peer-dependencies=false 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | dist 4 | dist-ssr 5 | *.local 6 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | npx lint-staged 5 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | dist 4 | dist-ssr 5 | *.local 6 | *.d.ts 7 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | dist 4 | dist-ssr 5 | *.local 6 | presets 7 | *.d.ts 8 | -------------------------------------------------------------------------------- /src/utils/dark.ts: -------------------------------------------------------------------------------- 1 | export const isDark = useDark(); 2 | export const toggleDark = useToggle(isDark); 3 | -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | npx --no-install commitlint --edit $1 5 | -------------------------------------------------------------------------------- /src/store/index.ts: -------------------------------------------------------------------------------- 1 | import { createPinia } from 'pinia'; 2 | 3 | const store = createPinia(); 4 | 5 | export default store; 6 | -------------------------------------------------------------------------------- /src/assets/styles/index.scss: -------------------------------------------------------------------------------- 1 | @import '@/assets/styles/nprogress.scss'; 2 | @import '@/assets/styles/markdown.scss'; 3 | @import '@/assets/styles/dark.scss'; 4 | -------------------------------------------------------------------------------- /src/assets/styles/dark.scss: -------------------------------------------------------------------------------- 1 | @import 'element-plus/theme-chalk/dark/css-vars.css'; 2 | 3 | body { 4 | @apply text-gray-700 dark: bg-gray-800 dark:text-gray-200; 5 | } 6 | -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- 1 | VITE_API_BASEURL = /api 2 | 3 | VITE_BASE = / 4 | 5 | VITE_APP_TITLE = Vitecamp 6 | 7 | VITE_APP_DESCRIPTION = A zero-config Vue3 template includes Vite3、Vue3 and TypeScript 8 | -------------------------------------------------------------------------------- /src/router/route.common.ts: -------------------------------------------------------------------------------- 1 | // 不需要鉴权的业务路由 2 | import { RouteRecordRaw } from 'vue-router'; 3 | 4 | const commonRoutes: Array = []; 5 | 6 | export default commonRoutes; 7 | -------------------------------------------------------------------------------- /src/api/modules/login.ts: -------------------------------------------------------------------------------- 1 | import service from '@/api/http'; 2 | 3 | const loginApi = { 4 | // 验证登录实例 5 | postVerification: (params: object) => service.post(`/login`, params), 6 | }; 7 | 8 | export default loginApi; 9 | -------------------------------------------------------------------------------- /src/views/example/MarkdownPage.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 9 | -------------------------------------------------------------------------------- /.commitlintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['@commitlint/config-conventional'], 3 | rules: { 4 | 'type-enum': [ 5 | 2, 6 | 'always', 7 | ['init', 'build', 'ci', 'chore', 'docs', 'feat', 'fix', 'perf', 'refactor', 'revert', 'style', 'test'], 8 | ], 9 | }, 10 | }; 11 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "typescript.tsdk": "node_modules/typescript/lib", 3 | "editor.codeActionsOnSave": { 4 | "source.fixAll.eslint": true, 5 | }, 6 | "editor.formatOnSave": true, 7 | "i18n-ally.localesPaths": [ 8 | "locales" 9 | ], 10 | "scss.lint.unknownAtRules": "ignore" 11 | } 12 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "johnsoncodehk.volar", 4 | "lokalise.i18n-ally", 5 | "antfu.iconify", 6 | "dbaeumer.vscode-eslint", 7 | "esbenp.prettier-vscode", 8 | "EditorConfig.EditorConfig", 9 | "voorjaar.windicss-intellisense", 10 | "csstools.postcss" 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 15 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /locales/zh-CN.json: -------------------------------------------------------------------------------- 1 | { 2 | "hello": "你好", 3 | "welcome to": "欢迎来到", 4 | "includes features": "是一个开箱即用的 Vue3 模板,它拥有这些功能:", 5 | "before coding": "在开始编码之前", 6 | "setup ide": "我建议将你的 IDE 设置为", 7 | "home": "主页", 8 | "change light": "点击切换为亮色主题", 9 | "change dark": "点击切换为暗黑主题", 10 | "change lang": "切换国际化语言", 11 | "method to using": "使用模板的方法", 12 | "template process": "模板配置流程" 13 | } 14 | -------------------------------------------------------------------------------- /src/views/exception/401.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 21 | -------------------------------------------------------------------------------- /src/views/exception/404.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 21 | -------------------------------------------------------------------------------- /src/utils/format.ts: -------------------------------------------------------------------------------- 1 | export declare interface instanceObject { 2 | [key: string]: string; 3 | } 4 | 5 | /** 6 | * JSON转url参数 7 | * @param data Json格式数据 8 | * */ 9 | export const formatJsonToUrlParams = (data: instanceObject) => { 10 | return typeof data === 'object' 11 | ? Object.keys(data) 12 | .map((key) => { 13 | return `${encodeURIComponent(key)}=${encodeURIComponent(data[key])}`; 14 | }) 15 | .join('&') 16 | : ''; 17 | }; 18 | 19 | export default formatJsonToUrlParams; 20 | -------------------------------------------------------------------------------- /locales/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "hello": "Hello", 3 | "welcome to": "Welcome to", 4 | "includes features": "is a zero-config Vue3 template, it includes these feature:", 5 | "before coding": "Before coding", 6 | "setup ide": "I recommended your IDE setup", 7 | "home": "Home", 8 | "change light": "Click to switch to bright color theme", 9 | "change dark": "Click to switch to dark theme", 10 | "change lang": "Switch languages", 11 | "method to using": "Method of using template", 12 | "template process": "Template configuration process" 13 | } 14 | -------------------------------------------------------------------------------- /prettier.config.js: -------------------------------------------------------------------------------- 1 | // https://prettier.io/docs/en/configuration.html 2 | module.exports = { 3 | // 每一行的宽度(显示的字符数) 4 | printWidth: 120, 5 | 6 | // tab健的空格数 7 | tabWidth: 2, 8 | 9 | // 是否在对象中的括号之间打印空格,{a:5}格式化为{ a: 5 } 10 | bracketSpacing: true, 11 | 12 | // 箭头函数的参数无论有几个,都要括号包裹 13 | arrowParens: 'always', 14 | 15 | // 换行符的使用 16 | endOfLine: 'lf', 17 | 18 | // 是否用单引号, 项目中全部使用单引号 19 | singleQuote: true, 20 | 21 | // 对象或者数组的最后一个元素后面是否要加逗号 22 | trailingComma: 'all', 23 | 24 | // 是否加分号,项目中统一加分号 25 | semi: true, 26 | 27 | // 是否使用tab格式化: 不使用 28 | useTabs: false, 29 | }; 30 | -------------------------------------------------------------------------------- /src/router/route.async.ts: -------------------------------------------------------------------------------- 1 | // 需要鉴权的业务路由 2 | import { RouteRecordRaw } from 'vue-router'; 3 | 4 | const asyncRoutes: Array = [ 5 | { 6 | path: '/', 7 | name: 'home', 8 | meta: { 9 | title: '', 10 | icon: '', 11 | }, 12 | component: () => import('@/views/home/index.vue'), 13 | }, 14 | { 15 | path: '/process', 16 | name: 'process', 17 | meta: { 18 | title: 'Template configuration process', 19 | icon: '', 20 | }, 21 | component: () => import('@/views/example/MarkdownPage.vue'), 22 | }, 23 | ]; 24 | 25 | export default asyncRoutes; 26 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: https://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | [*] # 表示所有文件都要遵循 7 | indent_style = space # 缩进风格,可选配置有space和tab 8 | indent_size = 2 # 缩进大小 9 | end_of_line = lf # 换行符,可选配置有lf、cr和crlf 10 | charset = utf-8 # 编码格式,通常都是选utf-8 11 | trim_trailing_whitespace = true # 去除多余的空格 12 | insert_final_newline = true # 在尾部插入一行 13 | 14 | [*.md] # 表示仅 md 文件适用 15 | insert_final_newline = false # 在尾部插入一行 16 | trim_trailing_whitespace = false # 去除多余的空格 17 | -------------------------------------------------------------------------------- /src/api/code.ts: -------------------------------------------------------------------------------- 1 | declare interface codeMessageMapTypes { 2 | 400: string; 3 | 401: string; 4 | 403: string; 5 | 404: string; 6 | 405: string; 7 | 500: string; 8 | [key: string]: string; 9 | } 10 | 11 | const codeMessageMap: codeMessageMapTypes = { 12 | 400: '[400]:请求参数错误', 13 | 401: '[401]:账户未登录', 14 | 403: '[403]:拒绝访问', 15 | 404: '[404]:请求路径错误', 16 | 405: '[405]:请求方法错误', 17 | 500: '[500]:服务器错误', 18 | }; 19 | 20 | const showCodeMessage = (code: number | string): string => { 21 | return codeMessageMap[JSON.stringify(code)] || '网络连接异常,请稍后再试!'; 22 | }; 23 | 24 | export default showCodeMessage; 25 | -------------------------------------------------------------------------------- /src/store/theme.ts: -------------------------------------------------------------------------------- 1 | import { defineStore } from 'pinia'; 2 | 3 | const theme = defineStore({ 4 | // 这里的id必须为唯一ID 5 | id: 'theme', 6 | state: () => { 7 | return { 8 | themeType: '亮蓝色', 9 | themeColor: '#2080F0FF', 10 | }; 11 | }, 12 | // 等同于vuex的getter 13 | getters: { 14 | getThemeType: (state) => state.themeType, 15 | getThemeColor: (state) => state.themeColor, 16 | }, 17 | // pinia 放弃了 mutations 只使用 actions 18 | actions: { 19 | // actions可以用async做成异步形式 20 | setThemeType(type: string) { 21 | this.themeType = type; 22 | }, 23 | }, 24 | }); 25 | 26 | export default theme; 27 | -------------------------------------------------------------------------------- /src/router/route.exception.ts: -------------------------------------------------------------------------------- 1 | // 跟鉴权无关的特殊路由 2 | import { RouteRecordRaw } from 'vue-router'; 3 | 4 | const exceptionRoutes: Array = [ 5 | { 6 | path: '/401', 7 | name: '401', 8 | meta: { 9 | title: '需要登录', 10 | }, 11 | component: () => import('@/views/exception/401.vue'), 12 | }, 13 | { 14 | path: '/404', 15 | name: '404', 16 | meta: { 17 | title: '非常抱歉,页面走丢了', 18 | }, 19 | component: () => import('@/views/exception/404.vue'), 20 | }, 21 | { 22 | path: '/:pathMatch(.*)', 23 | meta: {}, 24 | redirect: '/404', 25 | }, 26 | ]; 27 | 28 | export default exceptionRoutes; 29 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | // i18n 2 | import { createI18n } from 'vue-i18n'; 3 | import messages from '@intlify/vite-plugin-vue-i18n/messages'; 4 | // vue router 5 | import router from '@/router/index'; 6 | // pinia 7 | import store from '@/store'; 8 | import App from './App.vue'; 9 | 10 | import 'virtual:windi.css'; 11 | // Devtools: https://windicss.org/integrations/vite.html#design-in-devtools 12 | import 'virtual:windi-devtools'; 13 | import '@/assets/styles/index.scss'; 14 | 15 | const i18n = createI18n({ 16 | locale: 'en', 17 | messages, 18 | }); 19 | 20 | const app = createApp(App); 21 | 22 | app.use(router).use(store); 23 | 24 | app.use(i18n); 25 | 26 | app.mount('#app'); 27 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "esnext", 4 | "useDefineForClassFields": true, 5 | "module": "esnext", 6 | "moduleResolution": "node", 7 | "strict": true, 8 | "jsx": "preserve", 9 | "sourceMap": true, 10 | "resolveJsonModule": true, 11 | "esModuleInterop": true, 12 | "lib": ["esnext", "dom"], 13 | "types": ["@intlify/vite-plugin-vue-i18n/client"], 14 | // baseUrl来告诉编译器到哪里去查找模块,所有非相对模块导入都会被当做相对于 baseUrl。 15 | "baseUrl": ".", 16 | // 非相对模块导入的路径映射配置 17 | "paths": { 18 | "@/*": ["src/*"], 19 | } 20 | }, 21 | "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"], 22 | // 编译器默认排除的编译文件 23 | "exclude": ["node_modules"] 24 | } 25 | -------------------------------------------------------------------------------- /src/components/ZhProcess.md: -------------------------------------------------------------------------------- 1 | ## 现在可以试试! 2 | 3 | ### GitHub 模板 4 | 5 | [使用这个模板创建仓库](https://github.com/nekobc1998923/vitecamp/generate). 6 | 7 | ### 克隆到本地 8 | 9 | ```bash 10 | git clone https://github.com/nekobc1998923/vitecamp.git my-vitecamp-app 11 | cd my-vitecamp-app 12 | pnpm i 13 | ``` 14 | 15 | ## 清单 16 | 17 | 使用此模板时,请尝试按照清单正确更新您自己的信息 18 | 19 | - 在 `LICENSE` 中改变作者名 20 | - 在 `package.json` 中改变作者名 21 | - 在 `.env` 中改变标题 22 | - 在 `public` 目录下改变 favicon 23 | - 整理 `README `并删除路由 24 | 25 | 然后,你就可以享受编写代码的乐趣了 :) 26 | 27 | ## 使用 28 | 29 | ### 开发 30 | 31 | 只需要执行以下命令就可以在 http://localhost:8080 中看到 32 | 33 | ```bash 34 | pnpm run dev 35 | ``` 36 | 37 | ### 构建 38 | 39 | 构建该应用只需要执行以下命令 40 | 41 | ```bash 42 | pnpm run build 43 | ``` 44 | 45 | 然后你会看到用于发布的 `dist` 文件夹被生成。 46 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | browser: true, 4 | es2021: true, 5 | node: true, 6 | }, 7 | globals: { 8 | defineEmits: true, 9 | document: true, 10 | localStorage: true, 11 | GLOBAL_VAR: true, 12 | window: true, 13 | defineProps: true, 14 | defineExpose: true, 15 | withDefaults: true, 16 | }, 17 | extends: [ 18 | './.eslintrc-auto-import.json', 19 | 'airbnb-base', 20 | 'plugin:@typescript-eslint/recommended', 21 | 'plugin:vue/vue3-recommended', 22 | 'plugin:prettier/recommended', // 添加 prettier 插件 23 | ], 24 | parserOptions: { 25 | ecmaVersion: 'latest', 26 | parser: '@typescript-eslint/parser', 27 | sourceType: 'module', 28 | }, 29 | plugins: ['vue', '@typescript-eslint', 'import'], 30 | rules: { 31 | 'no-console': 'off', 32 | 'import/no-unresolved': 'off', 33 | 'import/extensions': 'off', 34 | 'import/no-extraneous-dependencies': 'off', 35 | }, 36 | }; 37 | -------------------------------------------------------------------------------- /src/components/EnProcess.md: -------------------------------------------------------------------------------- 1 | ## Try it now! 2 | 3 | ### GitHub Template 4 | 5 | [Create a repo from this template on GitHub](https://github.com/nekobc1998923/vitecamp/generate). 6 | 7 | ### Clone to local 8 | 9 | ```bash 10 | git clone https://github.com/nekobc1998923/vitecamp.git my-vitecamp-app 11 | cd my-vitecamp-app 12 | pnpm i 13 | ``` 14 | 15 | ## Checklist 16 | 17 | When you use this template, try follow the checklist to update your info properly 18 | 19 | - Change the author name in `LICENSE` 20 | - Change the author name in `package.json` 21 | - Change the title in `.env` 22 | - Change the favicon in `public` 23 | - Clean up the `README` and remove routes 24 | 25 | And then , you can enjoy coding fun :) 26 | 27 | ## Usage 28 | 29 | ### Development 30 | 31 | Just run and visit http://localhost:8080 32 | 33 | ```bash 34 | pnpm run dev 35 | ``` 36 | 37 | ### Build 38 | 39 | To build the App, run 40 | 41 | ```bash 42 | pnpm run build 43 | ``` 44 | 45 | And you will see the generated file in `dist` that ready to be served. 46 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 菜猫子neko 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | // 声明自动引入的 vue 组件 5 | declare module '*.vue' { 6 | import { DefineComponent } from 'vue'; 7 | // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types 8 | const component: DefineComponent<{}, {}, any>; 9 | export default component; 10 | } 11 | 12 | // 声明 icons 引入的组件 13 | declare module '~icons/*' { 14 | import { FunctionalComponent, SVGAttributes } from 'vue'; 15 | const component: FunctionalComponent; 16 | export default component; 17 | } 18 | 19 | // 声明 md 文件 20 | declare module '*.md' { 21 | import type { DefineComponent } from 'vue'; 22 | const component: DefineComponent<{}, {}, any>; 23 | export default component; 24 | } 25 | 26 | // 声明 vite 环境变量 27 | declare interface ImportMetaEnv { 28 | readonly VITE_BASE: string; 29 | readonly VITE_API_BASEURL: string; 30 | readonly VITE_APP_TITLE: string; 31 | // 更多环境变量... 32 | } 33 | 34 | declare interface ImportMeta { 35 | readonly env: ImportMetaEnv; 36 | } 37 | 38 | declare interface Window { 39 | // extend the window 40 | } 41 | -------------------------------------------------------------------------------- /src/router/index.ts: -------------------------------------------------------------------------------- 1 | import { createRouter, createWebHistory, Router, RouteRecordRaw } from 'vue-router'; 2 | import NProgress from 'nprogress'; 3 | import exceptionRoutes from '@/router/route.exception'; 4 | import asyncRoutes from '@/router/route.async'; 5 | import commonRoutes from '@/router/route.common'; 6 | 7 | const routes: Array = [ 8 | // 无鉴权的业务路由 ex:登录 9 | ...commonRoutes, 10 | // 带鉴权的业务路由 11 | ...asyncRoutes, 12 | // 异常页必须放在路由匹配规则的最后 13 | ...exceptionRoutes, 14 | ]; 15 | 16 | const router: Router = createRouter({ 17 | // 新的vue-router4 使用 history路由模式 和 base前缀 18 | history: createWebHistory(import.meta.env.VITE_BASE), 19 | routes, 20 | }); 21 | 22 | /** 23 | * @description: 全局路由前置守卫,在进入路由前触发,导航在所有守卫 resolve 完之前一直处于等待中。 24 | * @param {RouteLocationNormalized} to 即将要进入的目标 25 | * @param {RouteLocationNormalizedLoaded} from 当前导航正在离开的路由 26 | * @return {*} 27 | */ 28 | router.beforeEach((to, from) => { 29 | console.log('全局路由前置守卫:to,from\n', to, from); 30 | // 设置页面标题 31 | document.title = (to.meta.title as string) || import.meta.env.VITE_APP_TITLE; 32 | if (!NProgress.isStarted()) { 33 | NProgress.start(); 34 | } 35 | }); 36 | 37 | router.afterEach((to, from) => { 38 | console.log('全局路由后置守卫:to,from\n', to, from); 39 | NProgress.done(); 40 | }); 41 | 42 | export default router; 43 | -------------------------------------------------------------------------------- /windi.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite-plugin-windicss'; 2 | import typography from 'windicss/plugin/typography'; 3 | import colors from 'windicss/colors'; 4 | 5 | export default defineConfig({ 6 | darkMode: 'class', 7 | plugins: [typography()], 8 | theme: { 9 | fontFamily: { 10 | sans: ['Open Sans', 'ui-sans-serif', 'system-ui'], 11 | serif: ['Montserrat', 'ui-serif', 'Georgia'], 12 | mono: ['Fira Sans', 'ui-monospace', 'SFMono-Regular'], 13 | }, 14 | extend: { 15 | typography: { 16 | DEFAULT: { 17 | css: { 18 | maxWidth: '65ch', 19 | color: 'inherit', 20 | a: { 21 | color: 'inherit', 22 | opacity: 0.75, 23 | fontWeight: '500', 24 | textDecoration: 'underline', 25 | '&:hover': { 26 | opacity: 1, 27 | color: colors.teal[600], 28 | }, 29 | }, 30 | b: { color: 'inherit' }, 31 | strong: { color: 'inherit' }, 32 | em: { color: 'inherit' }, 33 | h1: { color: 'inherit' }, 34 | h2: { color: 'inherit' }, 35 | h3: { color: 'inherit' }, 36 | h4: { color: 'inherit' }, 37 | code: { color: 'inherit' }, 38 | }, 39 | }, 40 | }, 41 | }, 42 | }, 43 | }); 44 | -------------------------------------------------------------------------------- /src/components.d.ts: -------------------------------------------------------------------------------- 1 | // generated by unplugin-vue-components 2 | // We suggest you to commit this file into source control 3 | // Read more: https://github.com/vuejs/core/pull/3399 4 | import '@vue/runtime-core' 5 | 6 | export {} 7 | 8 | declare module '@vue/runtime-core' { 9 | export interface GlobalComponents { 10 | ElButton: typeof import('element-plus/es')['ElButton'] 11 | ElCol: typeof import('element-plus/es')['ElCol'] 12 | ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider'] 13 | ElResult: typeof import('element-plus/es')['ElResult'] 14 | ElRow: typeof import('element-plus/es')['ElRow'] 15 | ElTooltip: typeof import('element-plus/es')['ElTooltip'] 16 | EnProcess: typeof import('./components/EnProcess.md')['default'] 17 | IAkarIconsGithubFill: typeof import('~icons/akar-icons/github-fill')['default'] 18 | ILaLanguage: typeof import('~icons/la/language')['default'] 19 | IMdiContentDuplicate: typeof import('~icons/mdi/content-duplicate')['default'] 20 | IMdiHomeSearchOutline: typeof import('~icons/mdi/home-search-outline')['default'] 21 | IPhCloudMoonBold: typeof import('~icons/ph/cloud-moon-bold')['default'] 22 | IPhSunHorizonBold: typeof import('~icons/ph/sun-horizon-bold')['default'] 23 | IRiArticleLine: typeof import('~icons/ri/article-line')['default'] 24 | RouterLink: typeof import('vue-router')['RouterLink'] 25 | RouterView: typeof import('vue-router')['RouterView'] 26 | TheFooter: typeof import('./components/TheFooter.vue')['default'] 27 | ZhProcess: typeof import('./components/ZhProcess.md')['default'] 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/assets/styles/markdown.scss: -------------------------------------------------------------------------------- 1 | /* https://github.com/antfu/prism-theme-vars */ 2 | @import 'prism-theme-vars/base.css'; 3 | 4 | .prose { 5 | --prism-font-family: 'Input Mono', monospace; 6 | } 7 | 8 | .prose img { 9 | width: 100%; 10 | } 11 | 12 | html:not(.dark) .prose { 13 | --prism-foreground: #393a34; 14 | --prism-background: #fbfbfb; 15 | --prism-background-color: #fbfbfb; 16 | --prism-comment: #a0ada0; 17 | --prism-string: #b56959; 18 | --prism-literal: #2f8a89; 19 | --prism-number: #296aa3; 20 | --prism-keyword: #1c6b48; 21 | --prism-function: #6c7834; 22 | --prism-boolean: #1c6b48; 23 | --prism-constant: #a65e2b; 24 | --prism-deleted: #a14f55; 25 | --prism-class: #2993a3; 26 | --prism-builtin: #ab5959; 27 | --prism-property: #b58451; 28 | --prism-namespace: #b05a78; 29 | --prism-punctuation: #8e8f8b; 30 | --prism-decorator: #bd8f8f; 31 | --prism-regex: #ab5e3f; 32 | --prism-json-property: #698c96; 33 | } 34 | 35 | html.dark .prose { 36 | --prism-foreground: #d4cfbf; 37 | --prism-background: #151515; 38 | --prism-background-color: #151515; 39 | --prism-comment: #758575; 40 | --prism-string: #d48372; 41 | --prism-literal: #429988; 42 | --prism-keyword: #4d9375; 43 | --prism-boolean: #1c6b48; 44 | --prism-number: #6394bf; 45 | --prism-variable: #c2b36e; 46 | --prism-function: #a1b567; 47 | --prism-deleted: #a14f55; 48 | --prism-class: #54b1bf; 49 | --prism-builtin: #e0a569; 50 | --prism-property: #dd8e6e; 51 | --prism-namespace: #db889a; 52 | --prism-punctuation: #858585; 53 | --prism-decorator: #bd8f8f; 54 | --prism-regex: #ab5e3f; 55 | --prism-json-property: #6b8b9e; 56 | --prism-line-number: #888888; 57 | --prism-line-number-gutter: #eeeeee; 58 | --prism-line-highlight-background: #444444; 59 | --prism-selection-background: #444444; 60 | } 61 | -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig, loadEnv } from 'vite'; 2 | import { resolve } from 'path'; 3 | import presets from './presets/presets'; 4 | 5 | // https://vitejs.dev/config/ 6 | export default defineConfig((env) => { 7 | // env 环境变量 8 | const viteEnv = loadEnv(env.mode, process.cwd()); 9 | 10 | return { 11 | base: viteEnv.VITE_BASE, 12 | // 插件 13 | plugins: [presets(env)], 14 | // 别名设置 15 | resolve: { 16 | alias: { 17 | '@': resolve(__dirname, './src'), // 把 @ 指向到 src 目录去 18 | }, 19 | }, 20 | // 服务设置 21 | server: { 22 | host: true, // host设置为true才可以使用network的形式,以ip访问项目 23 | port: 8080, // 端口号 24 | open: true, // 自动打开浏览器 25 | cors: true, // 跨域设置允许 26 | strictPort: true, // 如果端口已占用直接退出 27 | // 接口代理 28 | proxy: { 29 | '/api': { 30 | // 本地 8000 前端代码的接口 代理到 8888 的服务端口 31 | target: 'http://localhost:8888/', 32 | changeOrigin: true, // 允许跨域 33 | rewrite: (path) => path.replace('/api/', '/'), 34 | }, 35 | }, 36 | }, 37 | build: { 38 | reportCompressedSize: false, 39 | // 消除打包大小超过500kb警告 40 | chunkSizeWarningLimit: 2000, 41 | minify: 'esbuild', 42 | assetsDir: 'static/assets', 43 | // 静态资源打包到dist下的不同目录 44 | rollupOptions: { 45 | output: { 46 | chunkFileNames: 'static/js/[name]-[hash].js', 47 | entryFileNames: 'static/js/[name]-[hash].js', 48 | assetFileNames: 'static/[ext]/[name]-[hash].[ext]', 49 | }, 50 | }, 51 | }, 52 | css: { 53 | preprocessorOptions: { 54 | // 全局引入了 scss 的文件 55 | scss: { 56 | additionalData: ` 57 | @import "@/assets/styles/variables.scss"; 58 | `, 59 | javascriptEnabled: true, 60 | }, 61 | }, 62 | }, 63 | }; 64 | }); 65 | -------------------------------------------------------------------------------- /src/assets/styles/nprogress.scss: -------------------------------------------------------------------------------- 1 | /* Make clicks pass-through */ 2 | #nprogress { 3 | pointer-events: none; 4 | } 5 | 6 | #nprogress .bar { 7 | background: $theme-color; 8 | 9 | position: fixed; 10 | z-index: 1031; 11 | top: 0; 12 | left: 0; 13 | 14 | width: 100%; 15 | height: 2px; 16 | } 17 | 18 | /* Fancy blur effect */ 19 | #nprogress .peg { 20 | display: block; 21 | position: absolute; 22 | right: 0px; 23 | width: 100px; 24 | height: 100%; 25 | box-shadow: 0 0 10px $theme-color, 0 0 5px $theme-color; 26 | opacity: 1.0; 27 | 28 | -webkit-transform: rotate(3deg) translate(0px, -4px); 29 | -ms-transform: rotate(3deg) translate(0px, -4px); 30 | transform: rotate(3deg) translate(0px, -4px); 31 | } 32 | 33 | /* Remove these to get rid of the spinner */ 34 | #nprogress .spinner { 35 | display: block; 36 | position: fixed; 37 | z-index: 1031; 38 | top: 15px; 39 | right: 15px; 40 | } 41 | 42 | #nprogress .spinner-icon { 43 | width: 18px; 44 | height: 18px; 45 | box-sizing: border-box; 46 | 47 | border: solid 2px transparent; 48 | border-top-color: $theme-color; 49 | border-left-color: $theme-color; 50 | border-radius: 50%; 51 | 52 | -webkit-animation: nprogress-spinner 400ms linear infinite; 53 | animation: nprogress-spinner 400ms linear infinite; 54 | } 55 | 56 | .nprogress-custom-parent { 57 | overflow: hidden; 58 | position: relative; 59 | } 60 | 61 | .nprogress-custom-parent #nprogress .spinner, 62 | .nprogress-custom-parent #nprogress .bar { 63 | position: absolute; 64 | } 65 | 66 | @-webkit-keyframes nprogress-spinner { 67 | 0% { 68 | -webkit-transform: rotate(0deg); 69 | } 70 | 71 | 100% { 72 | -webkit-transform: rotate(360deg); 73 | } 74 | } 75 | 76 | @keyframes nprogress-spinner { 77 | 0% { 78 | transform: rotate(0deg); 79 | } 80 | 81 | 100% { 82 | transform: rotate(360deg); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/components/TheFooter.vue: -------------------------------------------------------------------------------- 1 | 41 | 42 | 51 | 52 | 57 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vitecamp", 3 | "version": "0.0.0", 4 | "author": "菜猫子neko", 5 | "packageManager": "pnpm@7.9.0", 6 | "license": "MIT", 7 | "scripts": { 8 | "dev": "vite", 9 | "build": "vue-tsc --noEmit --skipLibCheck && vite build", 10 | "lint": "eslint src", 11 | "preview": "vite preview", 12 | "prepare": "husky install" 13 | }, 14 | "dependencies": { 15 | "@vueuse/core": "^8.9.2", 16 | "axios": "^0.25.0", 17 | "element-plus": "^2.0.1", 18 | "nprogress": "^0.2.0", 19 | "pinia": "^2.0.16", 20 | "prism-theme-vars": "^0.2.4", 21 | "vue": "^3.2.25", 22 | "vue-i18n": "^9.1.9", 23 | "vue-router": "^4.1.2" 24 | }, 25 | "devDependencies": { 26 | "@commitlint/cli": "^16.1.0", 27 | "@commitlint/config-conventional": "^16.0.0", 28 | "@iconify/json": "^2.0.29", 29 | "@intlify/vite-plugin-vue-i18n": "^6.0.0", 30 | "@types/node": "^17.0.10", 31 | "@types/nprogress": "^0.2.0", 32 | "@types/svgo": "^2.6.1", 33 | "@typescript-eslint/eslint-plugin": "^5.10.0", 34 | "@typescript-eslint/parser": "^5.10.0", 35 | "@vitejs/plugin-vue": "^3.0.1", 36 | "@vitejs/plugin-vue-jsx": "2.0.0", 37 | "eslint": "^8.19.0", 38 | "eslint-config-airbnb-base": "^15.0.0", 39 | "eslint-config-prettier": "^8.3.0", 40 | "eslint-plugin-import": "^2.25.4", 41 | "eslint-plugin-prettier": "^4.0.0", 42 | "eslint-plugin-vue": "^8.3.0", 43 | "husky": "^7.0.4", 44 | "lint-staged": "^12.3.2", 45 | "markdown-it-link-attributes": "^4.0.0", 46 | "markdown-it-prism": "^2.2.2", 47 | "pnpm": "^7.9.0", 48 | "prettier": "^2.5.1", 49 | "sass": "^1.49.0", 50 | "typescript": "^4.4.4", 51 | "unplugin-auto-import": "^0.9.2", 52 | "unplugin-icons": "^0.14.8", 53 | "unplugin-vue-components": "^0.21.1", 54 | "vite": "^3.0.5", 55 | "vite-plugin-fonts": "^0.6.0", 56 | "vite-plugin-vue-markdown": "^0.21.1", 57 | "vite-plugin-windicss": "^1.8.7", 58 | "vite-svg-loader": "^3.4.0", 59 | "vue-tsc": "^0.38.4" 60 | }, 61 | "lint-staged": { 62 | "*.{ts,js,vue}": [ 63 | "eslint" 64 | ] 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /public/favicon.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/svg/vitecamp.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/api/http.ts: -------------------------------------------------------------------------------- 1 | import axios, { AxiosError, AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'; 2 | import showCodeMessage from '@/api/code'; 3 | import { formatJsonToUrlParams, instanceObject } from '@/utils/format'; 4 | 5 | const BASE_PREFIX = import.meta.env.VITE_API_BASEURL; 6 | 7 | // 创建实例 8 | const axiosInstance: AxiosInstance = axios.create({ 9 | // 前缀 10 | baseURL: BASE_PREFIX, 11 | // 超时 12 | timeout: 1000 * 30, 13 | // 请求头 14 | headers: { 15 | 'Content-Type': 'application/json', 16 | }, 17 | }); 18 | 19 | // 请求拦截器 20 | axiosInstance.interceptors.request.use( 21 | (config: AxiosRequestConfig) => { 22 | // TODO 在这里可以加上想要在请求发送前处理的逻辑 23 | // TODO 比如 loading 等 24 | return config; 25 | }, 26 | (error: AxiosError) => { 27 | return Promise.reject(error); 28 | }, 29 | ); 30 | 31 | // 响应拦截器 32 | axiosInstance.interceptors.response.use( 33 | (response: AxiosResponse) => { 34 | if (response.status === 200) { 35 | return response.data; 36 | } 37 | ElMessage.info(JSON.stringify(response.status)); 38 | return response; 39 | }, 40 | (error: AxiosError) => { 41 | const { response } = error; 42 | if (response) { 43 | ElMessage.error(showCodeMessage(response.status)); 44 | return Promise.reject(response.data); 45 | } 46 | ElMessage.warning('网络连接异常,请稍后再试!'); 47 | return Promise.reject(error); 48 | }, 49 | ); 50 | const service = { 51 | get(url: string, data?: object): Promise { 52 | return axiosInstance.get(url, { params: data }); 53 | }, 54 | 55 | post(url: string, data?: object): Promise { 56 | return axiosInstance.post(url, data); 57 | }, 58 | 59 | put(url: string, data?: object): Promise { 60 | return axiosInstance.put(url, data); 61 | }, 62 | 63 | delete(url: string, data?: object): Promise { 64 | return axiosInstance.delete(url, data); 65 | }, 66 | 67 | upload: (url: string, file: FormData | File) => 68 | axiosInstance.post(url, file, { 69 | headers: { 'Content-Type': 'multipart/form-data' }, 70 | }), 71 | download: (url: string, data: instanceObject) => { 72 | window.location.href = `${BASE_PREFIX}/${url}?${formatJsonToUrlParams(data)}`; 73 | }, 74 | }; 75 | 76 | export default service; 77 | -------------------------------------------------------------------------------- /presets/presets.ts: -------------------------------------------------------------------------------- 1 | import vue from '@vitejs/plugin-vue'; 2 | import vueJsx from '@vitejs/plugin-vue-jsx'; 3 | import svgLoader from 'vite-svg-loader'; 4 | import AutoImport from 'unplugin-auto-import/vite'; 5 | import Components from 'unplugin-vue-components/vite'; 6 | import Icons from 'unplugin-icons/vite'; 7 | import IconsResolver from 'unplugin-icons/resolver'; 8 | import { ElementPlusResolver, VueUseComponentsResolver } from 'unplugin-vue-components/resolvers'; 9 | import WindiCSS from 'vite-plugin-windicss'; 10 | import Markdown from 'vite-plugin-vue-markdown' 11 | import Prism from 'markdown-it-prism'; 12 | import ViteFonts from 'vite-plugin-fonts'; 13 | import VueI18n from '@intlify/vite-plugin-vue-i18n'; 14 | import LinkAttributes from 'markdown-it-link-attributes'; 15 | import { ConfigEnv } from 'vite'; 16 | import { resolve } from 'path'; 17 | 18 | const defaultClasses = 'prose prose-sm m-auto text-left'; 19 | 20 | export default (env: ConfigEnv) => { 21 | return [ 22 | vue({ 23 | include: [/\.vue$/, /\.md$/], 24 | }), 25 | vueJsx(), 26 | svgLoader(), 27 | AutoImport({ 28 | dts: './src/auto-imports.d.ts', 29 | imports: ['vue', 'pinia', 'vue-router', 'vue-i18n', , '@vueuse/core'], 30 | // Generate corresponding .eslintrc-auto-import.json file. 31 | // eslint globals Docs - https://eslint.org/docs/user-guide/configuring/language-options#specifying-globals 32 | eslintrc: { 33 | enabled: false, // Default `false` 34 | filepath: './.eslintrc-auto-import.json', // Default `./.eslintrc-auto-import.json` 35 | globalsPropValue: true, // Default `true`, (true | false | 'readonly' | 'readable' | 'writable' | 'writeable') 36 | }, 37 | resolvers: [ElementPlusResolver()], 38 | }), 39 | Components({ 40 | dts: './src/components.d.ts', 41 | extensions: ['vue', 'md'], 42 | include: [/\.vue$/, /\.vue\?vue/, /\.md$/], 43 | // imports 指定组件所在位置,默认为 src/components; 有需要也可以加上 view 目录 44 | dirs: ['src/components/'], 45 | resolvers: [ElementPlusResolver(), IconsResolver(), VueUseComponentsResolver()], 46 | }), 47 | Icons({ 48 | compiler: 'vue3', 49 | autoInstall: true, 50 | }), 51 | ViteFonts({ 52 | google: { 53 | families: ['Open Sans', 'Montserrat', 'Fira Sans'], 54 | }, 55 | }), 56 | VueI18n({ 57 | include: [resolve(__dirname, '../locales/**')], 58 | }), 59 | WindiCSS({ 60 | safelist: defaultClasses, 61 | }), 62 | Markdown({ 63 | wrapperClasses: defaultClasses, 64 | headEnabled: false, 65 | markdownItSetup(md) { 66 | // https://prismjs.com/ 67 | md.use(Prism); 68 | // 为 md 中的所有链接设置为 新页面跳转 69 | md.use(LinkAttributes, { 70 | matcher: (link: string) => /^https?:\/\//.test(link), 71 | attrs: { 72 | target: '_blank', 73 | rel: 'noopener', 74 | }, 75 | }); 76 | }, 77 | }), 78 | ]; 79 | }; 80 | -------------------------------------------------------------------------------- /src/views/home/index.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 105 | 106 | 111 | -------------------------------------------------------------------------------- /README.zh-CN.md: -------------------------------------------------------------------------------- 1 |
2 | 3 |

4 | 在线 Demo 5 |

6 | 7 |
8 | 9 |

10 | English | 简体中文 11 |

12 | 13 |
14 | 15 | ## 特性 16 | 17 | - ⚡️ [Vue 3](https://github.com/vuejs/core), [Vite 3](https://github.com/vitejs/vite), [pnpm](https://pnpm.io/), [ESBuild](https://github.com/evanw/esbuild) - 快,且更快! 18 | - 💪 [Typescript](https://www.typescriptlang.org/) - 当然!必不可少 19 | - 🎉 [Element Plus 开箱即用](https://github.com/element-plus/element-plus) - 基于 Vue.js 3 的强大 UI 库 20 | - 🔥 [Axios 配置和封装](https://github.com/axios/axios) - 基于 Promise 的 HTTP 请求库 21 | - 💡 [Vue Router 4](https://router.vuejs.org/zh/) - Vuejs 的官方路由 22 | - 📦 [组件自动按需加载](https://github.com/antfu/unplugin-vue-components) - 自动按需注册组件, 无需 import 23 | - 📥 [API 自动按需加载](https://github.com/antfu/unplugin-auto-import) - 无需手动 import 进行引入 24 | - 🍍 [Pinia 状态管理](https://pinia.esm.dev/) - 你将会喜欢上的 Vue Store 25 | - 🎨 [Windi CSS](https://github.com/windicss/windicss) - 下一代实用的原子 css 框架 26 | - 😃 [icones](https://github.com/antfu/unplugin-icons) - 强大的图标库,各种图标集为你所用 27 | - 🌍 [I18n 国际化开箱即用](./locales) - 想要翻译?是的,都可以! 28 | - 👩‍🎨 [NProgress](https://github.com/rstacruz/nprogress) - 页面加载进度反馈 29 | - 😃 [SVG 支持](https://github.com/jpkleemans/vite-svg-loader) - 支持以 组件形式使用 SVG 图片 30 | - 📑 [Markdown 支持](https://github.com/antfu/vite-plugin-md) - 随意的在页面中嵌入 Markdown 31 | - 🔑 完整支持的代码风格规范和代码提交规范 32 | - ☁️ 支持零配置部署 Netlify 33 | 34 | ## 已配置 35 | 36 | ### UI 框架 37 | 38 | - [Windi CSS](https://github.com/windicss/windicss) (按需的 [TailwindCSS](https://tailwindcss.com/)) - 更轻,更快和和一系列额外的特性! 39 | - [Windi CSS Typography](https://windicss.org/plugins/official/typography.html) 40 | - [Element Plus](https://github.com/element-plus/element-plus) - 基于 Vue.js 3 的强大 UI 库 41 | 42 | ### Icons 43 | 44 | - [🔍Icônes](https://icones.netlify.app/) - 使用任意的图标集 45 | - [unplugin-icons](https://github.com/antfu/unplugin-icons) - 自动按需引入你所需要的图标! 46 | 47 | ### 插件 48 | 49 | - [Vue Router 4](https://router.vuejs.org/zh/) - Vuejs 的官方路由 50 | - [Pinia](https://pinia.esm.dev) - 新一代的 Vue Store 状态管理 51 | - [Axios](https://github.com/axios/axios) - 基于 Promise 的 HTTP 请求库 52 | - [unplugin-vue-components](https://github.com/antfu/unplugin-vue-components) - 自动按需加载组件 53 | - [unplugin-auto-import](https://github.com/antfu/unplugin-auto-import) - 自动按需加载 API 54 | - [vite-plugin-windicss](https://github.com/antfu/vite-plugin-windicss) - Windi CSS 的整合 55 | - [vite-plugin-vue-markdown](https://github.com/antfu/vite-plugin-vue-markdown) - Markdown 作为组件,也可以让组件在 Markdown 中使用 56 | - [markdown-it-prism](https://github.com/jGleitz/markdown-it-prism) - [Prism](https://prismjs.com/) 的语法高亮 57 | - [prism-theme-vars](https://github.com/antfu/prism-theme-vars) - 利用 CSS 变量自定义 Prism.js 的主题 58 | - [markdown-it-link-attributes](https://github.com/crookedneighbor/markdown-it-link-attributes) - 统一设置 Markdown 里的超链接跳转方式 59 | - [Vue I18n](https://github.com/intlify/vue-i18n-next) - 国际化 60 | - [vite-plugin-vue-i18n](https://github.com/intlify/vite-plugin-vue-i18n) - Vue I18n 的 Vite 插件 61 | - [vite-plugin-fonts](https://github.com/stafyniaksacha/vite-plugin-fonts) - Vite 的字体加载器 62 | - [VueUse](https://github.com/antfu/vueuse) - 实用的 Composition API 工具合集 63 | - [vite-svg-loader](https://github.com/jpkleemans/vite-svg-loader) - 支持以 组件形式使用 SVG 图片 64 | 65 | ### 编码风格 66 | 67 | - [ESLint](https://eslint.org/) 配置为 [Airbnb Style](https://github.com/airbnb/javascript) 68 | 69 | ### 开发工具 70 | 71 | - [TypeScript](https://www.typescriptlang.org/) 72 | - [Netlify](https://www.netlify.com/) - 零配置的部署 73 | - [VS Code 扩展](./.vscode/extensions.json) 74 | - [Volar](https://marketplace.visualstudio.com/items?itemName=johnsoncodehk.volar) - Vue 3 IDE 支持 75 | - [Iconify IntelliSense](https://marketplace.visualstudio.com/items?itemName=antfu.iconify) - 图标内联显示和自动补全 76 | - [i18n Ally](https://marketplace.visualstudio.com/items?itemName=lokalise.i18n-ally) - 多合一的 I18n 支持 77 | - [Windi CSS 智能感知](https://marketplace.visualstudio.com/items?itemName=voorjaar.windicss-intellisense) - Windi CSS 的 IDE 支持 78 | - [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) - 代码质量和规则检查 79 | - [Prettier - Code formatter](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode) - 专注于代码格式化、美化代码 80 | - [EditorConfig for VS Code](https://marketplace.visualstudio.com/items?itemName=EditorConfig.EditorConfig) - 编码风格检查 81 | 82 | ## 现在可以试试! 83 | 84 | ### GitHub 模板 85 | 86 | [使用这个模板创建仓库](https://github.com/nekobc1998923/vitecamp/generate). 87 | 88 | ### 克隆到本地 89 | 90 | ```bash 91 | git clone https://github.com/nekobc1998923/vitecamp.git my-vitecamp-app 92 | cd my-vitecamp-app 93 | pnpm i 94 | ``` 95 | 96 | ## 清单 97 | 98 | 使用此模板时,请尝试按照清单正确更新你自己的信息 99 | 100 | - [ ] 在 `LICENSE` 中改变作者名 101 | - [ ] 在 `package.json` 中改变作者名 102 | - [ ] 在 `.env` 中改变标题 103 | - [ ] 在 `public` 目录下改变 favicon 104 | - [ ] 整理 `README `并删除路由 105 | 106 | 然后,你就可以享受编写代码的乐趣了 :) 107 | 108 | ## 使用 109 | 110 | ### 开发 111 | 112 | 只需要执行以下命令就可以在 http://localhost:8080 中看到 113 | 114 | ```bash 115 | pnpm run dev 116 | ``` 117 | 118 | ### 构建 119 | 120 | 构建该应用只需要执行以下命令 121 | 122 | ```bash 123 | pnpm run build 124 | ``` 125 | 126 | 然后你会看到用于发布的 `dist` 文件夹被生成。 127 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 |

4 | Live Demo 5 |

6 | 7 |
8 | 9 |

10 | English | 简体中文 11 |

12 | 13 |
14 | 15 | ## Features 16 | 17 | - ⚡️ [Vue 3](https://github.com/vuejs/core), [Vite 3](https://github.com/vitejs/vite), [pnpm](https://pnpm.io/), [ESBuild](https://github.com/evanw/esbuild) - fast and faster ! 18 | - 💪 [Typescript](https://www.typescriptlang.org/) - of course! necessary 19 | - 🎉 [Element Plus ready](https://github.com/element-plus/element-plus) - UI Library based on Vue.js 3 20 | - 🔥 [Axios](https://github.com/axios/axios) - Http Library based on Promise 21 | - 💡 [Vue Router 4](https://router.vuejs.org/zh/) - The official router for Vue.js 22 | - 📦 [Components auto importing](https://github.com/antfu/unplugin-vue-components) - Automatically register components on demand without import 23 | - 📥 [Auto import APIs](https://github.com/antfu/unplugin-auto-import) - Automatically import APIs 24 | - 🍍 [State Management via Pinia](https://pinia.esm.dev/) - The Vue Store that you will enjoy using 25 | - 🎨 [Windi CSS](https://github.com/windicss/windicss) - next generation utility-first CSS framework 26 | - 😃 [icones](https://github.com/antfu/unplugin-icons) - Powerful Icon Library, Use icons from any icon sets 27 | - 🌍 [I18n ready](./locales) - Want to translate? Yes, you can! 28 | - 👩‍🎨 [NProgress](https://github.com/rstacruz/nprogress) - Page loading progress feedback 29 | - 😃 [SVG Support](https://github.com/jpkleemans/vite-svg-loader) - Support the use of SVG images as components 30 | - 📑 [Markdown Support](https://github.com/antfu/vite-plugin-md) - Markdown as components / components in Markdown 31 | - 🔑 Complete code style specification and code submission specification 32 | - ☁️ Deploy on Netlify, zero-config 33 | 34 | ## Pre-packed 35 | 36 | ### UI Frameworks 37 | 38 | - [Windi CSS](https://github.com/windicss/windicss) (On-demand [TailwindCSS](https://tailwindcss.com/)) - lighter and faster, with a bunch of additional features 39 | - [Windi CSS Typography](https://windicss.org/plugins/official/typography.html) 40 | - [Element Plus](https://github.com/element-plus/element-plus) - A powerful Vue.js 3 UI Library 41 | 42 | ### Icons 43 | 44 | - [🔍Icônes](https://icones.netlify.app/) - use icons from any icon sets 45 | - [unplugin-icons](https://github.com/antfu/unplugin-icons) - Automatically introduce the icons you need on demand 46 | 47 | ### Plugins 48 | 49 | - [Vue Router 4](https://router.vuejs.org/zh/) - The official router for Vue.js 50 | - [Pinia](https://pinia.esm.dev) - The Vue Store that you will enjoy using 51 | - [Axios](https://github.com/axios/axios) - Http Library based on Promise 52 | - [unplugin-vue-components](https://github.com/antfu/unplugin-vue-components) - components auto import 53 | - [unplugin-auto-import](https://github.com/antfu/unplugin-auto-import) - Automatically import APIs 54 | - [vite-plugin-windicss](https://github.com/antfu/vite-plugin-windicss) - Windi CSS Integration 55 | - [vite-plugin-vue-markdown](https://github.com/antfu/vite-plugin-vue-markdown) - Markdown as components / components in Markdown 56 | - [markdown-it-prism](https://github.com/jGleitz/markdown-it-prism) - [Prism](https://prismjs.com/) for syntax highlighting 57 | - [prism-theme-vars](https://github.com/antfu/prism-theme-vars) - customizable Prism.js theme using CSS variables 58 | - [markdown-it-link-attributes](https://github.com/crookedneighbor/markdown-it-link-attributes) - Uniformly set the hyperlink jump mode in markdown 59 | - [Vue I18n](https://github.com/intlify/vue-i18n-next) - Internationalization 60 | - [vite-plugin-vue-i18n](https://github.com/intlify/vite-plugin-vue-i18n) - Vite plugin for Vue I18n 61 | - [vite-plugin-fonts](https://github.com/stafyniaksacha/vite-plugin-fonts) - Vite's font loader 62 | - [VueUse](https://github.com/antfu/vueuse) - Collection of useful composition APIs 63 | - [vite-svg-loader](https://github.com/jpkleemans/vite-svg-loader) - Support the use of SVG images as components 64 | 65 | ### Coding Style 66 | 67 | - [ESLint](https://eslint.org/) with [Airbnb Style](https://github.com/airbnb/javascript) 68 | 69 | ### Dev tools 70 | 71 | - [TypeScript](https://www.typescriptlang.org/) 72 | - [Netlify](https://www.netlify.com/) - zero-config deployment 73 | - [VS Code Extensions](./.vscode/extensions.json) 74 | - [Volar](https://marketplace.visualstudio.com/items?itemName=johnsoncodehk.volar) -Vue 3 IDE support 75 | - [Iconify IntelliSense](https://marketplace.visualstudio.com/items?itemName=antfu.iconify) - Icon inline display and autocomplete 76 | - [i18n Ally](https://marketplace.visualstudio.com/items?itemName=lokalise.i18n-ally) - All in one i18n support 77 | - [Windi CSS Intellisense](https://marketplace.visualstudio.com/items?itemName=voorjaar.windicss-intellisense) - IDE support for Windi CSS 78 | - [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) - Code quality and rule checking 79 | - [Prettier - Code formatter](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode) - Focus on code formatting and beautifying code 80 | - [EditorConfig for VS Code](https://marketplace.visualstudio.com/items?itemName=EditorConfig.EditorConfig) - Coding style check 81 | 82 | ## Try it now! 83 | 84 | ### GitHub Template 85 | 86 | [Create a repo from this template on GitHub](https://github.com/nekobc1998923/vitecamp/generate). 87 | 88 | ### Clone to local 89 | 90 | ```bash 91 | git clone https://github.com/nekobc1998923/vitecamp.git my-vitecamp-app 92 | cd my-vitecamp-app 93 | pnpm i 94 | ``` 95 | 96 | ## Checklist 97 | 98 | When you use this template, try follow the checklist to update your info properly 99 | 100 | - [ ] Change the author name in `LICENSE` 101 | - [ ] Change the author name in `package.json` 102 | - [ ] Change the title in `.env` 103 | - [ ] Change the favicon in `public` 104 | - [ ] Clean up the `README` and remove routes 105 | 106 | And then , you can enjoy coding fun :) 107 | 108 | ## Usage 109 | 110 | ### Development 111 | 112 | Just run and visit http://localhost:8080 113 | 114 | ```bash 115 | pnpm run dev 116 | ``` 117 | 118 | ### Build 119 | 120 | To build the App, run 121 | 122 | ```bash 123 | pnpm run build 124 | ``` 125 | 126 | And you will see the generated file in `dist` that ready to be served. 127 | 128 | ## Thanks 129 | 130 | This template has some features inspired by [Vitesse](https://github.com/antfu/vitesse) ❤ 131 | -------------------------------------------------------------------------------- /.eslintrc-auto-import.json: -------------------------------------------------------------------------------- 1 | { 2 | "globals": { 3 | "acceptHMRUpdate": true, 4 | "asyncComputed": true, 5 | "autoResetRef": true, 6 | "biSyncRef": true, 7 | "computed": true, 8 | "computedInject": true, 9 | "controlledComputed": true, 10 | "controlledRef": true, 11 | "createApp": true, 12 | "createEventHook": true, 13 | "createGlobalState": true, 14 | "createPinia": true, 15 | "createReactiveFn": true, 16 | "createSharedComposable": true, 17 | "createUnrefFn": true, 18 | "customRef": true, 19 | "debouncedRef": true, 20 | "debouncedWatch": true, 21 | "defineAsyncComponent": true, 22 | "defineComponent": true, 23 | "defineStore": true, 24 | "eagerComputed": true, 25 | "effectScope": true, 26 | "EffectScope": true, 27 | "ElMessage": true, 28 | "ElNotification": true, 29 | "extendRef": true, 30 | "getActivePinia": true, 31 | "getCurrentInstance": true, 32 | "getCurrentScope": true, 33 | "h": true, 34 | "ignorableWatch": true, 35 | "inject": true, 36 | "isDefined": true, 37 | "isReadonly": true, 38 | "isRef": true, 39 | "makeDestructurable": true, 40 | "mapActions": true, 41 | "mapGetters": true, 42 | "mapState": true, 43 | "mapStores": true, 44 | "mapWritableState": true, 45 | "markRaw": true, 46 | "nextTick": true, 47 | "onActivated": true, 48 | "onBeforeMount": true, 49 | "onBeforeUnmount": true, 50 | "onBeforeUpdate": true, 51 | "onClickOutside": true, 52 | "onDeactivated": true, 53 | "onErrorCaptured": true, 54 | "onKeyStroke": true, 55 | "onLongPress": true, 56 | "onMounted": true, 57 | "onRenderTracked": true, 58 | "onRenderTriggered": true, 59 | "onScopeDispose": true, 60 | "onServerPrefetch": true, 61 | "onStartTyping": true, 62 | "onUnmounted": true, 63 | "onUpdated": true, 64 | "pausableWatch": true, 65 | "provide": true, 66 | "reactify": true, 67 | "reactifyObject": true, 68 | "reactive": true, 69 | "reactiveComputed": true, 70 | "reactiveOmit": true, 71 | "reactivePick": true, 72 | "readonly": true, 73 | "ref": true, 74 | "refDefault": true, 75 | "resolveComponent": true, 76 | "setActivePinia": true, 77 | "setMapStoreSuffix": true, 78 | "shallowReactive": true, 79 | "shallowReadonly": true, 80 | "shallowRef": true, 81 | "storeToRefs": true, 82 | "syncRef": true, 83 | "templateRef": true, 84 | "throttledRef": true, 85 | "throttledWatch": true, 86 | "toRaw": true, 87 | "toReactive": true, 88 | "toRef": true, 89 | "toRefs": true, 90 | "triggerRef": true, 91 | "tryOnBeforeUnmount": true, 92 | "tryOnMounted": true, 93 | "tryOnScopeDispose": true, 94 | "tryOnUnmounted": true, 95 | "unref": true, 96 | "unrefElement": true, 97 | "until": true, 98 | "useActiveElement": true, 99 | "useAsyncQueue": true, 100 | "useAsyncState": true, 101 | "useAttrs": true, 102 | "useBase64": true, 103 | "useBattery": true, 104 | "useBreakpoints": true, 105 | "useBroadcastChannel": true, 106 | "useBrowserLocation": true, 107 | "useCached": true, 108 | "useClamp": true, 109 | "useClipboard": true, 110 | "useColorMode": true, 111 | "useConfirmDialog": true, 112 | "useCounter": true, 113 | "useCssModule": true, 114 | "useCssVar": true, 115 | "useCssVars": true, 116 | "useCycleList": true, 117 | "useDark": true, 118 | "useDebounce": true, 119 | "useDebouncedRefHistory": true, 120 | "useDebounceFn": true, 121 | "useDeviceMotion": true, 122 | "useDeviceOrientation": true, 123 | "useDevicePixelRatio": true, 124 | "useDevicesList": true, 125 | "useDisplayMedia": true, 126 | "useDocumentVisibility": true, 127 | "useDraggable": true, 128 | "useElementBounding": true, 129 | "useElementByPoint": true, 130 | "useElementHover": true, 131 | "useElementSize": true, 132 | "useElementVisibility": true, 133 | "useEventBus": true, 134 | "useEventListener": true, 135 | "useEventSource": true, 136 | "useEyeDropper": true, 137 | "useFavicon": true, 138 | "useFetch": true, 139 | "useFocus": true, 140 | "useFocusWithin": true, 141 | "useFps": true, 142 | "useFullscreen": true, 143 | "useGeolocation": true, 144 | "useI18n": true, 145 | "useIdle": true, 146 | "useInfiniteScroll": true, 147 | "useIntersectionObserver": true, 148 | "useInterval": true, 149 | "useIntervalFn": true, 150 | "useKeyModifier": true, 151 | "useLastChanged": true, 152 | "useLocalStorage": true, 153 | "useMagicKeys": true, 154 | "useManualRefHistory": true, 155 | "useMediaControls": true, 156 | "useMediaQuery": true, 157 | "useMemoize": true, 158 | "useMemory": true, 159 | "useMounted": true, 160 | "useMouse": true, 161 | "useMouseInElement": true, 162 | "useMousePressed": true, 163 | "useMutationObserver": true, 164 | "useNavigatorLanguage": true, 165 | "useNetwork": true, 166 | "useNow": true, 167 | "useOffsetPagination": true, 168 | "useOnline": true, 169 | "usePageLeave": true, 170 | "useParallax": true, 171 | "usePermission": true, 172 | "usePointer": true, 173 | "usePointerSwipe": true, 174 | "usePreferredColorScheme": true, 175 | "usePreferredDark": true, 176 | "usePreferredLanguages": true, 177 | "useRafFn": true, 178 | "useRefHistory": true, 179 | "useResizeObserver": true, 180 | "useRoute": true, 181 | "useRouter": true, 182 | "useScreenSafeArea": true, 183 | "useScriptTag": true, 184 | "useScroll": true, 185 | "useScrollLock": true, 186 | "useSessionStorage": true, 187 | "useShare": true, 188 | "useSlots": true, 189 | "useSpeechRecognition": true, 190 | "useSpeechSynthesis": true, 191 | "useStorage": true, 192 | "useStorageAsync": true, 193 | "useStyleTag": true, 194 | "useSwipe": true, 195 | "useTemplateRefsList": true, 196 | "useTextSelection": true, 197 | "useThrottle": true, 198 | "useThrottledRefHistory": true, 199 | "useThrottleFn": true, 200 | "useTimeAgo": true, 201 | "useTimeout": true, 202 | "useTimeoutFn": true, 203 | "useTimestamp": true, 204 | "useTitle": true, 205 | "useToggle": true, 206 | "useTransition": true, 207 | "useUrlSearchParams": true, 208 | "useUserMedia": true, 209 | "useVibrate": true, 210 | "useVirtualList": true, 211 | "useVModel": true, 212 | "useVModels": true, 213 | "useWakeLock": true, 214 | "useWebNotification": true, 215 | "useWebSocket": true, 216 | "useWebWorker": true, 217 | "useWebWorkerFn": true, 218 | "useWindowFocus": true, 219 | "useWindowScroll": true, 220 | "useWindowSize": true, 221 | "watch": true, 222 | "watchAtMost": true, 223 | "watchEffect": true, 224 | "watchOnce": true, 225 | "watchWithFilter": true, 226 | "whenever": true 227 | } 228 | } -------------------------------------------------------------------------------- /src/auto-imports.d.ts: -------------------------------------------------------------------------------- 1 | // Generated by 'unplugin-auto-import' 2 | export {} 3 | declare global { 4 | const EffectScope: typeof import('vue')['EffectScope'] 5 | const ElMessage: typeof import('element-plus/es')['ElMessage'] 6 | const ElNotification: typeof import('element-plus/es')['ElNotification'] 7 | const acceptHMRUpdate: typeof import('pinia')['acceptHMRUpdate'] 8 | const asyncComputed: typeof import('@vueuse/core')['asyncComputed'] 9 | const autoResetRef: typeof import('@vueuse/core')['autoResetRef'] 10 | const computed: typeof import('vue')['computed'] 11 | const computedAsync: typeof import('@vueuse/core')['computedAsync'] 12 | const computedEager: typeof import('@vueuse/core')['computedEager'] 13 | const computedInject: typeof import('@vueuse/core')['computedInject'] 14 | const computedWithControl: typeof import('@vueuse/core')['computedWithControl'] 15 | const controlledComputed: typeof import('@vueuse/core')['controlledComputed'] 16 | const controlledRef: typeof import('@vueuse/core')['controlledRef'] 17 | const createApp: typeof import('vue')['createApp'] 18 | const createEventHook: typeof import('@vueuse/core')['createEventHook'] 19 | const createGlobalState: typeof import('@vueuse/core')['createGlobalState'] 20 | const createInjectionState: typeof import('@vueuse/core')['createInjectionState'] 21 | const createPinia: typeof import('pinia')['createPinia'] 22 | const createReactiveFn: typeof import('@vueuse/core')['createReactiveFn'] 23 | const createSharedComposable: typeof import('@vueuse/core')['createSharedComposable'] 24 | const createUnrefFn: typeof import('@vueuse/core')['createUnrefFn'] 25 | const customRef: typeof import('vue')['customRef'] 26 | const debouncedRef: typeof import('@vueuse/core')['debouncedRef'] 27 | const debouncedWatch: typeof import('@vueuse/core')['debouncedWatch'] 28 | const defineAsyncComponent: typeof import('vue')['defineAsyncComponent'] 29 | const defineComponent: typeof import('vue')['defineComponent'] 30 | const defineStore: typeof import('pinia')['defineStore'] 31 | const eagerComputed: typeof import('@vueuse/core')['eagerComputed'] 32 | const effectScope: typeof import('vue')['effectScope'] 33 | const extendRef: typeof import('@vueuse/core')['extendRef'] 34 | const getActivePinia: typeof import('pinia')['getActivePinia'] 35 | const getCurrentInstance: typeof import('vue')['getCurrentInstance'] 36 | const getCurrentScope: typeof import('vue')['getCurrentScope'] 37 | const h: typeof import('vue')['h'] 38 | const ignorableWatch: typeof import('@vueuse/core')['ignorableWatch'] 39 | const inject: typeof import('vue')['inject'] 40 | const isDefined: typeof import('@vueuse/core')['isDefined'] 41 | const isProxy: typeof import('vue')['isProxy'] 42 | const isReactive: typeof import('vue')['isReactive'] 43 | const isReadonly: typeof import('vue')['isReadonly'] 44 | const isRef: typeof import('vue')['isRef'] 45 | const logicAnd: typeof import('@vueuse/core')['logicAnd'] 46 | const logicNot: typeof import('@vueuse/core')['logicNot'] 47 | const logicOr: typeof import('@vueuse/core')['logicOr'] 48 | const makeDestructurable: typeof import('@vueuse/core')['makeDestructurable'] 49 | const mapActions: typeof import('pinia')['mapActions'] 50 | const mapGetters: typeof import('pinia')['mapGetters'] 51 | const mapState: typeof import('pinia')['mapState'] 52 | const mapStores: typeof import('pinia')['mapStores'] 53 | const mapWritableState: typeof import('pinia')['mapWritableState'] 54 | const markRaw: typeof import('vue')['markRaw'] 55 | const nextTick: typeof import('vue')['nextTick'] 56 | const onActivated: typeof import('vue')['onActivated'] 57 | const onBeforeMount: typeof import('vue')['onBeforeMount'] 58 | const onBeforeUnmount: typeof import('vue')['onBeforeUnmount'] 59 | const onBeforeUpdate: typeof import('vue')['onBeforeUpdate'] 60 | const onClickOutside: typeof import('@vueuse/core')['onClickOutside'] 61 | const onDeactivated: typeof import('vue')['onDeactivated'] 62 | const onErrorCaptured: typeof import('vue')['onErrorCaptured'] 63 | const onKeyStroke: typeof import('@vueuse/core')['onKeyStroke'] 64 | const onLongPress: typeof import('@vueuse/core')['onLongPress'] 65 | const onMounted: typeof import('vue')['onMounted'] 66 | const onRenderTracked: typeof import('vue')['onRenderTracked'] 67 | const onRenderTriggered: typeof import('vue')['onRenderTriggered'] 68 | const onScopeDispose: typeof import('vue')['onScopeDispose'] 69 | const onServerPrefetch: typeof import('vue')['onServerPrefetch'] 70 | const onStartTyping: typeof import('@vueuse/core')['onStartTyping'] 71 | const onUnmounted: typeof import('vue')['onUnmounted'] 72 | const onUpdated: typeof import('vue')['onUpdated'] 73 | const pausableWatch: typeof import('@vueuse/core')['pausableWatch'] 74 | const provide: typeof import('vue')['provide'] 75 | const reactify: typeof import('@vueuse/core')['reactify'] 76 | const reactifyObject: typeof import('@vueuse/core')['reactifyObject'] 77 | const reactive: typeof import('vue')['reactive'] 78 | const reactiveComputed: typeof import('@vueuse/core')['reactiveComputed'] 79 | const reactiveOmit: typeof import('@vueuse/core')['reactiveOmit'] 80 | const reactivePick: typeof import('@vueuse/core')['reactivePick'] 81 | const readonly: typeof import('vue')['readonly'] 82 | const ref: typeof import('vue')['ref'] 83 | const refAutoReset: typeof import('@vueuse/core')['refAutoReset'] 84 | const refDebounced: typeof import('@vueuse/core')['refDebounced'] 85 | const refDefault: typeof import('@vueuse/core')['refDefault'] 86 | const refThrottled: typeof import('@vueuse/core')['refThrottled'] 87 | const refWithControl: typeof import('@vueuse/core')['refWithControl'] 88 | const resolveComponent: typeof import('vue')['resolveComponent'] 89 | const resolveRef: typeof import('@vueuse/core')['resolveRef'] 90 | const resolveUnref: typeof import('@vueuse/core')['resolveUnref'] 91 | const setActivePinia: typeof import('pinia')['setActivePinia'] 92 | const setMapStoreSuffix: typeof import('pinia')['setMapStoreSuffix'] 93 | const shallowReactive: typeof import('vue')['shallowReactive'] 94 | const shallowReadonly: typeof import('vue')['shallowReadonly'] 95 | const shallowRef: typeof import('vue')['shallowRef'] 96 | const storeToRefs: typeof import('pinia')['storeToRefs'] 97 | const syncRef: typeof import('@vueuse/core')['syncRef'] 98 | const syncRefs: typeof import('@vueuse/core')['syncRefs'] 99 | const templateRef: typeof import('@vueuse/core')['templateRef'] 100 | const throttledRef: typeof import('@vueuse/core')['throttledRef'] 101 | const throttledWatch: typeof import('@vueuse/core')['throttledWatch'] 102 | const toRaw: typeof import('vue')['toRaw'] 103 | const toReactive: typeof import('@vueuse/core')['toReactive'] 104 | const toRef: typeof import('vue')['toRef'] 105 | const toRefs: typeof import('vue')['toRefs'] 106 | const triggerRef: typeof import('vue')['triggerRef'] 107 | const tryOnBeforeMount: typeof import('@vueuse/core')['tryOnBeforeMount'] 108 | const tryOnBeforeUnmount: typeof import('@vueuse/core')['tryOnBeforeUnmount'] 109 | const tryOnMounted: typeof import('@vueuse/core')['tryOnMounted'] 110 | const tryOnScopeDispose: typeof import('@vueuse/core')['tryOnScopeDispose'] 111 | const tryOnUnmounted: typeof import('@vueuse/core')['tryOnUnmounted'] 112 | const unref: typeof import('vue')['unref'] 113 | const unrefElement: typeof import('@vueuse/core')['unrefElement'] 114 | const until: typeof import('@vueuse/core')['until'] 115 | const useActiveElement: typeof import('@vueuse/core')['useActiveElement'] 116 | const useAsyncQueue: typeof import('@vueuse/core')['useAsyncQueue'] 117 | const useAsyncState: typeof import('@vueuse/core')['useAsyncState'] 118 | const useAttrs: typeof import('vue')['useAttrs'] 119 | const useBase64: typeof import('@vueuse/core')['useBase64'] 120 | const useBattery: typeof import('@vueuse/core')['useBattery'] 121 | const useBluetooth: typeof import('@vueuse/core')['useBluetooth'] 122 | const useBreakpoints: typeof import('@vueuse/core')['useBreakpoints'] 123 | const useBroadcastChannel: typeof import('@vueuse/core')['useBroadcastChannel'] 124 | const useBrowserLocation: typeof import('@vueuse/core')['useBrowserLocation'] 125 | const useCached: typeof import('@vueuse/core')['useCached'] 126 | const useClamp: typeof import('@vueuse/core')['useClamp'] 127 | const useClipboard: typeof import('@vueuse/core')['useClipboard'] 128 | const useColorMode: typeof import('@vueuse/core')['useColorMode'] 129 | const useConfirmDialog: typeof import('@vueuse/core')['useConfirmDialog'] 130 | const useCounter: typeof import('@vueuse/core')['useCounter'] 131 | const useCssModule: typeof import('vue')['useCssModule'] 132 | const useCssVar: typeof import('@vueuse/core')['useCssVar'] 133 | const useCssVars: typeof import('vue')['useCssVars'] 134 | const useCurrentElement: typeof import('@vueuse/core')['useCurrentElement'] 135 | const useCycleList: typeof import('@vueuse/core')['useCycleList'] 136 | const useDark: typeof import('@vueuse/core')['useDark'] 137 | const useDateFormat: typeof import('@vueuse/core')['useDateFormat'] 138 | const useDebounce: typeof import('@vueuse/core')['useDebounce'] 139 | const useDebounceFn: typeof import('@vueuse/core')['useDebounceFn'] 140 | const useDebouncedRefHistory: typeof import('@vueuse/core')['useDebouncedRefHistory'] 141 | const useDeviceMotion: typeof import('@vueuse/core')['useDeviceMotion'] 142 | const useDeviceOrientation: typeof import('@vueuse/core')['useDeviceOrientation'] 143 | const useDevicePixelRatio: typeof import('@vueuse/core')['useDevicePixelRatio'] 144 | const useDevicesList: typeof import('@vueuse/core')['useDevicesList'] 145 | const useDisplayMedia: typeof import('@vueuse/core')['useDisplayMedia'] 146 | const useDocumentVisibility: typeof import('@vueuse/core')['useDocumentVisibility'] 147 | const useDraggable: typeof import('@vueuse/core')['useDraggable'] 148 | const useDropZone: typeof import('@vueuse/core')['useDropZone'] 149 | const useElementBounding: typeof import('@vueuse/core')['useElementBounding'] 150 | const useElementByPoint: typeof import('@vueuse/core')['useElementByPoint'] 151 | const useElementHover: typeof import('@vueuse/core')['useElementHover'] 152 | const useElementSize: typeof import('@vueuse/core')['useElementSize'] 153 | const useElementVisibility: typeof import('@vueuse/core')['useElementVisibility'] 154 | const useEventBus: typeof import('@vueuse/core')['useEventBus'] 155 | const useEventListener: typeof import('@vueuse/core')['useEventListener'] 156 | const useEventSource: typeof import('@vueuse/core')['useEventSource'] 157 | const useEyeDropper: typeof import('@vueuse/core')['useEyeDropper'] 158 | const useFavicon: typeof import('@vueuse/core')['useFavicon'] 159 | const useFetch: typeof import('@vueuse/core')['useFetch'] 160 | const useFileDialog: typeof import('@vueuse/core')['useFileDialog'] 161 | const useFileSystemAccess: typeof import('@vueuse/core')['useFileSystemAccess'] 162 | const useFocus: typeof import('@vueuse/core')['useFocus'] 163 | const useFocusWithin: typeof import('@vueuse/core')['useFocusWithin'] 164 | const useFps: typeof import('@vueuse/core')['useFps'] 165 | const useFullscreen: typeof import('@vueuse/core')['useFullscreen'] 166 | const useGamepad: typeof import('@vueuse/core')['useGamepad'] 167 | const useGeolocation: typeof import('@vueuse/core')['useGeolocation'] 168 | const useI18n: typeof import('vue-i18n')['useI18n'] 169 | const useIdle: typeof import('@vueuse/core')['useIdle'] 170 | const useImage: typeof import('@vueuse/core')['useImage'] 171 | const useInfiniteScroll: typeof import('@vueuse/core')['useInfiniteScroll'] 172 | const useIntersectionObserver: typeof import('@vueuse/core')['useIntersectionObserver'] 173 | const useInterval: typeof import('@vueuse/core')['useInterval'] 174 | const useIntervalFn: typeof import('@vueuse/core')['useIntervalFn'] 175 | const useKeyModifier: typeof import('@vueuse/core')['useKeyModifier'] 176 | const useLastChanged: typeof import('@vueuse/core')['useLastChanged'] 177 | const useLocalStorage: typeof import('@vueuse/core')['useLocalStorage'] 178 | const useMagicKeys: typeof import('@vueuse/core')['useMagicKeys'] 179 | const useManualRefHistory: typeof import('@vueuse/core')['useManualRefHistory'] 180 | const useMediaControls: typeof import('@vueuse/core')['useMediaControls'] 181 | const useMediaQuery: typeof import('@vueuse/core')['useMediaQuery'] 182 | const useMemoize: typeof import('@vueuse/core')['useMemoize'] 183 | const useMemory: typeof import('@vueuse/core')['useMemory'] 184 | const useMounted: typeof import('@vueuse/core')['useMounted'] 185 | const useMouse: typeof import('@vueuse/core')['useMouse'] 186 | const useMouseInElement: typeof import('@vueuse/core')['useMouseInElement'] 187 | const useMousePressed: typeof import('@vueuse/core')['useMousePressed'] 188 | const useMutationObserver: typeof import('@vueuse/core')['useMutationObserver'] 189 | const useNavigatorLanguage: typeof import('@vueuse/core')['useNavigatorLanguage'] 190 | const useNetwork: typeof import('@vueuse/core')['useNetwork'] 191 | const useNow: typeof import('@vueuse/core')['useNow'] 192 | const useObjectUrl: typeof import('@vueuse/core')['useObjectUrl'] 193 | const useOffsetPagination: typeof import('@vueuse/core')['useOffsetPagination'] 194 | const useOnline: typeof import('@vueuse/core')['useOnline'] 195 | const usePageLeave: typeof import('@vueuse/core')['usePageLeave'] 196 | const useParallax: typeof import('@vueuse/core')['useParallax'] 197 | const usePermission: typeof import('@vueuse/core')['usePermission'] 198 | const usePointer: typeof import('@vueuse/core')['usePointer'] 199 | const usePointerSwipe: typeof import('@vueuse/core')['usePointerSwipe'] 200 | const usePreferredColorScheme: typeof import('@vueuse/core')['usePreferredColorScheme'] 201 | const usePreferredDark: typeof import('@vueuse/core')['usePreferredDark'] 202 | const usePreferredLanguages: typeof import('@vueuse/core')['usePreferredLanguages'] 203 | const useRafFn: typeof import('@vueuse/core')['useRafFn'] 204 | const useRefHistory: typeof import('@vueuse/core')['useRefHistory'] 205 | const useResizeObserver: typeof import('@vueuse/core')['useResizeObserver'] 206 | const useRoute: typeof import('vue-router')['useRoute'] 207 | const useRouter: typeof import('vue-router')['useRouter'] 208 | const useScreenOrientation: typeof import('@vueuse/core')['useScreenOrientation'] 209 | const useScreenSafeArea: typeof import('@vueuse/core')['useScreenSafeArea'] 210 | const useScriptTag: typeof import('@vueuse/core')['useScriptTag'] 211 | const useScroll: typeof import('@vueuse/core')['useScroll'] 212 | const useScrollLock: typeof import('@vueuse/core')['useScrollLock'] 213 | const useSessionStorage: typeof import('@vueuse/core')['useSessionStorage'] 214 | const useShare: typeof import('@vueuse/core')['useShare'] 215 | const useSlots: typeof import('vue')['useSlots'] 216 | const useSpeechRecognition: typeof import('@vueuse/core')['useSpeechRecognition'] 217 | const useSpeechSynthesis: typeof import('@vueuse/core')['useSpeechSynthesis'] 218 | const useStepper: typeof import('@vueuse/core')['useStepper'] 219 | const useStorage: typeof import('@vueuse/core')['useStorage'] 220 | const useStorageAsync: typeof import('@vueuse/core')['useStorageAsync'] 221 | const useStyleTag: typeof import('@vueuse/core')['useStyleTag'] 222 | const useSwipe: typeof import('@vueuse/core')['useSwipe'] 223 | const useTemplateRefsList: typeof import('@vueuse/core')['useTemplateRefsList'] 224 | const useTextSelection: typeof import('@vueuse/core')['useTextSelection'] 225 | const useTextareaAutosize: typeof import('@vueuse/core')['useTextareaAutosize'] 226 | const useThrottle: typeof import('@vueuse/core')['useThrottle'] 227 | const useThrottleFn: typeof import('@vueuse/core')['useThrottleFn'] 228 | const useThrottledRefHistory: typeof import('@vueuse/core')['useThrottledRefHistory'] 229 | const useTimeAgo: typeof import('@vueuse/core')['useTimeAgo'] 230 | const useTimeout: typeof import('@vueuse/core')['useTimeout'] 231 | const useTimeoutFn: typeof import('@vueuse/core')['useTimeoutFn'] 232 | const useTimeoutPoll: typeof import('@vueuse/core')['useTimeoutPoll'] 233 | const useTimestamp: typeof import('@vueuse/core')['useTimestamp'] 234 | const useTitle: typeof import('@vueuse/core')['useTitle'] 235 | const useToggle: typeof import('@vueuse/core')['useToggle'] 236 | const useTransition: typeof import('@vueuse/core')['useTransition'] 237 | const useUrlSearchParams: typeof import('@vueuse/core')['useUrlSearchParams'] 238 | const useUserMedia: typeof import('@vueuse/core')['useUserMedia'] 239 | const useVModel: typeof import('@vueuse/core')['useVModel'] 240 | const useVModels: typeof import('@vueuse/core')['useVModels'] 241 | const useVibrate: typeof import('@vueuse/core')['useVibrate'] 242 | const useVirtualList: typeof import('@vueuse/core')['useVirtualList'] 243 | const useWakeLock: typeof import('@vueuse/core')['useWakeLock'] 244 | const useWebNotification: typeof import('@vueuse/core')['useWebNotification'] 245 | const useWebSocket: typeof import('@vueuse/core')['useWebSocket'] 246 | const useWebWorker: typeof import('@vueuse/core')['useWebWorker'] 247 | const useWebWorkerFn: typeof import('@vueuse/core')['useWebWorkerFn'] 248 | const useWindowFocus: typeof import('@vueuse/core')['useWindowFocus'] 249 | const useWindowScroll: typeof import('@vueuse/core')['useWindowScroll'] 250 | const useWindowSize: typeof import('@vueuse/core')['useWindowSize'] 251 | const watch: typeof import('vue')['watch'] 252 | const watchArray: typeof import('@vueuse/core')['watchArray'] 253 | const watchAtMost: typeof import('@vueuse/core')['watchAtMost'] 254 | const watchDebounced: typeof import('@vueuse/core')['watchDebounced'] 255 | const watchEffect: typeof import('vue')['watchEffect'] 256 | const watchIgnorable: typeof import('@vueuse/core')['watchIgnorable'] 257 | const watchOnce: typeof import('@vueuse/core')['watchOnce'] 258 | const watchPausable: typeof import('@vueuse/core')['watchPausable'] 259 | const watchPostEffect: typeof import('vue')['watchPostEffect'] 260 | const watchSyncEffect: typeof import('vue')['watchSyncEffect'] 261 | const watchThrottled: typeof import('@vueuse/core')['watchThrottled'] 262 | const watchTriggerable: typeof import('@vueuse/core')['watchTriggerable'] 263 | const watchWithFilter: typeof import('@vueuse/core')['watchWithFilter'] 264 | const whenever: typeof import('@vueuse/core')['whenever'] 265 | } 266 | --------------------------------------------------------------------------------