refactor(eslint): ♻️ eslint 规则配置优化

This commit is contained in:
Ray.Hao
2025-05-09 12:56:00 +08:00
parent 3559336701
commit e36f5c813f
8 changed files with 579 additions and 1292 deletions

View File

@@ -1,99 +0,0 @@
// https://eslint.nodejs.cn/docs/latest/use/configure/configuration-files
import globals from "globals";
import pluginJs from "@eslint/js"; // JavaScript 规则
import pluginVue from "eslint-plugin-vue"; // Vue 规则
import pluginTypeScript from "@typescript-eslint/eslint-plugin"; // TypeScript 规则
import parserVue from "vue-eslint-parser"; // Vue 解析器
import parserTypeScript from "@typescript-eslint/parser"; // TypeScript 解析器
import configPrettier from "eslint-config-prettier"; // 禁用与 Prettier 冲突的规则
import pluginPrettier from "eslint-plugin-prettier"; // 运行 Prettier 规则
// 解析自动导入配置
import fs from "fs";
const autoImportConfig = JSON.parse(fs.readFileSync(".eslintrc-auto-import.json", "utf-8"));
/** @type {import('eslint').Linter.Config[]} */
export default [
// 指定检查文件和忽略文件
{
files: ["**/*.{js,mjs,cjs,ts,vue}"],
ignores: ["**/*.d.ts"],
},
// 全局配置
{
languageOptions: {
globals: {
...globals.browser,
...globals.node,
...autoImportConfig.globals,
...{
PageQuery: "readonly",
PageResult: "readonly",
OptionType: "readonly",
ResponseData: "readonly",
ExcelResult: "readonly",
TagView: "readonly",
AppSettings: "readonly",
__APP_INFO__: "readonly",
},
},
},
plugins: { prettier: pluginPrettier },
rules: {
...configPrettier.rules, // 关闭与 Prettier 冲突的规则
...pluginPrettier.configs.recommended.rules, // 启用 Prettier 规则
"prettier/prettier": "error", // 强制 Prettier 格式化
"no-unused-vars": [
"error",
{
argsIgnorePattern: "^_", // 忽略参数名以 _ 开头的参数未使用警告
varsIgnorePattern: "^[A-Z0-9_]+$", // 忽略变量名为大写字母、数字或下划线组合的未使用警告(枚举定义未使用场景)
ignoreRestSiblings: true, // 忽略解构赋值中同级未使用变量的警告
},
],
},
},
// JavaScript 配置
pluginJs.configs.recommended,
// TypeScript 配置
{
files: ["**/*.ts"],
ignores: ["**/*.d.ts"], // 排除d.ts文件
languageOptions: {
parser: parserTypeScript,
parserOptions: {
sourceType: "module",
},
},
plugins: { "@typescript-eslint": pluginTypeScript },
rules: {
...pluginTypeScript.configs.strict.rules, // TypeScript 严格规则
"@typescript-eslint/no-explicit-any": "off", // 允许使用 any
"@typescript-eslint/no-empty-function": "off", // 允许空函数
"@typescript-eslint/no-empty-object-type": "off", // 允许空对象类型
},
},
// Vue 配置
{
files: ["**/*.vue"],
languageOptions: {
parser: parserVue,
parserOptions: {
parser: parserTypeScript,
sourceType: "module",
},
},
plugins: { vue: pluginVue, "@typescript-eslint": pluginTypeScript },
processor: pluginVue.processors[".vue"],
rules: {
...pluginVue.configs.recommended.rules, // Vue 推荐规则
"vue/no-v-html": "off", // 允许 v-html
"vue/multi-word-component-names": "off", // 允许单个单词组件名
},
},
];

176
eslint.config.ts Normal file
View File

