Commit 555e5dea authored by fengyuncheng's avatar fengyuncheng

init: init

parents
Pipeline #460 failed with stages
module.exports = {
extends: ['@commitlint/config-conventional'],
rules: {
'type-enum': [
2,
'always',
['init', 'build', 'ci', 'chore', 'docs', 'feat', 'fix', 'perf', 'refactor', 'revert', 'style', 'test'],
],
},
};
# EditorConfig is awesome: https://EditorConfig.org
# top-most EditorConfig file
root = true
[*] # 表示所有文件都要遵循
indent_style = space # 缩进风格,可选配置有space和tab
indent_size = 2 # 缩进大小
end_of_line = lf # 换行符,可选配置有lf、cr和crlf
charset = utf-8 # 编码格式,通常都是选utf-8
trim_trailing_whitespace = true # 去除多余的空格
insert_final_newline = true # 在尾部插入一行
[*.md] # 表示仅 md 文件适用
insert_final_newline = false # 在尾部插入一行
trim_trailing_whitespace = false # 去除多余的空格
VITE_API_BASEURL = http://127.0.0.1:8080/api/v1
VITE_BASE = /
VITE_APP_TITLE = AronaConfigWebUI
VITE_APP_DESCRIPTION = A zero-config Vue3 template includes Vite3、Vue3 and TypeScript
node_modules
.DS_Store
dist
dist-ssr
*.local
presets
*.d.ts
gstc.wasm.esm.min.js
This diff was suppressed by a .gitattributes entry.
module.exports = {
env: {
browser: true,
es2021: true,
node: true,
},
globals: {
defineEmits: true,
document: true,
localStorage: true,
GLOBAL_VAR: true,
window: true,
defineProps: true,
defineExpose: true,
withDefaults: true,
},
extends: [
"./.eslintrc-auto-import.json",
"airbnb-base",
"plugin:@typescript-eslint/recommended",
"plugin:vue/vue3-recommended",
"plugin:prettier/recommended", // 添加 prettier 插件
],
parserOptions: {
ecmaVersion: "latest",
parser: "@typescript-eslint/parser",
sourceType: "module",
},
plugins: ["vue", "@typescript-eslint", "import"],
rules: {
"no-console": "off",
"no-plusplus": "off",
"no-param-reassign": "off",
"import/extensions": "off",
"no-use-before-define": "off",
"import/no-unresolved": "off",
"import/no-extraneous-dependencies": "off",
"@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/no-non-null-assertion": "off",
"no-shadow": "off",
"@typescript-eslint/no-shadow": ["error"],
"no-underscore-dangle": "off", // 允许使用带有下划线的成员变量, this._foo 表明这是一个私有变量
},
};
# Set the default behavior, in case people don't have core.autocrlf set.
* text=auto
# Explicitly declare text files you want to always be normalized and converted
# to native line endings on checkout.
# Declare files that will always have CRLF line endings on checkout.
*.vue text eol=lf
*.ts text eol=lf
*.js text eol=lf
*.scss text eol=lf
# Denote all files that are truly binary and should not be modified.
*.png binary
*.jpg binary
*.webp binary
*.svg binary
*.woff binary
*.woff2 binary
*.yaml binary
*.json binary
*.json binary
node_modules
.DS_Store
dist
dist-ssr
*.local
.idea
dist.7z
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
npx --no-install commitlint --edit $1
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
npx lint-staged
shamefully-hoist=true
strict-peer-dependencies=false
node_modules
.DS_Store
dist
dist-ssr
*.local
*.d.ts
MIT License
Copyright (c) 2022 diyigemt
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
<br>
<p align='center'>
<a href="https://vitecamp.netlify.app/">Live Demo</a>
</p>
<br>
<p align='center'>
<b>English</b> | <a href="https://github.com/nekobc1998923/vitecamp/blob/master/README.zh-CN.md">简体中文</a>
</p>
<br>
## Features
- ⚡️ [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 !
- 💪 [Typescript](https://www.typescriptlang.org/) - of course! necessary
- 🎉 [Element Plus ready](https://github.com/element-plus/element-plus) - UI Library based on Vue.js 3
- 🔥 [Axios](https://github.com/axios/axios) - Http Library based on Promise
- 💡 [Vue Router 4](https://router.vuejs.org/zh/) - The official router for Vue.js
- 📦 [Components auto importing](https://github.com/antfu/unplugin-vue-components) - Automatically register components on demand without import
- 📥 [Auto import APIs](https://github.com/antfu/unplugin-auto-import) - Automatically import APIs
- 🍍 [State Management via Pinia](https://pinia.esm.dev/) - The Vue Store that you will enjoy using
- 🎨 [Windi CSS](https://github.com/windicss/windicss) - next generation utility-first CSS framework
- 😃 [icones](https://github.com/antfu/unplugin-icons) - Powerful Icon Library, Use icons from any icon sets
- 🌍 [I18n ready](./locales) - Want to translate? Yes, you can!
- 👩‍🎨 [NProgress](https://github.com/rstacruz/nprogress) - Page loading progress feedback
- 😃 [SVG Support](https://github.com/jpkleemans/vite-svg-loader) - Support the use of SVG images as components
- 📑 [Markdown Support](https://github.com/antfu/vite-plugin-md) - Markdown as components / components in Markdown
- 🔑 Complete code style specification and code submission specification
- ☁️ Deploy on Netlify, zero-config
## Pre-packed
### UI Frameworks
- [Windi CSS](https://github.com/windicss/windicss) (On-demand [TailwindCSS](https://tailwindcss.com/)) - lighter and faster, with a bunch of additional features
- [Windi CSS Typography](https://windicss.org/plugins/official/typography.html)
- [Element Plus](https://github.com/element-plus/element-plus) - A powerful Vue.js 3 UI Library
### Icons
- [🔍Icônes](https://icones.netlify.app/) - use icons from any icon sets
- [unplugin-icons](https://github.com/antfu/unplugin-icons) - Automatically introduce the icons you need on demand
### Plugins
- [Vue Router 4](https://router.vuejs.org/zh/) - The official router for Vue.js
- [Pinia](https://pinia.esm.dev) - The Vue Store that you will enjoy using
- [Axios](https://github.com/axios/axios) - Http Library based on Promise
- [unplugin-vue-components](https://github.com/antfu/unplugin-vue-components) - components auto import
- [unplugin-auto-import](https://github.com/antfu/unplugin-auto-import) - Automatically import APIs
- [vite-plugin-windicss](https://github.com/antfu/vite-plugin-windicss) - Windi CSS Integration
- [vite-plugin-vue-markdown](https://github.com/antfu/vite-plugin-vue-markdown) - Markdown as components / components in Markdown
- [markdown-it-prism](https://github.com/jGleitz/markdown-it-prism) - [Prism](https://prismjs.com/) for syntax highlighting
- [prism-theme-vars](https://github.com/antfu/prism-theme-vars) - customizable Prism.js theme using CSS variables
- [markdown-it-link-attributes](https://github.com/crookedneighbor/markdown-it-link-attributes) - Uniformly set the hyperlink jump mode in markdown
- [Vue I18n](https://github.com/intlify/vue-i18n-next) - Internationalization
- [vite-plugin-vue-i18n](https://github.com/intlify/vite-plugin-vue-i18n) - Vite plugin for Vue I18n
- [vite-plugin-fonts](https://github.com/stafyniaksacha/vite-plugin-fonts) - Vite's font loader
- [VueUse](https://github.com/antfu/vueuse) - Collection of useful composition APIs
- [vite-svg-loader](https://github.com/jpkleemans/vite-svg-loader) - Support the use of SVG images as components
### Coding Style
- [ESLint](https://eslint.org/) with [Airbnb Style](https://github.com/airbnb/javascript)
### Dev tools
- [TypeScript](https://www.typescriptlang.org/)
- [Netlify](https://www.netlify.com/) - zero-config deployment
- [VS Code Extensions](./.vscode/extensions.json)
- [Volar](https://marketplace.visualstudio.com/items?itemName=johnsoncodehk.volar) -Vue 3 IDE support
- [Iconify IntelliSense](https://marketplace.visualstudio.com/items?itemName=antfu.iconify) - Icon inline display and autocomplete
- [i18n Ally](https://marketplace.visualstudio.com/items?itemName=lokalise.i18n-ally) - All in one i18n support
- [Windi CSS Intellisense](https://marketplace.visualstudio.com/items?itemName=voorjaar.windicss-intellisense) - IDE support for Windi CSS
- [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) - Code quality and rule checking
- [Prettier - Code formatter](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode) - Focus on code formatting and beautifying code
- [EditorConfig for VS Code](https://marketplace.visualstudio.com/items?itemName=EditorConfig.EditorConfig) - Coding style check
## Try it now!
### GitHub Template
[Create a repo from this template on GitHub](https://github.com/nekobc1998923/vitecamp/generate).
### Clone to local
```bash
git clone https://github.com/nekobc1998923/vitecamp.git my-vitecamp-app
cd my-vitecamp-app
pnpm i
```
## Checklist
When you use this template, try follow the checklist to update your info properly
- [ ] Change the author name in `LICENSE`
- [ ] Change the author name in `package.json`
- [ ] Change the title in `.env`
- [ ] Change the favicon in `public`
- [ ] Clean up the `README` and remove routes
And then , you can enjoy coding fun :)
## Usage
### Development
Just run and visit http://localhost:8080
```bash
pnpm run dev
```
### Build
To build the App, run
```bash
pnpm run build
```
And you will see the generated file in `dist` that ready to be served.
## Thanks
This template has some features inspired by [Vitesse](https://github.com/antfu/vitesse)
<br>
<p align='center'>
<a href="https://vitecamp.netlify.app/">在线 Demo</a>
</p>
<br>
<p align='center'>
<a href="https://github.com/nekobc1998923/vitecamp/blob/master/README.md">English</a> | <b>简体中文</b>
</p>
<br>
## 特性
- ⚡️ [Vue 3](https://github.com/vuejs/core), [Vite 3](https://github.com/vitejs/vite), [pnpm](https://pnpm.io/), [ESBuild](https://github.com/evanw/esbuild) - 快,且更快!
- 💪 [Typescript](https://www.typescriptlang.org/) - 当然!必不可少
- 🎉 [Element Plus 开箱即用](https://github.com/element-plus/element-plus) - 基于 Vue.js 3 的强大 UI 库
- 🔥 [Axios 配置和封装](https://github.com/axios/axios) - 基于 Promise 的 HTTP 请求库
- 💡 [Vue Router 4](https://router.vuejs.org/zh/) - Vuejs 的官方路由
- 📦 [组件自动按需加载](https://github.com/antfu/unplugin-vue-components) - 自动按需注册组件, 无需 import
- 📥 [API 自动按需加载](https://github.com/antfu/unplugin-auto-import) - 无需手动 import 进行引入
- 🍍 [Pinia 状态管理](https://pinia.esm.dev/) - 你将会喜欢上的 Vue Store
- 🎨 [Windi CSS](https://github.com/windicss/windicss) - 下一代实用的原子 css 框架
- 😃 [icones](https://github.com/antfu/unplugin-icons) - 强大的图标库,各种图标集为你所用
- 🌍 [I18n 国际化开箱即用](./locales) - 想要翻译?是的,都可以!
- 👩‍🎨 [NProgress](https://github.com/rstacruz/nprogress) - 页面加载进度反馈
- 😃 [SVG 支持](https://github.com/jpkleemans/vite-svg-loader) - 支持以 组件形式使用 SVG 图片
- 📑 [Markdown 支持](https://github.com/antfu/vite-plugin-md) - 随意的在页面中嵌入 Markdown
- 🔑 完整支持的代码风格规范和代码提交规范
- ☁️ 支持零配置部署 Netlify
## 已配置
### UI 框架
- [Windi CSS](https://github.com/windicss/windicss) (按需的 [TailwindCSS](https://tailwindcss.com/)) - 更轻,更快和和一系列额外的特性!
- [Windi CSS Typography](https://windicss.org/plugins/official/typography.html)
- [Element Plus](https://github.com/element-plus/element-plus) - 基于 Vue.js 3 的强大 UI 库
### Icons
- [🔍Icônes](https://icones.netlify.app/) - 使用任意的图标集
- [unplugin-icons](https://github.com/antfu/unplugin-icons) - 自动按需引入你所需要的图标!
### 插件
- [Vue Router 4](https://router.vuejs.org/zh/) - Vuejs 的官方路由
- [Pinia](https://pinia.esm.dev) - 新一代的 Vue Store 状态管理
- [Axios](https://github.com/axios/axios) - 基于 Promise 的 HTTP 请求库
- [unplugin-vue-components](https://github.com/antfu/unplugin-vue-components) - 自动按需加载组件
- [unplugin-auto-import](https://github.com/antfu/unplugin-auto-import) - 自动按需加载 API
- [vite-plugin-windicss](https://github.com/antfu/vite-plugin-windicss) - Windi CSS 的整合
- [vite-plugin-vue-markdown](https://github.com/antfu/vite-plugin-vue-markdown) - Markdown 作为组件,也可以让组件在 Markdown 中使用
- [markdown-it-prism](https://github.com/jGleitz/markdown-it-prism) - [Prism](https://prismjs.com/) 的语法高亮
- [prism-theme-vars](https://github.com/antfu/prism-theme-vars) - 利用 CSS 变量自定义 Prism.js 的主题
- [markdown-it-link-attributes](https://github.com/crookedneighbor/markdown-it-link-attributes) - 统一设置 Markdown 里的超链接跳转方式
- [Vue I18n](https://github.com/intlify/vue-i18n-next) - 国际化
- [vite-plugin-vue-i18n](https://github.com/intlify/vite-plugin-vue-i18n) - Vue I18n 的 Vite 插件
- [vite-plugin-fonts](https://github.com/stafyniaksacha/vite-plugin-fonts) - Vite 的字体加载器
- [VueUse](https://github.com/antfu/vueuse) - 实用的 Composition API 工具合集
- [vite-svg-loader](https://github.com/jpkleemans/vite-svg-loader) - 支持以 组件形式使用 SVG 图片
### 编码风格
- [ESLint](https://eslint.org/) 配置为 [Airbnb Style](https://github.com/airbnb/javascript)
### 开发工具
- [TypeScript](https://www.typescriptlang.org/)
- [Netlify](https://www.netlify.com/) - 零配置的部署
- [VS Code 扩展](./.vscode/extensions.json)
- [Volar](https://marketplace.visualstudio.com/items?itemName=johnsoncodehk.volar) - Vue 3 IDE 支持
- [Iconify IntelliSense](https://marketplace.visualstudio.com/items?itemName=antfu.iconify) - 图标内联显示和自动补全
- [i18n Ally](https://marketplace.visualstudio.com/items?itemName=lokalise.i18n-ally) - 多合一的 I18n 支持
- [Windi CSS 智能感知](https://marketplace.visualstudio.com/items?itemName=voorjaar.windicss-intellisense) - Windi CSS 的 IDE 支持
- [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) - 代码质量和规则检查
- [Prettier - Code formatter](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode) - 专注于代码格式化、美化代码
- [EditorConfig for VS Code](https://marketplace.visualstudio.com/items?itemName=EditorConfig.EditorConfig) - 编码风格检查
## 现在可以试试!
### GitHub 模板
[使用这个模板创建仓库](https://github.com/nekobc1998923/vitecamp/generate).
### 克隆到本地
```bash
git clone https://github.com/nekobc1998923/vitecamp.git my-vitecamp-app
cd my-vitecamp-app
pnpm i
```
## 清单
使用此模板时,请尝试按照清单正确更新你自己的信息
- [ ]`LICENSE` 中改变作者名
- [ ]`package.json` 中改变作者名
- [ ]`.env` 中改变标题
- [ ]`public` 目录下改变 favicon
- [ ] 整理 `README `并删除路由
然后,你就可以享受编写代码的乐趣了 :)
## 使用
### 开发
只需要执行以下命令就可以在 http://localhost:8080 中看到
```bash
pnpm run dev
```
### 构建
构建该应用只需要执行以下命令
```bash
pnpm run build
```
然后你会看到用于发布的 `dist` 文件夹被生成。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/icon.jpg" type="image/jpg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
import vue from '@vitejs/plugin-vue';
import vueJsx from '@vitejs/plugin-vue-jsx';
import svgLoader from 'vite-svg-loader';
import AutoImport from 'unplugin-auto-import/vite';
import Components from 'unplugin-vue-components/vite';
import Icons from 'unplugin-icons/vite';
import IconsResolver from 'unplugin-icons/resolver';
import { ElementPlusResolver, VueUseComponentsResolver } from 'unplugin-vue-components/resolvers';
import WindiCSS from 'vite-plugin-windicss';
import Markdown from 'vite-plugin-vue-markdown'
import Prism from 'markdown-it-prism';
import ViteFonts from 'vite-plugin-fonts';
import VueI18n from '@intlify/vite-plugin-vue-i18n';
// @ts-ignore
import LinkAttributes from 'markdown-it-link-attributes';
import { ConfigEnv } from 'vite';
import { resolve } from 'path';
const defaultClasses = 'prose prose-sm m-auto text-left';
export default (env: ConfigEnv) => {
return [
vue({
include: [/\.vue$/, /\.md$/],
}),
vueJsx(),
svgLoader(),
AutoImport({
dts: './src/auto-imports.d.ts',
// @ts-ignore
imports: ['vue', 'pinia', 'vue-router', 'vue-i18n', '@vueuse/core'],
// Generate corresponding .eslintrc-auto-import.json file.
// eslint globals Docs - https://eslint.org/docs/user-guide/configuring/language-options#specifying-globals
eslintrc: {
enabled: false, // Default `false`
filepath: './.eslintrc-auto-import.json', // Default `./.eslintrc-auto-import.json`
globalsPropValue: true, // Default `true`, (true | false | 'readonly' | 'readable' | 'writable' | 'writeable')
},
resolvers: [ElementPlusResolver()],
}),
Components({
dts: './src/components.d.ts',
extensions: ['vue', 'md'],
include: [/\.vue$/, /\.vue\?vue/, /\.md$/],
// imports 指定组件所在位置,默认为 src/components; 有需要也可以加上 view 目录
dirs: ['src/components/'],
resolvers: [ElementPlusResolver(), IconsResolver(), VueUseComponentsResolver()],
}),
Icons({
compiler: 'vue3',
autoInstall: true,
}),
ViteFonts({
google: {
families: ['Open Sans', 'Montserrat', 'Fira Sans'],
},
}),
VueI18n({
include: [resolve(__dirname, '../locales/**')],
}),
WindiCSS({
safelist: defaultClasses,
}),
Markdown({
wrapperClasses: defaultClasses,
headEnabled: false,
markdownItSetup(md) {
// https://prismjs.com/
md.use(Prism);
// 为 md 中的所有链接设置为 新页面跳转
md.use(LinkAttributes, {
matcher: (link: string) => /^https?:\/\//.test(link),
attrs: {
target: '_blank',
rel: 'noopener',
},
});
},
}),
];
};
// https://prettier.io/docs/en/configuration.html
module.exports = {
// 每一行的宽度(显示的字符数)
printWidth: 120,
// tab健的空格数
tabWidth: 2,
// 是否在对象中的括号之间打印空格,{a:5}格式化为{ a: 5 }
bracketSpacing: true,
// 箭头函数的参数无论有几个,都要括号包裹
arrowParens: "always",
// 换行符的使用
endOfLine: "lf",
// 是否用单引号, 项目中全部使用双引号
singleQuote: false,
// 对象或者数组的最后一个元素后面是否要加逗号
trailingComma: "all",
// 是否加分号,项目中统一加分号
semi: true,
// 是否使用tab格式化: 不使用
useTabs: false,
};
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
<template>
<el-config-provider :locale="locale">
<router-view />
</el-config-provider>
</template>
<script setup lang="ts">
import zhCn from "element-plus/lib/locale/lang/zh-cn";
const locale = zhCn;
</script>
<style lang="scss" scoped>
.arona-container {
position: absolute;
top: 100px;
left: 300px;
height: 600px;
width: 300px;
background-color: black;
display: none;
}
</style>
import axios, { AxiosError, AxiosInstance } from "axios";
import { ApiServiceAdapter, IRequestConfig, IResponse, IResponseError, ServerResponse } from "@/interface/http";
import { HTTP_OK } from "@/constant";
import { errorMessage, infoMessage, warningMessage } from "@/utils/message";
import showCodeMessage from "@/api/code";
import { formatJsonToUrlParams, instanceObject } from "@/utils/format";
const BASE_PREFIX = import.meta.env.VITE_API_BASEURL;
// 创建实例
const axiosInstance: AxiosInstance = axios.create({
// 前缀
baseURL: BASE_PREFIX,
// 超时
timeout: 1000 * 30,
// 请求头
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*",
},
});
// 请求拦截器
axiosInstance.interceptors.request.use(
(config: IRequestConfig) => {
if (!config.version) {
config.version = "v1";
config.baseURL = `${config.baseURL}/api/${config.version}/`;
}
config.showServerResponseError = config.showServerResponseError || true;
return config;
},
(error: AxiosError) => {
return Promise.reject(error);
},
);
// 响应拦截器
axiosInstance.interceptors.response.use(
(response: IResponse) => {
const { config } = response;
if (config.isBlob) {
return response;
}
if (response.status === HTTP_OK) {
const resp = response.data as ServerResponse<unknown>;
if (resp && resp.code !== HTTP_OK && resp.message && response.config.showServerResponseError) {
warningMessage(resp.message);
}
return response.data;
}
infoMessage(JSON.stringify(response.status));
return response;
},
(error: IResponseError) => {
const { response, config } = error;
if (response) {
if (config && config.showResponseError) {
errorMessage(showCodeMessage(response.status));
}
return Promise.reject(response.data);
}
if (config && config.showResponseError) {
warningMessage("网络连接异常,请稍后再试!");
}
return Promise.reject(error);
},
);
const LocalhostService: ApiServiceAdapter = {
upload(url: string, file: FormData | File) {
if (Object.hasOwn(file, "get")) {
const fileName = encodeURI(((file as FormData).get("file") as File).name);
return axiosInstance({
url,
method: "POST",
data: file,
headers: buildFileUploadHeader(fileName),
}) as unknown as Promise<ServerResponse<string>>;
}
const data = new FormData();
data.set("file", file as Blob);
const fileName = encodeURI((file as File).name);
return axiosInstance({
url,
method: "POST",
data,
headers: buildFileUploadHeader(fileName),
}) as unknown as Promise<ServerResponse<string>>;
},
download(id: string) {
const config: IRequestConfig = {
url: "/file/image",
params: {
id,
},
method: "GET",
responseType: "blob",
isBlob: true,
};
return axiosInstance(config);
},
raw<T>(config: IRequestConfig): Promise<ServerResponse<T>> {
return axiosInstance(config) as unknown as Promise<ServerResponse<T>>;
},
urlDownload(url: string, data: instanceObject) {
window.location.href = `${BASE_PREFIX}/${url}?${formatJsonToUrlParams(data)}`;
},
};
function buildFileUploadHeader(fileName: string) {
return {
"Content-Type": "multipart/form-data",
"arona-file-name": fileName,
};
}
export function updateAPIService(host: string, port: number) {
axiosInstance.defaults.baseURL = currentAPI(host, port);
}
export function currentAPI(host?: string, port?: number) {
if (!host || !port) {
return axiosInstance.defaults.baseURL;
}
return `${host}:${port}`;
}
export default LocalhostService;
declare interface codeMessageMapTypes {
400: string;
401: string;
403: string;
404: string;
405: string;
500: string;
[key: string]: string;
}
const codeMessageMap: codeMessageMapTypes = {
400: "[400]:请求参数错误",
401: "[401]:账户未登录",
403: "[403]:拒绝访问",
404: "[404]:请求路径错误",
405: "[405]:请求方法错误",
500: "[500]:服务器错误",
};
const showCodeMessage = (code: number | string): string => {
return codeMessageMap[JSON.stringify(code)] || "网络连接异常,请稍后再试!";
};
export default showCodeMessage;
import useSettingStore from "@/store/base";
import { ApiServiceAdapter, NetworkAdapterType } from "@/interface/http";
import LocalhostService from "@/api/adapter/localhost";
const ServiceHandler: ProxyHandler<ApiServiceAdapter> = {
get(_, key) {
const settingStore = useSettingStore();
const adapter = Reflect.get(AdapterMap, settingStore.adapter) || LocalhostService;
return Reflect.get(adapter, key);
},
};
type AdapterMap = {
[key in NetworkAdapterType]: ApiServiceAdapter;
};
// TODO
const AdapterMap: AdapterMap = {
Localhost: LocalhostService,
Offline: LocalhostService,
Proxy: LocalhostService,
};
const service = new Proxy(LocalhostService, ServiceHandler);
export default service;
body {
@apply text-gray-700 dark: bg-gray-800 dark:text-gray-200;
}
@import '@/assets/styles/nprogress.scss';
@import '@/assets/styles/markdown.scss';
@import '@/assets/styles/dark.scss';
@import "@/assets/styles/variables.scss";
@font-face {
font-family: "Game Font";
src: url("/font/U-OTF-ShinMGoUpr-Medium.woff");
}
@font-face {
font-family: "Chinese Game Font";
src: url("/font/ResourceHanRoundedCN-Medium.woff");
}
#app {
width: 100vw;
height: 100vh;
position: relative;
}
* {
font-family: ui-sans-serif, system-ui,
-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue',
Helvetica, Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji',
'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
}
// 隐藏横向滚动条
.scrollbar-hide-horizontal[class~=el-scrollbar] {
.is-horizontal {
display: none;
}
}
// 点模糊背景
.dot-bg {
background-image: radial-gradient(transparent 1px, #fff 1px);
backdrop-filter: saturate(50%) blur(4px);
background-size: 4px 4px;
}
// 菜单美化
.custom-menu {
.el-sub-menu {
.el-menu {
padding: 0 16px;
.el-menu-item[class~=is-active] {
background-color: var(--el-color-primary-light-8);
}
}
}
}
// 主配置文件连接
.config-drag-item {
background-color: white;
border: 1px solid #346789;
text-align: center;
cursor: pointer;
box-shadow: 2px 2px 19px #aaa;
border-radius: 6px;
position: absolute;
color: black;
width: 140px;
height: 60px;
line-height: 1;
user-select: none;
}
.dialog-body-padding-bottom-0 {
.el-dialog__body {
padding-bottom: 0;
}
}
/* https://github.com/antfu/prism-theme-vars */
@import 'prism-theme-vars/base.css';
.prose {
--prism-font-family: 'Input Mono', monospace;
}
.prose img {
width: 100%;
}
html:not(.dark) .prose {
--prism-foreground: #393a34;
--prism-background: #fbfbfb;
--prism-background-color: #fbfbfb;
--prism-comment: #a0ada0;
--prism-string: #b56959;
--prism-literal: #2f8a89;
--prism-number: #296aa3;
--prism-keyword: #1c6b48;
--prism-function: #6c7834;
--prism-boolean: #1c6b48;
--prism-constant: #a65e2b;
--prism-deleted: #a14f55;
--prism-class: #2993a3;
--prism-builtin: #ab5959;
--prism-property: #b58451;
--prism-namespace: #b05a78;
--prism-punctuation: #8e8f8b;
--prism-decorator: #bd8f8f;
--prism-regex: #ab5e3f;
--prism-json-property: #698c96;
}
html.dark .prose {
--prism-foreground: #d4cfbf;
--prism-background: #151515;
--prism-background-color: #151515;
--prism-comment: #758575;
--prism-string: #d48372;
--prism-literal: #429988;
--prism-keyword: #4d9375;
--prism-boolean: #1c6b48;
--prism-number: #6394bf;
--prism-variable: #c2b36e;
--prism-function: #a1b567;
--prism-deleted: #a14f55;
--prism-class: #54b1bf;
--prism-builtin: #e0a569;
--prism-property: #dd8e6e;
--prism-namespace: #db889a;
--prism-punctuation: #858585;
--prism-decorator: #bd8f8f;
--prism-regex: #ab5e3f;
--prism-json-property: #6b8b9e;
--prism-line-number: #888888;
--prism-line-number-gutter: #eeeeee;
--prism-line-highlight-background: #444444;
--prism-selection-background: #444444;
}
/* Make clicks pass-through */
#nprogress {
pointer-events: none;
}
#nprogress .bar {
background: $theme-color;
position: fixed;
z-index: 1031;
top: 0;
left: 0;
width: 100%;
height: 2px;
}
/* Fancy blur effect */
#nprogress .peg {
display: block;
position: absolute;
right: 0px;
width: 100px;
height: 100%;
box-shadow: 0 0 10px $theme-color, 0 0 5px $theme-color;
opacity: 1.0;
-webkit-transform: rotate(3deg) translate(0px, -4px);
-ms-transform: rotate(3deg) translate(0px, -4px);
transform: rotate(3deg) translate(0px, -4px);
}
/* Remove these to get rid of the spinner */
#nprogress .spinner {
display: block;
position: fixed;
z-index: 1031;
top: 15px;
right: 15px;
}
#nprogress .spinner-icon {
width: 18px;
height: 18px;
box-sizing: border-box;
border: solid 2px transparent;
border-top-color: $theme-color;
border-left-color: $theme-color;
border-radius: 50%;
-webkit-animation: nprogress-spinner 400ms linear infinite;
animation: nprogress-spinner 400ms linear infinite;
}
.nprogress-custom-parent {
overflow: hidden;
position: relative;
}
.nprogress-custom-parent #nprogress .spinner,
.nprogress-custom-parent #nprogress .bar {
position: absolute;
}
@-webkit-keyframes nprogress-spinner {
0% {
-webkit-transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
}
}
@keyframes nprogress-spinner {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
$theme-color: #2080F0FF
This diff was suppressed by a .gitattributes entry.
// Generated by 'unplugin-auto-import'
export {}
declare global {
const EffectScope: typeof import('vue')['EffectScope']
const acceptHMRUpdate: typeof import('pinia')['acceptHMRUpdate']
const asyncComputed: typeof import('@vueuse/core')['asyncComputed']
const autoResetRef: typeof import('@vueuse/core')['autoResetRef']
const computed: typeof import('vue')['computed']
const computedAsync: typeof import('@vueuse/core')['computedAsync']
const computedEager: typeof import('@vueuse/core')['computedEager']
const computedInject: typeof import('@vueuse/core')['computedInject']
const computedWithControl: typeof import('@vueuse/core')['computedWithControl']
const controlledComputed: typeof import('@vueuse/core')['controlledComputed']
const controlledRef: typeof import('@vueuse/core')['controlledRef']
const createApp: typeof import('vue')['createApp']
const createEventHook: typeof import('@vueuse/core')['createEventHook']
const createGlobalState: typeof import('@vueuse/core')['createGlobalState']
const createInjectionState: typeof import('@vueuse/core')['createInjectionState']
const createPinia: typeof import('pinia')['createPinia']
const createReactiveFn: typeof import('@vueuse/core')['createReactiveFn']
const createSharedComposable: typeof import('@vueuse/core')['createSharedComposable']
const createUnrefFn: typeof import('@vueuse/core')['createUnrefFn']
const customRef: typeof import('vue')['customRef']
const debouncedRef: typeof import('@vueuse/core')['debouncedRef']
const debouncedWatch: typeof import('@vueuse/core')['debouncedWatch']
const defineAsyncComponent: typeof import('vue')['defineAsyncComponent']
const defineComponent: typeof import('vue')['defineComponent']
const defineStore: typeof import('pinia')['defineStore']
const eagerComputed: typeof import('@vueuse/core')['eagerComputed']
const effectScope: typeof import('vue')['effectScope']
const extendRef: typeof import('@vueuse/core')['extendRef']
const getActivePinia: typeof import('pinia')['getActivePinia']
const getCurrentInstance: typeof import('vue')['getCurrentInstance']
const getCurrentScope: typeof import('vue')['getCurrentScope']
const h: typeof import('vue')['h']
const ignorableWatch: typeof import('@vueuse/core')['ignorableWatch']
const inject: typeof import('vue')['inject']
const isDefined: typeof import('@vueuse/core')['isDefined']
const isProxy: typeof import('vue')['isProxy']
const isReactive: typeof import('vue')['isReactive']
const isReadonly: typeof import('vue')['isReadonly']
const isRef: typeof import('vue')['isRef']
const logicAnd: typeof import('@vueuse/core')['logicAnd']
const logicNot: typeof import('@vueuse/core')['logicNot']
const logicOr: typeof import('@vueuse/core')['logicOr']
const makeDestructurable: typeof import('@vueuse/core')['makeDestructurable']
const mapActions: typeof import('pinia')['mapActions']
const mapGetters: typeof import('pinia')['mapGetters']
const mapState: typeof import('pinia')['mapState']
const mapStores: typeof import('pinia')['mapStores']
const mapWritableState: typeof import('pinia')['mapWritableState']
const markRaw: typeof import('vue')['markRaw']
const nextTick: typeof import('vue')['nextTick']
const onActivated: typeof import('vue')['onActivated']
const onBeforeMount: typeof import('vue')['onBeforeMount']
const onBeforeUnmount: typeof import('vue')['onBeforeUnmount']
const onBeforeUpdate: typeof import('vue')['onBeforeUpdate']
const onClickOutside: typeof import('@vueuse/core')['onClickOutside']
const onDeactivated: typeof import('vue')['onDeactivated']
const onErrorCaptured: typeof import('vue')['onErrorCaptured']
const onKeyStroke: typeof import('@vueuse/core')['onKeyStroke']
const onLongPress: typeof import('@vueuse/core')['onLongPress']
const onMounted: typeof import('vue')['onMounted']
const onRenderTracked: typeof import('vue')['onRenderTracked']
const onRenderTriggered: typeof import('vue')['onRenderTriggered']
const onScopeDispose: typeof import('vue')['onScopeDispose']
const onServerPrefetch: typeof import('vue')['onServerPrefetch']
const onStartTyping: typeof import('@vueuse/core')['onStartTyping']
const onUnmounted: typeof import('vue')['onUnmounted']
const onUpdated: typeof import('vue')['onUpdated']
const pausableWatch: typeof import('@vueuse/core')['pausableWatch']
const provide: typeof import('vue')['provide']
const reactify: typeof import('@vueuse/core')['reactify']
const reactifyObject: typeof import('@vueuse/core')['reactifyObject']
const reactive: typeof import('vue')['reactive']
const reactiveComputed: typeof import('@vueuse/core')['reactiveComputed']
const reactiveOmit: typeof import('@vueuse/core')['reactiveOmit']
const reactivePick: typeof import('@vueuse/core')['reactivePick']
const readonly: typeof import('vue')['readonly']
const ref: typeof import('vue')['ref']
const refAutoReset: typeof import('@vueuse/core')['refAutoReset']
const refDebounced: typeof import('@vueuse/core')['refDebounced']
const refDefault: typeof import('@vueuse/core')['refDefault']
const refThrottled: typeof import('@vueuse/core')['refThrottled']
const refWithControl: typeof import('@vueuse/core')['refWithControl']
const resolveComponent: typeof import('vue')['resolveComponent']
const resolveRef: typeof import('@vueuse/core')['resolveRef']
const resolveUnref: typeof import('@vueuse/core')['resolveUnref']
const setActivePinia: typeof import('pinia')['setActivePinia']
const setMapStoreSuffix: typeof import('pinia')['setMapStoreSuffix']
const shallowReactive: typeof import('vue')['shallowReactive']
const shallowReadonly: typeof import('vue')['shallowReadonly']
const shallowRef: typeof import('vue')['shallowRef']
const storeToRefs: typeof import('pinia')['storeToRefs']
const syncRef: typeof import('@vueuse/core')['syncRef']
const syncRefs: typeof import('@vueuse/core')['syncRefs']
const templateRef: typeof import('@vueuse/core')['templateRef']
const throttledRef: typeof import('@vueuse/core')['throttledRef']
const throttledWatch: typeof import('@vueuse/core')['throttledWatch']
const toRaw: typeof import('vue')['toRaw']
const toReactive: typeof import('@vueuse/core')['toReactive']
const toRef: typeof import('vue')['toRef']
const toRefs: typeof import('vue')['toRefs']
const triggerRef: typeof import('vue')['triggerRef']
const tryOnBeforeMount: typeof import('@vueuse/core')['tryOnBeforeMount']
const tryOnBeforeUnmount: typeof import('@vueuse/core')['tryOnBeforeUnmount']
const tryOnMounted: typeof import('@vueuse/core')['tryOnMounted']
const tryOnScopeDispose: typeof import('@vueuse/core')['tryOnScopeDispose']
const tryOnUnmounted: typeof import('@vueuse/core')['tryOnUnmounted']
const unref: typeof import('vue')['unref']
const unrefElement: typeof import('@vueuse/core')['unrefElement']
const until: typeof import('@vueuse/core')['until']
const useActiveElement: typeof import('@vueuse/core')['useActiveElement']
const useAsyncQueue: typeof import('@vueuse/core')['useAsyncQueue']
const useAsyncState: typeof import('@vueuse/core')['useAsyncState']
const useAttrs: typeof import('vue')['useAttrs']
const useBase64: typeof import('@vueuse/core')['useBase64']
const useBattery: typeof import('@vueuse/core')['useBattery']
const useBluetooth: typeof import('@vueuse/core')['useBluetooth']
const useBreakpoints: typeof import('@vueuse/core')['useBreakpoints']
const useBroadcastChannel: typeof import('@vueuse/core')['useBroadcastChannel']
const useBrowserLocation: typeof import('@vueuse/core')['useBrowserLocation']
const useCached: typeof import('@vueuse/core')['useCached']
const useClamp: typeof import('@vueuse/core')['useClamp']
const useClipboard: typeof import('@vueuse/core')['useClipboard']
const useColorMode: typeof import('@vueuse/core')['useColorMode']
const useConfirmDialog: typeof import('@vueuse/core')['useConfirmDialog']
const useCounter: typeof import('@vueuse/core')['useCounter']
const useCssModule: typeof import('vue')['useCssModule']
const useCssVar: typeof import('@vueuse/core')['useCssVar']
const useCssVars: typeof import('vue')['useCssVars']
const useCurrentElement: typeof import('@vueuse/core')['useCurrentElement']
const useCycleList: typeof import('@vueuse/core')['useCycleList']
const useDark: typeof import('@vueuse/core')['useDark']
const useDateFormat: typeof import('@vueuse/core')['useDateFormat']
const useDebounce: typeof import('@vueuse/core')['useDebounce']
const useDebounceFn: typeof import('@vueuse/core')['useDebounceFn']
const useDebouncedRefHistory: typeof import('@vueuse/core')['useDebouncedRefHistory']
const useDeviceMotion: typeof import('@vueuse/core')['useDeviceMotion']
const useDeviceOrientation: typeof import('@vueuse/core')['useDeviceOrientation']
const useDevicePixelRatio: typeof import('@vueuse/core')['useDevicePixelRatio']
const useDevicesList: typeof import('@vueuse/core')['useDevicesList']
const useDisplayMedia: typeof import('@vueuse/core')['useDisplayMedia']
const useDocumentVisibility: typeof import('@vueuse/core')['useDocumentVisibility']
const useDraggable: typeof import('@vueuse/core')['useDraggable']
const useDropZone: typeof import('@vueuse/core')['useDropZone']
const useElementBounding: typeof import('@vueuse/core')['useElementBounding']
const useElementByPoint: typeof import('@vueuse/core')['useElementByPoint']
const useElementHover: typeof import('@vueuse/core')['useElementHover']
const useElementSize: typeof import('@vueuse/core')['useElementSize']
const useElementVisibility: typeof import('@vueuse/core')['useElementVisibility']
const useEventBus: typeof import('@vueuse/core')['useEventBus']
const useEventListener: typeof import('@vueuse/core')['useEventListener']
const useEventSource: typeof import('@vueuse/core')['useEventSource']
const useEyeDropper: typeof import('@vueuse/core')['useEyeDropper']
const useFavicon: typeof import('@vueuse/core')['useFavicon']
const useFetch: typeof import('@vueuse/core')['useFetch']
const useFileDialog: typeof import('@vueuse/core')['useFileDialog']
const useFileSystemAccess: typeof import('@vueuse/core')['useFileSystemAccess']
const useFocus: typeof import('@vueuse/core')['useFocus']
const useFocusWithin: typeof import('@vueuse/core')['useFocusWithin']
const useFps: typeof import('@vueuse/core')['useFps']
const useFullscreen: typeof import('@vueuse/core')['useFullscreen']
const useGamepad: typeof import('@vueuse/core')['useGamepad']
const useGeolocation: typeof import('@vueuse/core')['useGeolocation']
const useI18n: typeof import('vue-i18n')['useI18n']
const useIdle: typeof import('@vueuse/core')['useIdle']
const useImage: typeof import('@vueuse/core')['useImage']
const useInfiniteScroll: typeof import('@vueuse/core')['useInfiniteScroll']
const useIntersectionObserver: typeof import('@vueuse/core')['useIntersectionObserver']
const useInterval: typeof import('@vueuse/core')['useInterval']
const useIntervalFn: typeof import('@vueuse/core')['useIntervalFn']
const useKeyModifier: typeof import('@vueuse/core')['useKeyModifier']
const useLastChanged: typeof import('@vueuse/core')['useLastChanged']
const useLocalStorage: typeof import('@vueuse/core')['useLocalStorage']
const useMagicKeys: typeof import('@vueuse/core')['useMagicKeys']
const useManualRefHistory: typeof import('@vueuse/core')['useManualRefHistory']
const useMediaControls: typeof import('@vueuse/core')['useMediaControls']
const useMediaQuery: typeof import('@vueuse/core')['useMediaQuery']
const useMemoize: typeof import('@vueuse/core')['useMemoize']
const useMemory: typeof import('@vueuse/core')['useMemory']
const useMounted: typeof import('@vueuse/core')['useMounted']
const useMouse: typeof import('@vueuse/core')['useMouse']
const useMouseInElement: typeof import('@vueuse/core')['useMouseInElement']
const useMousePressed: typeof import('@vueuse/core')['useMousePressed']
const useMutationObserver: typeof import('@vueuse/core')['useMutationObserver']
const useNavigatorLanguage: typeof import('@vueuse/core')['useNavigatorLanguage']
const useNetwork: typeof import('@vueuse/core')['useNetwork']
const useNow: typeof import('@vueuse/core')['useNow']
const useObjectUrl: typeof import('@vueuse/core')['useObjectUrl']
const useOffsetPagination: typeof import('@vueuse/core')['useOffsetPagination']
const useOnline: typeof import('@vueuse/core')['useOnline']
const usePageLeave: typeof import('@vueuse/core')['usePageLeave']
const useParallax: typeof import('@vueuse/core')['useParallax']
const usePermission: typeof import('@vueuse/core')['usePermission']
const usePointer: typeof import('@vueuse/core')['usePointer']
const usePointerSwipe: typeof import('@vueuse/core')['usePointerSwipe']
const usePreferredColorScheme: typeof import('@vueuse/core')['usePreferredColorScheme']
const usePreferredDark: typeof import('@vueuse/core')['usePreferredDark']
const usePreferredLanguages: typeof import('@vueuse/core')['usePreferredLanguages']
const useRafFn: typeof import('@vueuse/core')['useRafFn']
const useRefHistory: typeof import('@vueuse/core')['useRefHistory']
const useResizeObserver: typeof import('@vueuse/core')['useResizeObserver']
const useRoute: typeof import('vue-router')['useRoute']
const useRouter: typeof import('vue-router')['useRouter']
const useScreenOrientation: typeof import('@vueuse/core')['useScreenOrientation']
const useScreenSafeArea: typeof import('@vueuse/core')['useScreenSafeArea']
const useScriptTag: typeof import('@vueuse/core')['useScriptTag']
const useScroll: typeof import('@vueuse/core')['useScroll']
const useScrollLock: typeof import('@vueuse/core')['useScrollLock']
const useSessionStorage: typeof import('@vueuse/core')['useSessionStorage']
const useShare: typeof import('@vueuse/core')['useShare']
const useSlots: typeof import('vue')['useSlots']
const useSpeechRecognition: typeof import('@vueuse/core')['useSpeechRecognition']
const useSpeechSynthesis: typeof import('@vueuse/core')['useSpeechSynthesis']
const useStepper: typeof import('@vueuse/core')['useStepper']
const useStorage: typeof import('@vueuse/core')['useStorage']
const useStorageAsync: typeof import('@vueuse/core')['useStorageAsync']
const useStyleTag: typeof import('@vueuse/core')['useStyleTag']
const useSwipe: typeof import('@vueuse/core')['useSwipe']
const useTemplateRefsList: typeof import('@vueuse/core')['useTemplateRefsList']
const useTextSelection: typeof import('@vueuse/core')['useTextSelection']
const useTextareaAutosize: typeof import('@vueuse/core')['useTextareaAutosize']
const useThrottle: typeof import('@vueuse/core')['useThrottle']
const useThrottleFn: typeof import('@vueuse/core')['useThrottleFn']
const useThrottledRefHistory: typeof import('@vueuse/core')['useThrottledRefHistory']
const useTimeAgo: typeof import('@vueuse/core')['useTimeAgo']
const useTimeout: typeof import('@vueuse/core')['useTimeout']
const useTimeoutFn: typeof import('@vueuse/core')['useTimeoutFn']
const useTimeoutPoll: typeof import('@vueuse/core')['useTimeoutPoll']
const useTimestamp: typeof import('@vueuse/core')['useTimestamp']
const useTitle: typeof import('@vueuse/core')['useTitle']
const useToggle: typeof import('@vueuse/core')['useToggle']
const useTransition: typeof import('@vueuse/core')['useTransition']
const useUrlSearchParams: typeof import('@vueuse/core')['useUrlSearchParams']
const useUserMedia: typeof import('@vueuse/core')['useUserMedia']
const useVModel: typeof import('@vueuse/core')['useVModel']
const useVModels: typeof import('@vueuse/core')['useVModels']
const useVibrate: typeof import('@vueuse/core')['useVibrate']
const useVirtualList: typeof import('@vueuse/core')['useVirtualList']
const useWakeLock: typeof import('@vueuse/core')['useWakeLock']
const useWebNotification: typeof import('@vueuse/core')['useWebNotification']
const useWebSocket: typeof import('@vueuse/core')['useWebSocket']
const useWebWorker: typeof import('@vueuse/core')['useWebWorker']
const useWebWorkerFn: typeof import('@vueuse/core')['useWebWorkerFn']
const useWindowFocus: typeof import('@vueuse/core')['useWindowFocus']
const useWindowScroll: typeof import('@vueuse/core')['useWindowScroll']
const useWindowSize: typeof import('@vueuse/core')['useWindowSize']
const watch: typeof import('vue')['watch']
const watchArray: typeof import('@vueuse/core')['watchArray']
const watchAtMost: typeof import('@vueuse/core')['watchAtMost']
const watchDebounced: typeof import('@vueuse/core')['watchDebounced']
const watchEffect: typeof import('vue')['watchEffect']
const watchIgnorable: typeof import('@vueuse/core')['watchIgnorable']
const watchOnce: typeof import('@vueuse/core')['watchOnce']
const watchPausable: typeof import('@vueuse/core')['watchPausable']
const watchPostEffect: typeof import('vue')['watchPostEffect']
const watchSyncEffect: typeof import('vue')['watchSyncEffect']
const watchThrottled: typeof import('@vueuse/core')['watchThrottled']
const watchTriggerable: typeof import('@vueuse/core')['watchTriggerable']
const watchWithFilter: typeof import('@vueuse/core')['watchWithFilter']
const whenever: typeof import('@vueuse/core')['whenever']
}
// generated by unplugin-vue-components
// We suggest you to commit this file into source control
// Read more: https://github.com/vuejs/core/pull/3399
import '@vue/runtime-core'
export {}
declare module '@vue/runtime-core' {
export interface GlobalComponents {
ElAffix: typeof import('element-plus/es')['ElAffix']
ElAside: typeof import('element-plus/es')['ElAside']
ElButton: typeof import('element-plus/es')['ElButton']
ElCol: typeof import('element-plus/es')['ElCol']
ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider']
ElContainer: typeof import('element-plus/es')['ElContainer']
ElDialog: typeof import('element-plus/es')['ElDialog']
ElDivider: typeof import('element-plus/es')['ElDivider']
ElEmpty: typeof import('element-plus/es')['ElEmpty']
ElForm: typeof import('element-plus/es')['ElForm']
ElFormItem: typeof import('element-plus/es')['ElFormItem']
ElIcon: typeof import('element-plus/es')['ElIcon']
ElImage: typeof import('element-plus/es')['ElImage']
ElInput: typeof import('element-plus/es')['ElInput']
ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
ElMain: typeof import('element-plus/es')['ElMain']
ElMenu: typeof import('element-plus/es')['ElMenu']
ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
ElOption: typeof import('element-plus/es')['ElOption']
ElPageHeader: typeof import('element-plus/es')['ElPageHeader']
ElResult: typeof import('element-plus/es')['ElResult']
ElRow: typeof import('element-plus/es')['ElRow']
ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
ElSelect: typeof import('element-plus/es')['ElSelect']
ElSubMenu: typeof import('element-plus/es')['ElSubMenu']
ElSwitch: typeof import('element-plus/es')['ElSwitch']
ElTable: typeof import('element-plus/es')['ElTable']
ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
ElTag: typeof import('element-plus/es')['ElTag']
ElUpload: typeof import('element-plus/es')['ElUpload']
EnProcess: typeof import('./components/EnProcess.md')['default']
MainAsideMenu: typeof import('./components/MainAsideMenu.vue')['default']
MainBanner: typeof import('./components/MainBanner.vue')['default']
PageHeader: typeof import('./components/PageHeader.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
ShadowCard: typeof import('./components/ShadowCard.vue')['default']
SubPageIndex: typeof import('./components/SubPageIndex.vue')['default']
TheFooter: typeof import('./components/TheFooter.vue')['default']
ZhProcess: typeof import('./components/ZhProcess.md')['default']
}
}
## Try it now!
### GitHub Template
[Create a repo from this template on GitHub](https://github.com/nekobc1998923/vitecamp/generate).
### Clone to local
```bash
git clone https://github.com/nekobc1998923/vitecamp.git my-vitecamp-app
cd my-vitecamp-app
pnpm i
```
## Checklist
When you use this template, try follow the checklist to update your info properly
- Change the author name in `LICENSE`
- Change the author name in `package.json`
- Change the title in `.env`
- Change the favicon in `public`
- Clean up the `README` and remove routes
And then , you can enjoy coding fun :)
## Usage
### Development
Just run and visit http://localhost:8080
```bash
pnpm run dev
```
### Build
To build the App, run
```bash
pnpm run build
```
And you will see the generated file in `dist` that ready to be served.
<template>
<el-menu :default-active="currentActiveMenu" :default-openeds="mapExpand" router class="main-menu custom-menu">
<el-sub-menu index="1">
<template #title>
<span>{{ t("side menu config") }}</span>
</template>
<el-menu-item index="/config/config/config-arona-main">主配置</el-menu-item>
<el-menu-item index="/config/config/config-arona-blockly">条件执行</el-menu-item>
<el-menu-item index="/config/config/config-arona-reply-group">随机回复语句</el-menu-item>
<el-menu-item index="/config/config/config-arona-reply-label">随机回复语句标签</el-menu-item>
</el-sub-menu>
<el-sub-menu index="2">
<template #title>
<span>{{ t("side menu database") }}</span>
</template>
<el-menu-item index="/config/database/database-gacha-pool">GachaPool</el-menu-item>
<el-menu-item index="/config/database/database-gacha-history">GachaHistory</el-menu-item>
</el-sub-menu>
<el-sub-menu index="3">
<template #title>
<span>{{ t("side menu setting") }}</span>
</template>
<el-menu-item index="/config/setting/setting-api">api</el-menu-item>
</el-sub-menu>
</el-menu>
</template>
<script setup lang="ts">
const { t } = useI18n();
const route = useRoute();
const mapExpand = ["1", "2", "3"];
const currentActiveMenu = computed(() => route.path);
</script>
<style lang="scss" scoped>
.main-menu {
height: 100%;
border-right: none;
:deep(.el-sub-menu) {
.el-menu {
.el-menu-item {
border-radius: 4px;
}
}
}
}
</style>
<i18n>
{
"en": {
"side menu config": "config",
"side menu database": "database",
"side menu setting": "setting"
},
"zh-cn": {
"side menu config": "配置文件",
"side menu database": "数据库文件",
"side menu setting": "设置"
}
}
</i18n>
<template>
<div class="banner-container cursor-pointer dot-bg" @click="goHome">
<div class="font-bold text-left antialiased font-sans banner-text">Arona</div>
<div>
<el-select v-model="select" placeholder="全部" clearable @change="updateActiveGroup">
<el-option v-for="(e, index) in groups" :key="index" :value="e.id" :label="e.name" />
</el-select>
</div>
</div>
</template>
<script setup lang="ts">
import useBaseStore from "@/store/base";
const router = useRouter();
const baseStore = useBaseStore();
const select = ref<number>();
function goHome() {
router.push("/config");
}
function updateActiveGroup(group: number) {
baseStore.setActiveGroupId(group);
}
const groups = computed(() => baseStore.groups());
</script>
<style lang="scss" scoped>
.banner-container {
display: flex;
justify-content: space-between;
position: sticky;
z-index: 999;
$font-size: 36px;
line-height: $font-size + 12px;
top: 0;
width: 100%;
left: 0;
padding: 0 20px;
border-bottom: 1px solid var(--el-border-color);
> div {
flex: 1;
&:last-child {
text-align: right;
}
}
.banner-text {
font-size: $font-size;
}
}
</style>
<template>
<div class="dot-bg">
<el-page-header :content="routerTitle" class="page-header" @back="goBack">
<template v-if="!routerTitle" #title>
<slot name="title" />
</template>
</el-page-header>
<el-divider v-if="props.title" />
</div>
</template>
<script setup lang="ts">
const route = useRoute();
const router = useRouter();
const props = defineProps<Props>();
const goBack = () => {
router.go(-1);
};
const routerTitle = computed(() => (route.meta.title as string) || (props.title as string) || "");
interface Props {
title?: string;
}
</script>
<style lang="scss">
.dot-bg {
margin-right: 20px;
}
.page-header {
padding-top: 10px;
margin-bottom: 20px;
}
</style>
<template>
<div class="card" :style="paddingTop">
<slot />
</div>
</template>
<script setup lang="ts">
const props = withDefaults(defineProps<{ disablePaddingTop: boolean }>(), {
disablePaddingTop: false,
});
const paddingTop = computed(() => {
if (props.disablePaddingTop) {
return { "padding-top": "0" };
}
return {};
});
</script>
<style lang="scss" scoped>
.card {
padding: 16px;
border-radius: var(--el-border-radius-base);
box-shadow: var(--el-box-shadow-light);
}
</style>
<template>
<el-affix :offset="60">
<PageHeader />
</el-affix>
<div style="padding-right: 20px">
<router-view />
</div>
</template>
<script setup lang="ts"></script>
<style lang="scss" scoped></style>
<template>
<div class="text-center">
<el-tooltip :content="t('home')" placement="top">
<router-link class="icon-btn mx-2" to="/">
<i-mdi-home-search-outline class="icon-footer" />
</router-link>
</el-tooltip>
<el-tooltip :content="isDark ? t('change light') : t('change dark')" placement="top">
<button class="icon-btn mx-2 !outline-none" @click="toggleDark()">
<i-ph-cloud-moon-bold v-if="isDark" class="icon-footer" />
<i-ph-sun-horizon-bold v-else class="icon-footer" />
</button>
</el-tooltip>
<el-tooltip :content="t('change lang')" placement="top">
<button class="icon-btn mx-2" @click="toggleLocales()">
<i-la-language class="icon-footer" />
</button>
</el-tooltip>
<el-tooltip :content="t('method to using')" placement="top">
<router-link class="icon-btn mx-2" to="/process">
<i-ri-article-line class="icon-footer" />
</router-link>
</el-tooltip>
<el-tooltip :content="t('template process')" placement="top">
<a class="icon-btn mx-2" href="https://juejin.cn/post/7058201396113309703" target="_blank" title="JveJin">
<i-mdi-content-duplicate class="icon-footer" />
</a>
</el-tooltip>
<el-tooltip content="GitHub" placement="top">
<a class="icon-btn mx-2" href="https://github.com/nekobc1998923/vitecamp" target="_blank" title="GitHub">
<i-akar-icons-github-fill class="icon-footer" />
</a>
</el-tooltip>
</div>
</template>
<script setup lang="ts">
import { isDark, toggleDark } from '@/utils/dark';
const { t, availableLocales, locale } = useI18n();
const toggleLocales = () => {
const locales = availableLocales;
locale.value = locales[(locales.indexOf(locale.value) + 1) % locales.length];
};
</script>
<style lang="scss">
.icon-footer {
font-size: 1.3em;
}
</style>
## 现在可以试试!
### GitHub 模板
[使用这个模板创建仓库](https://github.com/nekobc1998923/vitecamp/generate).
### 克隆到本地
```bash
git clone https://github.com/nekobc1998923/vitecamp.git my-vitecamp-app
cd my-vitecamp-app
pnpm i
```
## 清单
使用此模板时,请尝试按照清单正确更新您自己的信息
-`LICENSE` 中改变作者名
-`package.json` 中改变作者名
-`.env` 中改变标题
-`public` 目录下改变 favicon
- 整理 `README `并删除路由
然后,你就可以享受编写代码的乐趣了 :)
## 使用
### 开发
只需要执行以下命令就可以在 http://localhost:8080 中看到
```bash
pnpm run dev
```
### 构建
构建该应用只需要执行以下命令
```bash
pnpm run build
```
然后你会看到用于发布的 `dist` 文件夹被生成。
// eslint-disable-next-line import/prefer-default-export
export const HTTP_OK = 200;
export const HTTP_ERROR = 100;
export * from "./http";
// @ts-nocheck
/// <reference types="vite/client" />
/// <reference types="vite-svg-loader" />
// 声明自动引入的 vue 组件
// @ts-ignore
// @ts-ignore
import { App } from "vue";
import {Block} from "blockly";
declare module '*.vue' {
import { DefineComponent } from "vue";
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types
const component: DefineComponent<{}, {}, any>;
export default component;
}
// 声明 icons 引入的组件
declare module '~icons/*' {
import { FunctionalComponent, SVGAttributes } from "vue";
const component: FunctionalComponent<SVGAttributes>;
export default component;
}
// 声明 md 文件
declare module '*.md' {
import type { DefineComponent } from "vue";
const component: DefineComponent<{}, {}, any>;
export default component;
}
// 声明 vite 环境变量
declare interface ImportMetaEnv {
readonly VITE_BASE: string;
readonly VITE_API_BASEURL: string;
readonly VITE_APP_TITLE: string;
// 更多环境变量...
}
declare interface ImportMeta {
readonly env: ImportMetaEnv;
}
type SelectType = "friend";
interface ExtendBlock extends Block {
data: SelectType | string;
}
interface Blocks {
[key: string]: ExtendBlock;
}
declare global {
module "blockly" {
export * from "blockly/core/blockly";
const Blocks: Blocks
}
}
import { AxiosError, AxiosPromise, AxiosRequestConfig, AxiosResponse } from "axios";
import { instanceObject } from "@/utils/format";
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export interface IRequestConfig<D = any> extends AxiosRequestConfig<D> {
// 当网络请求错误时是否显示错误
showResponseError?: boolean;
// 当http 200但是 serverResponse.code !== 200 时是否显示 serverResponse.message
// 默认开启
showServerResponseError?: boolean;
// 返回值是否是文件流
isBlob?: boolean;
version?: "v1" | "v2";
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export interface IResponseError<T = any, D = any> extends AxiosError<T, D> {
config: IRequestConfig<D>;
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export interface IResponse<T = any, D = any> extends AxiosResponse<T, D> {
config: IRequestConfig<D>;
}
export interface ServerResponse<T> {
code: number;
message: string;
data: T;
}
export interface ApiServiceAdapter {
upload(url: string, file: FormData | File): Promise<ServerResponse<string>>;
download(id: string): AxiosPromise;
raw<T>(config: IRequestConfig): Promise<ServerResponse<T>>;
urlDownload(url: string, data: instanceObject): void;
}
export const NetworkAdapter = {
Offline: "离线",
Localhost: "本地连接",
Proxy: "代理",
};
export type NetworkAdapterType = keyof typeof NetworkAdapter;
export type Config2Map<Config> = {
[key in keyof Config]: {
value: Config[key];
description: string;
};
};
export type Config2Form<Config> = {
[key in keyof Config]: Config[key] | null;
};
export function enumTypeList<T extends object>(list: T) {
return Object.keys(list).map((key) => ({
label: Reflect.get(list, key),
value: key,
}));
}
// i18n
import { createI18n } from "vue-i18n";
import messages from "@intlify/vite-plugin-vue-i18n/messages";
// vue router
import router from "@/router/index";
// pinia
import store from "@/store";
import App from "./App.vue";
import "virtual:windi.css";
// Devtools: https://windicss.org/integrations/vite.html#design-in-devtools
import "virtual:windi-devtools";
import "@/assets/styles/index.scss";
import "element-plus/dist/index.css";
import { setApp } from "@/utils/vueTools";
const i18n = createI18n({
locale: "zh-cn",
fallbackLocale: "zh",
messages,
});
const app = createApp(App);
app.use(router).use(store);
app.use(i18n);
app.mount("#app");
setApp(app);
import { createRouter, createWebHistory, Router, RouteRecordRaw } from "vue-router";
import NProgress from "nprogress";
import exceptionRoutes from "@/router/route.exception";
import asyncRoutes from "@/router/route.async";
import commonRoutes from "@/router/route.common";
const routes: Array<RouteRecordRaw> = [
// 无鉴权的业务路由 ex:登录
...commonRoutes,
// 带鉴权的业务路由
...asyncRoutes,
// 异常页必须放在路由匹配规则的最后
...exceptionRoutes,
];
const router: Router = createRouter({
// 新的vue-router4 使用 history路由模式 和 base前缀
history: createWebHistory(import.meta.env.VITE_BASE),
routes,
});
/**
* @description: 全局路由前置守卫,在进入路由前触发,导航在所有守卫 resolve 完之前一直处于等待中。
* @param { RouteLocationNormalized } to 即将要进入的目标
* @param { RouteLocationNormalizedLoaded } from 当前导航正在离开的路由
* @return {*}
*/
router.beforeEach((to, from) => {
// console.log("全局路由前置守卫:to,from\n", to, from);
// 设置页面标题
document.title = (to.meta.title as string) || import.meta.env.VITE_APP_TITLE;
if (!NProgress.isStarted()) {
NProgress.start();
}
});
router.afterEach((to, from) => {
// console.log("全局路由后置守卫:to,from\n", to, from);
NProgress.done();
});
export default router;
// 需要鉴权的业务路由
import { RouteRecordRaw } from "vue-router";
const asyncRoutes: Array<RouteRecordRaw> = [
{
path: "/",
redirect: "/home",
},
{
path: "/home",
name: "home",
meta: {
title: "",
icon: "",
},
component: () => import("@/views/home/HomeIndex.vue"),
},
];
export default asyncRoutes;
// 不需要鉴权的业务路由
import { RouteRecordRaw } from "vue-router";
const commonRoutes: Array<RouteRecordRaw> = [];
export default commonRoutes;
// 跟鉴权无关的特殊路由
import { RouteRecordRaw } from "vue-router";
const exceptionRoutes: Array<RouteRecordRaw> = [
{
path: "/401",
name: "401",
meta: {
title: "需要登录",
},
component: () => import("@/views/exception/401.vue"),
},
{
path: "/404",
name: "404",
meta: {
title: "非常抱歉,页面走丢了",
},
component: () => import("@/views/exception/404.vue"),
},
{
path: "/:pathMatch(.*)",
meta: {},
redirect: "/404",
},
];
export default exceptionRoutes;
import { defineStore } from "pinia";
import { NetworkAdapterType } from "@/interface/http";
import { updateAPIService } from "@/api/adapter/localhost";
import { BaseStoreState } from "@/store/type";
const useBaseStore = defineStore({
id: "setting",
state: (): BaseStoreState => ({
adapter: "Localhost",
theme: {
themeType: "亮蓝色",
themeColor: "#2080F0FF",
},
}),
getters: {
getThemeType: (state: BaseStoreState) => state.theme.themeType,
getThemeColor: (state: BaseStoreState) => state.theme.themeColor,
},
actions: {
setAdapter(adapter: NetworkAdapterType) {
this.adapter = adapter;
},
setThemeType(type: string) {
this.theme.themeType = type;
},
},
persist: {
key: "setting",
afterRestore: (ctx) => {
if (ctx.store.isRestoreBackend) {
updateAPIService(ctx.store.api.host, ctx.store.api.port);
}
},
},
});
export default useBaseStore;
import { createPinia } from "pinia";
import piniaPluginPersistedstate from "pinia-plugin-persistedstate";
const store = createPinia();
store.use(piniaPluginPersistedstate);
export default store;
import { NetworkAdapterType } from "@/interface/http";
export interface BaseStoreState {
adapter: NetworkAdapterType;
theme: {
themeType: string;
themeColor: string | number;
};
}
export const isDark = useDark();
export const toggleDark = useToggle(isDark);
export declare interface instanceObject {
[key: string]: string;
}
/**
* JSON转url参数
* @param data Json格式数据
* */
export const formatJsonToUrlParams = (data: instanceObject) => {
return typeof data === "object"
? Object.keys(data)
.map((key) => {
return `${encodeURIComponent(key)}=${encodeURIComponent(data[key])}`;
})
.join("&")
: "";
};
export default formatJsonToUrlParams;
import { forOwn } from "lodash";
import { Config2Form, Config2Map } from "@/interface";
export function extraDomBounding(dom: HTMLElement) {
const style = getComputedStyle(dom);
return {
width: Number(style.width.replace("px", "")),
height: Number(style.width.replace("px", "")),
};
}
export function fillConfigMap<T>(remote: Config2Map<T>, local: Config2Form<T>) {
forOwn(remote, (value, key) => {
Reflect.set(local, key, value.value);
});
}
export function deepCopy<T>(data: T): T {
return JSON.parse(JSON.stringify(data));
}
export function fillForm<IForm extends object>(form: IForm, data: IForm, keys: (keyof IForm)[]) {
keys.forEach((key) => {
const value = Reflect.get(data, key);
Reflect.set(form, key, value);
});
}
export function dataFilterChain<T, Form extends object>(
data: T[],
filterForm: Form,
filterFn: ((data: T[], value: any) => T[])[],
keys: (keyof Form)[],
): T[] {
if (keys.length !== filterFn.length) {
return data;
}
filterFn.forEach((fn, index) => {
const key = keys[index];
const value = Reflect.get(filterForm, key);
if (!value || (Array.isArray(value) && value.length === 0)) {
return;
}
data = fn(data, value);
});
return data;
}
/**
* 返回start至end之间的随机整数
* @param start
* @param end
* @return [start,end)
*/
export function randomInt(start: number, end: number) {
return Math.floor(Math.random() * (end - start) + start);
}
/**
* 随机选取arr里的一个item
* @param arr
*/
export function randomArrayItem<T>(arr: T[]): T {
const index = randomInt(0, arr.length);
return arr[index];
}
/**
* 随机选取arr里0至size-1的一个item,并放回最后
* @param arr
*/
export function pickRandomArrayItemAndPutBack<T>(arr: T[]) {
if (arr.length < 1) {
return {
arr,
item: arr[0],
};
}
const pickItem = randomArrayItem(arr.slice(0, arr.length - 1));
arr.splice(arr.indexOf(pickItem), 1);
arr.push(pickItem);
return {
arr,
item: pickItem,
};
}
import { ElMessage, ElMessageBox } from "element-plus";
import { ElMessageBoxOptions, MessageBoxData } from "element-plus/es/components/message-box/src/message-box.type";
export function infoMessage(info: any) {
return ElMessage.info(info);
}
export function successMessage(info: any) {
return ElMessage.success(info);
}
export function warningMessage(info: any) {
return ElMessage.warning(info);
}
export function errorMessage(info: any) {
return ElMessage.error(info);
}
export function IPrompt(title: string, message: string, config?: ElMessageBoxOptions): Promise<MessageBoxData> {
return ElMessageBox.prompt(message, title, config);
}
export function IConfirm(title: string, message: string, config?: ElMessageBoxOptions) {
return ElMessageBox.confirm(message, title, config);
}
export function IWarningConfirm(title: string, message: string, config?: ElMessageBoxOptions) {
return IConfirm(title, message, {
...config,
type: "warning",
});
}
import dayjs from "dayjs";
/**
* 获取格式化的当前时间
* @param format 格式化字符串
* return 格式化的当前时间
*/
// eslint-disable-next-line import/prefer-default-export
export function nowTime(format = "yyyy-MM-dd HH:mm:ss"): string {
return dayjs().format(format);
}
export function nowSecond(time: number): string {
return dayjs().startOf("day").second(time).format("mm:ss");
}
import { App, createVNode, defineAsyncComponent, render } from "vue";
import { VNodeProps } from "@vue/runtime-core";
type NodeEventListener<K extends keyof HTMLElementEventMap> = {
type: K;
handler: (ev: HTMLElementEventMap[K]) => void;
};
export function mountAsyncComponent(
loader: Parameters<typeof defineAsyncComponent>[0],
props?: (Record<string, unknown> & VNodeProps) | null,
hook?: NodeEventListener<keyof HTMLElementEventMap>[],
): HTMLElement {
const component = defineAsyncComponent(loader);
const componentVNode = createVNode(component, props);
componentVNode.appContext = _app._context;
const container = document.createElement("div");
if (hook) {
hook.forEach((it) => container.addEventListener(it.type, it.handler));
}
render(componentVNode, container);
return container;
}
let _app: App;
export function setApp(app: App) {
_app = app;
}
export function useApp() {
return _app;
}
<template>
<el-row>
<el-col>
<el-result icon="warning" title="页面无权限" sub-title="请联系管理员申请权限">
<template #extra>
<el-button type="primary" @click="goBack">Back</el-button>
</template>
</el-result>
</el-col>
</el-row>
</template>
<script setup lang="ts">
const router = useRouter();
const goBack = () => {
router.push({
name: 'home',
});
};
</script>
<template>
<el-row>
<el-col>
<el-result icon="warning" title="页面未找到" sub-title="请检查路径后重试或返回首页">
<template #extra>
<el-button type="primary" @click="goBack">Back</el-button>
</template>
</el-result>
</el-col>
</el-row>
</template>
<script setup lang="ts">
const router = useRouter();
const goBack = () => {
router.push({
name: 'home',
});
};
</script>
<template>
<div class="home">
<h1>Home</h1>
<div>
<img src="/favicon.svg" alt="icon" />
</div>
</div>
</template>
<script setup lang="ts">
</script>
<style lang="scss" scoped>
.home {
width: 100dvw;
height: 100dvh;
text-align: center;
justify-content: center;
display: flex;
flex-direction: column;
img {
width: 300px;
}
div {
display: flex;
justify-content: center;
}
}
</style>
This diff was suppressed by a .gitattributes entry.
import { defineConfig, loadEnv, normalizePath } from "vite";
import { resolve } from "path";
import OptimizationPersist from "vite-plugin-optimize-persist";
import PkgConfig from "vite-plugin-package-config";
import VueTypeImports from "vite-plugin-vue-type-imports";
// @ts-ignore
import path from "node:path";
import { viteStaticCopy } from "vite-plugin-static-copy";
import presets from "./presets/presets";
// https://vitejs.dev/config/
export default defineConfig((env) => {
// env 环境变量
const viteEnv = loadEnv(env.mode, process.cwd());
return {
base: viteEnv.VITE_BASE,
// 插件
plugins: [
presets(env),
VueTypeImports(),
PkgConfig(),
OptimizationPersist(),
viteStaticCopy({
targets: [
{
// eslint-disable-next-line no-undef
src: normalizePath(path.resolve(__dirname, "./node_modules/blockly/media/*")),
dest: "media",
},
],
}),
],
// 别名设置
resolve: {
alias: {
"@": resolve(__dirname, "./src"), // 把 @ 指向到 src 目录去
},
},
// 服务设置
server: {
host: true, // host设置为true才可以使用network的形式,以ip访问项目
port: 12590, // 端口号
open: true, // 自动打开浏览器
cors: true, // 跨域设置允许
strictPort: false, // 如果端口已占用直接退出
// 接口代理
// proxy: {
// "/api": {
// // 本地 8000 前端代码的接口 代理到 8888 的服务端口
// target: "http://localhost:8888/",
// changeOrigin: true, // 允许跨域
// rewrite: (path) => path.replace("/api/", "/"),
// },
// },
},
build: {
reportCompressedSize: false,
// 消除打包大小超过500kb警告
chunkSizeWarningLimit: 2000,
minify: "esbuild",
assetsDir: "static/assets",
target: "esnext",
// 静态资源打包到dist下的不同目录
rollupOptions: {
output: {
chunkFileNames: "static/js/[name]-[hash].js",
entryFileNames: "static/js/[name]-[hash].js",
assetFileNames: "static/[ext]/[name]-[hash].[ext]",
},
},
},
css: {
preprocessorOptions: {
// 全局引入了 scss 的文件
scss: {
additionalData: `
@import "@/assets/styles/variables.scss";
`,
javascriptEnabled: true,
},
},
},
};
});
import { defineConfig } from "vite-plugin-windicss";
import typography from "windicss/plugin/typography";
import colors from "windicss/colors";
export default defineConfig({
darkMode: "class",
plugins: [typography()],
theme: {
fontFamily: {
sans: ["Open Sans", "ui-sans-serif", "system-ui"],
serif: ["Montserrat", "ui-serif", "Georgia"],
mono: ["Fira Sans", "ui-monospace", "SFMono-Regular"],
},
extend: {
typography: {
DEFAULT: {
css: {
maxWidth: "65ch",
color: "inherit",
a: {
color: "inherit",
opacity: 0.75,
fontWeight: "500",
textDecoration: "underline",
"&:hover": {
opacity: 1,
color: colors.teal[600],
},
},
b: { color: "inherit" },
strong: { color: "inherit" },
em: { color: "inherit" },
h1: { color: "inherit" },
h2: { color: "inherit" },
h3: { color: "inherit" },
h4: { color: "inherit" },
code: { color: "inherit" },
},
},
},
},
},
});
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment