feat(init): 项目初始化构建
Some checks failed
Lint Code / Lint Code (push) Failing after 35s

This commit is contained in:
2026-03-27 16:50:27 +08:00
commit 2b62486364
637 changed files with 108813 additions and 0 deletions

4
.browserslistrc Normal file
View File

@@ -0,0 +1,4 @@
> 1%
last 2 versions
not dead
not ie 11

21
.dockerignore Normal file
View File

@@ -0,0 +1,21 @@
node_modules
.DS_Store
dist
dist-ssr
*.local
.eslintcache
report.html
yarn.lock
npm-debug.log*
.pnpm-error.log*
.pnpm-debug.log
tests/**/coverage/
# Editor directories and files
.idea
*.suo
*.ntvs*
*.njsproj
*.sln
tsconfig.tsbuildinfo

14
.editorconfig Normal file
View File

@@ -0,0 +1,14 @@
# http://editorconfig.org
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
insert_final_newline = false
trim_trailing_whitespace = false

5
.env Normal file
View File

@@ -0,0 +1,5 @@
# 平台本地运行端口号
VITE_PORT = 8848
# 是否隐藏首页 隐藏 true 不隐藏 false 勿删除VITE_HIDE_HOME只需在.env文件配置
VITE_HIDE_HOME = false

8
.env.development Normal file
View File

@@ -0,0 +1,8 @@
# 平台本地运行端口号
VITE_PORT = 8848
# 开发环境读取配置文件路径
VITE_PUBLIC_PATH = /
# 开发环境路由历史模式Hash模式传"hash"、HTML5模式传"h5"、Hash模式带base参数传"hash,base参数"、HTML5模式带base参数传"h5,base参数"
VITE_ROUTER_HISTORY = "hash"

13
.env.production Normal file
View File

@@ -0,0 +1,13 @@
# 线上环境平台打包路径
VITE_PUBLIC_PATH = /
# 线上环境路由历史模式Hash模式传"hash"、HTML5模式传"h5"、Hash模式带base参数传"hash,base参数"、HTML5模式带base参数传"h5,base参数"
VITE_ROUTER_HISTORY = "hash"
# 是否在打包时使用cdn替换本地库 替换 true 不替换 false
VITE_CDN = false
# 是否启用gzip压缩或brotli压缩分两种情况删除原始文件和不删除原始文件
# 压缩时不删除原始文件的配置gzip、brotli、both同时开启 gzip 与 brotli 压缩、none不开启压缩默认
# 压缩时删除原始文件的配置gzip-clear、brotli-clear、both-clear同时开启 gzip 与 brotli 压缩、none不开启压缩默认
VITE_COMPRESSION = "none"

16
.env.staging Normal file
View File

@@ -0,0 +1,16 @@
# 预发布也需要生产环境的行为
# https://cn.vitejs.dev/guide/env-and-mode.html#modes
# NODE_ENV = development
VITE_PUBLIC_PATH = /
# 预发布环境路由历史模式Hash模式传"hash"、HTML5模式传"h5"、Hash模式带base参数传"hash,base参数"、HTML5模式带base参数传"h5,base参数"
VITE_ROUTER_HISTORY = "hash"
# 是否在打包时使用cdn替换本地库 替换 true 不替换 false
VITE_CDN = true
# 是否启用gzip压缩或brotli压缩分两种情况删除原始文件和不删除原始文件
# 压缩时不删除原始文件的配置gzip、brotli、both同时开启 gzip 与 brotli 压缩、none不开启压缩默认
# 压缩时删除原始文件的配置gzip-clear、brotli-clear、both-clear同时开启 gzip 与 brotli 压缩、none不开启压缩默认
VITE_COMPRESSION = "none"

2
.gitattributes vendored Normal file
View File

@@ -0,0 +1,2 @@
public/wasm/capture.worker.js linguist-language=Vue
public/wasm/index.js linguist-language=Vue

38
.github/ISSUE_TEMPLATE/bug_report.yml vendored Normal file
View File