@@ -0,0 +1,176 @@
// https://eslint.org/docs/latest/use/configure/configuration-files-new
import eslint from "@eslint/js";
import pluginVue from "eslint-plugin-vue";
import pluginTypeScript from "@typescript-eslint/eslint-plugin";
import parserTypeScript from "@typescript-eslint/parser";
import vueParser from "vue-eslint-parser";
import globals from "globals";
import configPrettier from "eslint-config-prettier";
// 解析自动导入配置
import fs from "node:fs";
let autoImportGlobals = {};
try {
autoImportGlobals =
JSON.parse(fs.readFileSync("./.eslintrc-auto-import.json", "utf-8")).globals || {};
} catch (error) {
// 文件不存在或解析错误时使用空对象
console.warn("Could not load auto-import globals", error);
}
// Element Plus组件
const elementPlusComponents = {
// Element Plus 组件添加为全局变量,避免 no-undef 报错
ElInput: "readonly",
ElSelect: "readonly",
ElSwitch: "readonly",
ElCascader: "readonly",
ElInputNumber: "readonly",
ElTimePicker: "readonly",
ElTimeSelect: "readonly",
ElDatePicker: "readonly",
ElTreeSelect: "readonly",
ElText: "readonly",
ElRadioGroup: "readonly",
ElCheckboxGroup: "readonly",
ElOption: "readonly",
ElRadio: "readonly",
ElCheckbox: "readonly",
ElInputTag: "readonly",
ElForm: "readonly",
ElFormItem: "readonly",
ElTable: "readonly",
ElTableColumn: "readonly",
ElButton: "readonly",
ElDialog: "readonly",
ElPagination: "readonly",
ElMessage: "readonly",
ElMessageBox: "readonly",
ElNotification: "readonly",
ElTree: "readonly",
};
export default [
// 全局配置
{
// 指定要检查的文件
files: ["**/*.js", "**/*.ts", "**/*.vue"],
ignores: ["node_modules/**", "dist/**", "build/**"],
languageOptions: {
ecmaVersion: 2022,
sourceType: "module",
globals: {
...globals.browser, // 浏览器环境全局变量
...globals.node, // Node.js 环境全局变量
...autoImportGlobals, // 自动导入的 API 函数
...elementPlusComponents, // Element Plus 组件
// 全局类型定义,解决 TypeScript 中定义但 ESLint 不识别的问题
PageQuery: "readonly",
PageResult: "readonly",
OptionType: "readonly",
ResponseData: "readonly",
ExcelResult: "readonly",
TagView: "readonly",
AppSettings: "readonly",
__APP_INFO__: "readonly",
},
parser: parserTypeScript,
parserOptions: {
sourceType: "module",
},
},
rules: {
// 全局规则
"no-unused-vars": [
"error",
{
vars: "all",
args: "after-used",
ignoreRestSiblings: true,
argsIgnorePattern: "^_", // 忽略以下划线开头的参数
varsIgnorePattern: "^[A-Z][A-Z0-9_]*$", // 忽略全大写的常量/枚举
},
],
// 禁用未定义变量检查TypeScript 已处理类型检查
"no-undef": "off",
},
},
// 基础 JavaScript 配置
eslint.configs.recommended,
// Vue 配置
{
files: ["**/*.vue"],
plugins: {
vue: pluginVue,
},
languageOptions: {
parser: vueParser,
parserOptions: {
ecmaVersion: 2022,
sourceType: "module",
parser: parserTypeScript,
},
},
processor: pluginVue.processors[".vue"],
rules: {
"vue/multi-word-component-names": "off",
"vue/no-v-html": "off",
"vue/require-default-prop": "off",
"vue/html-self-closing": [
"error",
{
html: {
void: "always",
normal: "never",
component: "always",
},
},
],
"vue/no-unused-vars": "off",
},
},
// TypeScript 配置
{
files: ["**/*.ts", "**/*.tsx", "**/*.vue"],
plugins: {
"@typescript-eslint": pluginTypeScript,
},
rules: {
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-empty-function": "off",
"@typescript-eslint/no-empty-object-type": "off",
"@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/no-non-null-assertion": "off",
"@typescript-eslint/no-unused-vars": [
"error",
{
vars: "all",
args: "after-used",
ignoreRestSiblings: true,
argsIgnorePattern: "^_", // 忽略以下划线开头的参数
varsIgnorePattern: "^[A-Z][A-Z0-9_]*$", // 忽略全大写的常量/枚举
},
],
},
},
// CURD 组件配置
{
files: ["**/components/CURD/**/*.{ts,vue}"],
rules: {
"no-unused-vars": "off",
"@typescript-eslint/no-unused-vars": "off",
},
},
// Prettier 集成
{
rules: {
...configPrettier.rules,
},
},
];

View File

