package.json
{
"devDependencies": {
"@eslint/js": "9.39.2",
"@stylistic/eslint-plugin": "5.6.1",
"eslint": "9.39.2",
"eslint-config-prettier": "10.1.8",
"eslint-import-resolver-typescript": "4.4.4",
"eslint-plugin-import": "2.32.0",
"eslint-plugin-prettier": "5.5.4",
"eslint-plugin-unused-imports": "4.3.0",
"eslint-plugin-vue": "10.6.2",
"globals": "16.5.0",
"prettier": "3.7.4",
"typescript-eslint": "8.50.0"
}
}
eslint.config.mjs
import eslint from '@eslint/js';
import stylistic from '@stylistic/eslint-plugin';
import importPlugin from 'eslint-plugin-import';
import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended';
import unusedImports from 'eslint-plugin-unused-imports';
import eslintPluginVue from 'eslint-plugin-vue';
import { defineConfig } from 'eslint/config';
import globals from 'globals';
import typescriptEslint from 'typescript-eslint';
export default defineConfig(
{
ignores: [
'node_modules',
'dist',
'public',
'release',
],
},
/**
* 配置全局变量
*/
{
extends: [
/** js推荐配置 */
eslint.configs.recommended,
/** ts推荐配置 */
...typescriptEslint.configs.recommended,
/** vue推荐配置 */
...eslintPluginVue.configs['flat/recommended'],
],
files: ['**/*.{ts,js,vue}'],
plugins: {
'import': importPlugin,
'unused-imports': unusedImports,
},
languageOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
globals: {
...globals.browser, // window, document, console, etc.
...globals.node, // process, require, module, __dirname, etc.
...globals.electron, // electron-specific globals (if available)
electronAPI: true, // 自定义全局变量
// Electron 特有全局变量(如果 globals.electron 不存在)
require: 'readonly', // Node.js require
module: 'readonly', // Node.js module
__dirname: 'readonly', // Node.js __dirname
__filename: 'readonly', // Node.js __filename
process: 'readonly', // Node.js process
Buffer: 'readonly', // Node.js Buffer
setTimeout: 'readonly', // Browser/Node.js
clearTimeout: 'readonly', // Browser/Node.js
setInterval: 'readonly', // Browser/Node.js
clearInterval: 'readonly', // Browser/Node.js
},
parserOptions: {
parser: typescriptEslint.parser,
// 为 import 插件提供解析器
ecmaFeatures: {
modules: true,
},
},
},
settings: {
// 为 import 插件提供路径解析
'import/resolver': {
node: {
extensions: ['.js', '.ts', '.vue'],
},
},
},
rules: {
// ===================== 核心 ESLint 基础规则 =====================
'no-case-declarations': 'off', // 关闭switch case内变量声明校验
'space-before-function-paren': 'off', // 关闭函数括号前空格格式校验
'prefer-const': 'off', // 关闭优先使用const声明变量校验
'no-undef': 'off', // 关闭未定义变量校验
// ===================== Import 导入规范规则 =====================
'import/first': 'error', // 强制导入语句放在文件顶部
'import/newline-after-import': 'error', // 强制导入语句后空行
'import/no-duplicates': 'error', // 禁止重复导入同一模块
// 优化:仅管控导入语句内部成员排序,放弃整体排序(避免与 import/order 冲突)
'sort-imports': [
'error', // 启用导入语句排序校验
{
ignoreCase: false, // 排序区分大小写
ignoreDeclarationSort: true, // 关键:关闭整体排序,仅管内部成员
ignoreMemberSort: false, // 启用导入内部成员排序
memberSyntaxSortOrder: ['none', 'all', 'multiple', 'single'], // 导入语法优先级
allowSeparatedGroups: false, // 禁止空行分隔导入组
},
],
// 核心:管控导入语句整体顺序(内置→第三方→本地),与 sort-imports 功能隔离
'import/order': [
'error', // 启用导入模块来源排序校验
{
'groups': [
'builtin', // Node.js内置模块
'external', // 第三方库
'internal', // 项目内部模块
'parent', // 上级目录模块组
'sibling', // 同级目录模块组
'index', // 索引文件
'object', // 导入对象
'type', // 类型导入
],
'pathGroups': [
{
pattern: 'vue', // 匹配vue模块
group: 'external', // 归为第三方库组
position: 'before', // 排在其他第三方库前
},
],
'pathGroupsExcludedImportTypes': ['builtin'], // 排除内置模块
'newlines-between': 'always', // 不同组间强制空行
'alphabetize': {
order: 'asc', // 组内按字母升序排列
caseInsensitive: true, // 排序忽略大小写
},
},
],
'unused-imports/no-unused-imports': 'error', // 强制校验未使用的导入语句
// ===================== TypeScript 专属规则 =====================
'@typescript-eslint/ban-ts-ignore': 'off', // 关闭禁止使用@ts-ignore注释校验
'@typescript-eslint/ban-ts-comment': 'off', // 关闭禁止使用ts相关注释校验
'@typescript-eslint/ban-types': 'off', // 关闭禁止使用特定类型校验
'@typescript-eslint/explicit-function-return-type': 'off', // 关闭强制函数显式返回类型校验
'@typescript-eslint/no-explicit-any': 'off', // 关闭禁止使用any类型校验
'@typescript-eslint/no-var-requires': 'off', // 关闭禁止使用require导入校验
'@typescript-eslint/no-empty-function': 'off', // 关闭禁止空函数校验
'@typescript-eslint/no-non-null-assertion': 'off', // 关闭禁止非空断言校验
'@typescript-eslint/explicit-module-boundary-types': 'off', // 关闭模块边界类型显式声明校验
'@typescript-eslint/no-empty-interface': 'off', // 关闭禁止空接口校验
'@typescript-eslint/no-inferrable-types': 'off', // 关闭禁止显式声明可推断类型校验
// ===================== Vue 专属规则 =====================
// Vue 核心规范
'vue/script-setup-uses-vars': 'error', // 强制校验script-setup中使用的变量
'vue/no-reserved-component-names': 'off', // 关闭禁止使用保留字作为组件名校验
'vue/custom-event-name-casing': 'off', // 关闭自定义事件名大小写规范校验
'vue/one-component-per-file': 'off', // 关闭单文件仅包含一个组件校验
'vue/multi-word-component-names': 'off', // 关闭组件名多单词校验
'vue/no-v-html': 'off', // 关闭禁止使用v-html指令校验
// Vue 模板格式/属性规则
'vue/attributes-order': 'off', // 关闭模板属性排序校验
'vue/html-closing-bracket-newline': 'off', // 关闭标签闭合括号换行校验
'vue/max-attributes-per-line': 'off', // 关闭每行最大属性数校验
'vue/multiline-html-element-content-newline': 'off', // 关闭多行元素内容换行校验
'vue/singleline-html-element-content-newline': 'off', // 关闭单行元素内容换行校验
'vue/attribute-hyphenation': 'off', // 关闭属性名连字符校验
// Vue 组件属性/事件规则
'vue/require-default-prop': 'off', // 关闭强制props设置默认值校验
'vue/require-explicit-emits': 'off', // 关闭强制显式声明emits校验
// Vue 标签自闭合规则(唯一启用的 Vue 格式规则)
'vue/html-self-closing': [
'error', // 启用标签自闭合规范校验
{
html: {
void: 'always', // HTML空标签强制自闭合
normal: 'never', // HTML普通标签禁止自闭合
component: 'always', // Vue组件强制自闭合
},
svg: 'always', // SVG标签强制自闭合
math: 'always', // Math标签强制自闭合
},
],
},
},
stylistic.configs.customize({
indent: 2,
quotes: 'single',
semi: false,
jsx: true,
braceStyle: '1tbs',
arrowParens: 'always',
}),
/**
* prettier 配置
* 会合并根目录下的.prettier.config.js 文件
* @see https://github.com/prettier/eslint-plugin-prettier
*/
eslintPluginPrettierRecommended,
);
prettier.config.js
/**
* Prettier 代码格式化配置
* @type {import('prettier').Config}
* @see https://www.prettier.cn/docs/options.html Prettier 官方配置文档
*/
export default {
/**
* 尾逗号配置:强制在所有多行结构(对象、数组、函数参数等)末尾添加尾逗号
* @value "all" 所有多行结构都加尾逗号(包括函数参数、对象、数组)
* @value "es5" 仅在 ES5 兼容场景加(对象、数组),函数参数不加
* @value "none" 不添加尾逗号
*/
trailingComma: 'all',
/**
* 字符串引号配置:JS/TS 字符串默认使用单引号(JSX 由 jsxSingleQuote 控制)
* @value true 单引号
* @value false 双引号
*/
singleQuote: true,
/**
* 语句分号配置:强制在语句末尾添加分号
* @value true 加尾部分号(如 const a = 1;)
* @value false 省略尾部分号(如 const a = 1)
*/
semi: true,
/**
* 行宽限制:代码行的最大字符宽度,超过则自动换行
* @value 80 行业通用值,兼顾可读性和屏幕适配
*/
printWidth: 80,
/**
* 箭头函数括号配置:箭头函数参数强制加括号(即使只有一个参数)
* @value "always" 始终加括号(如 (x) => x)
* @value "avoid" 单个参数时省略括号(如 x => x)
*/
arrowParens: 'always',
/**
* 纯文本换行配置:Markdown 等纯文本超出 printWidth 时强制换行
* @value "always" 始终换行
* @value "never" 从不换行
* @value "preserve" 保留原文本换行格式
*/
proseWrap: 'preserve',
/**
* 换行符配置:强制使用 LF(\n)作为换行符(Unix/Linux/macOS 风格)
* @value "lf" LF 换行符(推荐跨平台统一)
* @value "crlf" Windows 换行符(\r\n)
* @value "cr" 老式 Mac 换行符(\r)
* @value "auto" 跟随系统自动识别
*/
endOfLine: 'lf',
/**
* 实验性三元表达式格式化:禁用实验性规则,使用稳定的传统格式化方式
* @value true 启用实验性排版
* @value false 禁用(推荐,避免格式不稳定)
*/
experimentalTernaries: false,
/**
* 缩进空格数:缩进使用 2 个空格
* @value 2 前端通用缩进值(React/Vue 主流规范)
*/
tabWidth: 2,
/**
* 缩进方式:禁用 Tab 符,统一使用空格缩进
* @value true 使用 Tab 符缩进
* @value false 使用空格缩进(推荐,避免 Tab/空格混用)
*/
useTabs: false,
/**
* 对象属性引号配置:保持引号风格一致性
* @value "consistent" 有一个属性需要引号则全部加,否则都不加
* @value "as-needed" 仅必要时加引号(如特殊字符属性)
* @value "preserve" 保留原格式
*/
quoteProps: 'consistent',
/**
* JSX 引号配置:JSX 中使用双引号(与 singleQuote 区分)
* @value true JSX 使用单引号
* @value false JSX 使用双引号(推荐,符合 React 官方规范)
*/
jsxSingleQuote: false,
/**
* 对象大括号空格:大括号内侧保留空格
* @value true 保留空格(如 { a: 1 })
* @value false 不保留(如 {a: 1})
*/
bracketSpacing: true,
/**
* JSX 闭合括号换行:多行 JSX 闭合括号单独换行
* @value true 闭合括号与最后一个属性同行
* @value false 闭合括号单独换行(推荐,提升可读性)
*/
bracketSameLine: false,
/**
* 兼容旧版配置:等价于 bracketSameLine,控制 JSX 闭合括号换行
* @deprecated 建议使用 bracketSameLine,此配置为兼容低版本 Prettier
*/
jsxBracketSameLine: false,
/**
* Vue 缩进规则:禁用 Vue 文件中 <script>/<style> 标签内的额外缩进
* @value true 标签内代码额外缩进
* @value false 保持标签内代码原有缩进(避免与模板缩进冲突)
*/
vueIndentScriptAndStyle: false,
/**
* JSX/Vue 属性换行:禁用「单个属性占一行」,多个属性可同行(超宽时自动换行)
* @value true 每个属性单独占一行
* @value false 多个属性同行(推荐,减少冗余换行)
*/
singleAttributePerLine: false,
};