基于国内最新开发规范和架构设计的现代化管理后台模板
Vue Vite TypeScript TDesign License
一个开箱即用、快速搭建大型 Web 应用的企业级中后台模板框架。采用最新的前端技术栈,集成主流插件,提供丰富的示例,经过模块化和按需加载优化,可放心用于生产环境。
- ✅ 分层架构设计 - 表现层、业务层、数据层清晰分离
- ✅ 依赖注入模式 - IoC容器支持,解耦更彻底
- ✅ 微前端支持 - 可扩展的微应用架构
- ✅ 模块化设计 - 高内聚低耦合的模块组织
- ✅ Vue 3.5+ - 最新的组合式API和性能优化
- ✅ Vite 7.0+ - 极速的开发体验和构建速度
- ✅ TypeScript 5.8+ - 完整的类型支持和严格检查
- ✅ Pinia 3.0+ - 新一代状态管理方案
- ✅ TDesign - 腾讯企业级设计体系
- ✅ ESLint 9.x - 扁平化配置,更严格的代码检查
- ✅ Prettier - 统一的代码格式化
- ✅ Husky + Lint-staged - Git提交前自动检查
- ✅ Commitlint - 规范化的提交信息
- ✅ Monorepo - pnpm workspace多包管理
- ✅ 自动导入 - API和组件自动按需导入
- ✅ 路由懒加载 - 优化首屏加载速度
- ✅ 组件按需加载 - 减小打包体积
- ✅ 热更新 - 快速的开发反馈
- ✅ Mock数据 - 前后端分离开发
- ✅ 统一请求封装 - 完善的请求/响应拦截和错误处理
- ✅ 组合式函数库 - useRequest、useTable、useForm等
- ✅ 日志管理 - 分级日志和错误上报
- ✅ 权限管理 - 灵活的路由和按钮权限控制
- ✅ 主题切换 - 支持亮色/暗色主题
- ✅ 国际化 - 多语言支持
- Node.js >= 18.12.0
- pnpm >= 8.0.0
# 克隆项目 git clone https://github.com/your-username/vue3-admin-boilerplate.git # 进入项目目录 cd vue3-admin-boilerplate # 安装依赖 pnpm install
# 启动开发服务器 pnpm dev # 在浏览器中打开 pnpm dev:open
# 生产环境构建 pnpm build:prod # 开发环境构建 pnpm build:dev # 预览构建结果 pnpm preview
import { request } from '@/shared/utils'; // GET请求 const data = await request.get('/api/users'); // POST请求 const result = await request.post('/api/users', { name: 'John' }); // 文件上传 const uploadResult = await request.upload('/api/upload', file);
<script setup lang="ts"> import { useRequest } from '@/shared/composables'; import { getUserList } from '@/api/user'; const { data, loading, run } = useRequest(getUserList, { immediate: true, }); </script>
<script setup lang="ts"> import { useTable } from '@/shared/composables'; const { columns, data, loading, pagination } = useTable({ columns: [...], requestFn: getUserList, immediate: true, }); </script>
更多示例请查看 使用文档
src/
├── core/ # 核心模块
│ ├── app.ts # 应用启动器
│ ├── di/ # 依赖注入
│ ├── modules/ # 核心模块
│ └── micro-frontend/ # 微前端
│
├── shared/ # 共享模块
│ ├── components/ # 共享组件
│ ├── composables/ # 组合式函数
│ │ ├── use-request.ts # 请求Hook
│ │ ├── use-table.ts # 表格Hook
│ │ ├── use-form.ts # 表单Hook
│ │ └── use-modal.ts # 弹窗Hook
│ ├── utils/ # 工具函数
│ │ ├── request.ts # 请求封装
│ │ └── logger.ts # 日志工具
│ ├── constants/ # 常量定义
│ ├── enums/ # 枚举定义
│ └── types/ # 类型定义
│
├── features/ # 业务功能模块
│ └── navigation/tabs/ # ✅ 新增:导航标签领域模块
├── layouts/ # 布局组件
├── pages/ # 页面组件
├── router/ # 路由配置
├── store/ # 状态管理
└── api/ # API接口
- ✅ 采用分层架构,职责清晰
- ✅ 依赖注入容器,解耦更彻底
- ✅ 微前端支持,可扩展性强
- ✅ TypeScript覆盖率 95%+
- ✅ ESLint规则 100+
- ✅ 代码复用率 85%+
- ✅ 首屏加载时间 -49%
- ✅ 路由切换时间 -60%
- ✅ 包体积 -52%
- ✅ 内存占用 -44%
- ✅ 新增页面时间 -75%
- ✅ 代码维护成本 -60%
- ✅ Bug修复时间 -67%
- ✅ 新人上手时间 -67%
- ✅ 导航标签切换性能提升 40%
- ✅ 标签刷新时组件状态保留
- ✅ 支持批量关闭(左侧/右侧/其他)
- ✅ 保留旧 tabs 持久化数据、自动迁移
详细数据请查看 重构总结
ESLint 是在 ECMAScript/JavaScript 代码中识别和报告模式匹配的工具,它的目标是保证代码的一致性和避免错误。
相较于 Prettier 更为自由,并且更为严苛,也可以发现 JS 当中的错误。
Prettier 能够解析代码,使用你自己设定的规则来重新打印出格式规范的代码。正因为 Prettier Opinionated 的特性,所以我们不需要配置过多的规则,并且它能够支持更多编辑器的插件以及对于 html、css 等文件的格式化。
husky 让 Git 钩子变得容易,把 git 钩子的功能加到了 package 的 script 里面,使我们有能力直接调用其他命令而不用把钩子脚本写在项目的 .git/hook 里面, 方便团队间 git 钩子命令的共享.
lint-staged 检查所有被 git add 加入的文件,对这些文件执行你需要的命令。
由于每次在提交代码之前,对整个项目进行 eslint 处理耗时长且容易对老项目产生致命的 bug。为了解决这个问题,我们引入 husky + lint-staged 可以只对我们本次 commit 修改的代码进行 eslint 处理,让 linting 更有意义。这样,您可以确保没有错误进入存储库并强制执行代码样式。
Commitizen 是一个撰写合格 Commit message 的工具,当您使用 Commitizen 进行提交时,系统将提示您在提交时填写所有必填的提交字段。
commitlint 检查您的提交消息是否符合常规的提交格式。
conventional-changelog GitHub 仓库
如果你的所有 Commit 都符合 Angular 格式,那么发布新版本时, Change log 就可以用脚本自动生成。
生成的文档包括以下三个部分。
New features
Bug fixes
Breaking changes.
每个部分都会罗列相关的 commit ,并且有指向这些 commit 的链接。当然,生成的文档允许手动修改,所以发布前,你还可以添加其他内容。
利用 standard-version 进行版本控制,可以省去 git tag 手动打标签以及手动生成 changelog 的过程。
NPM
npm install eslint --save-dev
在 root 文件夹下创建文件 .eslintrc.js 和 .editorconfig
module.exports = {
env: {
browser: true,
node: true,
commonjs: true,
es6: true,
amd: true,
},
extends: ['eslint:recommended'],
parserOptions: {
ecmaVersion: 12,
sourceType: 'module',
},
globals: {
// 全局变量
__DEV__: true,
getCurrentPages: true,
},
rules: {
// 大家可以参考官方团队的配置
},
};
.editorconfig
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
终端中输入以下代码即可修复代码文件
// 全局安装eslint
eslint --fix index.js // fix后接文件名
// 没有全局安装eslint
npx eslint --fix index.js // fix后接文件名
在 package.json 中配置以下代码
"scripts": {
"lint": "eslint src --fix --ext .ts,.tsx,.vue,.js,.jsx",
},
这样就可以在终端中输入以下代码就可以实现整个项目的 eslint 格式化
npm run lint
NPM
npm install prettier --save-dev
在 root 文件夹下创建文件 .prettierrc.js, 由于 prettier 是 Opinionated code formatter,所以配置项相对较少。
module.exports = {
// 使用 4 个空格缩进
tabWidth: 2,
// 不使用缩进符,而使用空格
useTabs: false,
semi: true,
singleQuote: true,
overrides: [
// 使用css/html的规则格式化wxss/wxml
{
files: '*.wxss',
options: {
parser: 'css',
},
},
{
files: '*.wxml',
options: {
parser: 'html',
},
},
],
};
终端中输入以下代码即可修复代码文件
// 全局安装prettier
prettier --fix index.js // fix后接文件名
// 没有全局安装prettier
npx prettier --write index.js // fix后接文件名
在 package.json 中配置以下代码
"scripts": {
"prettier": "npx prettier--write **/*.js",
},
这样就可以在终端中输入以下代码就可以实现整个项目的 eslint 格式化
npm run prettier
由于两者都会进行代码的格式化,我们并不希望代码的重复格式化以及发生不必要的冲突,所以我们要安装中间件来保证两者和谐运行
npm install --save-dev eslint-config-prettier
npm install --save-dev eslint-plugin-prettier
修改 .eslintrc.js 中的部分配置项
module.exports = {
extends: ['eslint:recommended', 'plugin:prettier/recommended'],
plugins: ['prettier'],
}
NPM
npm install husky --save-dev
npm install lint-staged --save-dev
在 package.json 中配置
{
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"miniprogram/**/*.js": [
"npx eslint --fix",
"prettier --write",
"git add"
]
},
}
npm install commitizen --save-dev
// 使用npx初始化常规更新日志适配器
npx commitizen init cz-conventional-changelog --save-dev --save-exact
在 package.json 中配置
{
"scripts": {
"commit": "cz"
}
}
在 git add 提交代码后,可以使用 npm run commit 或者 npx cz 来提示填写 commit 信息
git add .
npm run commit
// npx cz
虽然 GitHub 仓库中提到 commitizen 可以结合 husky 使用,从而达到在 git commit 的钩子中执行 commitizen,但是至少 Windows 环境下使用这一方法会导致 commitizen 每次输入都会重复呈现提示信息,给人不友好的交互,因此并不建议在 Windows 环境下结合 husky 使用。
这个问题在其 GitHub 仓库的 issue 中有提及,不过暂时没有解决办法。issue 网址
npm install --save-dev @ commitlint / config-conventional @ commitlint / cli
在 package.json 中配置
{
"husky": {
"hooks": {
"pre-commit": "lint-staged", // 这个是之前配置的内容
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
}
},
}
新建 commitlint.config.js
module.exports = {
extends: ['@commitlint/config-conventional'],
rules: {
'body-leading-blank': [1, 'always'],
'footer-leading-blank': [1, 'always'],
'header-max-length': [2, 'always', 72],
'scope-case': [2, 'always', 'lower-case'],
'subject-case': [
2,
'never',
['sentence-case', 'start-case', 'pascal-case', 'upper-case'],
],
'subject-empty': [2, 'never'],
'subject-full-stop': [2, 'never', '.'],
'type-case': [2, 'always', 'lower-case'],
'type-empty': [2, 'never'],
'type-enum': [
2,
'always',
[
'build',
'chore',
'ci',
'docs',
'feat',
'fix',
'improvement',
'perf',
'refactor',
'revert',
'style',
'test',
],
],
},
};
在你 git commit 提交代码的时候会自动检查你的 commit 信息是否符合规范
虽然 GitHub 仓库中的初始步骤中使用的方法是借助以下代码生成 commitlint.config.js 文件,但是在 Windows 环境下生成的文件解码方式是 UTF-16,所以在自动运行时会报错。因此建议自己手动创建一个 commitlint.config.js,输入以上代码进行配置。
npm install --save-dev conventional-changelog-cli
在 package.json 中配置
{
"scripts": {
"version": "npx conventional-changelog -p angular -i CHANGELOG.md -s"
}
}
npm run version
// 或者不进行配置,直接使用以下代码
npx conventional-changelog -p angular -i CHANGELOG.md -s
// 假如希望生成至今所有的改动
npx conventional-changelog -p angular -i CHANGELOG.md -s -r 0
npm install --save-dev standard-version
在 package.json 中配置
{
"scripts": {
"release": "npx standard-version"
}
}
npm run release
## 或者不进行配置,直接使用以下代码
npx standard-version
## 使用以上两种方式,默认是生成下一个大版本,假如希望手动规定版本号
npm run release -- -r 1.1.0
- 提交代码
git add .
npm run commit
git pull origin master
git push origin master
- 版本更新
提交所有上线前代码后
npm run release -- -r 1.0.0 ## 输入本次版本号
git push --follow-tags origin master
以下是项目的目录结构
├── config
│ ├── env // 环境变量配置
│ ├── vite // vite插件配置
│ ├── constant // 系统常量
├── docs // 文档相关
├── mock // mock数据
├── plop-tpls // plop模板
├── src
│ ├── api // api请求
│ ├── assets // 静态文件
│ ├── components // 业务通用组件
│ ├── config // 系统配置
│ ├── directives // vue指令集
│ ├── enum // 项目中使用到的枚举定义
│ ├── hooks // hooks定义
│ ├── i18n // 国际化翻译
│ ├── layouts // 应用布局模板
│ ├── components // 业务通用组件
│ ├── components // 业务通用组件
│ ├── pages // 业务页面
│ ├── plugins // vue plugins配置
│ ├── router // 路由
│ ├── store // 状态管理
│ ├── style // 全局样式
│ ├── utils // 工具类
│ ├── app.vue // vue模板入口
│ ├── main.ts // vue模板js
├── types // 类型定义
├── wind.config.js // windicss全局配置
├── tsconfig.json // ts配置
└── vite.config.ts // vite全局配置
└── *.config.ts // 脚手架配置
{
...
"@vitejs/plugin-vue-jsx": "^1.3.3"
...
}//模块化写法 import Components from 'unplugin-vue-components/vite'; export const AutoRegistryComponents = () => { return Components({ extensions: ['vue', 'md'], deep: true, dts: 'types/components.d.ts', directoryAsNamespace: false, globalNamespaces: [], directives: true, include: [/\.vue$/, /\.vue\?vue/, /\.md$/], exclude: [/[\\/]node_modules[\\/]/, /[\\/]\.git[\\/]/, /[\\/]\.nuxt[\\/]/], resolvers: [ IconsResolver({ componentPrefix: '' }), TDesignResolver({ importStyle: 'less' }), //根据你需要增加UI框架 VueUseComponentsResolver() //默认使用VueUse组件 ] }); };
为了方便管理插件,将所有的config统一放入config/vite/plugins里面,未来还会有更多插件直接分文件夹管理十分干净。值得一提的是,Vue3-Boilerplate增加了统一环境变量管理,来区分动态开启某些插件。
// vite/plugins/index.ts /** * @name createVitePlugins * @description 封装plugins数组统一调用 */ import type { Plugin } from 'vite'; import vue from '@vitejs/plugin-vue'; import vueJsx from '@vitejs/plugin-vue-jsx'; import { ConfigSvgIconsPlugin } from './svgIcons'; import { AutoRegistryComponents } from './component'; import { AutoImportDeps } from './autoImport'; import { ConfigMockPlugin } from './mock'; import { ConfigVisualizerConfig } from './visualizer'; import { ConfigCompressPlugin } from './compress'; import { ConfigPagesPlugin } from './pages'; import { ConfigMarkDownPlugin } from './markdown'; import { ConfigRestartPlugin } from './restart'; export function createVitePlugins(isBuild: boolean) { const vitePlugins: (Plugin | Plugin[])[] = [ // vue支持 vue(), // JSX支持 vueJsx(), // 自动按需引入组件 AutoRegistryComponents(), // 自动按需引入依赖 AutoImportDeps(), // 自动生成路由 ConfigPagesPlugin(), // 开启.gz压缩 rollup-plugin-gzip ConfigCompressPlugin(), //支持markdown ConfigMarkDownPlugin(), // 监听配置文件改动重启 ConfigRestartPlugin() ]; // vite-plugin-svg-icons vitePlugins.push(ConfigSvgIconsPlugin(isBuild)); // vite-plugin-mock vitePlugins.push(ConfigMockPlugin(isBuild)); // rollup-plugin-visualizer vitePlugins.push(ConfigVisualizerConfig()); return vitePlugins; }
而vite.config.ts便干净多了
import { createVitePlugins } from './build/vite/plugins' ... return { resolve: { alias: { "@": path.resolve(__dirname, './src'), '@api': path.resolve(__dirname, './src/api'), } }, // plugins plugins: createVitePlugins(isBuild) } ...
创建文件src/store/index.ts
// 支持模块化,配合plop可以通过命令行一键生成 import { createPinia } from 'pinia'; import { useAppStore } from './modules/app'; import { useUserStore } from './modules/user'; const pinia = createPinia(); export { useAppStore, useUserStore }; export default pinia;
创建文件src/store/modules/user/index.ts
import { defineStore } from 'pinia'; import piniaStore from '@/store'; export const useUserStore = defineStore( // 唯一ID 'user', { state: () => ({}), getters: {}, actions: {} } );
⚙️ 代码文件自动生成,提供三种预设模板pages,components,store,也可以根据自己需要设计更多自动生成脚本。一般后端同学惯用此形式,十分高效。
# 安装plop
pnpm add plop根目录创建plopfile.ts
import { NodePlopAPI } from 'plop'; export default function (plop: NodePlopAPI) { plop.setWelcomeMessage('请选择需要创建的模式:'); plop.setGenerator('page', require('./plop-tpls/page/prompt')); plop.setGenerator('component', require('./plop-tpls/component/prompt')); plop.setGenerator('store', require('./plop-tpls/store/prompt')); }
# 启动命令
pnpm run plop随着浏览器兼容性的提升,SVG 的性能逐渐凸显,很多大厂团队都在创建自己的 SVG 管理库,后面工具库会有推荐。
# 安装svg依赖
pnpm add vite-plugin-svg-icons配置vite.config.ts
import viteSvgIcons from 'vite-plugin-svg-icons'; export default defineConfig({ plugins:[ ... viteSvgIcons({ // 指定需要缓存的图标文件夹 iconDirs: [path.resolve(process.cwd(), 'src/assets/svg')], // 指定symbolId格式 symbolId: 'icon-[dir]-[name]', }), ] ... })
已封装一个简单的SvgIcon组件,可以直接读取文件下的svg,可以根据文件夹目录自动查找文件。
<template> <svg aria-hidden="true" class="svg-icon-spin" :class="calsses" > <use :xlink:href="symbolId" :fill="color" /> </svg> </template> <script lang="ts" setup > const props = defineProps({ prefix: { type: String, default: 'icon' }, name: { type: String, required: true }, color: { type: String, default: '#333' }, size: { type: String, default: 'default' } }); const symbolId = computed(() => `#${props.prefix}-${props.name}`); const calsses = computed(() => { return { [`sdms-size-${props.size}`]: props.size }; }); const fontSize = reactive({ default: '32px', small: '20px', large: '48px' }); </script>
已封装了主流的拦截器,请求调用等方法,区分了模块index.ts/status.ts/type.ts
使用vite-plugin-mock插件,支持自动区分和启停的环境配置
// vite config viteMockServe({ ignore: /^\_/, mockPath: 'mock', localEnabled: !isBuild, prodEnabled: false, // https://github.com/anncwb/vite-plugin-mock/issues/9 injectCode: ` import { setupProdMockServer } from '../mock/_createProdMockServer'; setupProdMockServer(); ` });
根目录下创建 _createProductionServer.ts文件,非_开头文件会被自动加载成 mock 文件
import { createProdMockServer } from 'vite-plugin-mock/es/createProdMockServer'; // 批量加载 const modules = import.meta.globEager('./mock/*.ts'); const mockModules: Array<string> = []; Object.keys(modules).forEach(key => { if (key.includes('/_')) { return; } mockModules.push(...modules[key].default); }); export function setupProdMockServer() { createProdMockServer(mockModules); }
// vite config import proxy from '@config/vite/proxy'; export default defineConfig({ ... server: { hmr: { overlay: false }, // 禁用或配置 HMR 连接 设置 server.hmr.overlay 为 false 可以禁用服务器错误遮罩层 // 服务配置 port: VITE_PORT, // 类型: number 指定服务器端口; open: false, // 类型: boolean | string在服务器启动时自动在浏览器中打开应用程序; cors: false, // 类型: boolean | CorsOptions 为开发服务器配置 CORS。默认启用并允许任何源 host: '0.0.0.0', // IP配置,支持从IP启动 proxy, } ... })
// proxy.ts import { API_BASE_URL, API_TARGET_URL, MOCK_API_BASE_URL, MOCK_API_TARGET_URL } from '@config/constant'; import { ProxyOptions } from 'vite'; type ProxyTargetList = Record<string, ProxyOptions>; const init: ProxyTargetList = { // test [API_BASE_URL]: { target: API_TARGET_URL, changeOrigin: true, rewrite: path => path.replace(new RegExp(`^${API_BASE_URL}`), '') }, // mock [MOCK_API_BASE_URL]: { target: MOCK_API_TARGET_URL, changeOrigin: true, rewrite: path => path.replace(new RegExp(`^${MOCK_API_BASE_URL}`), '/api') } }; export default init;
- 🏗 支持
vw/vh移动端布局兼容,也可以使用plop自己配置生成文件 - 还有更多新功能增在
commiting,如果你有更好的方案欢迎PR
一键三连: Star 或 Fork
# 拉取仓库代码 git clone https://github.com/hiliyongke/vue3-boilerplate.git # 进入项目文件夹 cd Vue3-Boilerplate # 安装项目依赖 pnpm install # 运行 pnpm run dev
如果不报错,恭喜你点火成功。否则,请看下面常见问题。
学会使用适当的工具库,让coding事半功倍。尤其是开源的工具库,值得每个人学习,因为这本身就是你应该达到的层次。这里推荐一些大厂常用的类库,因为我喜新...,以下工具均可直接引入。
-
pnpm,一个依赖包全局管理的工具,老板再也不用担心我的 C 盘不够用。Vite 官方推荐
-
mitt 全局事件监听库,Vue3 官方推荐
-
Hammer,可以识别由触摸、鼠标和指针事件做出的手势,只有 7.34kb
-
outils,开发中常用的函数集,也可以使用
lodash -
windicss,艾玛香的一塌糊涂,一行 css 不写,3 分钟出一个页面。不适合初中级前端,建议还是先踏实学基础再用框架。
-
Vue I18n 是 Vue.js 的国际化插件,如果你想做开源框架,国际化首选插件。
-
ViteSSG,SEO 优化,这个项目有点意思,大家可以玩玩这个方案,之前我都是通过服务端渲染搞 SEO,后来了解到这个可以直接在 Vue3 的服务器上生成。
-
Vitest,基于 Vite 的单元测试工具,目前迭代比较快,尤大金牌赞助。可以持续关注,不建议使用在小项目中。
- 官方配置文档入口vite、pinia、vue-router4、plop...
- git cz 报错的原因,需要全局安装 commitizen npm install -g commitizen
该模板不限定大家使用某一特定的包管理器,npm,yarn 和 pnpm 都行。同时注意 npm 的版本应该尽量的新。
强烈推荐大家使用更快更合理的 pnpm 包管理器 👉 安装教程
- 安装依赖
pnpm install # 或者 npm install # 或者 yarn
- 开发
pnpm dev # 或者 npm run dev # 或者 yarn dev # 自动打开浏览器 pnpm dev:open # 或者 npm run dev:open # 或者 yarn dev:open
- 预览
pnpm preview # 或者 npm run preview # 或者 yarn preview 4. 打包 ```shell pnpm build # 或者 npm run build # 或者 yarn build # 打包开发环境 pnpm build:dev # 或者 npm run build:dev # 或者 yarn build:dev
- 单元测试
pnpm test # 或者 npm run test # 或者 yarn test
- 单元测试报告生成
pnpm coverage # 或者 npm run coverage # 或者 yarn coverage
- 类型检查
pnpm typecheck # 或者 npm run typecheck # 或者 yarn typecheck
- 自动创建组件
pnpm plop # 或者 npm run plop # 或者 yarn plop
- 依赖更新
# 安全版本更新 pnpm deps:update # 或者 npm run deps:update # 或者 yarn deps:update # 主版本更新,可能是破坏性更新,谨慎使用,做好测试 pnpm deps:update:major # 或者 npm run deps:update:major # 或者 yarn deps:update:major # 次版本更新,可能是破坏性更新,谨慎使用,做好测试 pnpm deps:update:minor # 或者 npm run deps:update:minor # 或者 yarn deps:update:minor # 补丁版本更新 pnpm deps:update:patch # 或者 npm run deps:fresh:patch # 或者 yarn deps:fresh:patch
# 以上命令仅对包信息 package.json 进行写入,需要重新执行包安装命令 pnpm i # 或者 npm i # 或者 yarn
- 代码规范校验修复
pnpm lint # 或者 npm run lint # 或者 yarn lint # css规范校验修复 pnpm lint:css # 或者 npm run lint:css # 或者 yarn lint:css