@@ -10,10 +10,11 @@
"preview": "vite preview", "preview": "vite preview",
"build-only": "vite build", "build-only": "vite build",
"type-check": "vue-tsc --noEmit", "type-check": "vue-tsc --noEmit",
"lint:eslint": "eslint --cache \"src/**/*.{vue,ts}\" --fix", "lint:eslint": "eslint --cache \"src/**/*.{vue,ts,js}\" --fix",
"lint:prettier": "prettier --write \"**/*.{js,cjs,ts,json,css,scss,vue,html,md}\"", "lint:prettier": "prettier --write \"**/*.{js,cjs,ts,json,css,scss,vue,html,md}\"",
"lint:stylelint": "stylelint --cache \"**/*.{css,scss,vue}\" --fix", "lint:stylelint": "stylelint --cache \"**/*.{css,scss,vue}\" --fix",
"lint:lint-staged": "lint-staged", "lint:lint-staged": "lint-staged",
"lint": "npm run lint:eslint && npm run lint:prettier && npm run lint:stylelint",
"preinstall": "npx only-allow pnpm", "preinstall": "npx only-allow pnpm",
"prepare": "husky", "prepare": "husky",
"commit": "git-cz" "commit": "git-cz"

View File

@@ -124,7 +124,6 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, computed, onMounted, onBeforeUnmount } from "vue";
import router from "@/router"; import router from "@/router";
import { usePermissionStore } from "@/store"; import { usePermissionStore } from "@/store";
import { isExternal } from "@/utils"; import { isExternal } from "@/utils";
@@ -304,7 +303,9 @@ function loadRoutes(routes: RouteRecordRaw[], parentPath = "") {
name: typeof route.name === "string" ? route.name : undefined, name: typeof route.name === "string" ? route.name : undefined,
icon: route.meta.icon, icon: route.meta.icon,
redirect: typeof route.redirect === "string" ? route.redirect : undefined, redirect: typeof route.redirect === "string" ? route.redirect : undefined,
params: route.meta.params ? JSON.parse(JSON.stringify(toRaw(route.meta.params))) : undefined params: route.meta.params
? JSON.parse(JSON.stringify(toRaw(route.meta.params)))
: undefined,
}); });
} }
}); });

View File

@@ -242,7 +242,7 @@ export function useStomp(options: UseStompOptions = {}) {
* @param callback 接收到消息时的回调函数 * @param callback 接收到消息时的回调函数
* @returns 返回订阅 id用于后续取消订阅 * @returns 返回订阅 id用于后续取消订阅
*/ */
const subscribe = (destination: string, callback: (message: IMessage) => void): string => { const subscribe = (destination: string, callback: (_message: IMessage) => void): string => {
if (!client.value) { if (!client.value) {
return ""; return "";
} }

View File

@@ -10,7 +10,7 @@ export interface DictMessage {
} }
// 字典事件回调类型 // 字典事件回调类型
export type DictMessageCallback = (message: DictMessage) => void; export type DictMessageCallback = (_message: DictMessage) => void;
// 全局单例实例 // 全局单例实例
let instance: ReturnType<typeof createDictSyncHook> | null = null; let instance: ReturnType<typeof createDictSyncHook> | null = null;

File diff suppressed because it is too large Load Diff

View File

@@ -55,7 +55,7 @@ export default defineConfig(({ mode }: ConfigEnv) => {
vue(), vue(),
env.VITE_MOCK_DEV_SERVER === "true" ? mockDevServerPlugin() : null, env.VITE_MOCK_DEV_SERVER === "true" ? mockDevServerPlugin() : null,
UnoCSS(), UnoCSS(),
// 自动导入配置 https://github.com/sxzz/element-plus-best-practices/blob/main/vite.config.ts // API 导入
AutoImport({ AutoImport({
// 导入 Vue 函数ref, reactive, toRef 等 // 导入 Vue 函数ref, reactive, toRef 等
imports: ["vue", "@vueuse/core", "pinia", "vue-router", "vue-i18n"], imports: ["vue", "@vueuse/core", "pinia", "vue-router", "vue-i18n"],
@@ -74,10 +74,7 @@ export default defineConfig(({ mode }: ConfigEnv) => {
// dts: "src/types/auto-imports.d.ts", // dts: "src/types/auto-imports.d.ts",
}), }),
Components({ Components({
resolvers: [ resolvers: [ElementPlusResolver()],
// 导入 Element Plus 组件
ElementPlusResolver({ importStyle: "sass" }),
],
// 指定自定义组件位置(默认:src/components) // 指定自定义组件位置(默认:src/components)
dirs: ["src/components", "src/**/components"], dirs: ["src/components", "src/**/components"],
// 导入组件类型声明文件路径 (false:关闭自动生成) // 导入组件类型声明文件路径 (false:关闭自动生成)