@@ -0,0 +1,38 @@
name: "\U0001F41E Bug report"
description: Report an issue with vue-pure-admin
body:
- type: markdown
attributes:
value: |
感谢您花时间填写此错误报告 (Thanks for taking the time to fill out this bug report)
- type: textarea
id: bug-description
attributes:
label: 描述问题 (Describe the problem)
placeholder: 请描述您的问题 (Please describe your problem)
validations:
required: true
- type: textarea
id: reproduction-steps
attributes:
label: 如何复现该问题 (How to reproduce the problem)
placeholder: 请提供复现问题的具体操作步骤以便平台快速定位、高效地解决问题。当然如果问题的操作步骤较复杂您可以fork平台然后去改动代码复现问题这样更高效 (Please provide specific steps to reproduce the problem, so that the platform can quickly locate and solve the problem efficiently. Of course, if the operation steps of the problem are more complicated, you can fork the platform, and then modify the code to reproduce the problem, which is more efficient)
validations:
required: true
- type: textarea
id: system-info
attributes:
label: 操作系统和浏览器信息 (Operating system and browser information)
placeholder: 如果您遇到操作系统或浏览器兼容性问题,可选填此项 (Optional if you encounter operating system or browser compatibility issues)
validations:
required: false
- type: checkboxes
id: checkboxes
attributes:
label: 验证 (Verify)
description: 在提交问题之前,请确保您执行以下操作 (Before submitting an issue, please ensure you do the following)
options:
- label: 是否仔细阅读过 [文档](https://pure-admin.cn/) (Have you read [documentation](https://pure-admin.cn/) carefully)
required: true
- label: 检查是否存在相同或类似的问题 [issues](https://github.com/pure-admin/vue-pure-admin/issues) (Check for the same or similar [issues](https://github.com/pure-admin/vue-pure-admin/issues))
required: true

1
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@@ -0,0 +1 @@
blank_issues_enabled: false

52
.github/workflows/linter.yml vendored Normal file
View File

@@ -0,0 +1,52 @@
name: Lint Code
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
build:
name: Lint Code
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- uses: pnpm/action-setup@v3
name: Install pnpm
id: pnpm-install
with:
version: 9
run_install: false
- name: Get pnpm store directory
id: pnpm-cache
shell: bash
run: |
echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
- uses: actions/cache@v4
name: Setup pnpm cache
with:
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-
- name: Start Lint Code
run: |
pnpm install --no-frozen-lockfile
pnpm lint
pnpm typecheck
env:
VALIDATE_ALL_CODEBASE: false
DEFAULT_BRANCH: main
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

42
.github/workflows/pages.yml vendored Normal file
View File

@@ -0,0 +1,42 @@
name: Build and Deploy
permissions:
contents: write
on:
push:
branches:
- pages
jobs:
deploy:
concurrency: ci-${{ github.ref }}
runs-on: ubuntu-latest
steps:
- name: Checkout 🛎️
uses: actions/checkout@v4
- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version: 20
registry-url: https://registry.npmjs.com/
- uses: pnpm/action-setup@v3
name: Install pnpm
id: pnpm-install
with:
version: 9
run_install: false
- name: Deploy 🔧
run: |
pnpm install --no-frozen-lockfile
sed -i "s#VITE_PUBLIC_PATH = /#VITE_PUBLIC_PATH = /vue-pure-admin/#g" $(pwd)/.env.production
pnpm build
cd dist
touch README.md .nojekyll
- name: Deploy 🚀
uses: JamesIves/github-pages-deploy-action@v4
with:
folder: dist
clean: true

22
.gitignore vendored Normal file
View File

@@ -0,0 +1,22 @@
node_modules
.DS_Store
dist
dist-ssr
*.local
.eslintcache
report.html
vite.config.*.timestamp*
yarn.lock
npm-debug.log*
.pnpm-error.log*
.pnpm-debug.log
tests/**/coverage/
# Editor directories and files
.idea
*.suo
*.ntvs*
*.njsproj
*.sln
tsconfig.tsbuildinfo

5
.gitpod.yml Normal file
View File

@@ -0,0 +1,5 @@
ports:
- port: 3344
onOpen: open-preview
tasks:
- init: pnpm install && pnpm serve

1
.husky/commit-msg Normal file
View File

@@ -0,0 +1 @@
pnpm exec commitlint --edit $1

1
.husky/pre-commit Normal file
View File

@@ -0,0 +1 @@
pnpm exec lint-staged

20
.lintstagedrc Normal file
View File

@@ -0,0 +1,20 @@
{
"*.{js,jsx,ts,tsx}": [
"prettier --cache --ignore-unknown --write",
"eslint --cache --fix"
],
"{!(package)*.json,*.code-snippets,.!({browserslist,npm,nvm})*rc}": [
"prettier --cache --write --parser json"
],
"package.json": ["prettier --cache --write"],
"*.vue": [
"prettier --write",
"eslint --cache --fix",
"stylelint --fix --allow-empty-input"
],
"*.{css,scss,html}": [
"prettier --cache --ignore-unknown --write",
"stylelint --fix --allow-empty-input"
],
"*.md": ["prettier --cache --ignore-unknown --write"]
}

11
.markdownlint.json Normal file
View File

@@ -0,0 +1,11 @@
{
"default": true,
"MD003": false,
"MD033": false,
"MD013": false,
"MD001": false,
"MD025": false,
"MD024": false,
"MD007": { "indent": 4 },
"no-hard-tabs": false
}

4
.npmrc Normal file
View File

@@ -0,0 +1,4 @@
shell-emulator=true
shamefully-hoist=true
enable-pre-post-scripts=false
strict-peer-dependencies=false

1
.nvmrc Normal file
View File

@@ -0,0 +1 @@
v24.12.0

1
.prettierignore Normal file
View File

@@ -0,0 +1 @@
src/views/system/menu/README.md

9
.prettierrc.js Normal file
View File

@@ -0,0 +1,9 @@
// @ts-check
/** @type {import("prettier").Config} */
export default {
bracketSpacing: true,
singleQuote: false,
arrowParens: "avoid",
trailingComma: "none"
};

4
.stylelintignore Normal file
View File

@@ -0,0 +1,4 @@
/dist/*
/public/*
public/*
src/style/reset.scss

20
.vscode/extensions.json vendored Normal file
View File

@@ -0,0 +1,20 @@
{
"recommendations": [
"christian-kohler.path-intellisense",
"warmthsea.vscode-custom-code-color",
"vscode-icons-team.vscode-icons",
"davidanson.vscode-markdownlint",
"ms-azuretools.vscode-docker",
"stylelint.vscode-stylelint",
"bradlc.vscode-tailwindcss",
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"lokalise.i18n-ally",
"redhat.vscode-yaml",
"csstools.postcss",
"mikestead.dotenv",
"eamodio.gitlens",
"antfu.iconify",
"Vue.volar"
]
}

65
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,65 @@
{
"tailwindCSS.experimental.configFile": "src/style/tailwind.css",
"editor.formatOnType": true,
"editor.formatOnSave": true,
"[vue]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"editor.tabSize": 2,
"editor.formatOnPaste": true,
"editor.guides.bracketPairs": "active",
"files.autoSave": "afterDelay",
"git.confirmSync": false,
"workbench.startupEditor": "newUntitledFile",
"editor.suggestSelection": "first",
"editor.acceptSuggestionOnCommitCharacter": false,
"css.lint.propertyIgnoredDueToDisplay": "ignore",
"editor.quickSuggestions": {
"other": true,
"comments": true,
"strings": true
},
"files.associations": {
"editor.snippetSuggestions": "top"
},
"[css]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
},
"i18n-ally.localesPaths": "locales",
"i18n-ally.keystyle": "nested",
"i18n-ally.sortKeys": true,
"i18n-ally.namespace": true,
"i18n-ally.enabledParsers": [
"yaml",
"js"
],
"i18n-ally.sourceLanguage": "en",
"i18n-ally.displayLanguage": "zh-CN",
"i18n-ally.enabledFrameworks": [
"vue"
],
"iconify.excludes": [
"el"
],
"vsmqtt.brokerProfiles": [
{
"name": "broker.emqx.io",
"host": "broker.emqx.io/mqtt",
"port": 1883,
"clientId": "vsmqtt_client_db34"
}
],
"vscodeCustomCodeColor.highlightValue": [
"v-loading",
"v-auth",
"v-copy",
"v-longpress",
"v-optimize",
"v-perms",
"v-ripple"
],
"vscodeCustomCodeColor.highlightValueColor": "#b392f0",
}

22
.vscode/vue3.0.code-snippets vendored Normal file
View File

@@ -0,0 +1,22 @@
{
"Vue3.0快速生成模板": {
"scope": "vue",
"prefix": "Vue3.0",
"body": [
"<template>",
"\t<div>test</div>",
"</template>\n",
"<script lang='ts'>",
"export default {",
"\tsetup() {",
"\t\treturn {}",
"\t}",
"}",
"</script>\n",
"<style lang='scss' scoped>\n",
"</style>",
"$2"
],
"description": "Vue3.0"
}
}

17
.vscode/vue3.2.code-snippets vendored Normal file
View File

@@ -0,0 +1,17 @@
{
"Vue3.2+快速生成模板": {
"scope": "vue",
"prefix": "Vue3.2+",
"body": [
"<script setup lang='ts'>",
"</script>\n",
"<template>",
"\t<div>test</div>",
"</template>\n",
"<style lang='scss' scoped>\n",
"</style>",
"$2"
],
"description": "Vue3.2+"
}
}

20
.vscode/vue3.3.code-snippets vendored Normal file
View File

@@ -0,0 +1,20 @@
{
"Vue3.3+defineOptions快速生成模板": {
"scope": "vue",
"prefix": "Vue3.3+",
"body": [
"<script setup lang='ts'>",
"defineOptions({",
"\tname: ''",
"})",
"</script>\n",
"<template>",
"\t<div>test</div>",
"</template>\n",
"<style lang='scss' scoped>\n",
"</style>",
"$2"
],
"description": "Vue3.3+defineOptions快速生成模板"
}
}

1038
CHANGELOG.en_US.md Normal file

File diff suppressed because it is too large Load Diff

1038
CHANGELOG.md Normal file

File diff suppressed because it is too large Load Diff

1037
CHANGELOG.zh_CN.md Normal file

File diff suppressed because it is too large Load Diff

20
Dockerfile Normal file
View File

@@ -0,0 +1,20 @@
FROM node:20-alpine as build-stage
WORKDIR /app
RUN corepack enable
RUN corepack prepare pnpm@latest --activate
RUN npm config set registry https://registry.npmmirror.com
COPY .npmrc package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile
COPY . .
RUN pnpm build
FROM nginx:stable-alpine as production-stage
COPY --from=build-stage /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

21
LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020-present, pure-admin
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.

237
README.en-US.md Normal file
View File

@@ -0,0 +1,237 @@
<h1>vue-pure-admin</h1>
![GitHub license](https://img.shields.io/github/license/pure-admin/vue-pure-admin?style=flat)
![GitHub stars](https://img.shields.io/github/stars/pure-admin/vue-pure-admin?color=fa6470&style=flat)
![GitHub forks](https://img.shields.io/github/forks/pure-admin/vue-pure-admin?style=flat)
**English** | [中文](./README.md)
## Introduction
`vue-pure-admin` is an open source, free and out-of-the-box middle and backend management system template. Completely adopts `ECMAScript` module (`ESM`) specifications to write and organize code, using the latest `Vue3`, `Vite`, `Element-Plus`, `TypeScript`, `Pinia`, `Tailwindcss` and other mainstream technologies develop
## R&D philosophy
Seek innovation in stability and see the future in technology
## Thin version (offering non-internationalized and internationalized versions)
The simplified version is based on the shelf extracted from [vue-pure-admin](https://github.com/pure-admin/vue-pure-admin), which contains main functions and is more suitable for actual project development. The packaged size is introduced globally [element-plus](https://element-plus.org) is still below `2.3MB`, and the full version of the code will be permanently synchronized. After enabling `brotli` compression and `cdn` to replace the local library mode, the package size is less than `350kb`
[Click to view the non-internationalized version](https://github.com/pure-admin/pure-admin-thin)
[Click to view Internationalization version](https://github.com/pure-admin/pure-admin-thin/tree/i18n)
## Supporting video
[Click me to view UI design](https://www.bilibili.com/video/BV17g411T7rq)
[Click me to view the rapid development tutorial](https://www.bilibili.com/video/BV1kg411v7QT)
## Nanny-level documents
[Click me to view vue-pure-admin documentation](https://pure-admin.cn/)
[Click me to view @pureadmin/utils documentation](https://pure-admin-utils.netlify.app)
## Premium service
[Click me for details](https://pure-admin.cn/pages/service/)
## Tauri
[Click Watch Tauri](https://github.com/pure-admin/tauri-pure-admin)
## Electron
[Click Watch Electron](https://github.com/pure-admin/electron-pure-admin)
## Preview
[preview station](https://pure-admin.github.io/vue-pure-admin)
`PC`
<p align="center">
<img alt="PureAdmin" src="https://xiaoxian521.github.io/hyperlink/img/vue-pure-admin/1.jpg">
<br />
<img alt="PureAdmin" src="https://xiaoxian521.github.io/hyperlink/img/vue-pure-admin/2.jpg">
</p>
`DarkMode`
<p align="center">
<img alt="PureAdmin" src="https://xiaoxian521.github.io/hyperlink/img/vue-pure-admin/3.jpg">
<br />
<img alt="PureAdmin" src="https://xiaoxian521.github.io/hyperlink/img/vue-pure-admin/4.jpg">
</p>
`Mobile`
<p align="center">
<img alt="PureAdmin" src="https://xiaoxian521.github.io/hyperlink/img/vue-pure-admin/5.jpg">
</p>
### Use Gitpod
Open the project in Gitpod (free online dev environment for GitHub) and start coding immediately.
[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/pure-admin/vue-pure-admin)
## Install And Use
### Pull code
#### It is recommended to use `@pureadmin/cli` scaffolding
<br/>
<img src="https://xiaoxian521.github.io/hyperlink/gif/pure-admin-cli.gif" alt="pure-admin-cli" />
1. Global installation
```bash
npm install -g @pureadmin/cli
```
2. Interactively select templates and create projects
```bash
pure create
```
[Click to view the detailed usage of @pureadmin/cli scaffolding](https://github.com/pure-admin/pure-admin-cli#pureadmincli)
#### Pull from `GitHub`
```bash
git clone https://github.com/pure-admin/vue-pure-admin.git
```
#### Pulled from `Gitee`
```bash
git clone https://gitee.com/yiming_chang/vue-pure-admin.git
```
### Install dependencies
```bash
cd vue-pure-admin
pnpm install
```
### Run platform
```bash
pnpm dev
```
### Project packaging
```bash
pnpm build
```
## Docker support
1. Customize the image named `vue-pure-admin` (please note that there is a dot `.` at the end of the command below, indicating that the `Dockerfile` file in the current path is used, and the path can be specified according to the actual situation)
```bash
docker build -t vue-pure-admin .
```
2. Port mapping and start the `docker` container (`8080:80`: indicates that the `80` port is used in the container, and the port is forwarded to the `8080` port of the host; `pure-admin`: indicates a custom container name; `vue-pure-admin`: indicates the custom image name)
```bash
docker run -dp 8080:80 --name pure-admin vue-pure-admin
```
After operating the above two commands, open `http://localhost:8080` in the browser to preview
Of course, you can also operate the `docker` project through the [Docker Desktop](https://www.docker.com/products/docker-desktop/) visual interface, as shown below
<p align="center">
<img alt="docker-desktop" width="100%" src="https://xiaoxian521.github.io/hyperlink/img/docker-desktop.jpg">
</p>
## Change Log
[CHANGELOG](./CHANGELOG.en_US.md)
## How to contribute
You are very welcome to join[Raise an issue](https://github.com/pure-admin/vue-pure-admin/issues/new/choose) Or submit a Pull Request
**Pull Request:**
1. Fork code!
2. Create your own branch: `git checkout -b feat/xxxx`
3. Submit your changes: `git commit -am 'feat(function): add xxxxx'`
4. Push your branch: `git push origin feat/xxxx`
5. submit`pull request`
## Special code contributions
Thank you very much for your in-depth understanding of the source code and your outstanding contributions to the `pure-admin` organization ❤️
| **Contributor** | **SpecificCode** |
| :---------------------------------------------: | :------------------------------------------------------------------------------: |
| [hb0730](https://github.com/hb0730) | [code](https://github.com/pure-admin/vue-pure-admin/commits?author=hb0730) |
| [o-cc](https://github.com/o-cc) | [code](https://github.com/pure-admin/vue-pure-admin/commits?author=o-cc) |
| [yj-liuzepeng](https://github.com/yj-liuzepeng) | [code](https://github.com/pure-admin/vue-pure-admin/commits?author=yj-liuzepeng) |
| [skyline523](https://github.com/skyline523) | [code](https://github.com/pure-admin/vue-pure-admin/commits?author=skyline523) |
| [shark-lajiao](https://github.com/shark-lajiao) | [code](https://github.com/pure-admin/vue-pure-admin/commits?author=shark-lajiao) |
| [WitMiao](https://github.com/WitMiao) | [code](https://github.com/pure-admin/vue-pure-admin/commits?author=WitMiao) |
| [QFifteen](https://github.com/QFifteen) | [code](https://github.com/pure-admin/vue-pure-admin/commits?author=QFifteen) |
| [edgexie](https://github.com/edgexie) | [code](https://github.com/pure-admin/vue-pure-admin/commits?author=edgexie) |
| [way-jm](https://github.com/way-jm) | [code](https://github.com/pure-admin/vue-pure-admin/commits?author=way-jm) |
| [simple-hui](https://github.com/simple-hui) | [code](https://github.com/pure-admin/vue-pure-admin/commits?author=simple-hui) |
| [tinysimple](https://github.com/tinysimple) | [code](https://github.com/pure-admin/vue-pure-admin/commits?author=tinysimple) |
## Git Contribution submission specification
reference [vue](https://github.com/vuejs/vue/blob/dev/.github/COMMIT_CONVENTION.md) specification ([Angular](https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-changelog-angular))
- `feat` Add new features
- `fix` Fix the problem/BUG
- `style` The code style is related and does not affect the running result
- `perf` Optimization/performance improvement
- `refactor` Refactor
- `revert` Undo edit
- `test` Test related
- `docs` Documentation/notes
- `chore` Dependency update/scaffolding configuration modification etc.
- `workflow` Workflow improvements
- `ci` Continuous integration
- `types` Type definition file changes
- `wip` In development
## Browser support
It is recommended to use `Chrome`, `Edge`, and `Firefox` browsers for local development. The author commonly uses the latest version of `Chrome` browser.
In actual use, I feel that `Firefox` is smoother in animation than other browsers, but the author is used to using `Chrome`. It depends on personal preference.
For more detailed browser compatibility support, please see [Which browsers does Vue support? ](https://vuejs.org/about/faq.html#what-browsers-does-vue-support) and [Vite browser compatibility](https://vitejs.dev/guide/build.html#browser-compatibility)
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt=" Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>IE | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt=" Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari |
| :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
| not support | last 2 versions | last 2 versions | last 2 versions | last 2 versions |
## Maintainer
[xiaoxian521](https://github.com/xiaoxian521)、[Ten-K](https://github.com/Ten-K)
## License
Completely free and open source
[MIT © 2020-present, pure-admin](./LICENSE)
## `Star`
Many thanks to the kind individuals who leave a star. Your support is much appreciated :heart:
[![Stargazers repo roster for @pure-admin/vue-pure-admin](https://bytecrank.com/nastyox/reporoster/php/stargazersSVG.php?user=pure-admin&repo=vue-pure-admin)](https://github.com/pure-admin/vue-pure-admin/stargazers)
## `Fork`
It's so cool that you study hard :heart:
[![Forkers repo roster for @pure-admin/vue-pure-admin](https://bytecrank.com/nastyox/reporoster/php/forkersSVG.php?user=pure-admin&repo=vue-pure-admin)](https://github.com/pure-admin/vue-pure-admin/network/members)

238
README.md Normal file
View File

@@ -0,0 +1,238 @@
<h1>vue-pure-admin</h1>
![GitHub license](https://img.shields.io/github/license/pure-admin/vue-pure-admin?style=flat)
![GitHub stars](https://img.shields.io/github/stars/pure-admin/vue-pure-admin?color=fa6470&style=flat)
![GitHub forks](https://img.shields.io/github/forks/pure-admin/vue-pure-admin?style=flat)
**中文** | [English](./README.en-US.md)
## 简介
`vue-pure-admin` 是一款开源免费且开箱即用的中后台管理系统模版。完全采用 `ECMAScript` 模块(`ESM`)规范来编写和组织代码,使用了最新的 `Vue3`
`Vite``Element-Plus``TypeScript``Pinia``Tailwindcss` 等主流技术开发
## 研发理念
稳定中求创新,技术中见未来
## 精简版本(实际项目开发请用精简版本,提供 `非国际化` 、`国际化` 两个版本选择)
精简版本是基于 [vue-pure-admin](https://github.com/pure-admin/vue-pure-admin) 提炼出的架子,包含主体功能,更适合实际项目开发,打包后的大小在全局引入 [element-plus](https://element-plus.org) 的情况下仍然低于 `2.3MB`,并且会永久同步完整版的代码。开启 `brotli` 压缩和 `cdn` 替换本地库模式后,打包大小低于 `350kb`
[点我查看非国际化精简版本](https://github.com/pure-admin/pure-admin-thin)
[点我查看国际化精简版本](https://github.com/pure-admin/pure-admin-thin/tree/i18n)
## 配套视频
[点我查看 UI 设计](https://www.bilibili.com/video/BV17g411T7rq)
[点我查看快速开发教程](https://www.bilibili.com/video/BV1kg411v7QT)
## 配套保姆级文档
[点我查看 vue-pure-admin 文档](https://pure-admin.cn/)
[点我查看 @pureadmin/utils 文档](https://pure-admin-utils.netlify.app)
## 高级服务
[点我查看详情](https://pure-admin.cn/pages/service/)
## `Tauri` 版本
[点我查看 Tauri 版本](https://github.com/pure-admin/tauri-pure-admin)
## `Electron` 版本
[点我查看 Electron 版本](https://github.com/pure-admin/electron-pure-admin)
## 预览
[点我查看预览](https://pure-admin.github.io/vue-pure-admin)
`PC`
<p align="center">
<img alt="PureAdmin" src="https://xiaoxian521.github.io/hyperlink/img/vue-pure-admin/1.jpg">
<br />
<img alt="PureAdmin" src="https://xiaoxian521.github.io/hyperlink/img/vue-pure-admin/2.jpg">
</p>
暗色风格
<p align="center">
<img alt="PureAdmin" src="https://xiaoxian521.github.io/hyperlink/img/vue-pure-admin/3.jpg">
<br />
<img alt="PureAdmin" src="https://xiaoxian521.github.io/hyperlink/img/vue-pure-admin/4.jpg">
</p>
移动端
<p align="center">
<img alt="PureAdmin" src="https://xiaoxian521.github.io/hyperlink/img/vue-pure-admin/5.jpg">
</p>
### 使用 `Gitpod`
`Gitpod`(适用于 `GitHub` 的免费在线开发环境)中打开项目,并立即开始编码.
[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/pure-admin/vue-pure-admin)
## 安装使用
### 拉取代码
#### 推荐使用 `@pureadmin/cli` 脚手架
<br/>
<img src="https://xiaoxian521.github.io/hyperlink/gif/pure-admin-cli.gif" alt="pure-admin-cli" />
1. 全局安装
```bash
npm install -g @pureadmin/cli
```
2. 交互式选择模板并创建项目
```bash
pure create
```
[点我查看 @pureadmin/cli 脚手架详细用法](https://github.com/pure-admin/pure-admin-cli#pureadmincli)
#### 从 `GitHub` 上拉取
```bash
git clone https://github.com/pure-admin/vue-pure-admin.git
```
#### 从 `Gitee` 上拉取
```bash
git clone https://gitee.com/yiming_chang/vue-pure-admin.git
```
### 安装依赖
```bash
cd vue-pure-admin
pnpm install
```
### 启动平台
```bash
pnpm dev
```
### 项目打包
```bash
pnpm build
```
## Docker 支持
1. 自定义镜像名为 `vue-pure-admin` 的镜像(请注意下面命令末尾有一个点 `.` 表示使用当前路径下的 `Dockerfile` 文件,可根据实际情况指定路径)
```bash
docker build -t vue-pure-admin .
```
2. 端口映射并启动 `docker` 容器(`8080:80`:表示在容器中使用 `80` 端口,并将该端口转发到主机的 `8080` 端口;`pure-admin`:表示自定义容器名;`vue-pure-admin`:表示自定义镜像名)
```bash
docker run -dp 8080:80 --name pure-admin vue-pure-admin
```
操作完上面两个命令后,在浏览器打开 `http://localhost:8080` 即可预览
当然也可以通过 [Docker Desktop](https://www.docker.com/products/docker-desktop/) 可视化界面去操作 `docker` 项目,如下图
<p align="center">
<img alt="docker-desktop" width="100%" src="https://xiaoxian521.github.io/hyperlink/img/docker-desktop.jpg">
</p>
## 更新日志
[CHANGELOG](./CHANGELOG.zh_CN.md)
## 如何贡献
非常欢迎您的加入![提一个 Issue](https://github.com/pure-admin/vue-pure-admin/issues/new/choose) 或者提交一个 `Pull Request`
**Pull Request:**
1. Fork 代码!
2. 创建自己的分支: `git checkout -b feat/xxxx`
3. 提交您的修改: `git commit -am 'feat(function): add xxxxx'`
4. 推送您的分支: `git push origin feat/xxxx`
5. 提交`pull request`
## 特别代码贡献
非常感谢你们能深入了解源码并对 `pure-admin` 组织作出优秀贡献 ❤️
| **贡献人** | **具体代码** |
| :---------------------------------------------: | :------------------------------------------------------------------------------: |
| [hb0730](https://github.com/hb0730) | [代码](https://github.com/pure-admin/vue-pure-admin/commits?author=hb0730) |
| [o-cc](https://github.com/o-cc) | [代码](https://github.com/pure-admin/vue-pure-admin/commits?author=o-cc) |
| [yj-liuzepeng](https://github.com/yj-liuzepeng) | [代码](https://github.com/pure-admin/vue-pure-admin/commits?author=yj-liuzepeng) |
| [skyline523](https://github.com/skyline523) | [代码](https://github.com/pure-admin/vue-pure-admin/commits?author=skyline523) |
| [shark-lajiao](https://github.com/shark-lajiao) | [代码](https://github.com/pure-admin/vue-pure-admin/commits?author=shark-lajiao) |
| [WitMiao](https://github.com/WitMiao) | [代码](https://github.com/pure-admin/vue-pure-admin/commits?author=WitMiao) |
| [QFifteen](https://github.com/QFifteen) | [代码](https://github.com/pure-admin/vue-pure-admin/commits?author=QFifteen) |
| [edgexie](https://github.com/edgexie) | [代码](https://github.com/pure-admin/vue-pure-admin/commits?author=edgexie) |
| [way-jm](https://github.com/way-jm) | [代码](https://github.com/pure-admin/vue-pure-admin/commits?author=way-jm) |
| [simple-hui](https://github.com/simple-hui) | [代码](https://github.com/pure-admin/vue-pure-admin/commits?author=simple-hui) |
| [tinysimple](https://github.com/tinysimple) | [代码](https://github.com/pure-admin/vue-pure-admin/commits?author=tinysimple) |
## `Git` 贡献提交规范
参考 [vue](https://github.com/vuejs/vue/blob/dev/.github/COMMIT_CONVENTION.md) 规范 ([Angular](https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-changelog-angular))
- `feat` 增加新功能
- `fix` 修复问题/BUG
- `style` 代码风格相关无影响运行结果的
- `perf` 优化/性能提升
- `refactor` 重构
- `revert` 撤销修改
- `test` 测试相关
- `docs` 文档/注释
- `chore` 依赖更新/脚手架配置修改等
- `workflow` 工作流改进
- `ci` 持续集成
- `types` 类型定义文件更改
- `wip` 开发中
## 浏览器支持
本地开发推荐使用 `Chrome``Edge``Firefox` 浏览器,作者常用的是最新版 `Chrome` 浏览器
实际使用中感觉 `Firefox` 在动画上要比别的浏览器更加丝滑,只是作者用 `Chrome` 已经习惯了,看个人爱好选择吧
更详细的浏览器兼容性支持请看 [Vue 支持哪些浏览器?](https://cn.vuejs.org/about/faq.html#what-browsers-does-vue-support) 和 [Vite 浏览器兼容性](https://cn.vitejs.dev/guide/build#browser-compatibility)
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt=" Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>IE | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt=" Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari |
| :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
| 不支持 | 最后两个版本 | 最后两个版本 | 最后两个版本 | 最后两个版本 |
## 维护者
[xiaoxian521](https://github.com/xiaoxian521)、[Ten-K](https://github.com/Ten-K)
## 许可证
完全免费开源
[MIT © 2020-present, pure-admin](./LICENSE)
## `Star`
非常感谢留下星星的好心人,感谢您的支持 :heart:
[![Stargazers repo roster for @pure-admin/vue-pure-admin](https://bytecrank.com/nastyox/reporoster/php/stargazersSVG.php?user=pure-admin&repo=vue-pure-admin)](https://github.com/pure-admin/vue-pure-admin/stargazers)
## `Fork`
瞧,那些 `小哥哥``小姐姐` 认真 `学习` 的样子真滴是 `哎呦不错哦` :heart:
[![Forkers repo roster for @pure-admin/vue-pure-admin](https://bytecrank.com/nastyox/reporoster/php/forkersSVG.php?user=pure-admin&repo=vue-pure-admin)](https://github.com/pure-admin/vue-pure-admin/network/members)

49
build/cdn.ts Normal file
View File

@@ -0,0 +1,49 @@
import { Plugin as importToCDN } from "vite-plugin-cdn-import";
/**
* @description 打包时采用`cdn`模式仅限外网使用默认不采用如果需要采用cdn模式请在 .env.production 文件,将 VITE_CDN 设置成true
* 平台采用国内cdnhttps://www.bootcdn.cn当然你也可以选择 https://unpkg.com 或者 https://www.jsdelivr.com
* 注意上面提到的仅限外网使用也不是完全肯定的如果你们公司内网部署的有相关js、css文件也可以将下面配置对应改一下整一套内网版cdn
*/
export const cdn = importToCDN({
//prodUrl解释 name: 对应下面modules的nameversion: 自动读取本地package.json中dependencies依赖中对应包的版本号path: 对应下面modules的path当然也可写完整路径会替换prodUrl
prodUrl: "https://cdn.bootcdn.net/ajax/libs/{name}/{version}/{path}",
modules: [
{
name: "vue",
var: "Vue",
path: "vue.global.prod.min.js"
},
{
name: "vue-router",
var: "VueRouter",
path: "vue-router.global.min.js"
},
{
name: "vue-i18n",
var: "VueI18n",
path: "vue-i18n.runtime.global.prod.min.js"
},
{
name: "element-plus",
var: "ElementPlus",
path: "index.full.min.js",
css: "index.min.css"
},
{
name: "axios",
var: "axios",
path: "axios.min.js"
},
{
name: "dayjs",
var: "dayjs",
path: "dayjs.min.js"
},
{
name: "echarts",
var: "echarts",
path: "echarts.min.js"
}
]
});

63
build/compress.ts Normal file
View File

@@ -0,0 +1,63 @@
import type { Plugin } from "vite";
import { isArray } from "@pureadmin/utils";
import compressPlugin from "vite-plugin-compression";
export const configCompressPlugin = (
compress: ViteCompression
): Plugin | Plugin[] => {
if (compress === "none") return null;
const gz = {
// 生成的压缩包后缀
ext: ".gz",
// 体积大于threshold才会被压缩
threshold: 0,
// 默认压缩.js|mjs|json|css|html后缀文件设置成true压缩全部文件
filter: () => true,
// 压缩后是否删除原始文件
deleteOriginFile: false
};
const br = {
ext: ".br",
algorithm: "brotliCompress",
threshold: 0,
filter: () => true,
deleteOriginFile: false
};
const codeList = [
{ k: "gzip", v: gz },
{ k: "brotli", v: br },
{ k: "both", v: [gz, br] }
];
const plugins: Plugin[] = [];
codeList.forEach(item => {
if (compress.includes(item.k)) {
if (compress.includes("clear")) {
if (isArray(item.v)) {
item.v.forEach(vItem => {
plugins.push(
compressPlugin(Object.assign(vItem, { deleteOriginFile: true }))
);
});
} else {
plugins.push(
compressPlugin(Object.assign(item.v, { deleteOriginFile: true }))
);
}
} else {
if (isArray(item.v)) {
item.v.forEach(vItem => {
plugins.push(compressPlugin(vItem));
});
} else {
plugins.push(compressPlugin(item.v));
}
}
}
});
return plugins;
};

57
build/info.ts Normal file
View File

@@ -0,0 +1,57 @@
import type { Plugin } from "vite";
import gradient from "gradient-string";
import { getPackageSize } from "./utils";
import dayjs, { type Dayjs } from "dayjs";
import duration from "dayjs/plugin/duration";
import boxen, { type Options as BoxenOptions } from "boxen";
dayjs.extend(duration);
const welcomeMessage = gradient(["cyan", "magenta"]).multiline(
`您好! 欢迎使用 pure-admin 开源项目\n我们为您精心准备了下面两个贴心的保姆级文档\nhttps://pure-admin.cn\nhttps://pure-admin-utils.netlify.app`
);
const boxenOptions: BoxenOptions = {
padding: 0.5,
borderColor: "cyan",
borderStyle: "round"
};
export function viteBuildInfo(): Plugin {
let config: { command: string };
let startTime: Dayjs;
let endTime: Dayjs;
let outDir: string;
return {
name: "vite:buildInfo",
configResolved(resolvedConfig) {
config = resolvedConfig;
outDir = resolvedConfig.build?.outDir ?? "dist";
},
buildStart() {
console.log(boxen(welcomeMessage, boxenOptions));
if (config.command === "build") {
startTime = dayjs(new Date());
}
},
closeBundle() {
if (config.command === "build") {
endTime = dayjs(new Date());
getPackageSize({
folder: outDir,
callback: (size: string) => {
console.log(
boxen(
gradient(["cyan", "magenta"]).multiline(
`🎉 恭喜打包完成(总用时${dayjs
.duration(endTime.diff(startTime))
.format("mm分ss秒")},打包后的大小为${size}`
),
boxenOptions
)
);
}
});
}
}
};
}

64
build/optimize.ts Normal file
View File

@@ -0,0 +1,64 @@
/**
* 此文件作用于 `vite.config.ts` 的 `optimizeDeps.include` 依赖预构建配置项
* 依赖预构建,`vite` 启动时会将下面 include 里的模块,编译成 esm 格式并缓存到 node_modules/.vite 文件夹,页面加载到对应模块时如果浏览器有缓存就读取浏览器缓存,如果没有会读取本地缓存并按需加载
* 尤其当您禁用浏览器缓存时(这种情况只应该发生在调试阶段)必须将对应模块加入到 include里否则会遇到开发环境切换页面卡顿的问题vite 会认为它是一个新的依赖包会重新加载并强制刷新页面),因为它既无法使用浏览器缓存,又没有在本地 node_modules/.vite 里缓存
* 温馨提示:如果您使用的第三方库是全局引入,也就是引入到 src/main.ts 文件里,就不需要再添加到 include 里了,因为 vite 会自动将它们缓存到 node_modules/.vite
*/
const include = [
"qs",
"mitt",
"xlsx",
"dayjs",
"axios",
"pinia",
"vditor",
"typeit",
"swiper",
"qrcode",
"intro.js",
"vue-i18n",
"deep-chat",
"vxe-table",
"vue-types",
"js-cookie",
"vue-tippy",
"cropperjs",
"jsbarcode",
"codemirror",
"pinyin-pro",
"sortablejs",
"swiper/vue",
"mint-filter",
"highlight.js",
"@vueuse/core",
"vue3-danmaku",
"v-contextmenu",
"vue-pdf-embed",
"wavesurfer.js",
"swiper/modules",
"china-area-data",
"vue-json-pretty",
"@logicflow/core",
"@pureadmin/utils",
"@wangeditor/editor",
"responsive-storage",
"plus-pro-components",
"@howdyjs/mouse-menu",
"@logicflow/extension",
"vue-virtual-scroller",
"codemirror-editor-vue3",
"@amap/amap-jsapi-loader",
"el-table-infinite-scroll",
"vue-waterfall-plugin-next",
"@infectoone/vue-ganttastic",
"@wangeditor/editor-for-vue",
"vuedraggable/src/vuedraggable"
];
/**
* 在预构建中强制排除的依赖项
* 温馨提示:平台推荐的使用方式是哪里需要哪里引入而且都是单个的引入,不需要预构建,直接让浏览器加载就好
*/
const exclude = ["@iconify/json"];
export { include, exclude };

76
build/plugins.ts Normal file
View File

@@ -0,0 +1,76 @@
import vue from "@vitejs/plugin-vue";
import { pathResolve } from "./utils";
import { viteBuildInfo } from "./info";
import svgLoader from "vite-svg-loader";
import Icons from "unplugin-icons/vite";
import type { PluginOption } from "vite";
import vueJsx from "@vitejs/plugin-vue-jsx";
import tailwindcss from "@tailwindcss/vite";
import { configCompressPlugin } from "./compress";
import removeNoMatch from "vite-plugin-router-warn";
import { visualizer } from "rollup-plugin-visualizer";
import removeConsole from "vite-plugin-remove-console";
import VueI18nPlugin from "@intlify/unplugin-vue-i18n/vite";
import { codeInspectorPlugin } from "code-inspector-plugin";
import { vitePluginFakeServer } from "vite-plugin-fake-server";
export async function getPluginsList(
VITE_CDN: boolean,
VITE_COMPRESSION: ViteCompression
): Promise<PluginOption[]> {
const lifecycle = process.env.npm_lifecycle_event;
return [
tailwindcss(),
vue({
template: {
compilerOptions: {
isCustomElement: tag => tag === "deep-chat"
}
}
}),
// jsx、tsx语法支持
vueJsx(),
VueI18nPlugin({
include: [pathResolve("../locales/**")]
}),
/**
* 在页面上按住组合键时,鼠标在页面移动即会在 DOM 上出现遮罩层并显示相关信息,点击一下将自动打开 IDE 并将光标定位到元素对应的代码位置
* Mac 默认组合键 Option + Shift
* Windows 默认组合键 Alt + Shift
* 更多用法看 https://inspector.fe-dev.cn/guide/start.html
*/
codeInspectorPlugin({
bundler: "vite",
hideConsole: true
}),
viteBuildInfo(),
/**
* 开发环境下移除非必要的vue-router动态路由警告No match found for location with path
* 非必要具体看 https://github.com/vuejs/router/issues/521 和 https://github.com/vuejs/router/issues/359
* vite-plugin-router-warn只在开发环境下启用只处理vue-router文件并且只在服务启动或重启时运行一次性能消耗可忽略不计
*/
removeNoMatch(),
// mock支持
vitePluginFakeServer({
logger: false,
include: "mock",
infixName: false,
enableProd: true
}),
// svg组件化支持
svgLoader(),
// 自动按需加载图标
Icons({
compiler: "vue3",
scale: 1
}),
VITE_CDN ? (await import("./cdn")).cdn : null,
configCompressPlugin(VITE_COMPRESSION),
// 线上环境删除console
removeConsole({ external: ["src/assets/iconfont/iconfont.js"] }),
// 打包分析
lifecycle === "report"
? visualizer({ open: true, brotliSize: true, filename: "report.html" })
: (null as any)
];
}

110
build/utils.ts Normal file
View File

@@ -0,0 +1,110 @@
import dayjs from "dayjs";
import { readdir, stat } from "node:fs";
import { fileURLToPath } from "node:url";
import { dirname, resolve } from "node:path";
import { sum, formatBytes } from "@pureadmin/utils";
import {
name,
version,
engines,
dependencies,
devDependencies
} from "../package.json";
/** 启动`node`进程时所在工作目录的绝对路径 */
const root: string = process.cwd();
/**
* @description 根据可选的路径片段生成一个新的绝对路径
* @param dir 路径片段,默认`build`
* @param metaUrl 模块的完整`url`,如果在`build`目录外调用必传`import.meta.url`
*/
const pathResolve = (dir = ".", metaUrl = import.meta.url) => {
// 当前文件目录的绝对路径
const currentFileDir = dirname(fileURLToPath(metaUrl));
// build 目录的绝对路径
const buildDir = resolve(currentFileDir, "build");
// 解析的绝对路径
const resolvedPath = resolve(currentFileDir, dir);
// 检查解析的绝对路径是否在 build 目录内
if (resolvedPath.startsWith(buildDir)) {
// 在 build 目录内,返回当前文件路径
return fileURLToPath(metaUrl);
}
// 不在 build 目录内,返回解析后的绝对路径
return resolvedPath;
};
/** 设置别名 */
const alias: Record<string, string> = {
"@": pathResolve("../src"),
"@build": pathResolve()
};
/** 平台的名称、版本、运行所需的`node`和`pnpm`版本、依赖、最后构建时间的类型提示 */
const __APP_INFO__ = {
pkg: { name, version, engines, dependencies, devDependencies },
lastBuildTime: dayjs(new Date()).format("YYYY-MM-DD HH:mm:ss")
};
/** 处理环境变量 */
const wrapperEnv = (envConf: Recordable): ViteEnv => {
// 默认值
const ret: ViteEnv = {
VITE_PORT: 8848,
VITE_PUBLIC_PATH: "",
VITE_ROUTER_HISTORY: "",
VITE_CDN: false,
VITE_HIDE_HOME: "false",
VITE_COMPRESSION: "none"
};
for (const envName of Object.keys(envConf)) {
let realName = envConf[envName].replace(/\\n/g, "\n");
realName =
realName === "true" ? true : realName === "false" ? false : realName;
if (envName === "VITE_PORT") {
realName = Number(realName);
}
ret[envName] = realName;
if (typeof realName === "string") {
process.env[envName] = realName;
} else if (typeof realName === "object") {
process.env[envName] = JSON.stringify(realName);
}
}
return ret;
};
const fileListTotal: number[] = [];
/** 获取指定文件夹中所有文件的总大小 */
const getPackageSize = options => {
const { folder = "dist", callback, format = true } = options;
readdir(folder, (err, files: string[]) => {
if (err) throw err;
let count = 0;
const checkEnd = () => {
++count == files.length &&
callback(format ? formatBytes(sum(fileListTotal)) : sum(fileListTotal));
};
files.forEach((item: string) => {
stat(`${folder}/${item}`, async (err, stats) => {
if (err) throw err;
if (stats.isFile()) {
fileListTotal.push(stats.size);
checkEnd();
} else if (stats.isDirectory()) {
getPackageSize({
folder: `${folder}/${item}/`,
callback: checkEnd
});
}
});
});
files.length === 0 && callback(0);
});
};
export { root, pathResolve, alias, __APP_INFO__, wrapperEnv, getPackageSize };

35
commitlint.config.js Normal file
View File

@@ -0,0 +1,35 @@
// @ts-check
/** @type {import("@commitlint/types").UserConfig} */
export default {
ignores: [commit => commit.includes("init")],
extends: ["@commitlint/config-conventional"],
rules: {
"body-leading-blank": [2, "always"],
"footer-leading-blank": [1, "always"],
"header-max-length": [2, "always", 108],
"subject-empty": [2, "never"],
"type-empty": [2, "never"],
"type-enum": [
2,
"always",
[
"feat",
"fix",
"perf",
"style",
"docs",
"test",
"refactor",
"build",
"ci",
"chore",
"revert",
"wip",
"workflow",
"types",
"release"
]
]
}
};

190
eslint.config.js Normal file
View File

@@ -0,0 +1,190 @@
import js from "@eslint/js";
import tseslint from "typescript-eslint";
import pluginVue from "eslint-plugin-vue";
import * as parserVue from "vue-eslint-parser";
import configPrettier from "eslint-config-prettier";
import pluginPrettier from "eslint-plugin-prettier";
import { defineConfig, globalIgnores } from "eslint/config";
import eslintPluginBetterTailwindcss from "eslint-plugin-better-tailwindcss";
export default defineConfig([
globalIgnores([
"**/.*",
"dist/*",
"*.d.ts",
"public/*",
"src/assets/**",
"src/**/iconfont/**"
]),
{
...js.configs.recommended,
languageOptions: {
globals: {
// types/index.d.ts
RefType: "readonly",
EmitType: "readonly",
TargetContext: "readonly",
ComponentRef: "readonly",
ElRef: "readonly",
ForDataType: "readonly",
AnyFunction: "readonly",
PropType: "readonly",
Writable: "readonly",
Nullable: "readonly",
NonNullable: "readonly",
Recordable: "readonly",
ReadonlyRecordable: "readonly",
Indexable: "readonly",
DeepPartial: "readonly",
Without: "readonly",
Exclusive: "readonly",
TimeoutHandle: "readonly",
IntervalHandle: "readonly",
Effect: "readonly",
ChangeEvent: "readonly",
WheelEvent: "readonly",
ImportMetaEnv: "readonly",
Fn: "readonly",
PromiseFn: "readonly",
ComponentElRef: "readonly",
parseInt: "readonly",
parseFloat: "readonly"
}
},
plugins: {
prettier: pluginPrettier
},
rules: {
...configPrettier.rules,
...pluginPrettier.configs.recommended.rules,
"no-debugger": "off",
"no-unused-vars": [
"error",
{
argsIgnorePattern: "^_",
varsIgnorePattern: "^_"
}
],
"prettier/prettier": [
"error",
{
endOfLine: "auto"
}
]
}
},
...tseslint.configs.recommended.map(config => ({
...config,
files: ["**/*.?([cm])ts", "**/*.?([cm])tsx"]
})),
{
files: ["**/*.?([cm])ts", "**/*.?([cm])tsx"],
rules: {
"@typescript-eslint/no-redeclare": "error",
"@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/prefer-as-const": "warn",
"@typescript-eslint/no-empty-function": "off",
"@typescript-eslint/no-non-null-assertion": "off",
"@typescript-eslint/no-unused-expressions": "off",
"@typescript-eslint/no-unsafe-function-type": "off",
"@typescript-eslint/no-import-type-side-effects": "error",
"@typescript-eslint/explicit-module-boundary-types": "off",
"@typescript-eslint/consistent-type-imports": [
"error",
{ disallowTypeAnnotations: false, fixStyle: "inline-type-imports" }
],
"@typescript-eslint/prefer-literal-enum-member": [
"error",
{ allowBitwiseExpressions: true }
],
"@typescript-eslint/no-unused-vars": [
"error",
{
argsIgnorePattern: "^_",
varsIgnorePattern: "^_"
}
]
}
},
{
files: ["**/*.d.ts"],
rules: {
"no-restricted-syntax": "off"
}
},
{
files: ["**/*.?([cm])js"],
rules: {
"@typescript-eslint/no-require-imports": "off"
}
},
{
files: ["**/*.vue"],
languageOptions: {
globals: {
$: "readonly",
$$: "readonly",
$computed: "readonly",
$customRef: "readonly",
$ref: "readonly",
$shallowRef: "readonly",
$toRef: "readonly"
},
parser: parserVue,
parserOptions: {
ecmaFeatures: {
jsx: true
},
extraFileExtensions: [".vue"],
parser: tseslint.parser,
sourceType: "module"
}
},
plugins: {
"@typescript-eslint": tseslint.plugin,
vue: pluginVue
},
processor: pluginVue.processors[".vue"],
rules: {
...pluginVue.configs.base.rules,
...pluginVue.configs.essential.rules,
...pluginVue.configs.recommended.rules,
"no-undef": "off",
"no-unused-vars": "off",
"vue/no-v-html": "off",
"vue/require-default-prop": "off",
"vue/require-explicit-emits": "off",
"vue/multi-word-component-names": "off",
"vue/no-setup-props-reactivity-loss": "off",
"vue/html-self-closing": [
"error",
{
html: {
void: "always",
normal: "always",
component: "always"
},
svg: "always",
math: "always"
}
]
}
},
{
files: ["**/*.vue", "**/*.tsx"],
plugins: {
"better-tailwindcss": eslintPluginBetterTailwindcss
},
rules: {
"better-tailwindcss/enforce-consistent-variable-syntax": "warn",
"better-tailwindcss/enforce-canonical-classes": "warn"
},
settings: {
"better-tailwindcss": {
entryPoint: "src/style/tailwind.css",
rootFontSize: 16
}
}
}
]);

84
index.html Normal file
View File

@@ -0,0 +1,84 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="renderer" content="webkit" />
<meta
name="viewport"
content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=0"
/>
<title>vue-pure-admin</title>
<link rel="icon" href="/favicon.ico" />
</head>
<body>
<div id="app">
<style>
html,
body,
#app {
position: relative;
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
overflow: hidden;
}
.loader,
.loader::before,
.loader::after {
width: 2.5em;
height: 2.5em;
border-radius: 50%;
animation: load-animation 1.8s infinite ease-in-out;
animation-fill-mode: both;
}
.loader {
position: relative;
top: 0;
margin: 80px auto;
font-size: 10px;
color: #406eeb;
text-indent: -9999em;
transform: translateZ(0);
transform: translate(-50%, 0);
animation-delay: -0.16s;
}
.loader::before,
.loader::after {
position: absolute;
top: 0;
content: "";
}
.loader::before {
left: -3.5em;
animation-delay: -0.32s;
}
.loader::after {
left: 3.5em;
}
@keyframes load-animation {
0%,
80%,
100% {
box-shadow: 0 2.5em 0 -1.3em;
}
40% {
box-shadow: 0 2.5em 0 0;
}
}
</style>
<div class="loader"></div>
</div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

265
locales/en.yaml Normal file
View File

@@ -0,0 +1,265 @@
buttons:
pureAccountSettings: Account
pureLoginOut: LoginOut
pureLogin: Login
pureOpenSystemSet: Open System Configs
pureReload: Reload
pureCloseCurrentTab: Close CurrentTab
pureCloseLeftTabs: Close LeftTabs
pureCloseRightTabs: Close RightTabs
pureCloseOtherTabs: Close OtherTabs
pureCloseAllTabs: Close AllTabs
pureContentFullScreen: Content FullScreen
pureContentExitFullScreen: Content ExitFullScreen
pureClickCollapse: Collapse
pureClickExpand: Expand
pureConfirm: Confirm
pureSwitch: Switch
pureClose: Close
pureBackTop: BackTop
pureOpenText: Open
pureCloseText: Close
pureWatchMore: Watch More
pureMarkAsRead: Mark As Read
search:
pureTotal: Total
pureHistory: History
pureCollect: Collect
pureDragSort: Drag Sort
pureEmpty: Empty
purePlaceholder: Search Menu
panel:
pureSystemSet: System Configs
pureCloseSystemSet: Close System Configs
pureClearCacheAndToLogin: Clear cache and return to login page
pureClearCache: Clear Cache
pureThemeMode: Theme Mode
pureThemeModeLight: Light
pureThemeModeLightTip: Set sail freshly and light up the comfortable work interface
pureThemeModeDark: Dark
pureThemeModeDarkTip: Moonlight Overture, indulge in the tranquility and elegance of the night
pureThemeModeSystem: Auto
pureThemeModeSystemTip: Synchronize time, the interface naturally responds to morning and dusk
pureThemeColor: Theme Color
pureMenuLayout: Menu Layout
pureVerticalTip: The menu on the left is familiar and friendly
pureHorizontalTip: Top menu, concise overview
pureMixTip: Mixed menu, flexible
pureStretch: Stretch Page
pureStretchFixed: Fixed
pureStretchFixedTip: Compact pages make it easy to find the information you need
pureStretchCustom: Custom
pureStretchCustomTip: Minimum 1280, maximum 1600
pureTagsStyle: Tags Style
pureTagsStyleSmart: Smart
pureTagsStyleSmartTip: Smart tags add fun and brilliance
pureTagsStyleCard: Card
pureTagsStyleCardTip: Card tags for efficient browsing
pureTagsStyleChrome: Chrome
pureTagsStyleChromeTip: Chrome style is classic and elegant
pureFullScreenWatermark: FullScreen Watermark
pureEnableWatermark: Watermark
pureWatermarkText: Text
pureWatermarkTextPlaceholder: Please enter text
pureInterfaceDisplay: Interface Display
pureGreyModel: Grey Model
pureWeakModel: Weak Model
pureHiddenTags: Hidden Tags
pureHiddenFooter: Hidden Footer
pureMultiTagsCache: MultiTags Cache
menus:
pureHome: Home
pureLogin: Login
pureEmpty: Empty Page
pureTable: Table
pureSysManagement: System Manage
pureUser: User Manage
pureRole: Role Manage
pureSystemMenu: Menu Manage
pureDept: Dept Manage
pureSysMonitor: System Monitor
pureOnlineUser: Online User
pureLoginLog: Login Log
pureOperationLog: Operation Log
pureSystemLog: System Log
pureCodeMirror: CodeMirror
pureMarkdown: Markdown
pureEditor: Editor
pureAbnormal: Abnormal Page
purePageNotFound: "404"
pureAccessDenied: "403"
pureServerError: "500"
pureComponents: Components
pureDialog: Dialog
pureDrawer: Drawer
pureMessage: Message Tips
pureVideo: Video
pureSegmented: Segmented
pureWaterfall: Waterfall
pureMap: Map
pureDraggable: Draggable
pureSplitPane: Split Pane
pureText: Text Ellipsis
pureSlider: Slider
pureElButton: Button
pureButton: Button Animation
pureCheckButton: Check Button
pureCropping: Picture Cropping
pureAnimatecss: AnimateCss Selector
pureCountTo: Digital Animation
pureSelector: Scope Selector
pureFlowChart: Flow Chart
pureSeamless: Seamless Scroll
pureContextmenu: Context Menu
pureTypeit: Typeit
pureJsonEditor: JSON Editor
pureColorPicker: Color Picker
pureColorPickerPanel: Color PickerPanel
pureDatePicker: Date Picker
pureDateTimePicker: DateTimePicker
pureTimePicker: TimePicker
pureTag: Tag
pureStatistic: Statistic
pureCollapse: Collapse
pureGanttastic: Gantt Chart
pureProgress: Progress
pureUpload: File Upload
pureCheckCard: CheckCard
pureMenus: MultiLevel Menu
pureMenu1: Menu1
pureMenu1-1: Menu1-1
pureMenu1-2: Menu1-2
pureMenu1-2-1: Menu1-2-1
pureMenu1-2-2: Menu1-2-2
pureMenu1-3: Menu1-3
pureMenu2: Menu2
purePermission: Permission Manage
purePermissionPage: Page Permission
purePermissionButton: Button Permission
purePermissionButtonRouter: Route return button permission
purePermissionButtonLogin: Login interface return button permission
pureTabs: Tabs Operate
pureGuide: Guide
pureAble: Able
pureMenuTree: Menu Tree
pureVideoFrame: Video Frame Capture
pureWavesurfer: Audio Visualization
pureRipple: Ripple
pureMqtt: Mqtt Client
pureOptimize: Debounce、Throttle、Copy、Longpress Directives
pureVerify: Captcha
pureWatermark: Water Mark
purePrint: Print
pureDownload: Download
pureExternalPage: External Page
pureExternalDoc: Docs External
pureEmbeddedDoc: Docs Embedded
pureExternalLink: Vue-Pure-Admin
pureUtilsLink: Pure-Admin-Utils
pureColorHuntDoc: ColorHunt
pureUiGradients: UiGradients
pureEpDoc: Element-Plus
pureTailwindcssDoc: Tailwindcss
pureVueDoc: Vue3
pureViteDoc: Vite
purePiniaDoc: Pinia
pureRouterDoc: Vue-Router
pureAbout: About
pureResult: Result Page
pureSuccess: Success Page
pureFail: Fail Page
pureIconSelect: Icon Select
pureTimeline: Time Line
pureLineTree: LineTree
pureList: List Page
pureCardList: Card List Page
pureDebounce: Debounce & Throttle
pureFormDesign: Form Design
pureBarcode: Barcode
pureQrcode: Qrcode
pureCascader: Area Cascader
pureSwiper: Swiper Plugin
pureVirtualList: Virtual List
purePdf: PDF Preview
pureExcel: Export Excel
pureInfiniteScroll: Table Infinite Scroll
pureSensitive: Sensitive Filter
purePinyin: PinYin
pureDanmaku: Danmaku
pureSchemaForm: Form
pureTableBase: Base Usage
pureTableHigh: High Usage
pureTableEdit: Edit Usage
pureVxeTable: Virtual Usage
pureBoard: Paint Board
pureMindMap: Mind Map
pureMenuOverflow: Menu Overflow Show Tooltip Text
pureChildMenuOverflow: Child Menu Overflow Show Tooltip Text
status:
pureLoad: Loading...
pureMessage: Message
pureNotify: Notify
pureTodo: Todo
pureNoMessage: No Message
pureNoNotify: No Notify
pureNoTodo: No Todo
login:
pureUsername: Username
purePassword: Password
pureVerifyCode: VerifyCode
pureRemember: days no need to login
pureRememberInfo: After checking and logging in, will automatically log in to the system without entering your username and password within the specified number of days.
pureSure: Sure Password
pureForget: Forget Password?
pureLogin: Login
pureThirdLogin: Third Login
purePhoneLogin: Phone Login
pureQRCodeLogin: QRCode Login
pureRegister: Register
pureWeChatLogin: WeChat Login
pureAlipayLogin: Alipay Login
pureQQLogin: QQ Login
pureWeiBoLogin: Weibo Login
purePhone: Phone
pureSmsVerifyCode: SMS VerifyCode
pureBack: Back
pureTest: Mock Test
pureTip: After scanning the code, click "Confirm" to complete the login
pureDefinite: Definite
pureLoginSuccess: Login Success
pureLoginFail: Login Fail
pureRegisterSuccess: Regist Success
pureTickPrivacy: Please tick Privacy Policy
pureReadAccept: I have read it carefully and accept
purePrivacyPolicy: Privacy Policy
pureGetVerifyCode: Get VerifyCode
pureInfo: Seconds
pureUsernameReg: Please enter username
purePassWordReg: Please enter password
pureVerifyCodeReg: Please enter verify code
pureVerifyCodeCorrectReg: Please enter correct verify code
pureVerifyCodeSixReg: Please enter a 6-digit verify code
purePhoneReg: Please enter the phone
purePhoneCorrectReg: Please enter the correct phone number format
purePassWordRuleReg: The password format should be any combination of 8-18 digits
purePassWordSureReg: Please enter confirm password
purePassWordDifferentReg: The two passwords do not match!
purePassWordUpdateReg: Password has been updated
pureLoginExpired: Login expired, please login again
tableBar:
pureList: List
pureLarge: Large
pureDefault: Default
pureSmall: Small
pureColumnSettings: ColumnSettings
pureCollapse: Collapse
pureExpand: Expand
pureRefresh: Refresh
pureDensity: Density
pureColumnDisplay: ColumnDisplay
pureReset: Reset
pureExitFullScreen: ExitFullScreen
pureFullScreen: FullScreen
purePinLeft: Pin Left
purePinRight: Pin Right
pureUnpin: Unpin

265
locales/zh-CN.yaml Normal file
View File

@@ -0,0 +1,265 @@
buttons:
pureAccountSettings: 账户设置
pureLoginOut: 退出系统
pureLogin: 登录
pureOpenSystemSet: 打开系统配置
pureReload: 重新加载
pureCloseCurrentTab: 关闭当前标签页
pureCloseLeftTabs: 关闭左侧标签页
pureCloseRightTabs: 关闭右侧标签页
pureCloseOtherTabs: 关闭其他标签页
pureCloseAllTabs: 关闭全部标签页
pureContentFullScreen: 内容区全屏
pureContentExitFullScreen: 内容区退出全屏
pureClickCollapse: 点击折叠
pureClickExpand: 点击展开
pureConfirm: 确认
pureSwitch: 切换
pureClose: 关闭
pureBackTop: 回到顶部
pureOpenText:
pureCloseText:
pureWatchMore: 查看更多
pureMarkAsRead: 标为已读
search:
pureTotal:
pureHistory: 搜索历史
pureCollect: 收藏
pureDragSort: (可拖拽排序)
pureEmpty: 暂无搜索结果
purePlaceholder: 搜索菜单(支持拼音搜索)
panel:
pureSystemSet: 系统配置
pureCloseSystemSet: 关闭配置
pureClearCacheAndToLogin: 清空缓存并返回登录页
pureClearCache: 清空缓存
pureThemeMode: 主题模式
pureThemeModeLight: 浅色
pureThemeModeLightTip: 清新启航,点亮舒适的工作界面
pureThemeModeDark: 深色
pureThemeModeDarkTip: 月光序曲,沉醉于夜的静谧雅致
pureThemeModeSystem: 自动
pureThemeModeSystemTip: 同步时光,界面随晨昏自然呼应
pureThemeColor: 主题色
pureMenuLayout: 菜单布局
pureVerticalTip: 左侧菜单,亲切熟悉
pureHorizontalTip: 顶部菜单,简洁概览
pureMixTip: 混合菜单,灵活多变
pureStretch: 页宽
pureStretchFixed: 固定
pureStretchFixedTip: 紧凑页面,轻松找到所需信息
pureStretchCustom: 自定义
pureStretchCustomTip: 最小1280、最大1600
pureTagsStyle: 页签风格
pureTagsStyleSmart: 灵动
pureTagsStyleSmartTip: 灵动标签,添趣生辉
pureTagsStyleCard: 卡片
pureTagsStyleCardTip: 卡片标签,高效浏览
pureTagsStyleChrome: 谷歌
pureTagsStyleChromeTip: 谷歌风格,经典美观
pureFullScreenWatermark: 全屏水印
pureEnableWatermark: 水印
pureWatermarkText: 文本
pureWatermarkTextPlaceholder: 请输入水印文本
pureInterfaceDisplay: 界面显示
pureGreyModel: 灰色模式
pureWeakModel: 色弱模式
pureHiddenTags: 隐藏标签页
pureHiddenFooter: 隐藏页脚
pureMultiTagsCache: 页签持久化
menus:
pureHome: 首页
pureLogin: 登录
pureEmpty: 无Layout页
pureTable: 表格
pureSysManagement: 系统管理
pureUser: 用户管理
pureRole: 角色管理
pureSystemMenu: 菜单管理
pureDept: 部门管理
pureSysMonitor: 系统监控
pureOnlineUser: 在线用户
pureLoginLog: 登录日志
pureOperationLog: 操作日志
pureSystemLog: 系统日志
pureCodeMirror: 代码编辑器
pureMarkdown: Markdown
pureEditor: 编辑器
pureAbnormal: 异常页面
purePageNotFound: "404"
pureAccessDenied: "403"
pureServerError: "500"
pureComponents: 组件
pureDialog: 函数式弹框
pureDrawer: 函数式抽屉
pureMessage: 消息提示
pureVideo: 视频
pureSegmented: 分段控制器
pureWaterfall: 瀑布流无限滚动
pureMap: 地图
pureDraggable: 拖拽
pureSplitPane: 切割面板
pureText: 文本省略
pureSlider: 滑块
pureElButton: 按钮
pureCheckButton: 可选按钮
pureButton: 按钮动效
pureCropping: 图片裁剪
pureAnimatecss: animate.css选择器
pureCountTo: 数字动画
pureSelector: 范围选择器
pureFlowChart: 流程图
pureSeamless: 无缝滚动
pureContextmenu: 右键菜单
pureTypeit: 打字机
pureJsonEditor: JSON编辑器
pureColorPicker: 颜色选择器
pureColorPickerPanel: 颜色选择器面板
pureDatePicker: 日期选择器
pureDateTimePicker: 日期时间选择器
pureTimePicker: 时间选择器
pureTag: 标签
pureStatistic: 统计组件
pureCollapse: 折叠面板
pureGanttastic: 甘特图
pureProgress: 进度条
pureUpload: 文件上传
pureCheckCard: 多选卡片
pureMenus: 多级菜单
pureMenu1: 菜单1
pureMenu1-1: 菜单1-1
pureMenu1-2: 菜单1-2
pureMenu1-2-1: 菜单1-2-1
pureMenu1-2-2: 菜单1-2-2
pureMenu1-3: 菜单1-3
pureMenu2: 菜单二
purePermission: 权限管理
purePermissionPage: 页面权限
purePermissionButton: 按钮权限
purePermissionButtonRouter: 路由返回按钮权限
purePermissionButtonLogin: 登录接口返回按钮权限
pureTabs: 标签页操作
pureGuide: 引导页
pureAble: 功能
pureMenuTree: 菜单树结构
pureVideoFrame: 视频帧截取-wasm版
pureWavesurfer: 音频可视化
pureRipple: 波纹(Ripple)
pureMqtt: MQTT客户端(mqtt)
pureOptimize: 防抖、截流、复制、长按指令
pureVerify: 图形验证码
pureWatermark: 水印
purePrint: 打印
pureDownload: 下载
pureExternalPage: 外部页面
pureExternalDoc: 文档外链
pureEmbeddedDoc: 文档内嵌
pureExternalLink: vue-pure-admin
pureUtilsLink: pure-admin-utils
pureColorHuntDoc: 调色板
pureUiGradients: 渐变色
pureEpDoc: element-plus
pureTailwindcssDoc: tailwindcss
pureVueDoc: vue3
pureViteDoc: vite
purePiniaDoc: pinia
pureRouterDoc: vue-router
pureAbout: 关于
pureResult: 结果页面
pureSuccess: 成功页面
pureFail: 失败页面
pureIconSelect: 图标选择器
pureTimeline: 时间线
pureLineTree: 树形连接线
pureList: 列表页面
pureCardList: 卡片列表页
pureDebounce: 防抖节流
pureFormDesign: 表单设计器
pureBarcode: 条形码
pureQrcode: 二维码
pureCascader: 区域级联选择器
pureSwiper: Swiper插件
pureVirtualList: 虚拟列表
purePdf: PDF预览
pureExcel: 导出Excel
pureInfiniteScroll: 表格无限滚动
pureSensitive: 敏感词过滤
purePinyin: 汉语拼音
pureDanmaku: 弹幕
pureSchemaForm: 表单
pureTableBase: 基础用法
pureTableHigh: 高级用法
pureTableEdit: 可编辑用法
pureVxeTable: 虚拟滚动
pureBoard: 艺术画板
pureMindMap: 思维导图
pureMenuOverflow: 目录超出显示 Tooltip 文字提示
pureChildMenuOverflow: 菜单超出显示 Tooltip 文字提示
status:
pureLoad: 加载中...
pureMessage: 消息
pureNotify: 通知
pureTodo: 待办
pureNoMessage: 暂无消息
pureNoNotify: 暂无通知
pureNoTodo: 暂无待办
login:
pureUsername: 账号
purePassword: 密码
pureVerifyCode: 验证码
pureRemember: 天内免登录
pureRememberInfo: 勾选并登录后,规定天数内无需输入用户名和密码会自动登入系统
pureSure: 确认密码
pureForget: 忘记密码?
pureLogin: 登录
pureThirdLogin: 第三方登录
purePhoneLogin: 手机登录
pureQRCodeLogin: 二维码登录
pureRegister: 注册
pureWeChatLogin: 微信登录
pureAlipayLogin: 支付宝登录
pureQQLogin: QQ登录
pureWeiBoLogin: 微博登录
purePhone: 手机号码
pureSmsVerifyCode: 短信验证码
pureBack: 返回
pureTest: 模拟测试
pureTip: 扫码后点击"确认",即可完成登录
pureDefinite: 确定
pureLoginSuccess: 登录成功
pureLoginFail: 登录失败
pureRegisterSuccess: 注册成功
pureTickPrivacy: 请勾选隐私政策
pureReadAccept: 我已仔细阅读并接受
purePrivacyPolicy: 《隐私政策》
pureGetVerifyCode: 获取验证码
pureInfo: 秒后重新获取
pureUsernameReg: 请输入账号
purePassWordReg: 请输入密码
pureVerifyCodeReg: 请输入验证码
pureVerifyCodeCorrectReg: 请输入正确的验证码
pureVerifyCodeSixReg: 请输入6位数字验证码
purePhoneReg: 请输入手机号码
purePhoneCorrectReg: 请输入正确的手机号码格式
purePassWordRuleReg: 密码格式应为8-18位数字、字母、符号的任意两种组合
purePassWordSureReg: 请输入确认密码
purePassWordDifferentReg: 两次密码不一致!
purePassWordUpdateReg: 修改密码成功
pureLoginExpired: 登录已过期,请重新登录
tableBar:
pureList: 列表
pureLarge: 宽松
pureDefault: 默认
pureSmall: 紧凑
pureColumnSettings: 列设置
pureCollapse: 折叠
pureExpand: 展开
pureRefresh: 刷新
pureDensity: 密度
pureColumnDisplay: 列展示
pureReset: 重置
pureExitFullScreen: 退出全屏
pureFullScreen: 全屏
purePinLeft: 固定在左边
purePinRight: 固定在右边
pureUnpin: 取消固定

341
mock/asyncRoutes.ts Normal file
View File

@@ -0,0 +1,341 @@
// 模拟后端动态生成路由
import { defineFakeRoute } from "vite-plugin-fake-server/client";
import { system, monitor, permission, frame, tabs } from "@/router/enums";
/**
* roles页面级别权限这里模拟二种 "admin"、"common"
* admin管理员角色
* common普通角色
*/
const systemManagementRouter = {
path: "/system",
meta: {
icon: "ri:settings-3-line",
title: "menus.pureSysManagement",
rank: system
},
children: [
{
path: "/system/user/index",
name: "SystemUser",
meta: {
icon: "ri:admin-line",
title: "menus.pureUser",
roles: ["admin"]
}
},
{
path: "/system/role/index",
name: "SystemRole",
meta: {
icon: "ri:admin-fill",
title: "menus.pureRole",
roles: ["admin"]
}
},
{
path: "/system/menu/index",
name: "SystemMenu",
meta: {
icon: "ep:menu",
title: "menus.pureSystemMenu",
roles: ["admin"]
}
},
{
path: "/system/dept/index",
name: "SystemDept",
meta: {
icon: "ri:git-branch-line",
title: "menus.pureDept",
roles: ["admin"]
}
}
]
};
const systemMonitorRouter = {
path: "/monitor",
meta: {
icon: "ep:monitor",
title: "menus.pureSysMonitor",
rank: monitor
},
children: [
{
path: "/monitor/online-user",
component: "monitor/online/index",
name: "OnlineUser",
meta: {
icon: "ri:user-voice-line",
title: "menus.pureOnlineUser",
roles: ["admin"]
}
},
{
path: "/monitor/login-logs",
component: "monitor/logs/login/index",
name: "LoginLog",
meta: {
icon: "ri:window-line",
title: "menus.pureLoginLog",
roles: ["admin"]
}
},
{
path: "/monitor/operation-logs",
component: "monitor/logs/operation/index",
name: "OperationLog",
meta: {
icon: "ri:history-fill",
title: "menus.pureOperationLog",
roles: ["admin"]
}
},
{
path: "/monitor/system-logs",
component: "monitor/logs/system/index",
name: "SystemLog",
meta: {
icon: "ri:file-search-line",
title: "menus.pureSystemLog",
roles: ["admin"]
}
}
]
};
const permissionRouter = {
path: "/permission",
meta: {
title: "menus.purePermission",
icon: "ep:lollipop",
rank: permission
},
children: [
{
path: "/permission/page/index",
name: "PermissionPage",
meta: {
title: "menus.purePermissionPage",
roles: ["admin", "common"]
}
},
{
path: "/permission/button",
meta: {
title: "menus.purePermissionButton",
roles: ["admin", "common"]
},
children: [
{
path: "/permission/button/router",
component: "permission/button/index",
name: "PermissionButtonRouter",
meta: {
title: "menus.purePermissionButtonRouter",
auths: [
"permission:btn:add",
"permission:btn:edit",
"permission:btn:delete"
]
}
},
{
path: "/permission/button/login",
component: "permission/button/perms",
name: "PermissionButtonLogin",
meta: {
title: "menus.purePermissionButtonLogin"
}
}
]
}
]
};
const frameRouter = {
path: "/iframe",
meta: {
icon: "ri:links-fill",
title: "menus.pureExternalPage",
rank: frame
},
children: [
{
path: "/iframe/embedded",
meta: {
title: "menus.pureEmbeddedDoc"
},
children: [
{
path: "/iframe/colorhunt",
name: "FrameColorHunt",
meta: {
title: "menus.pureColorHuntDoc",
frameSrc: "https://colorhunt.co/",
keepAlive: true,
roles: ["admin", "common"]
}
},
{
path: "/iframe/uigradients",
name: "FrameUiGradients",
meta: {
title: "menus.pureUiGradients",
frameSrc: "https://uigradients.com/",
keepAlive: true,
roles: ["admin", "common"]
}
},
{
path: "/iframe/ep",
name: "FrameEp",
meta: {
title: "menus.pureEpDoc",
frameSrc: "https://element-plus.org/zh-CN/",
keepAlive: true,
roles: ["admin", "common"]
}
},
{
path: "/iframe/tailwindcss",
name: "FrameTailwindcss",
meta: {
title: "menus.pureTailwindcssDoc",
frameSrc: "https://tailwindcss.com/docs/installation",
keepAlive: true,
roles: ["admin", "common"]
}
},
{
path: "/iframe/vue3",
name: "FrameVue",
meta: {
title: "menus.pureVueDoc",
frameSrc: "https://cn.vuejs.org/",
keepAlive: true,
roles: ["admin", "common"]
}
},
{
path: "/iframe/vite",
name: "FrameVite",
meta: {
title: "menus.pureViteDoc",
frameSrc: "https://cn.vitejs.dev/",
keepAlive: true,
roles: ["admin", "common"]
}
},
{
path: "/iframe/pinia",
name: "FramePinia",
meta: {
title: "menus.purePiniaDoc",
frameSrc: "https://pinia.vuejs.org/zh/index.html",
keepAlive: true,
roles: ["admin", "common"]
}
},
{
path: "/iframe/vue-router",
name: "FrameRouter",
meta: {
title: "menus.pureRouterDoc",
frameSrc: "https://router.vuejs.org/zh/",
keepAlive: true,
roles: ["admin", "common"]
}
}
]
},
{
path: "/iframe/external",
meta: {
title: "menus.pureExternalDoc"
},
children: [
{
path: "/external",
name: "https://pure-admin.cn/",
meta: {
title: "menus.pureExternalLink",
roles: ["admin", "common"]
}
},
{
path: "/pureUtilsLink",
name: "https://pure-admin-utils.netlify.app/",
meta: {
title: "menus.pureUtilsLink",
roles: ["admin", "common"]
}
}
]
}
]
};
const tabsRouter = {
path: "/tabs",
meta: {
icon: "ri:bookmark-2-line",
title: "menus.pureTabs",
rank: tabs
},
children: [
{
path: "/tabs/index",
name: "Tabs",
meta: {
title: "menus.pureTabs",
roles: ["admin", "common"]
}
},
// query 传参模式
{
path: "/tabs/query-detail",
name: "TabQueryDetail",
meta: {
// 不在menu菜单中显示
showLink: false,
activePath: "/tabs/index",
roles: ["admin", "common"]
}
},
// params 传参模式
{
path: "/tabs/params-detail/:id",
component: "params-detail",
name: "TabParamsDetail",
meta: {
// 不在menu菜单中显示
showLink: false,
activePath: "/tabs/index",
roles: ["admin", "common"]
}
}
]
};
export default defineFakeRoute([
{
url: "/get-async-routes",
method: "get",
response: () => {
return {
code: 0,
message: "操作成功",
data: [
systemManagementRouter,
systemMonitorRouter,
permissionRouter,
frameRouter,
tabsRouter
]
};
}
}
]);

456
mock/list.ts Normal file
View File

@@ -0,0 +1,456 @@
import { defineFakeRoute } from "vite-plugin-fake-server/client";
export default defineFakeRoute([
{
url: "/get-card-list",
method: "post",
response: () => {
return {
code: 0,
message: "操作成功",
data: {
list: [
{
index: 1,
isSetup: true,
type: 4,
banner: "https://tdesign.gtimg.com/tdesign-pro/cloud-server.jpg",
name: "SSL证书",
description:
"SSL证书又叫服务器证书腾讯云为您提供证书的一站式服务包括免费、付费证书的申请、管理及部"
},
{
index: 2,
isSetup: false,
type: 4,
banner: "https://tdesign.gtimg.com/tdesign-pro/t-sec.jpg",
name: "人脸识别",
description:
"SSL证书又叫服务器证书腾讯云为您提供证书的一站式服务包括免费、付费证书的申请、管理及部"
},
{
index: 3,
isSetup: false,
type: 5,
banner: "https://tdesign.gtimg.com/tdesign-pro/ssl.jpg",
name: "CVM",
description:
"云硬盘为您提供用于CVM的持久性数据块级存储服务。云硬盘中的数据自动地可用区内以多副本冗"
},
{
index: 4,
isSetup: false,
type: 2,
banner: "https://tdesign.gtimg.com/tdesign-pro/ssl.jpg",
name: "SSL证书",
description:
"云数据库MySQL为用户提供安全可靠性能卓越、易于维护的企业级云数据库服务。"
},
{
index: 5,
isSetup: true,
type: 3,
banner:
"https://tdesign.gtimg.com/tdesign-pro/face-recognition.jpg",
name: "SSL证书",
description:
"云数据库MySQL为用户提供安全可靠性能卓越、易于维护的企业级云数据库服务。"
},
{
index: 6,
isSetup: true,
type: 3,
banner: "https://tdesign.gtimg.com/tdesign-pro/ssl.jpg",
name: "T-Sec 云防火墙",
description:
"腾讯安全云防火墙产品是腾讯云安全团队结合云原生的优势自主研发的SaaS化防火墙产品无需客无需客无需客无需客无需客无需客无需客"
},
{
index: 7,
isSetup: false,
type: 1,
banner: "https://tdesign.gtimg.com/tdesign-pro/t-sec.jpg",
name: "CVM",
description:
"腾讯安全云防火墙产品是腾讯云安全团队结合云原生的优势自主研发的SaaS化防火墙产品无需客无需客无需客无需客无需客无需客无需客"
},
{
index: 8,
isSetup: true,
type: 3,
banner: "https://tdesign.gtimg.com/tdesign-pro/t-sec.jpg",
name: "SSL证书",
description:
"云硬盘为您提供用于CVM的持久性数据块级存储服务。云硬盘中的数据自动地可用区内以多副本冗"
},
{
index: 9,
isSetup: false,
type: 1,
banner: "https://tdesign.gtimg.com/tdesign-pro/cloud-server.jpg",
name: "SSL证书",
description:
"腾讯安全云防火墙产品是腾讯云安全团队结合云原生的优势自主研发的SaaS化防火墙产品无需客无需客无需客无需客无需客无需客无需客"
},
{
index: 10,
isSetup: true,
type: 4,
banner: "https://tdesign.gtimg.com/tdesign-pro/ssl.jpg",
name: "CVM",
description:
"云数据库MySQL为用户提供安全可靠性能卓越、易于维护的企业级云数据库服务。"
},
{
index: 11,
isSetup: true,
type: 5,
banner: "https://tdesign.gtimg.com/tdesign-pro/t-sec.jpg",
name: "云数据库",
description:
"SSL证书又叫服务器证书腾讯云为您提供证书的一站式服务包括免费、付费证书的申请、管理及部"
},
{
index: 12,
isSetup: true,
type: 2,
banner: "https://tdesign.gtimg.com/tdesign-pro/t-sec.jpg",
name: "SSL证书",
description:
"SSL证书又叫服务器证书腾讯云为您提供证书的一站式服务包括免费、付费证书的申请、管理及部"
},
{
index: 13,
isSetup: true,
type: 3,
banner: "https://tdesign.gtimg.com/tdesign-pro/cloud-db.jpg",
name: "云数据库",
description:
"腾讯安全云防火墙产品是腾讯云安全团队结合云原生的优势自主研发的SaaS化防火墙产品无需客无需客无需客无需客无需客无需客无需客"
},
{
index: 14,
isSetup: false,
type: 5,
banner: "https://tdesign.gtimg.com/tdesign-pro/t-sec.jpg",
name: "SSL证书",
description:
"基于腾讯优图强大的面部分析技术,提供包括人脸检测与分析、五官定位、人脸搜索、人脸比对、人脸"
},
{
index: 15,
isSetup: true,
type: 2,
banner: "https://tdesign.gtimg.com/tdesign-pro/t-sec.jpg",
name: "云数据库",
description:
"SSL证书又叫服务器证书腾讯云为您提供证书的一站式服务包括免费、付费证书的申请、管理及部"
},
{
index: 16,
isSetup: false,
type: 3,
banner: "https://tdesign.gtimg.com/tdesign-pro/cloud-server.jpg",
name: "CVM",
description:
"基于腾讯优图强大的面部分析技术,提供包括人脸检测与分析、五官定位、人脸搜索、人脸比对、人脸"
},
{
index: 17,
isSetup: false,
type: 5,
banner:
"https://tdesign.gtimg.com/tdesign-pro/face-recognition.jpg",
name: "云数据库",
description:
"SSL证书又叫服务器证书腾讯云为您提供证书的一站式服务包括免费、付费证书的申请、管理及部"
},
{
index: 18,
isSetup: false,
type: 4,
banner:
"https://tdesign.gtimg.com/tdesign-pro/face-recognition.jpg",
name: "云数据库",
description:
"腾讯安全云防火墙产品是腾讯云安全团队结合云原生的优势自主研发的SaaS化防火墙产品无需客无需客无需客无需客无需客无需客无需客"
},
{
index: 19,
isSetup: true,
type: 2,
banner: "https://tdesign.gtimg.com/tdesign-pro/ssl.jpg",
name: "CVM",
description:
"SSL证书又叫服务器证书腾讯云为您提供证书的一站式服务包括免费、付费证书的申请、管理及部"
},
{
index: 20,
isSetup: true,
type: 4,
banner:
"https://tdesign.gtimg.com/tdesign-pro/face-recognition.jpg",
name: "SSL证书",
description:
"SSL证书又叫服务器证书腾讯云为您提供证书的一站式服务包括免费、付费证书的申请、管理及部"
},
{
index: 21,
isSetup: false,
type: 4,
banner: "https://tdesign.gtimg.com/tdesign-pro/t-sec.jpg",
name: "云数据库",
description:
"云硬盘为您提供用于CVM的持久性数据块级存储服务。云硬盘中的数据自动地可用区内以多副本冗"
},
{
index: 22,
isSetup: false,
type: 3,
banner: "https://tdesign.gtimg.com/tdesign-pro/cloud-db.jpg",
name: "CVM",
description:
"SSL证书又叫服务器证书腾讯云为您提供证书的一站式服务包括免费、付费证书的申请、管理及部"
},
{
index: 23,
isSetup: true,
type: 1,
banner: "https://tdesign.gtimg.com/tdesign-pro/ssl.jpg",
name: "人脸识别",
description:
"基于腾讯优图强大的面部分析技术,提供包括人脸检测与分析、五官定位、人脸搜索、人脸比对、人脸"
},
{
index: 24,
isSetup: true,
type: 4,
banner: "https://tdesign.gtimg.com/tdesign-pro/ssl.jpg",
name: "人脸识别",
description:
"基于腾讯优图强大的面部分析技术,提供包括人脸检测与分析、五官定位、人脸搜索、人脸比对、人脸"
},
{
index: 25,
isSetup: false,
type: 5,
banner:
"https://tdesign.gtimg.com/tdesign-pro/face-recognition.jpg",
name: "CVM",
description:
"云硬盘为您提供用于CVM的持久性数据块级存储服务。云硬盘中的数据自动地可用区内以多副本冗"
},
{
index: 26,
isSetup: true,
type: 4,
banner: "https://tdesign.gtimg.com/tdesign-pro/cloud-server.jpg",
name: "SSL证书",
description:
"云硬盘为您提供用于CVM的持久性数据块级存储服务。云硬盘中的数据自动地可用区内以多副本冗"
},
{
index: 27,
isSetup: true,
type: 5,
banner: "https://tdesign.gtimg.com/tdesign-pro/ssl.jpg",
name: "CVM",
description:
"SSL证书又叫服务器证书腾讯云为您提供证书的一站式服务包括免费、付费证书的申请、管理及部"
},
{
index: 28,
isSetup: false,
type: 4,
banner: "https://tdesign.gtimg.com/tdesign-pro/ssl.jpg",
name: "云数据库",
description:
"基于腾讯优图强大的面部分析技术,提供包括人脸检测与分析、五官定位、人脸搜索、人脸比对、人脸"
},
{
index: 29,
isSetup: false,
type: 5,
banner: "https://tdesign.gtimg.com/tdesign-pro/cloud-db.jpg",
name: "CVM",
description:
"SSL证书又叫服务器证书腾讯云为您提供证书的一站式服务包括免费、付费证书的申请、管理及部"
},
{
index: 30,
isSetup: true,
type: 1,
banner: "https://tdesign.gtimg.com/tdesign-pro/ssl.jpg",
name: "CVM",
description:
"云硬盘为您提供用于CVM的持久性数据块级存储服务。云硬盘中的数据自动地可用区内以多副本冗"
},
{
index: 31,
isSetup: true,
type: 4,
banner: "https://tdesign.gtimg.com/tdesign-pro/cloud-server.jpg",
name: "CVM",
description:
"基于腾讯优图强大的面部分析技术,提供包括人脸检测与分析、五官定位、人脸搜索、人脸比对、人脸"
},
{
index: 32,
isSetup: false,
type: 3,
banner: "https://tdesign.gtimg.com/tdesign-pro/cloud-server.jpg",
name: "T-Sec 云防火墙",
description:
"腾讯安全云防火墙产品是腾讯云安全团队结合云原生的优势自主研发的SaaS化防火墙产品无需客无需客无需客无需客无需客无需客无需客"
},
{
index: 33,
isSetup: true,
type: 3,
banner: "https://tdesign.gtimg.com/tdesign-pro/t-sec.jpg",
name: "CVM",
description:
"云数据库MySQL为用户提供安全可靠性能卓越、易于维护的企业级云数据库服务。"
},
{
index: 34,
isSetup: false,
type: 2,
banner: "https://tdesign.gtimg.com/tdesign-pro/ssl.jpg",
name: "SSL证书",
description:
"腾讯安全云防火墙产品是腾讯云安全团队结合云原生的优势自主研发的SaaS化防火墙产品无需客无需客无需客无需客无需客无需客无需客"
},
{
index: 35,
isSetup: false,
type: 1,
banner: "https://tdesign.gtimg.com/tdesign-pro/cloud-server.jpg",
name: "云数据库",
description:
"基于腾讯优图强大的面部分析技术,提供包括人脸检测与分析、五官定位、人脸搜索、人脸比对、人脸"
},
{
index: 36,
isSetup: false,
type: 4,
banner:
"https://tdesign.gtimg.com/tdesign-pro/face-recognition.jpg",
name: "SSL证书",
description:
"腾讯安全云防火墙产品是腾讯云安全团队结合云原生的优势自主研发的SaaS化防火墙产品无需客无需客无需客无需客无需客无需客无需客"
},
{
index: 37,
isSetup: true,
type: 5,
banner: "https://tdesign.gtimg.com/tdesign-pro/cloud-server.jpg",
name: "CVM",
description:
"云数据库MySQL为用户提供安全可靠性能卓越、易于维护的企业级云数据库服务。"
},
{
index: 38,
isSetup: false,
type: 4,
banner: "https://tdesign.gtimg.com/tdesign-pro/ssl.jpg",
name: "云数据库",
description:
"云硬盘为您提供用于CVM的持久性数据块级存储服务。云硬盘中的数据自动地可用区内以多副本冗"
},
{
index: 39,
isSetup: false,
type: 3,
banner: "https://tdesign.gtimg.com/tdesign-pro/t-sec.jpg",
name: "人脸识别",
description:
"云硬盘为您提供用于CVM的持久性数据块级存储服务。云硬盘中的数据自动地可用区内以多副本冗"
},
{
index: 40,
isSetup: true,
type: 4,
banner: "https://tdesign.gtimg.com/tdesign-pro/ssl.jpg",
name: "CVM",
description:
"SSL证书又叫服务器证书腾讯云为您提供证书的一站式服务包括免费、付费证书的申请、管理及部"
},
{
index: 41,
isSetup: true,
type: 4,
banner: "https://tdesign.gtimg.com/tdesign-pro/ssl.jpg",
name: "T-Sec 云防火墙",
description:
"云硬盘为您提供用于CVM的持久性数据块级存储服务。云硬盘中的数据自动地可用区内以多副本冗"
},
{
index: 42,
isSetup: true,
type: 3,
banner: "https://tdesign.gtimg.com/tdesign-pro/cloud-server.jpg",
name: "T-Sec 云防火墙",
description:
"云硬盘为您提供用于CVM的持久性数据块级存储服务。云硬盘中的数据自动地可用区内以多副本冗"
},
{
index: 43,
isSetup: false,
type: 3,
banner: "https://tdesign.gtimg.com/tdesign-pro/cloud-db.jpg",
name: "SSL证书",
description:
"云硬盘为您提供用于CVM的持久性数据块级存储服务。云硬盘中的数据自动地可用区内以多副本冗"
},
{
index: 44,
isSetup: true,
type: 4,
banner: "https://tdesign.gtimg.com/tdesign-pro/t-sec.jpg",
name: "SSL证书",
description:
"云硬盘为您提供用于CVM的持久性数据块级存储服务。云硬盘中的数据自动地可用区内以多副本冗"
},
{
index: 45,
isSetup: false,
type: 3,
banner: "https://tdesign.gtimg.com/tdesign-pro/ssl.jpg",
name: "T-Sec 云防火墙",
description:
"SSL证书又叫服务器证书腾讯云为您提供证书的一站式服务包括免费、付费证书的申请、管理及部"
},
{
index: 46,
isSetup: true,
type: 2,
banner: "https://tdesign.gtimg.com/tdesign-pro/cloud-server.jpg",
name: "SSL证书",
description:
"SSL证书又叫服务器证书腾讯云为您提供证书的一站式服务包括免费、付费证书的申请、管理及部"
},
{
index: 47,
isSetup: false,
type: 4,
banner: "https://tdesign.gtimg.com/tdesign-pro/cloud-server.jpg",
name: "SSL证书",
description:
"腾讯安全云防火墙产品是腾讯云安全团队结合云原生的优势自主研发的SaaS化防火墙产品无需客无需客无需客无需客无需客无需客无需客"
},
{
index: 48,
isSetup: false,
type: 3,
banner: "https://tdesign.gtimg.com/tdesign-pro/ssl.jpg",
name: "T-Sec 云防火墙",
description:
"SSL证书又叫服务器证书腾讯云为您提供证书的一站式服务包括免费、付费证书的申请、管理及部"
}
]
}
};
}
}
]);

44
mock/login.ts Normal file
View File

@@ -0,0 +1,44 @@
// 根据角色动态生成路由
import { defineFakeRoute } from "vite-plugin-fake-server/client";
export default defineFakeRoute([
{
url: "/login",
method: "post",
response: ({ body }) => {
if (body.username === "admin") {
return {
code: 0,
message: "操作成功",
data: {
avatar: "https://avatars.githubusercontent.com/u/44761321",
username: "admin",
nickname: "小铭",
// 一个用户可能有多个角色
roles: ["admin"],
// 按钮级别权限
permissions: ["*:*:*"],
accessToken: "eyJhbGciOiJIUzUxMiJ9.admin",
refreshToken: "eyJhbGciOiJIUzUxMiJ9.adminRefresh",
expires: "2030/10/30 00:00:00"
}
};
} else {
return {
code: 0,
message: "操作成功",
data: {
avatar: "https://avatars.githubusercontent.com/u/52823142",
username: "common",
nickname: "小林",
roles: ["common"],
permissions: ["permission:btn:add", "permission:btn:edit"],
accessToken: "eyJhbGciOiJIUzUxMiJ9.common",
refreshToken: "eyJhbGciOiJIUzUxMiJ9.commonRefresh",
expires: "2030/10/30 00:00:00"
}
};
}
}
}
]);

42
mock/map.ts Normal file
View File

@@ -0,0 +1,42 @@
import { defineFakeRoute } from "vite-plugin-fake-server/client";
import { faker } from "@faker-js/faker/locale/zh_CN";
type mapType = {
plateNumber: string;
driver: string;
orientation: number;
lng: number;
lat: number;
};
const mapList = (): Array<mapType> => {
const result: Array<mapType> = [];
for (let index = 0; index < 200; index++) {
result.push({
plateNumber: `豫A${faker.string.numeric({
length: 5
})}${faker.string.alphanumeric({
casing: "upper"
})}`,
driver: faker.person.firstName(),
orientation: faker.number.int({ min: 1, max: 360 }),
lng: faker.location.latitude({ max: 114.1, min: 113 }),
lat: faker.location.latitude({ max: 35.1, min: 34 })
});
}
return result;
};
export default defineFakeRoute([
{
url: "/get-map-info",
method: "get",
response: () => {
return {
code: 0,
message: "操作成功",
data: mapList()
};
}
}
]);

61
mock/mine.ts Normal file
View File

@@ -0,0 +1,61 @@
import { defineFakeRoute } from "vite-plugin-fake-server/client";
import { faker } from "@faker-js/faker/locale/zh_CN";
export default defineFakeRoute([
// 账户设置-个人信息
{
url: "/mine",
method: "get",
response: () => {
return {
code: 0,
message: "操作成功",
data: {
avatar: "https://avatars.githubusercontent.com/u/44761321",
username: "admin",
nickname: "小铭",
email: "pureadmin@163.com",
phone: "15888886789",
description: "一个热爱开源的前端工程师"
}
};
}
},
// 账户设置-个人安全日志
{
url: "/mine-logs",
method: "get",
response: () => {
const list = [
{
id: 1,
ip: faker.internet.ipv4(),
address: "中国河南省信阳市",
system: "macOS",
browser: "Chrome",
summary: "账户登录", // 详情
operatingTime: new Date() // 时间
},
{
id: 2,
ip: faker.internet.ipv4(),
address: "中国广东省深圳市",
system: "Windows",
browser: "Firefox",
summary: "绑定了手机号码",
operatingTime: new Date().setDate(new Date().getDate() - 1)
}
];
return {
code: 0,
message: "操作成功",
data: {
list,
total: list.length, // 总条目数
pageSize: 10, // 每页显示条目个数
currentPage: 1 // 当前页数
}
};
}
}
]);

29
mock/refreshToken.ts Normal file
View File

@@ -0,0 +1,29 @@
import { defineFakeRoute } from "vite-plugin-fake-server/client";
// 模拟刷新token接口
export default defineFakeRoute([
{
url: "/refresh-token",
method: "post",
response: ({ body }) => {
if (body.refreshToken) {
return {
code: 0,
message: "操作成功",
data: {
accessToken: "eyJhbGciOiJIUzUxMiJ9.newAdmin",
refreshToken: "eyJhbGciOiJIUzUxMiJ9.newAdminRefresh",
// `expires`选择这种日期格式是为了方便调试,后端直接设置时间戳或许更方便(每次都应该递增)。如果后端返回的是时间戳格式,前端开发请来到这个目录`src/utils/auth.ts`,把第`38`行的代码换成expires = data.expires即可。
expires: "2030/10/30 23:59:59"
}
};
} else {
return {
code: 10001,
message: "请求参数缺失或格式不正确",
data: {}
};
}
}
}
]);

1815
mock/system.ts Normal file

File diff suppressed because it is too large Load Diff

209
package.json Normal file
View File

@@ -0,0 +1,209 @@
{
"name": "vue-pure-admin",
"version": "6.3.0",
"private": true,
"type": "module",
"scripts": {
"dev": "NODE_OPTIONS=--max-old-space-size=4096 vite",
"serve": "pnpm dev",
"build": "rimraf dist && NODE_OPTIONS=--max-old-space-size=8192 vite build && generate-version-file",
"build:staging": "rimraf dist && vite build --mode staging",
"report": "rimraf dist && vite build",
"preview": "vite preview",
"preview:build": "pnpm build && vite preview",
"typecheck": "tsc --noEmit && vue-tsc --noEmit --skipLibCheck",
"svgo": "svgo -f . -r",
"clean:cache": "rimraf .eslintcache && rimraf pnpm-lock.yaml && rimraf node_modules && pnpm store prune && pnpm install",
"lint:eslint": "eslint --cache --max-warnings 0 src mock build --fix",
"lint:prettier": "prettier --write \"src/**/*.{js,ts,json,tsx,css,scss,vue,html,md}\"",
"lint:stylelint": "stylelint --cache --fix \"**/*.{html,vue,css,scss}\" --cache-location node_modules/.cache/stylelint/",
"lint": "pnpm lint:eslint && pnpm lint:prettier && pnpm lint:stylelint",
"prepare": "husky",
"preinstall": "npx only-allow pnpm"
},
"keywords": [
"vue-pure-admin",
"element-plus",
"tailwindcss",
"pure-admin",
"typescript",
"pinia",
"vue3",
"vite",
"esm"
],
"homepage": "https://github.com/pure-admin/vue-pure-admin",
"repository": {
"type": "git",
"url": "git+https://github.com/pure-admin/vue-pure-admin.git"
},
"bugs": {
"url": "https://github.com/pure-admin/vue-pure-admin/issues"
},
"license": "MIT",
"author": {
"name": "xiaoxian521",
"email": "pureadmin@163.com",
"url": "https://github.com/xiaoxian521"
},
"dependencies": {
"@amap/amap-jsapi-loader": "^1.0.1",
"@howdyjs/mouse-menu": "^2.1.7",
"@infectoone/vue-ganttastic": "^2.3.2",
"@logicflow/core": "^1.2.28",
"@logicflow/extension": "^1.2.28",
"@pureadmin/descriptions": "^1.2.1",
"@pureadmin/table": "^3.3.0",
"@pureadmin/utils": "^2.6.4",
"@vue-flow/background": "^1.3.2",
"@vue-flow/core": "^1.48.2",
"@vueuse/core": "^14.2.1",
"@vueuse/motion": "^3.0.3",
"@wangeditor/editor": "^5.1.23",
"@wangeditor/editor-for-vue": "^5.1.12",
"@zxcvbn-ts/core": "^3.0.4",
"animate.css": "^4.1.1",
"axios": "^1.13.6",
"china-area-data": "^5.0.1",
"codemirror": "^5.65.21",
"codemirror-editor-vue3": "^2.8.0",
"cropperjs": "^1.6.2",
"dayjs": "^1.11.20",
"deep-chat": "^2.4.2",
"echarts": "^6.0.0",
"el-table-infinite-scroll": "^3.0.8",
"element-plus": "^2.13.6",
"highlight.js": "^11.11.1",
"intro.js": "^7.2.0",
"js-cookie": "^3.0.5",
"jsbarcode": "^3.12.3",
"localforage": "^1.10.0",
"mint-filter": "^4.0.3",
"mitt": "^3.0.1",
"mqtt": "4.3.7",
"nprogress": "^0.2.0",
"path-browserify": "^1.0.1",
"pinia": "^3.0.4",
"pinyin-pro": "^3.28.0",
"plus-pro-components": "^0.1.30",
"qrcode": "^1.5.4",
"qs": "^6.15.0",
"responsive-storage": "^2.2.0",
"sortablejs": "^1.15.7",
"swiper": "^12.1.2",
"typeit": "^8.8.7",
"v-contextmenu": "^3.2.0",
"vditor": "^3.11.2",
"version-rocket": "^1.7.4",
"vue": "^3.5.30",
"vue-i18n": "^11.3.0",
"vue-json-pretty": "^2.6.0",
"vue-pdf-embed": "^2.1.4",
"vue-router": "^5.0.4",
"vue-tippy": "^6.7.1",
"vue-types": "^6.0.0",
"vue-virtual-scroller": "2.0.0-beta.10",
"vue-waterfall-plugin-next": "^2.6.9",
"vue3-danmaku": "^1.6.7",
"vue3-puzzle-vcode": "^1.1.7",
"vuedraggable": "^4.1.0",
"vxe-table": "4.6.25",
"wavesurfer.js": "^7.12.4",
"xgplayer": "^3.0.24",
"xlsx": "^0.18.5"
},
"devDependencies": {
"@commitlint/cli": "^20.5.0",
"@commitlint/config-conventional": "^20.5.0",
"@commitlint/types": "^20.5.0",
"@eslint/js": "^10.0.1",
"@faker-js/faker": "^10.3.0",
"@iconify/json": "^2.2.452",
"@iconify/vue": "4.2.0",
"@intlify/unplugin-vue-i18n": "^11.0.7",
"@tailwindcss/vite": "^4.2.2",
"@types/codemirror": "^5.60.17",
"@types/dagre": "^0.7.54",
"@types/intro.js": "^5.1.5",
"@types/js-cookie": "^3.0.6",
"@types/node": "^20.19.37",
"@types/nprogress": "^0.2.3",
"@types/path-browserify": "^1.0.3",
"@types/qrcode": "^1.5.6",
"@types/qs": "^6.15.0",
"@types/sortablejs": "^1.15.9",
"@vitejs/plugin-vue": "^6.0.5",
"@vitejs/plugin-vue-jsx": "^5.1.5",
"boxen": "^8.0.1",
"code-inspector-plugin": "^1.4.5",
"cssnano": "^7.1.3",
"dagre": "^0.8.5",
"eslint": "^10.1.0",
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-better-tailwindcss": "^4.3.2",
"eslint-plugin-prettier": "^5.5.5",
"eslint-plugin-vue": "^10.8.0",
"gradient-string": "^3.0.0",
"husky": "^9.1.7",
"lint-staged": "^16.4.0",
"postcss": "^8.5.8",
"postcss-html": "^1.8.1",
"postcss-load-config": "^6.0.1",
"postcss-scss": "^4.0.9",
"prettier": "^3.8.1",
"rimraf": "^6.1.3",
"rollup-plugin-visualizer": "^6.0.11",
"sass": "^1.98.0",
"stylelint": "^17.5.0",
"stylelint-config-recess-order": "^7.7.0",
"stylelint-config-recommended-vue": "^1.6.1",
"stylelint-config-standard-scss": "^17.0.0",
"stylelint-prettier": "^5.0.3",
"svgo": "^4.0.1",
"tailwindcss": "^4.2.2",
"typescript": "^5.9.3",
"typescript-eslint": "^8.57.1",
"unplugin-icons": "^23.0.1",
"vite": "^8.0.1",
"vite-plugin-cdn-import": "^1.0.1",
"vite-plugin-compression": "^0.5.1",
"vite-plugin-fake-server": "^2.2.3",
"vite-plugin-remove-console": "^2.2.0",
"vite-plugin-router-warn": "^2.0.0",
"vite-svg-loader": "^5.1.1",
"vue-eslint-parser": "^10.4.0",
"vue-tsc": "^3.2.6"
},
"engines": {
"node": "^20.19.0 || >=22.13.0",
"pnpm": ">=9"
},
"pnpm": {
"allowedDeprecatedVersions": {
"are-we-there-yet": "*",
"sourcemap-codec": "*",
"lodash.isequal": "*",
"domexception": "*",
"w3c-hr-time": "*",
"inflight": "*",
"npmlog": "*",
"rimraf": "*",
"stable": "*",
"gauge": "*",
"abab": "*",
"glob": "*"
},
"onlyBuiltDependencies": [
"@parcel/watcher",
"core-js",
"es5-ext",
"esbuild",
"typeit",
"vue-demi"
],
"ignoredBuiltDependencies": [
"@tailwindcss/oxide",
"vue3-danmaku"
]
}
}

11869
pnpm-lock.yaml generated Normal file

File diff suppressed because it is too large Load Diff

8
postcss.config.js Normal file
View File

@@ -0,0 +1,8 @@
// @ts-check
/** @type {import('postcss-load-config').Config} */
export default {
plugins: {
...(process.env.NODE_ENV === "production" ? { cssnano: {} } : {})
}
};

Binary file not shown.

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

721
public/html/button.html Normal file
View File

@@ -0,0 +1,721 @@
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8" />
</head>
<body>
<div class="btns">
<div class="btn java">JAVA攻城狮</div>
<div class="btn golang">Golang工程师!</div>
<div class="btn js"><span>js攻城狮</span></div>
<div class="btn nodd-ruby ruby">
<div class="anim"></div>
<span>Ruby攻城狮</span>
</div>
<div class="btn vb">
<span>VB攻城狮</span>
<div class="dot"></div>
</div>
<div class="btn python python-1">python攻城狮</div>
<div class="btn python python-2">python攻城狮</div>
<div class="btn python python-3">python攻城狮</div>
<div class="btn python python-4">python攻城狮</div>
<div class="btn python python-5">python攻城狮</div>
<div class="btn php php-1">php攻城狮</div>
<div class="btn php php-2">php攻城狮</div>
<div class="btn php php-3">php攻城狮</div>
<div class="btn php php-4">php攻城狮</div>
<div class="btn php php-5">php攻城狮</div>
<div class="btn kotlin kotlin-3">kotlin攻城狮</div>
<div class="btn kotlin kotlin-1">kotlin攻城狮</div>
<div class="btn kotlin kotlin-4">kotlin攻城狮</div>
<div class="btn kotlin kotlin-2">kotlin攻城狮</div>
<div class="btn kotlin kotlin-5">kotlin攻城狮</div>
<div class="btn c">C语言攻城狮</div>
</div>
</body>
<style>
.text-info {
position: absolute;
top: calc(50vh - 245px);
text-align: center;
font-size: 12px;
color: #999;
width: 100%;
margin-left: -5px;
}
.btn {
vertical-align: top;
margin: 15px;
display: inline-block;
text-align: center;
width: 122px;
height: 44px;
line-height: 44px;
border-radius: 4px;
color: #fff;
cursor: pointer;
}
.java {
color: #eb9e05;
height: 42px;
line-height: 42px;
width: 120px;
border: 1px solid #eb9e05;
opacity: 1;
transition: all 0.6s;
}
.java:hover {
background: #eb9e05;
color: #fff;
}
.java:active {
opacity: 0.7;
}
.c {
height: 44px;
line-height: 44px;
background: #55acee;
transition: all 0.5s;
box-shadow: 0px 5px 0px 0px #3486d5;
}
.c:hover {
background-color: #6fc6ff;
}
.c:active {
transform: translate(0px, 4px);
box-shadow: 0px 1px 0px 0px #3486d5;
}
@keyframes sheen {
0% {
transform: skewY(-45deg) translateX(0);
}
100% {
transform: skewY(-45deg) translateX(12.5em);
}
}
.golang {
vertical-align: top;
height: 42px;
line-height: 42px;
width: 120px;
color: #2194e0;
border: 1px solid #2194e0;
transition: all 0.2s ease-in-out;
position: relative;
opacity: 1;
overflow: hidden;
}
.golang:before {
content: "";
background-color: rgba(255, 255, 255, 0.5);
height: 100%;
width: 3em;
display: block;
position: absolute;
top: 0;
left: -4.5em;
transform: skewX(-45deg) translateX(0);
transition: none;
}
.golang:hover {
background-color: #2194e0;
color: #fff;
}
.golang:hover:before {
transform: skewX(-45deg) translateX(260px);
transition: all 0.5s ease-in-out;
}
.golang:active {
opacity: 0.8;
}
.js {
width: 160px;
height: 42px;
line-height: 42px;
background: #0d6;
width: 120px;
border: 1px solid #0d6;
overflow: hidden;
transition: all 0.5s;
opacity: 1;
}
.js:hover,
.js:active {
text-decoration: none;
color: #0c5;
border-color: #0c5;
background: #fff;
}
.js:active {
opacity: 0.8;
}
.js span {
display: inline-block;
position: relative;
padding-right: 0;
transition: padding-right 0.5s;
}
.js span:after {
content: " ";
position: absolute;
top: 0;
right: -18px;
opacity: 0;
width: 10px;
height: 10px;
margin-top: -10px;
background: rgba(0, 0, 0, 0);
border: 2px solid #fff;
border-top: none;
border-right: none;
transition: opacity 0.5s, top 0.5s, right 0.5s;
transform: rotate(-140deg);
}
.js:hover span,
.js:active span {
padding-right: 30px;
}
.js:hover span:after,
.js:active span:after {
transition: opacity 0.5s, top 0.5s, right 0.5s;
opacity: 1;
border-color: #0c5;
right: 0;
top: calc(50% + 2.5px);
transform: rotate(-140deg);
}
.nodd-ruby {
background: #c147e6;
position: relative;
overflow: hidden;
z-index: 0;
cursor: pointer;
opacity: 1;
transition: all 0.3s;
}
input[type="checkbox"].toggle {
position: absolute;
width: 100%;
height: 100%;
margin: 0;
left: 0;
top: 0;
cursor: pointer;
}
input[type="checkbox"].toggle:focus {
outline: 0;
}
.anim {
transform: translate(-50%, -50%);
position: absolute;
top: 50%;
left: 50%;
z-index: -1;
}
.anim:before {
position: relative;
content: "";
display: block;
margin-top: 100%;
}
.anim:after {
content: "";
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
border-radius: 50%;
}
.node .toggle:checked + .anim {
animation: 0.75s anim-in;
}
.node .toggle:checked + .anim:after {
animation: anim-in-pseudo 0.75s;
}
.node .toggle:not(:checked) + .anim {
animation: anim-out 0.75s;
}
.node .toggle:not(:checked) + .anim:after {
animation: anim-out-pseudo 0.75s;
}
.node {
background: #ed3f14;
}
.node:hover {
opacity: 0.8;
}
.ruby:active {
opacity: 0.8;
}
.ruby:hover > .anim {
animation: anim-out 0.75s;
}
.ruby:hover > .anim:after {
animation: anim-out-pseudo 0.75s;
}
@keyframes anim-in {
0% {
width: 0%;
}
100% {
width: 100%;
}
}
@keyframes anim-in-pseudo {
0% {
background: rgba(0, 0, 0, 0.3);
}
100% {
background: transparent;
}
}
@keyframes anim-out {
0% {
width: 0%;
}
100% {
width: 100%;
}
}
@keyframes anim-out-pseudo {
0% {
background: rgba(0, 0, 0, 0.35);
}
100% {
background: transparent;
}
}
.python {
transition: 0.5s;
background-size: 200% auto;
}
.python:hover {
background-position: right center;
}
.python-1 {
background-image: linear-gradient(
to right,
#f6d365 0%,
#fda085 51%,
#f6d365 100%
);
}
.python-2 {
background-image: linear-gradient(
to right,
#fbc2eb 0%,
#a6c1ee 51%,
#fbc2eb 100%
);
}
.python-3 {
background-image: linear-gradient(
to right,
#84fab0 0%,
#8fd3f4 51%,
#84fab0 100%
);
}
.python-4 {
background-image: linear-gradient(
to right,
#a1c4fd 0%,
#c2e9fb 51%,
#a1c4fd 100%
);
}
.python-5 {
background-image: linear-gradient(
to right,
#ffecd2 0%,
#fcb69f 51%,
#ffecd2 100%
);
}
.php,
.php::after {
transition: all 0.5s;
}
.php {
border: 1px solid #c147e6;
color: #c147e6;
width: 120px;
height: 42px;
line-height: 42px;
position: relative;
z-index: 1;
text-transform: uppercase;
}
.php:hover {
color: #fff;
}
.php::before,
.php::after {
background: #c147e6;
content: "";
position: absolute;
z-index: -2;
border-radius: 3px;
}
.php-1::after {
height: 0;
left: 0;
top: 0;
width: 100%;
}
.php-1:hover:after {
height: 100%;
}
.php-2::after {
height: 100%;
left: 0;
top: 0;
width: 0;
}
.php-2:hover:after {
width: 100%;
}
.php-3::after {
height: 0;
left: 50%;
top: 50%;
width: 0;
}
.php-3:hover:after {
height: 100%;
left: 0;
top: 0;
width: 100%;
}
.php-4::before {
height: 100%;
left: 0;
top: 0;
width: 100%;
}
.php-4::after {
background: #fff;
height: 100%;
left: 0;
top: 0;
width: 100%;
}
.php-4:hover:after {
height: 0;
left: 50%;
top: 50%;
width: 0;
}
.php-5 {
overflow: hidden;
}
.php-5::after {
height: 100%;
left: -35%;
top: 0;
transform: skew(50deg);
transition-duration: 0.6s;
transform-origin: top left;
width: 0;
}
.php-5:hover:after {
height: 100%;
width: 135%;
}
.kotlin {
background: none;
border: 1px solid;
width: 120px;
height: 42px;
line-height: 42px;
letter-spacing: inherit;
text-transform: inherit;
transition: color 1s;
}
.kotlin-1 {
color: #9c89f7;
}
.kotlin-1:hover {
animation: halftone 1s forwards;
background: radial-gradient(circle, #9c89f7 0.2em, transparent 0.25em) 0 0/1.25em
1.25em,
radial-gradient(circle, #9c89f7 0.2em, transparent 0.25em) 6.25em 6.25em/1.25em
1.25em;
color: #e4f789;
}
@keyframes halftone {
100% {
background-size: 2.375em 2.375em, 0.1em 0.1em;
}
}
.kotlin-2 {
color: #82f6d8;
}
.kotlin-2:hover {
animation: stripes-move 0.75s infinite linear;
background: repeating-linear-gradient(
45deg,
#82f6d8 0,
#82f6d8 0.25em,
transparent 0.25em,
transparent 0.5em
);
color: #f682a0;
}
@keyframes stripes-move {
100% {
background-position: 5em 0px;
}
}
.kotlin-3 {
color: #d3f169;
}
.kotlin-3:hover {
animation: sawtooth 0.35s infinite linear;
background: linear-gradient(45deg, #d3f169 0.5em, transparent 0.5em) 0 0/1em
1em,
linear-gradient(-45deg, #d3f169 0.5em, transparent 0.5em) 0 0/1em 1em;
color: #8769f1;
}
@keyframes sawtooth {
100% {
background-position: 1em 0;
}
}
.kotlin-4 {
color: #eea163;
}
.kotlin-4:hover {
animation: zigzag 1s linear infinite;
background: linear-gradient(
135deg,
rgba(238, 161, 99, 0.25) 0.25em,
transparent 0.25em
) -0.5em 0,
linear-gradient(
225deg,
rgba(238, 161, 99, 0.25) 0.25em,
transparent 0.25em
) -0.5em 0,
linear-gradient(
315deg,
rgba(238, 161, 99, 0.25) 0.25em,
transparent 0.25em
)
0 0,
linear-gradient(
45deg,
rgba(238, 161, 99, 0.25) 0.25em,
transparent 0.25em
)
0 0;
background-size: 0.75em 0.75em;
color: #63b0ee;
}
@keyframes zigzag {
100% {
background-position: 1em 0, 1em 0, -0.75em 0, -0.75em 0;
}
}
.kotlin-5 {
color: #f9879b;
}
.kotlin-5:hover {
animation: pulse 1s ease-in infinite;
background: radial-gradient(
circle,
rgba(249, 135, 155, 0.25) 43%,
transparent 50%
)
0 0/1em 1em,
radial-gradient(circle, rgba(249, 135, 155, 0.25) 43%, transparent 50%)
0.5em 0.5em/2em 2em;
color: #0bdcb7;
}
@keyframes pulse {
50% {
background-position: 0.66em 0.66em, -0.33em -0.33em;
}
100% {
background-size: 2em 2em, 1em 1em;
background-position: -1.5em -1.5em, -1em -1em;
}
}
.vb:before,
.vb:after {
box-sizing: border-box;
}
.vb {
position: relative;
width: 120px;
color: #fa5555;
height: 40px;
line-height: 42px;
border: 2px solid #fa5555;
border-radius: 14px;
text-transform: uppercase;
}
.dot {
content: "";
position: absolute;
top: 0;
width: 32px;
height: 100%;
border-radius: 50%;
transition: all 300ms ease;
display: none;
}
.dot:after {
content: "";
position: absolute;
top: -6px;
height: 5px;
width: 5px;
background: #fa5555;
border-radius: 50%;
border: 4px solid #fa5555;
box-shadow: 0 0 0.7em #fff, 0 0 2em #fa5555;
}
.vb:hover .dot,
.vb:focus .dot {
animation: atom 2s infinite linear;
display: block;
}
/*calc(122px - 36px) 按钮宽度 - dot宽度 - 边框宽度*/
@keyframes atom {
0% {
transform: translateX(0) rotate(0);
}
30% {
transform: translateX(calc(122px - 36px)) rotate(0);
}
50% {
transform: translateX(calc(122px - 36px)) rotate(180deg);
}
80% {
transform: translateX(0) rotate(180deg);
}
100% {
transform: translateX(0) rotate(360deg);
}
}
.btn-down {
position: absolute;
top: calc(50vh - 280px);
text-align: center;
border-radius: 4px;
cursor: pointer;
left: calc(50vw - 87px);
width: 122px;
line-height: 44px;
color: #fff;
background: #2194e0;
opacity: 1;
}
.btn-down:active {
opacity: 0.8;
}
</style>
</html>

1
public/logo.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" class="icon" viewBox="0 0 1024 1024"><path fill="#386BF3" d="M410.558.109c0 210.974-300.876 361.752-300.876 633.548 0 174.943 134.704 316.787 300.876 316.787s300.877-141.817 300.877-316.787C711.408 361.752 410.558 210.974 410.558.109"/><path fill="#C3D2FB" d="M613.469 73.665c0 211.055-300.877 361.914-300.877 633.547C312.592 882.156 447.296 1024 613.47 1024s300.876-141.817 300.876-316.788C914.29 435.58 613.469 284.72 613.469 73.665"/><path fill="#303F5B" d="M312.592 707.212c0-183.713 137.636-312.171 226.723-441.39 81.702 106.112 172.12 218.74 172.12 367.726A309.755 309.755 0 0 1 420.36 950.064a323.1 323.1 0 0 1-107.769-242.852z"/></svg>

After

Width:  |  Height:  |  Size: 706 B

View File

@@ -0,0 +1,36 @@
{
"Version": "6.3.0",
"Title": "PureAdmin",
"FixedHeader": true,
"HiddenSideBar": false,
"MultiTagsCache": false,
"KeepAlive": true,
"Locale": "zh",
"Layout": "vertical",
"Theme": "light",
"DarkMode": false,
"ThemeMode": "light",
"Grey": false,
"Weak": false,
"HideTabs": false,
"HideFooter": false,
"Stretch": false,
"SidebarStatus": true,
"EpThemeColor": "#409EFF",
"ShowLogo": true,
"Watermark": false,
"TagsStyle": "chrome",
"MenuArrowIconNoTransition": false,
"CachingAsyncRoutes": false,
"TooltipEffect": "light",
"ResponsiveStorageNameSpace": "responsive-",
"MenuSearchHistory": 6,
"MapConfigure": {
"amapKey": "adc139d56406f3844c8f1cf1c6b65c41",
"options": {
"resizeEnable": true,
"center": [113.6401, 34.72468],
"zoom": 12
}
}
}

11349
public/wasm/capture.worker.js Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

5477
public/wasm/index.js Normal file

File diff suppressed because it is too large Load Diff

90
src/App.vue Normal file
View File

@@ -0,0 +1,90 @@
<template>
<el-config-provider :locale="currentLocale">
<router-view />
<ReDialog />
<ReDrawer />
</el-config-provider>
</template>
<script lang="ts">
import { checkVersion } from "version-rocket";
import { ElConfigProvider } from "element-plus";
import { useRouter, useRoute } from "vue-router";
import { useGlobal, useWatermark } from "@pureadmin/utils";
import { defineComponent, computed, watch, nextTick } from "vue";
import { ReDialog, closeAllDialog } from "@/components/ReDialog";
import { ReDrawer, closeAllDrawer } from "@/components/ReDrawer";
import en from "element-plus/es/locale/lang/en";
import zhCn from "element-plus/es/locale/lang/zh-cn";
import plusEn from "plus-pro-components/es/locale/lang/en";
import plusZhCn from "plus-pro-components/es/locale/lang/zh-cn";
export default defineComponent({
name: "app",
components: {
[ElConfigProvider.name]: ElConfigProvider,
ReDialog,
ReDrawer
},
setup() {
const route = useRoute();
const router = useRouter();
const { setWatermark, clear } = useWatermark();
const { $storage } = useGlobal<GlobalPropertiesApi>();
const watermarkEnable = computed(() => $storage.configure?.watermark);
const watermarkText = computed(() => $storage.configure?.watermarkText);
const currentLocale = computed(() => {
return $storage.locale?.locale === "zh"
? { ...zhCn, ...plusZhCn }
: { ...en, ...plusEn };
});
router.beforeEach(() => {
closeAllDialog();
closeAllDrawer();
});
watch(
[watermarkEnable, watermarkText, () => route.name],
async ([enable, text, name]) => {
await nextTick();
if (enable && name !== "Login") {
setWatermark(text, { verticalOffset: 170 });
} else {
clear();
}
},
{
immediate: true
}
);
return {
currentLocale
};
},
beforeCreate() {
const { version, name: title } = __APP_INFO__.pkg;
const { VITE_PUBLIC_PATH, MODE } = import.meta.env;
// https://github.com/guMcrey/version-rocket/blob/main/README.zh-CN.md#api
if (MODE === "production") {
// 版本实时更新检测,只作用于线上环境
checkVersion(
// config
{
// 5分钟检测一次版本
pollingTime: 300000,
localPackageVersion: version,
originVersionFileUrl: `${location.origin}${VITE_PUBLIC_PATH}version.json`
},
// options
{
title,
description: "检测到新版本",
buttonText: "立即更新"
}
);
}
}
});
</script>

15
src/api/list.ts Normal file
View File

@@ -0,0 +1,15 @@
import { http } from "@/utils/http";
type Result = {
code: number;
message: string;
data?: {
/** 列表数据 */
list: Array<any>;
};
};
/** 卡片列表 */
export const getCardList = (data?: object) => {
return http.request<Result>("post", "/get-card-list", { data });
};

26
src/api/mock.ts Normal file
View File

@@ -0,0 +1,26 @@
import { http } from "@/utils/http";
type Result = {
code: number;
message: string;
data: Array<any>;
};
/** 地图数据 */
export const mapJson = (params?: object) => {
return http.request<Result>("get", "/get-map-info", { params });
};
/** 文件上传 */
export const formUpload = data => {
return http.request<Result>(
"post",
"https://pureadmin.free.beeceptor.com/images",
{ data },
{
headers: {
"Content-Type": "multipart/form-data"
}
}
);
};

11
src/api/routes.ts Normal file
View File

@@ -0,0 +1,11 @@
import { http } from "@/utils/http";
type Result = {
code: number;
message: string;
data: Array<any>;
};
export const getAsyncRoutes = () => {
return http.request<Result>("get", "/get-async-routes");
};

87
src/api/system.ts Normal file
View File

@@ -0,0 +1,87 @@
import { http } from "@/utils/http";
type Result = {
code: number;
message: string;
data?: Array<any>;
};
type ResultTable = {
code: number;
message: string;
data?: {
/** 列表数据 */
list: Array<any>;
/** 总条目数 */
total?: number;
/** 每页显示条目个数 */
pageSize?: number;
/** 当前页数 */
currentPage?: number;
};
};
/** 获取系统管理-用户管理列表 */
export const getUserList = (data?: object) => {
return http.request<ResultTable>("post", "/user", { data });
};
/** 系统管理-用户管理-获取所有角色列表 */
export const getAllRoleList = () => {
return http.request<Result>("get", "/list-all-role");
};
/** 系统管理-用户管理-根据userId获取对应角色id列表userId用户id */
export const getRoleIds = (data?: object) => {
return http.request<Result>("post", "/list-role-ids", { data });
};
/** 获取系统管理-角色管理列表 */
export const getRoleList = (data?: object) => {
return http.request<ResultTable>("post", "/role", { data });
};
/** 获取系统管理-菜单管理列表 */
export const getMenuList = (data?: object) => {
return http.request<Result>("post", "/menu", { data });
};
/** 获取系统管理-部门管理列表 */
export const getDeptList = (data?: object) => {
return http.request<Result>("post", "/dept", { data });
};
/** 获取系统监控-在线用户列表 */
export const getOnlineLogsList = (data?: object) => {
return http.request<ResultTable>("post", "/online-logs", { data });
};
/** 获取系统监控-登录日志列表 */
export const getLoginLogsList = (data?: object) => {
return http.request<ResultTable>("post", "/login-logs", { data });
};
/** 获取系统监控-操作日志列表 */
export const getOperationLogsList = (data?: object) => {
return http.request<ResultTable>("post", "/operation-logs", { data });
};
/** 获取系统监控-系统日志列表 */
export const getSystemLogsList = (data?: object) => {
return http.request<ResultTable>("post", "/system-logs", { data });
};
/** 获取系统监控-系统日志-根据 id 查日志详情 */
export const getSystemLogsDetail = (data?: object) => {
return http.request<Result>("post", "/system-logs-detail", { data });
};
/** 获取角色管理-权限-菜单权限 */
export const getRoleMenu = (data?: object) => {
return http.request<Result>("post", "/role-menu", { data });
};
/** 获取角色管理-权限-菜单权限-根据角色 id 查对应菜单 */
export const getRoleMenuIds = (data?: object) => {
return http.request<Result>("post", "/role-menu-ids", { data });
};

93
src/api/user.ts Normal file
View File

@@ -0,0 +1,93 @@
import { http } from "@/utils/http";
export type UserResult = {
code: number;
message: string;
data: {
/** 头像 */
avatar: string;
/** 用户名 */
username: string;
/** 昵称 */
nickname: string;
/** 当前登录用户的角色 */
roles: Array<string>;
/** 按钮级别权限 */
permissions: Array<string>;
/** `token` */
accessToken: string;
/** 用于调用刷新`accessToken`的接口时所需的`token` */
refreshToken: string;
/** `accessToken`的过期时间(格式'xxxx/xx/xx xx:xx:xx' */
expires: Date;
};
};
export type RefreshTokenResult = {
code: number;
message: string;
data: {
/** `token` */
accessToken: string;
/** 用于调用刷新`accessToken`的接口时所需的`token` */
refreshToken: string;
/** `accessToken`的过期时间(格式'xxxx/xx/xx xx:xx:xx' */
expires: Date;
};
};
export type UserInfo = {
/** 头像 */
avatar: string;
/** 用户名 */
username: string;
/** 昵称 */
nickname: string;
/** 邮箱 */
email: string;
/** 联系电话 */
phone: string;
/** 简介 */
description: string;
};
export type UserInfoResult = {
code: number;
message: string;
data: UserInfo;
};
type ResultTable = {
code: number;
message: string;
data?: {
/** 列表数据 */
list: Array<any>;
/** 总条目数 */
total?: number;
/** 每页显示条目个数 */
pageSize?: number;
/** 当前页数 */
currentPage?: number;
};
};
/** 登录 */
export const getLogin = (data?: object) => {
return http.request<UserResult>("post", "/login", { data });
};
/** 刷新`token` */
export const refreshTokenApi = (data?: object) => {
return http.request<RefreshTokenResult>("post", "/refresh-token", { data });
};
/** 账户设置-个人信息 */
export const getMine = (data?: object) => {
return http.request<UserInfoResult>("get", "/mine", { data });
};
/** 账户设置-个人安全日志 */
export const getMineLogs = (data?: object) => {
return http.request<ResultTable>("get", "/mine-logs", { data });
};

BIN
src/assets/car.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -0,0 +1,27 @@
@font-face {
font-family: "iconfont"; /* Project id 2208059 */
src:
url("iconfont.woff2?t=1671895108120") format("woff2"),
url("iconfont.woff?t=1671895108120") format("woff"),
url("iconfont.ttf?t=1671895108120") format("truetype");
}
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.pure-iconfont-tabs:before {
content: "\e63e";
}
.pure-iconfont-logo:before {
content: "\e620";
}
.pure-iconfont-new:before {
content: "\e615";
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,30 @@
{
"id": "2208059",
"name": "pure-admin",
"font_family": "iconfont",
"css_prefix_text": "pure-iconfont-",
"description": "pure-admin-iconfont",
"glyphs": [
{
"icon_id": "20594647",
"name": "Tabs",
"font_class": "tabs",
"unicode": "e63e",
"unicode_decimal": 58942
},
{
"icon_id": "22129506",
"name": "PureLogo",
"font_class": "logo",
"unicode": "e620",
"unicode_decimal": 58912
},
{
"icon_id": "7795615",
"name": "New",
"font_class": "new",
"unicode": "e615",
"unicode_decimal": 58901
}
]
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" class="icon" viewBox="0 0 1024 1024"><path fill="#386BF3" d="M410.558.109c0 210.974-300.876 361.752-300.876 633.548 0 174.943 134.704 316.787 300.876 316.787s300.877-141.817 300.877-316.787C711.408 361.752 410.558 210.974 410.558.109"/><path fill="#C3D2FB" d="M613.469 73.665c0 211.055-300.877 361.914-300.877 633.547C312.592 882.156 447.296 1024 613.47 1024s300.876-141.817 300.876-316.788C914.29 435.58 613.469 284.72 613.469 73.665"/><path fill="#303F5B" d="M312.592 707.212c0-183.713 137.636-312.171 226.723-441.39 81.702 106.112 172.12 218.74 172.12 367.726A309.755 309.755 0 0 1 420.36 950.064a323.1 323.1 0 0 1-107.769-242.852z"/></svg>

After

Width:  |  Height:  |  Size: 706 B

BIN
src/assets/login/bg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6.7 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 10 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 11 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 13 KiB

1
src/assets/svg/back.svg Normal file
View File

@@ -0,0 +1 @@
<svg width="32" height="32" viewBox="0 0 48 48"><path fill="#2F88FF" fill-rule="evenodd" stroke="#000" stroke-linejoin="round" stroke-width="4" d="M44 40.836q-7.34-8.96-13.036-10.168t-10.846-.365V41L4 23.545 20.118 7v10.167q9.523.075 16.192 6.833 6.668 6.758 7.69 16.836Z" clip-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 300 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M2.88 18.054a35.9 35.9 0 0 1 8.531-16.32.8.8 0 0 1 1.178 0q.25.27.413.455a35.9 35.9 0 0 1 8.118 15.865c-2.141.451-4.34.747-6.584.874l-2.089 4.178a.5.5 0 0 1-.894 0l-2.089-4.178a44 44 0 0 1-6.584-.874m6.698-1.123 1.157.066L12 19.527l1.265-2.53 1.157-.066a42 42 0 0 0 4.227-.454A33.9 33.9 0 0 0 12 4.09a33.9 33.9 0 0 0-6.649 12.387q2.093.334 4.227.454M12 15a3 3 0 1 1 0-6 3 3 0 0 1 0 6m0-2a1 1 0 1 0 0-2 1 1 0 0 0 0 2"/></svg>

After

Width:  |  Height:  |  Size: 533 B

View File

@@ -0,0 +1 @@
<svg width="1em" height="1em" fill="none" class="t-icon t-icon-calendar" viewBox="0 0 16 16"><path fill="currentColor" d="M10 3H6V1.5H5V3H3a1 1 0 0 0-1 1v9a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1h-2V1.5h-1zM5 5h1V4h4v1h1V4h2v2H3V4h2zM3 7h10v6H3z"/></svg>

After

Width:  |  Height:  |  Size: 261 B

1
src/assets/svg/dark.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M11.38 2.019a7.5 7.5 0 1 0 10.6 10.6C21.662 17.854 17.316 22 12.001 22 6.477 22 2 17.523 2 12c0-5.315 4.146-9.661 9.38-9.981"/></svg>

After

Width:  |  Height:  |  Size: 262 B

1
src/assets/svg/day.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M12 18a6 6 0 1 1 0-12 6 6 0 0 1 0 12M11 1h2v3h-2zm0 19h2v3h-2zM3.515 4.929l1.414-1.414L7.05 5.636 5.636 7.05zM16.95 18.364l1.414-1.414 2.121 2.121-1.414 1.414zm2.121-14.85 1.414 1.415-2.121 2.121-1.414-1.414 2.121-2.121zM5.636 16.95l1.414 1.414-2.121 2.121-1.414-1.414zM23 11v2h-3v-2zM4 11v2H1v-2z"/></svg>

After

Width:  |  Height:  |  Size: 435 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" class="iconify iconify--ant-design" viewBox="0 0 1024 1024"><path fill="currentColor" d="M864 170h-60c-4.4 0-8 3.6-8 8v518H310v-73c0-6.7-7.8-10.5-13-6.3l-141.9 112a8 8 0 0 0 0 12.6l141.9 112c5.3 4.2 13 .4 13-6.3v-75h498c35.3 0 64-28.7 64-64V178c0-4.4-3.6-8-8-8"/></svg>

After

Width:  |  Height:  |  Size: 332 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" class="re-screen" color="#00000073" viewBox="0 0 16 16"><path fill="currentColor" d="M3.5 4H1V3h2V1h1v2.5zM13 3V1h-1v2.5l.5.5H15V3zm-1 9.5V15h1v-2h2v-1h-2.5zM1 12v1h2v2h1v-2.5l-.5-.5zm11-1.5-.5.5h-7l-.5-.5v-5l.5-.5h7l.5.5zM10 7H6v2h4z"/></svg>

After

Width:  |  Height:  |  Size: 308 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" class="re-screen" color="#00000073" viewBox="0 0 16 16"><path fill="currentColor" d="M3 12h10V4H3zm2-6h6v4H5zM2 6H1V2.5l.5-.5H5v1H2zm13-3.5V6h-1V3h-3V2h3.5zM14 10h1v3.5l-.5.5H11v-1h3zM2 13h3v1H1.5l-.5-.5V10h1z"/></svg>

After

Width:  |  Height:  |  Size: 283 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" class="globalization" viewBox="0 0 512 512"><path fill="currentColor" d="m478.33 433.6-90-218a22 22 0 0 0-40.67 0l-90 218a22 22 0 1 0 40.67 16.79L316.66 406h102.67l18.33 44.39A22 22 0 0 0 458 464a22 22 0 0 0 20.32-30.4zM334.83 362 368 281.65 401.17 362zm-66.99-19.08a22 22 0 0 0-4.89-30.7c-.2-.15-15-11.13-36.49-34.73 39.65-53.68 62.11-114.75 71.27-143.49H330a22 22 0 0 0 0-44H214V70a22 22 0 0 0-44 0v20H54a22 22 0 0 0 0 44h197.25c-9.52 26.95-27.05 69.5-53.79 108.36-31.41-41.68-43.08-68.65-43.17-68.87a22 22 0 0 0-40.58 17c.58 1.38 14.55 34.23 52.86 83.93.92 1.19 1.83 2.35 2.74 3.51-39.24 44.35-77.74 71.86-93.85 80.74a22 22 0 1 0 21.07 38.63c2.16-1.18 48.6-26.89 101.63-85.59 22.52 24.08 38 35.44 38.93 36.1a22 22 0 0 0 30.75-4.9z"/></svg>

After

Width:  |  Height:  |  Size: 807 B

1
src/assets/svg/hot.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 1024 1024"><path fill="#FF5D50" d="M428.698 107.315c-6.503 72.192-36.352 207.258-160.256 337.408 3.686-48.025-7.117-83.763-19.047-107.673-6.605-13.159-26.06-10.599-28.877 3.84-5.734 29.44-20.582 75.059-57.6 137.779-71.628 121.395-62.566 459.878 340.736 459.878S934.093 585.728 876.8 442.522c-37.376-93.44-93.952-152.525-128.82-182.324-11.417-9.779-29.132-1.945-29.593 13.056-.921 30.464-7.321 73.37-33.075 102.144-.666-52.787-38.144-208.384-202.445-296.857-23.296-12.544-51.763 2.457-54.17 28.774z"/><path fill="#FFDF99" d="M702.26 678.4c-4.2-45.056-60.673-166.554-212.634-246.426-10.599-5.58-23.092 3.124-21.504 15.002 6.246 46.848 12.953 140.493-24.064 184.73 4.044-40.397-18.125-73.83-36.66-94.31-8.396-9.217-23.552-4.66-25.497 7.68-3.533 22.322-12.851 56.268-36.557 97.945-42.086 74.035-86.989 188.672 124.57 294.656 10.956.563 22.17.87 33.74.87a618 618 0 0 0 32.717-.87C694.631 878.182 709.837 759.706 702.26 678.4"/></svg>

After

Width:  |  Height:  |  Size: 1004 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" class="iconify iconify--mdi" viewBox="0 0 24 24"><path fill="currentColor" d="M1 7h6v2H3v2h4v2H3v2h4v2H1zm10 0h4v2h-4v2h2a2 2 0 0 1 2 2v2c0 1.11-.89 2-2 2H9v-2h4v-2h-2a2 2 0 0 1-2-2V9c0-1.1.9-2 2-2m8 0h2a2 2 0 0 1 2 2v1h-2V9h-2v6h2v-1h2v1c0 1.11-.89 2-2 2h-2a2 2 0 0 1-2-2V9c0-1.1.9-2 2-2"/></svg>

After

Width:  |  Height:  |  Size: 360 B

View File

@@ -0,0 +1 @@
<svg width="1em" height="1em" fill="none" class="t-icon t-icon-laptop" viewBox="0 0 16 16"><path fill="currentColor" d="M2.5 12a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h11a1 1 0 0 1 1 1v7a1 1 0 0 1-1 1zm0-1h11V4h-11zM15 13H1v1h14z"/></svg>

After

Width:  |  Height:  |  Size: 228 B

View File

@@ -0,0 +1 @@
<svg width="1em" height="1em" fill="none" class="t-icon t-icon-service" viewBox="0 0 16 16"><path fill="currentColor" d="M2.52 6.37a5.5 5.5 0 0 1 10.98.13v4c0 .05 0 .1-.02.15A4.5 4.5 0 0 1 9 14.7H8v-1h1a3.5 3.5 0 0 0 3.4-2.7h-1.9a.5.5 0 0 1-.5-.5v-4c0-.28.22-.5.5-.5h1.93a4.5 4.5 0 0 0-8.86 0H5.5c.28 0 .5.22.5.5v4a.5.5 0 0 1-.5.5H3a.5.5 0 0 1-.5-.5v-4c0-.04 0-.09.02-.13M12.5 7H11v3h1.5zm-9 0v3H5V7z"/></svg>

After

Width:  |  Height:  |  Size: 409 B

1
src/assets/svg/shop.svg Normal file
View File

@@ -0,0 +1 @@
<svg width="1em" height="1em" fill="none" class="t-icon t-icon-shop" viewBox="0 0 16 16"><path fill="currentColor" d="M8 1a2.5 2.5 0 0 0-2.5 2.5V5h-2a.5.5 0 0 0-.5.5v9c0 .28.22.5.5.5h9a.5.5 0 0 0 .5-.5v-9a.5.5 0 0 0-.5-.5h-2V3.5A2.5 2.5 0 0 0 8 1m1.5 5v2h1V6H12v8H4V6h1.5v2h1V6zm0-1h-3V3.5a1.5 1.5 0 1 1 3 0z"/></svg>

After

Width:  |  Height:  |  Size: 317 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" class="icon" viewBox="0 0 1024 1024"><path d="M554 849.574c0 23.365-18.635 42.307-42 42.307s-42-18.941-42-42.307V662.719c0-23.365 18.635-42.307 42-42.307v-7.051c23.365 0 42 25.993 42 49.358z"/><path d="M893 888.5c0 17.397-14.103 31.5-31.5 31.5h-700c-17.397 0-31.5-14.103-31.5-31.5s14.103-31.5 31.5-31.5h700c17.397 0 31.5 14.103 31.5 31.5m33-714.074C926 135.484 894.686 105 855.744 105H168.256C129.314 105 98 135.484 98 174.426V533h828zM98 630.988C98 669.931 129.314 702 168.256 702h687.488C894.686 702 926 669.931 926 630.988V596H98z"/></svg>

After

Width:  |  Height:  |  Size: 605 B

View File

@@ -0,0 +1 @@
<svg width="1em" height="1em" fill="none" class="t-icon t-icon-user-avatar" viewBox="0 0 16 16"><path fill="currentColor" d="M8 10.5c1.24 0 2.42.31 3.5.88v1.12h1v-1.14a.94.94 0 0 0-.49-.84 8.48 8.48 0 0 0-8.02 0 .94.94 0 0 0-.49.84v1.14h1v-1.12A7.5 7.5 0 0 1 8 10.5M10.5 6a2.5 2.5 0 1 1-5 0 2.5 2.5 0 0 1 5 0m-1 0a1.5 1.5 0 1 0-3 0 1.5 1.5 0 0 0 3 0"/><path fill="currentColor" d="M2.5 1.5a1 1 0 0 0-1 1v11a1 1 0 0 0 1 1h11a1 1 0 0 0 1-1v-11a1 1 0 0 0-1-1zm11 1v11h-11v-11z"/></svg>

After

Width:  |  Height:  |  Size: 482 B

View File

@@ -0,0 +1 @@
<svg width="32" height="32" viewBox="0 0 24 24"><path fill="currentColor" d="M13.79 10.21a1 1 0 0 0 1.42 0 1 1 0 0 0 0-1.42l-2.5-2.5a1 1 0 0 0-.33-.21 1 1 0 0 0-.76 0 1 1 0 0 0-.33.21l-2.5 2.5a1 1 0 0 0 1.42 1.42l.79-.8v5.18l-.79-.8a1 1 0 0 0-1.42 1.42l2.5 2.5a1 1 0 0 0 .33.21.94.94 0 0 0 .76 0 1 1 0 0 0 .33-.21l2.5-2.5a1 1 0 0 0-1.42-1.42l-.79.8V9.41ZM7 4h10a1 1 0 0 0 0-2H7a1 1 0 0 0 0 2m10 16H7a1 1 0 0 0 0 2h10a1 1 0 0 0 0-2"/></svg>

After

Width:  |  Height:  |  Size: 439 B

Some files were not shown because too many files have changed in this diff Show More