feat: 🚀 多语言配置,修复vite打包无法跳转路由

This commit is contained in:
bunny 2024-05-27 14:48:44 +08:00
parent fe70679ea2
commit d348a8cc37
21 changed files with 1830 additions and 4129 deletions

View File

@ -1,69 +1,67 @@
// @see: http://eslint.cn
module.exports = {
root: true,
env: {
browser: true,
node: true,
es6: true,
},
/* 指定如何解析语法 */
parser: 'vue-eslint-parser',
/* 优先级低于 parse 的语法解析配置 */
parserOptions: {
parser: '@typescript-eslint/parser',
ecmaVersion: 2020,
sourceType: 'module',
jsxPragma: 'React',
ecmaFeatures: {
jsx: true,
},
},
/* 继承某些已有的规则 */
extends: ['plugin:vue/vue3-recommended', 'plugin:@typescript-eslint/recommended', 'prettier', 'plugin:prettier/recommended'],
/*
* "off" 0 ==> 关闭规则
* "warn" 1 ==> 打开的规则作为警告不影响代码执行
* "error" 2 ==> 规则作为一个错误代码不能执行界面报错
*/
rules: {
// eslint (http://eslint.cn/docs/rules)
'no-var': 'error', // 要求使用 let 或 const 而不是 var
'no-multiple-empty-lines': ['error', { max: 1 }], // 不允许多个空行
'no-use-before-define': 'off', // 禁止在 函数/类/变量 定义之前使用它们
'prefer-const': 'off', // 此规则旨在标记使用 let 关键字声明但在初始分配后从未重新分配的变量,要求使用 const
'no-irregular-whitespace': 'off', // 禁止不规则的空白
root: true,
env: {
browser: true,
node: true,
es6: true
},
/* 指定如何解析语法 */
parser: "vue-eslint-parser",
/* 优先级低于 parse 的语法解析配置 */
parserOptions: {
parser: "@typescript-eslint/parser",
ecmaVersion: 2020,
sourceType: "module",
jsxPragma: "React",
ecmaFeatures: {
jsx: true
}
},
/* 继承某些已有的规则 */
extends: ["plugin:vue/vue3-recommended", "plugin:@typescript-eslint/recommended", "prettier", "plugin:prettier/recommended"],
/*
* "off" 0 ==> 关闭规则
* "warn" 1 ==> 打开的规则作为警告不影响代码执行
* "error" 2 ==> 规则作为一个错误代码不能执行界面报错
*/
rules: {
// eslint (http://eslint.cn/docs/rules)
"no-var": "error", // 要求使用 let 或 const 而不是 var
"no-multiple-empty-lines": ["error", { max: 1 }], // 不允许多个空行
"no-use-before-define": "off", // 禁止在 函数/类/变量 定义之前使用它们
"prefer-const": "off", // 此规则旨在标记使用 let 关键字声明但在初始分配后从未重新分配的变量,要求使用 const
"no-irregular-whitespace": "off", // 禁止不规则的空白
// typeScript (https://typescript-eslint.io/rules)
'@typescript-eslint/no-unused-vars': 'error', // 禁止定义未使用的变量
'@typescript-eslint/prefer-ts-expect-error': 'error', // 禁止使用 @ts-ignore
'@typescript-eslint/no-inferrable-types': 'off', // 可以轻松推断的显式类型可能会增加不必要的冗长
'@typescript-eslint/no-namespace': 'off', // 禁止使用自定义 TypeScript 模块和命名空间。
'@typescript-eslint/no-explicit-any': 'off', // 禁止使用 any 类型
'@typescript-eslint/ban-types': 'off', // 禁止使用特定类型
'@typescript-eslint/explicit-function-return-type': 'off', // 不允许对初始化为数字、字符串或布尔值的变量或参数进行显式类型声明
'@typescript-eslint/no-var-requires': 'off', // 不允许在 import 语句中使用 require 语句
'@typescript-eslint/no-empty-function': 'off', // 禁止空函数
'@typescript-eslint/no-use-before-define': 'off', // 禁止在变量定义之前使用它们
'@typescript-eslint/ban-ts-comment': 'off', // 禁止 @ts-<directive> 使用注释或要求在指令后进行描述
'@typescript-eslint/no-non-null-assertion': 'off', // 不允许使用后缀运算符的非空断言(!)
'@typescript-eslint/explicit-module-boundary-types': 'off', // 要求导出函数和类的公共类方法的显式返回和参数类型
'@typescript-eslint/no-unused-vars': 'off',
// typeScript (https://typescript-eslint.io/rules)
"@typescript-eslint/prefer-ts-expect-error": "error", // 禁止使用 @ts-ignore
"@typescript-eslint/no-inferrable-types": "off", // 可以轻松推断的显式类型可能会增加不必要的冗长
"@typescript-eslint/no-namespace": "off", // 禁止使用自定义 TypeScript 模块和命名空间。
"@typescript-eslint/no-explicit-any": "off", // 禁止使用 any 类型
"@typescript-eslint/ban-types": "off", // 禁止使用特定类型
"@typescript-eslint/explicit-function-return-type": "off", // 不允许对初始化为数字、字符串或布尔值的变量或参数进行显式类型声明
"@typescript-eslint/no-var-requires": "off", // 不允许在 import 语句中使用 require 语句
"@typescript-eslint/no-empty-function": "off", // 禁止空函数
"@typescript-eslint/no-use-before-define": "off", // 禁止在变量定义之前使用它们
"@typescript-eslint/ban-ts-comment": "off", // 禁止 @ts-<directive> 使用注释或要求在指令后进行描述
"@typescript-eslint/no-non-null-assertion": "off", // 不允许使用后缀运算符的非空断言(!)
"@typescript-eslint/explicit-module-boundary-types": "off", // 要求导出函数和类的公共类方法的显式返回和参数类型
"@typescript-eslint/no-unused-vars": "off",
// vue (https://eslint.vuejs.org/rules)
'vue/no-v-html': 'off', // 禁止使用 v-html
'vue/script-setup-uses-vars': 'error', // 防止<script setup>使用的变量<template>被标记为未使用此规则仅在启用该no-unused-vars规则时有效。
'vue/v-slot-style': 'error', // 强制执行 v-slot 指令样式
'vue/no-mutating-props': 'off', // 不允许组件 prop的改变
'vue/custom-event-name-casing': 'off', // 为自定义事件名称强制使用特定大小写
'vue/attributes-order': 'off', // vue api使用顺序强制执行属性顺序
'vue/one-component-per-file': '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/require-default-prop': 'off', // 此规则要求为每个 prop 为必填时,必须提供默认值
'vue/multi-word-component-names': 'off', // 要求组件名称始终为 “-” 链接的单词
},
// vue (https://eslint.vuejs.org/rules)
"vue/no-v-html": "off", // 禁止使用 v-html
"vue/script-setup-uses-vars": "error", // 防止<script setup>使用的变量<template>被标记为未使用此规则仅在启用该no-unused-vars规则时有效。
"vue/v-slot-style": "error", // 强制执行 v-slot 指令样式
"vue/no-mutating-props": "off", // 不允许组件 prop的改变
"vue/custom-event-name-casing": "off", // 为自定义事件名称强制使用特定大小写
"vue/attributes-order": "off", // vue api使用顺序强制执行属性顺序
"vue/one-component-per-file": "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/require-default-prop": "off", // 此规则要求为每个 prop 为必填时,必须提供默认值
"vue/multi-word-component-names": "off" // 要求组件名称始终为 “-” 链接的单词
}
};

View File

@ -1,39 +1,39 @@
// @see: https://www.prettier.cn
module.exports = {
// 超过最大值换行
printWidth: 130,
// 缩进字节数
tabWidth: 1,
// 使用制表符而不是空格缩进行
useTabs: true,
// 结尾不用分号(true有false没有)
semi: true,
// 使用单引号(true单引号false双引号)
singleQuote: true,
// 更改引用对象属性的时间 可选值"<as-needed|consistent|preserve>"
quoteProps: 'as-needed',
// 在对象,数组括号与文字之间加空格 "{ foo: bar }"
bracketSpacing: true,
// 多行时尽可能打印尾随逗号。(例如,单行数组永远不会出现逗号结尾。) 可选值"<none|es5|all>"默认none
trailingComma: 'all',
// 在JSX中使用单引号而不是双引号
jsxSingleQuote: true,
// (x) => {} 箭头函数参数只有一个时是否要有小括号。avoid省略括号 ,always不省略括号
arrowParens: 'avoid',
// 如果文件顶部已经有一个 doclock这个选项将新建一行注释并打上@format标记。
insertPragma: false,
// 指定要使用的解析器,不需要写文件开头的 @prettier
requirePragma: false,
// 默认值。因为使用了一些折行敏感型的渲染器如GitHub comment而按照markdown文本样式进行折行
proseWrap: 'preserve',
// 在html中空格是否是敏感的 "css" - 遵守CSS显示属性的默认值 "strict" - 空格被认为是敏感的 "ignore" - 空格被认为是不敏感的
htmlWhitespaceSensitivity: 'css',
// 换行符使用 lf 结尾是 可选值"<auto|lf|crlf|cr>"
endOfLine: 'auto',
// 这两个选项可用于格式化以给定字符偏移量(分别包括和不包括)开始和结束的代码
rangeStart: 0,
rangeEnd: Infinity,
export default {
// 超过最大值换行
printWidth: 130,
// 缩进字节数
tabWidth: 1,
// 使用制表符而不是空格缩进行
useTabs: true,
// 结尾不用分号(true有false没有)
semi: true,
// 使用单引号(true单引号false双引号)
singleQuote: true,
// 更改引用对象属性的时间 可选值"<as-needed|consistent|preserve>"
quoteProps: "as-needed",
// 在对象,数组括号与文字之间加空格 "{ foo: bar }"
bracketSpacing: true,
// 多行时尽可能打印尾随逗号。(例如,单行数组永远不会出现逗号结尾。) 可选值"<none|es5|all>"默认none
trailingComma: "all",
// 在JSX中使用单引号而不是双引号
jsxSingleQuote: true,
// (x) => {} 箭头函数参数只有一个时是否要有小括号。avoid省略括号 ,always不省略括号
arrowParens: "avoid",
// 如果文件顶部已经有一个 doclock这个选项将新建一行注释并打上@format标记。
insertPragma: false,
// 指定要使用的解析器,不需要写文件开头的 @prettier
requirePragma: false,
// 默认值。因为使用了一些折行敏感型的渲染器如GitHub comment而按照markdown文本样式进行折行
proseWrap: "preserve",
// 在html中空格是否是敏感的 "css" - 遵守CSS显示属性的默认值 "strict" - 空格被认为是敏感的 "ignore" - 空格被认为是不敏感的
htmlWhitespaceSensitivity: "css",
// 换行符使用 lf 结尾是 可选值"<auto|lf|crlf|cr>"
endOfLine: "auto",
// 这两个选项可用于格式化以给定字符偏移量(分别包括和不包括)开始和结束的代码
rangeStart: 0,
rangeEnd: Infinity,
vueIndentScriptAndStyle: false, // Vue文件脚本和样式标签缩进
vueIndentScriptAndStyle: false // Vue文件脚本和样式标签缩进
};

View File

@ -1,62 +1,62 @@
// @see: https://stylelint.io
module.exports = {
root: true,
defaultSeverity: 'error',
plugins: ['stylelint-order', 'stylelint-scss'],
/* 继承某些已有的规则 */
extends: [
'stylelint-config-standard', // 配置stylelint拓展插件
'stylelint-config-html/html', // the shareable html config for Stylelint.
'stylelint-config-html/vue', // 配置 vue 中 template 样式格式化
'stylelint-config-recess-order', // 配置stylelint css属性书写顺序插件,
'stylelint-config-prettier', // 配置stylelint和prettier兼容
],
overrides: [
// 扫描 .vue/html 文件中的<style>标签内的样式
{
files: ['**/*.{vue,html}'],
customSyntax: 'postcss-html',
rules: {
// 禁止未知的伪类选择器
'selector-pseudo-class-no-unknown': [true, { ignorePseudoClasses: ['deep', 'global'] }],
// 禁止未知的伪元素选择器
'selector-pseudo-element-no-unknown': [true, { ignorePseudoElements: ['v-deep', 'v-global', 'v-slotted'] }],
},
},
{
files: ['*.less', '**/*.less', '*.scss', '**/*.scss'],
customSyntax: 'postcss-less',
rules: {
'less/color-no-invalid-hex': true,
'less/no-duplicate-variables': true,
},
},
],
/**
* null => 关闭该规则
*/
rules: {
'value-keyword-case': null, // 在 css 中使用 v-bind不报错
'no-descending-specificity': null, // 禁止在具有较高优先级的选择器后出现被其覆盖的较低优先级的选择器
'function-url-quotes': 'always', // 要求或禁止 URL 的引号 "always(必须加上引号)"|"never(没有引号)"
'string-quotes': 'double', // 指定字符串使用单引号或双引号
'unit-case': null, // 指定单位的大小写 "lower(全小写)"|"upper(全大写)"
'color-hex-case': 'lower', // 指定 16 进制颜色的大小写 "lower(全小写)"|"upper(全大写)"
'color-hex-length': 'long', // 指定 16 进制颜色的简写或扩写 "short(16进制简写)"|"long(16进制扩写)"
'rule-empty-line-before': 'never', // 要求或禁止在规则之前的空行 "always(规则之前必须始终有一个空行)"|"never(规则前绝不能有空行)"|"always-multi-line(多行规则之前必须始终有一个空行)"|"never-multi-line(多行规则之前绝不能有空行。)"
'font-family-no-missing-generic-family-keyword': null, // 禁止在字体族名称列表中缺少通用字体族关键字
'block-opening-brace-space-before': 'always', // 要求在块的开大括号之前必须有一个空格或不能有空白符 "always(大括号前必须始终有一个空格)"|"never(左大括号之前绝不能有空格)"|"always-single-line(在单行块中的左大括号之前必须始终有一个空格)"|"never-single-line(在单行块中的左大括号之前绝不能有空格)"|"always-multi-line(在多行块中,左大括号之前必须始终有一个空格)"|"never-multi-line(多行块中的左大括号之前绝不能有空格)"
'property-no-unknown': null, // 禁止未知的属性(true 为不允许)
'no-empty-source': null, // 禁止空源码
'declaration-block-trailing-semicolon': null, // 要求或不允许在声明块中使用尾随分号 string"always(必须始终有一个尾随分号)"|"never(不得有尾随分号)"
'selector-class-pattern': null, // 强制选择器类名的格式
'value-no-vendor-prefix': null, // 关闭 vendor-prefix(为了解决多行省略 -webkit-box)
'selector-pseudo-class-no-unknown': [
true,
{
ignorePseudoClasses: ['global', 'v-deep', 'deep'],
},
],
},
export default {
root: true,
defaultSeverity: "error",
plugins: ["stylelint-order", "stylelint-scss"],
/* 继承某些已有的规则 */
extends: [
"stylelint-config-standard", // 配置stylelint拓展插件
"stylelint-config-html/html", // the shareable html config for Stylelint.
"stylelint-config-html/vue", // 配置 vue 中 template 样式格式化
"stylelint-config-recess-order", // 配置stylelint css属性书写顺序插件,
"stylelint-config-prettier" // 配置stylelint和prettier兼容
],
overrides: [
// 扫描 .vue/html 文件中的<style>标签内的样式
{
files: ["**/*.{vue,html}"],
customSyntax: "postcss-html",
rules: {
// 禁止未知的伪类选择器
"selector-pseudo-class-no-unknown": [true, { ignorePseudoClasses: ["deep", "global"] }],
// 禁止未知的伪元素选择器
"selector-pseudo-element-no-unknown": [true, { ignorePseudoElements: ["v-deep", "v-global", "v-slotted"] }]
}
},
{
files: ["*.less", "**/*.less", "*.scss", "**/*.scss"],
customSyntax: "postcss-less",
rules: {
"less/color-no-invalid-hex": true,
"less/no-duplicate-variables": true
}
}
],
/**
* null => 关闭该规则
*/
rules: {
"value-keyword-case": null, // 在 css 中使用 v-bind不报错
"no-descending-specificity": null, // 禁止在具有较高优先级的选择器后出现被其覆盖的较低优先级的选择器
"function-url-quotes": "always", // 要求或禁止 URL 的引号 "always(必须加上引号)"|"never(没有引号)"
"string-quotes": "double", // 指定字符串使用单引号或双引号
"unit-case": null, // 指定单位的大小写 "lower(全小写)"|"upper(全大写)"
"color-hex-case": "lower", // 指定 16 进制颜色的大小写 "lower(全小写)"|"upper(全大写)"
"color-hex-length": "long", // 指定 16 进制颜色的简写或扩写 "short(16进制简写)"|"long(16进制扩写)"
"rule-empty-line-before": "never", // 要求或禁止在规则之前的空行 "always(规则之前必须始终有一个空行)"|"never(规则前绝不能有空行)"|"always-multi-line(多行规则之前必须始终有一个空行)"|"never-multi-line(多行规则之前绝不能有空行。)"
"font-family-no-missing-generic-family-keyword": null, // 禁止在字体族名称列表中缺少通用字体族关键字
"block-opening-brace-space-before": "always", // 要求在块的开大括号之前必须有一个空格或不能有空白符 "always(大括号前必须始终有一个空格)"|"never(左大括号之前绝不能有空格)"|"always-single-line(在单行块中的左大括号之前必须始终有一个空格)"|"never-single-line(在单行块中的左大括号之前绝不能有空格)"|"always-multi-line(在多行块中,左大括号之前必须始终有一个空格)"|"never-multi-line(多行块中的左大括号之前绝不能有空格)"
"property-no-unknown": null, // 禁止未知的属性(true 为不允许)
"no-empty-source": null, // 禁止空源码
"declaration-block-trailing-semicolon": null, // 要求或不允许在声明块中使用尾随分号 string"always(必须始终有一个尾随分号)"|"never(不得有尾随分号)"
"selector-class-pattern": null, // 强制选择器类名的格式
"value-no-vendor-prefix": null, // 关闭 vendor-prefix(为了解决多行省略 -webkit-box)
"selector-pseudo-class-no-unknown": [
true,
{
ignorePseudoClasses: ["global", "v-deep", "deep"]
}
]
}
};

View File

@ -1,108 +1,108 @@
// @see: https://cz-git.qbenben.com/zh/guide
/** @type {import('cz-git').UserConfig} */
/** @type {import("cz-git").UserConfig} */
module.exports= {
ignores: [commit => commit === 'init'],
extends: ['@commitlint/config-conventional'],
rules: {
// @see: https://commitlint.js.org/#/reference-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'],
'subject-case': [0],
'type-enum': [
2,
'always',
[
'init',
'feat',
'page',
'media',
'completepage',
'fix',
'fixbug',
'docs',
'style',
'refactor',
'perf',
'test',
'build',
'ci',
'chore',
'revert',
'wip',
'workflow',
'types',
'release',
'optimize',
],
],
},
prompt: {
messages: {
type: '选择你要提交的类型 :',
scope: '选择一个提交范围(可选):',
customScope: '请输入自定义的提交范围 :',
subject: '填写简短精炼的变更描述 :\n',
body: '填写更加详细的变更描述(可选)。使用 "|" 换行 :\n',
breaking: '列举非兼容性重大的变更(可选)。使用 "|" 换行 :\n',
footerPrefixsSelect: '选择关联issue前缀可选:',
customFooterPrefixs: '输入自定义issue前缀 :',
footer: '列举关联issue (可选) 例如: #31, #I3244 :\n',
confirmCommit: '是否提交或修改commit ?',
},
types: [
{ value: 'init', name: '初始化: ⏳ 初始化项目', emoji: '⏳' },
{ value: 'optimize', name: '优化代码: ♻️ 优化项目代码', emoji: '♻️' },
{ value: 'feat', name: '新增: 🚀 新增功能', emoji: '🚀' },
{ value: 'media', name: '媒体: 🎁 新增媒体资源', emoji: '🎁' },
{ value: 'page', name: '页面: 📄 新增页面', emoji: '📄' },
{ value: 'completepage', name: '完成页面: 🍻 完成页面', emoji: '🍻' },
{ value: 'fixbug', name: 'bug: 🐛 修改bug', emoji: '🐛' },
{ value: 'fix', name: '修复: 🧩 修复缺陷', emoji: '🧩' },
{ value: 'docs', name: '文档: 📚 文档变更', emoji: '📚' },
{ value: 'style', name: '格式: 🎨 代码格式(不影响功能,例如空格、分号等格式修正)', emoji: '🎨' },
{ value: 'refactor', name: '重构: 〽️ 代码重构(不包括 bug 修复、功能新增)', emoji: '〽️' },
{ value: 'perf', name: '性能: ⚡️ 性能优化', emoji: '⚡️' },
{ value: 'test', name: '测试: ✅ 添加疏漏测试或已有测试改动', emoji: '✅' },
{
value: 'chore',
name: '构建: 📦️ 构建流程、外部依赖变更(如升级 npm 包、修改 webpack 配置等)',
emoji: '📦️',
},
{ value: 'ci', name: '集成: 🎡 修改 CI 配置、脚本', emoji: '🎡' },
{ value: 'revert', name: '回退: ⏪️ 回滚 commit', emoji: '⏪️' },
{ value: 'build', name: '打包: 🔨 项目打包发布', emoji: '🔨' },
],
useEmoji: true,
themeColorCode: '',
scopes: [],
allowCustomScopes: true,
allowEmptyScopes: true,
customScopesAlign: 'bottom',
customScopesAlias: 'custom',
emptyScopesAlias: 'empty',
upperCaseSubject: false,
allowBreakingChanges: ['feat', 'fix'],
breaklineNumber: 100,
breaklineChar: '|',
skipQuestions: [],
issuePrefixs: [{ value: 'closed', name: 'closed: ISSUES has been processed' }],
customIssuePrefixsAlign: 'top',
emptyIssuePrefixsAlias: 'skip',
customIssuePrefixsAlias: 'custom',
allowCustomIssuePrefixs: true,
allowEmptyIssuePrefixs: true,
confirmColorize: true,
maxHeaderLength: Infinity,
maxSubjectLength: Infinity,
minSubjectLength: 0,
scopeOverrides: undefined,
defaultBody: '',
defaultIssues: '',
defaultScope: '',
defaultSubject: '',
},
export default {
ignores: [commit => commit === "init"],
extends: ["@commitlint/config-conventional"],
rules: {
// @see: https://commitlint.js.org/#/reference-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"],
"subject-case": [0],
"type-enum": [
2,
"always",
[
"init",
"feat",
"page",
"media",
"completepage",
"fix",
"fixbug",
"docs",
"style",
"refactor",
"perf",
"test",
"build",
"ci",
"chore",
"revert",
"wip",
"workflow",
"types",
"release",
"optimize"
]
]
},
prompt: {
messages: {
type: "选择你要提交的类型 :",
scope: "选择一个提交范围(可选):",
customScope: "请输入自定义的提交范围 :",
subject: "填写简短精炼的变更描述 :\n",
body: "填写更加详细的变更描述(可选)。使用 \"|\" 换行 :\n",
breaking: "列举非兼容性重大的变更(可选)。使用 \"|\" 换行 :\n",
footerPrefixsSelect: "选择关联issue前缀可选:",
customFooterPrefixs: "输入自定义issue前缀 :",
footer: "列举关联issue (可选) 例如: #31, #I3244 :\n",
confirmCommit: "是否提交或修改commit ?"
},
types: [
{ value: "init", name: "初始化: ⏳ 初始化项目", emoji: "⏳" },
{ value: "optimize", name: "优化代码: ♻️ 优化项目代码", emoji: "♻️" },
{ value: "feat", name: "新增: 🚀 新增功能", emoji: "🚀" },
{ value: "media", name: "媒体: 🎁 新增媒体资源", emoji: "🎁" },
{ value: "page", name: "页面: 📄 新增页面", emoji: "📄" },
{ value: "completepage", name: "完成页面: 🍻 完成页面", emoji: "🍻" },
{ value: "fixbug", name: "bug: 🐛 修改bug", emoji: "🐛" },
{ value: "fix", name: "修复: 🧩 修复缺陷", emoji: "🧩" },
{ value: "docs", name: "文档: 📚 文档变更", emoji: "📚" },
{ value: "style", name: "格式: 🎨 代码格式(不影响功能,例如空格、分号等格式修正)", emoji: "🎨" },
{ value: "refactor", name: "重构: 〽️ 代码重构(不包括 bug 修复、功能新增)", emoji: "〽️" },
{ value: "perf", name: "性能: ⚡️ 性能优化", emoji: "⚡️" },
{ value: "test", name: "测试: ✅ 添加疏漏测试或已有测试改动", emoji: "✅" },
{
value: "chore",
name: "构建: 📦️ 构建流程、外部依赖变更(如升级 npm 包、修改 webpack 配置等)",
emoji: "📦️"
},
{ value: "ci", name: "集成: 🎡 修改 CI 配置、脚本", emoji: "🎡" },
{ value: "revert", name: "回退: ⏪️ 回滚 commit", emoji: "⏪️" },
{ value: "build", name: "打包: 🔨 项目打包发布", emoji: "🔨" }
],
useEmoji: true,
themeColorCode: "",
scopes: [],
allowCustomScopes: true,
allowEmptyScopes: true,
customScopesAlign: "bottom",
customScopesAlias: "custom",
emptyScopesAlias: "empty",
upperCaseSubject: false,
allowBreakingChanges: ["feat", "fix"],
breaklineNumber: 100,
breaklineChar: "|",
skipQuestions: [],
issuePrefixs: [{ value: "closed", name: "closed: ISSUES has been processed" }],
customIssuePrefixsAlign: "top",
emptyIssuePrefixsAlias: "skip",
customIssuePrefixsAlias: "custom",
allowCustomIssuePrefixs: true,
allowEmptyIssuePrefixs: true,
confirmColorize: true,
maxHeaderLength: Infinity,
maxSubjectLength: Infinity,
minSubjectLength: 0,
scopeOverrides: undefined,
defaultBody: "",
defaultIssues: "",
defaultScope: "",
defaultSubject: ""
}
};

View File

@ -1,8 +1,8 @@
module.exports = {
'*.{js,jsx,ts,tsx}': ['eslint --fix --no-ignore', 'prettier --write'],
'{!(package)*.json,*.code-snippets,.!(browserslist)*rc}': ['prettier --write--parser json'],
'package.json': ['prettier --write'],
'*.vue': ['eslint --fix --no-ignore', 'prettier --write'],
'*.{scss,less,styl,html}': ['prettier --write', 'eslint --fix --no-ignore'], // 'stylelint --fix',
'*.md': ['prettier --write'],
export default {
// "*.{js,jsx,ts,tsx}": ["eslint --fix --no-ignore", "prettier --write"],
"{!(package)*.json,*.code-snippets,.!(browserslist)*rc}": ["prettier --write--parser json"],
"package.json": ["prettier --write"],
// "*.vue": ["eslint --fix", "prettier --write"],
"*.{scss,less,styl,html}": ["prettier --write", "eslint --fix --no-ignore"], // 'stylelint --fix',
"*.md": ["prettier --write"]
};

4931
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -2,6 +2,7 @@
"name": "vite_ts_auto",
"private": true,
"version": "1.0.0",
"type": "module",
"description": "Bunny-Vite模板",
"author": "Bunny-Admin <1319900154@qq.com>",
"license": "MIT",
@ -28,7 +29,6 @@
"dayjs": "^1.11.10",
"dotenv": "^16.4.5",
"echarts": "^5.5.0",
"loadsh": "^0.0.4",
"lodash": "^4.17.21",
"mitt": "^3.0.1",
"moment": "^2.30.1",
@ -36,13 +36,13 @@
"pinia-plugin-persistedstate": "^3.2.1",
"stylelint-scss": "^6.3.0",
"uuid": "^9.0.1",
"vite-plugin-cdn-import": "^1.0.1",
"vite-plugin-compression2": "^1.1.1",
"vue": "^3.4.21",
"vue-cookies": "^1.8.3",
"vue-i18n": "^9.13.1",
"vue-lazyload": "^3.0.0",
"vue-router": "^4.3.0",
"webpackbar": "^6.0.1"
"vue-router": "^4.3.0"
},
"devDependencies": {
"@commitlint/cli": "^17.8.1",
@ -70,6 +70,7 @@
"file-loader": "^6.2.0",
"husky": "^8.0.1",
"lint-staged": "^15.2.2",
"mockjs": "^1.1.0",
"postcss": "^8.4.35",
"postcss-html": "^1.6.0",
"prettier": "^3.2.5",
@ -77,6 +78,7 @@
"sass-loader": "^14.1.1",
"typescript": "~5.3.3",
"vite": "^5.2.0",
"vite-plugin-mock": "^3.0.2",
"vue-tsc": "^2.0.6"
},
"gitHooks": {

View File

@ -1,8 +1,31 @@
<script setup lang="ts">
</script>
<template>
<RouterView />
<RouterView />
</template>
<script lang="ts" setup>
import { userI18nStore } from "@/store/i18n.ts";
import { useI18n } from "vue-i18n";
import { onMounted } from "vue";
const i18nStore = userI18nStore();
const i18n = useI18n();
/**
* * 设置多语言内容
*/
const setI18n = async () => {
await i18nStore.fetchI18n();
const languageData = JSON.parse(localStorage.getItem("i18nStore") as any);
const local = languageData.i18n.local;
//
i18n.locale.value = local;
i18n.mergeLocaleMessage(local, languageData.i18n[local]);
};
onMounted(async () => {
await setI18n();
});
</script>
<style scoped></style>

9
src/api/mock/i18n.ts Normal file
View File

@ -0,0 +1,9 @@
import Request from "@/service/request-mock.ts";
export const fetchGetI18n = () => {
return Request({
url: "/getI18n",
method: "GET"
});
};

View File

@ -1,12 +1,16 @@
import { createI18n } from 'vue-i18n';
import en from './modules/en';
import zh_CN from './modules/zh_CN';
import { createI18n } from "vue-i18n";
// ? 从本地存储中获取数据
const languageData = localStorage.getItem("i18nStore");
// 配置多语言
const i18n = createI18n({
legacy: false, // 如果要支持 compositionAPI此项必须设置为 false
locale: 'zh_CN', // 设置语言类型
globalInjection: true, // 全局注册$t方法
messages: { zh_CN, en },
// 如果要支持 compositionAPI此项必须设置为 false
legacy: false,
// ? 全局注册$t方法
globalInjection: true,
// 本地内容存在时,首次加载如果本地存储没有多语言需要再刷新
messages: languageData ? JSON.parse(languageData).i18n : {}
});
export default i18n;

View File

@ -1,18 +0,0 @@
export default {
login: {
reset: 'reset',
register: 'register',
},
home: {},
tabs: {},
header: {
fullScreen: 'Full Screen',
exitFullScreen: 'Exit Full Screen',
personalData: 'Personal Data',
changePassword: 'Change Password',
logout: 'Logout',
},
tip: {
loading: 'Loading...',
},
};

View File

@ -1,18 +0,0 @@
export default {
login: {
reset: '重置',
register: '登录',
},
home: {},
tabs: {},
header: {
fullScreen: '全屏',
exitFullScreen: '退出全屏',
personalData: '个人信息',
changePassword: '修改密码',
logout: '退出登录',
},
tip: {
loading: '加载中...',
},
};

View File

@ -1,12 +1,12 @@
import directives from '@/directives';
import i18n from '@/i18n/index.ts';
import { createPinia } from 'pinia';
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate';
import { createApp } from 'vue';
import App from './App.vue';
import './assets/css/index.scss';
import './assets/css/reset.css';
import router from './router';
import directives from "@/directives";
import i18n from "@/i18n/index.ts";
import { createPinia } from "pinia";
import piniaPluginPersistedstate from "pinia-plugin-persistedstate";
import { createApp } from "vue";
import App from "./App.vue";
import "./assets/css/index.scss";
import "./assets/css/reset.css";
import router from "./router";
const pinia = createPinia();
const app = createApp(App);
@ -15,4 +15,5 @@ const app = createApp(App);
pinia.use(piniaPluginPersistedstate);
app.use(router).use(pinia).use(i18n).use(directives);
app.mount('#app');
app.mount("#app");

13
src/mock/i18n/index.ts Normal file
View File

@ -0,0 +1,13 @@
import { MockMethod } from "vite-plugin-mock";
import { zh_cn } from "@/mock/i18n/modules/zh_cn.ts";
import { en } from "@/mock/i18n/modules/en.ts";
const list: MockMethod[] = [
{
url: "/mock/getI18n",
method: "get",
response: () => ({ data: { zh_cn, en, local: "zh_cn" } })
}
];
export default list;

View File

@ -0,0 +1,18 @@
export const en = {
login: {
reset: "reset",
register: "register"
},
home: {},
tabs: {},
header: {
fullScreen: "Full Screen",
exitFullScreen: "Exit Full Screen",
personalData: "Personal Data",
changePassword: "Change Password",
logout: "Logout"
},
tip: {
loading: "Loading..."
}
};

View File

@ -0,0 +1,19 @@
export const zh_cn = {
login: {
reset: "重置",
register: "登录"
},
home: {},
tabs: {},
header: {
fullScreen: "全屏",
exitFullScreen: "退出全屏",
personalData: "个人信息",
changePassword: "修改密码",
logout: "退出登录"
},
tip: {
loading: "加载中..."
}
};

View File

@ -1,25 +1,26 @@
import { ResultEnum } from '@/enums/httpEnum';
import axios from 'axios';
import { BASE_MOCK } from './config/servicePort';
import { ResultEnum } from "@/enums/httpEnum";
import axios from "axios";
import { BASE_MOCK } from "./config/servicePort";
const request = axios.create({
baseURL: BASE_MOCK,
timeout: ResultEnum.TIMEOUT as number,
baseURL: BASE_MOCK,
timeout: ResultEnum.TIMEOUT as number
});
// 请求拦截器
request.interceptors.request.use(config => {
return config;
return config;
});
// 响应拦截器
request.interceptors.response.use(
response => {
return response.data;
},
error => {
return Promise.reject(new Error('网络错误'));
},
response => {
return response.data;
},
error => {
console.log(error);
return Promise.reject(new Error("网络错误"));
}
);
export default request;

View File

@ -1,29 +1,30 @@
import { ResultEnum } from '@/enums/httpEnum';
import axios from 'axios';
import { BASE_API } from './config/servicePort';
import { ResultEnum } from "@/enums/httpEnum";
import axios from "axios";
import { BASE_API } from "./config/servicePort";
const request = axios.create({
// 默认请求地址
baseURL: BASE_API,
// 设置超时时间
timeout: ResultEnum.TIMEOUT as number,
// 跨域允许携带凭证
// withCredentials: true,
// 默认请求地址
baseURL: BASE_API,
// 设置超时时间
timeout: ResultEnum.TIMEOUT as number
// 跨域允许携带凭证
// withCredentials: true,
});
// 请求拦截器
request.interceptors.request.use(config => {
return config;
return config;
});
// 响应拦截器
request.interceptors.response.use(
response => {
return response.data;
},
error => {
return Promise.reject(new Error('网络错误'));
},
response => {
return response.data;
},
error => {
console.log(error);
return Promise.reject(new Error("网络错误"));
}
);
export default request;

21
src/store/i18n.ts Normal file
View File

@ -0,0 +1,21 @@
import { defineStore } from "pinia";
import { fetchGetI18n } from "@/api/mock/i18n.ts";
export const userI18nStore = defineStore("i18nStore", {
persist: true,
state() {
return {
// ? 多语言内容
i18n: {} as any
};
},
getters: {},
actions: {
async fetchI18n() {
this.i18n = (await fetchGetI18n()).data;
}
}
});

View File

@ -1,30 +1,47 @@
<template>
<h1>vite-pinia 模板</h1>
<h1>成功</h1>
<ul>
<li v-for="(route, index) in pageRoutes" :key="index">
<RouterLink :to="route.path">{{ `${route.path}${String(route.name)}` }}</RouterLink>
</li>
</ul>
<h1>vite-pinia 模板</h1>
<h1>多语言{{ $t("tip.loading") }}</h1>
<button @click="handleI18n('en')">切换英文</button>
<button @click="handleI18n('zh_cn')">切换中文</button>
<ul>
<li v-for="(route, index) in pageRoutes" :key="index">
<RouterLink :to="route.path">{{ `${route.path}${String(route.name)}` }}</RouterLink>
</li>
</ul>
<Test />
<RouterView />
<Test />
<RouterView />
</template>
<script lang="ts" setup>
import Test from '@/views/test-tsx/index.tsx';
import { pageRoutes } from '@/router/module/pageRoutes';
import Test from "@/views/test-tsx/index.tsx";
import { pageRoutes } from "@/router/module/pageRoutes";
import { userI18nStore } from "@/store/i18n.ts";
import { useI18n } from "vue-i18n";
const i18nStore = userI18nStore();
const i18n = useI18n();
/**
* * 切换多语言
* @param value
*/
const handleI18n = (value: string) => {
i18n.locale.value = value;
i18n.mergeLocaleMessage(value, i18nStore.i18n[value]);
};
</script>
<style lang="scss" scoped>
ul {
padding-left: 50px;
padding-left: 50px;
li {
list-style: circle !important;
}
li {
list-style: circle !important;
}
a {
color: #8185a7;
}
a {
color: #8185a7;
}
}
</style>

View File

@ -1,90 +1,101 @@
import vue from '@vitejs/plugin-vue';
import { resolve } from 'path';
import { defineConfig, UserConfig } from 'vite';
import legacy from '@vitejs/plugin-legacy';
import vueJsx from '@vitejs/plugin-vue2-jsx';
import { compression } from 'vite-plugin-compression2';
import vue from "@vitejs/plugin-vue";
import { resolve } from "path";
import { defineConfig, UserConfig } from "vite";
import legacy from "@vitejs/plugin-legacy";
import vueJsx from "@vitejs/plugin-vue2-jsx";
import { compression } from "vite-plugin-compression2";
import cdn from "vite-plugin-cdn-import";
import { viteMockServe } from "vite-plugin-mock";
export default defineConfig(
(): UserConfig => ({
// base: './', // ? 在每个文件前加上这个前缀
// publicDir: './static',// ? 设置静态资源目录
envPrefix: 'BUNNY',
resolve: {
alias: {
'@': resolve(__dirname, './src'),
'vue-i18n': 'vue-i18n/dist/vue-i18n.cjs.js',
},
},
server: {
host: '0.0.0.0',
port: 6261,
open: true,
cors: true,
proxy: {
'/api': {
target: process.env.BUNNY_APP_URL,
changeOrigin: true,
rewrite: (path: string) => path.replace(/^\/api/, '/api'),
},
'/mock': {
target: process.env.BUNNY_APP_URL,
changeOrigin: true,
rewrite: (path: string) => path.replace(/^\/mock/, '/mock'),
},
},
},
plugins: [vue(), legacy({ targets: ['defaults', 'not IE 11'] }), vueJsx(), compression()],
esbuild: {
pure: ['console.log', 'debugger'],
jsxFactory: 'h',
jsxFragment: 'Fragment',
jsxInject: "import { h } from 'vue';",
},
// 配置构建过程的选项,例如是否生成压缩文件和源映射
build: {
assetsInlineLimit: 20000,
// 构建输出的目录,默认值为"dist"
outDir: 'dist',
// 用于指定使用的代码压缩工具。在这里minify 被设置为 'terser',表示使用 Terser 进行代码压缩。默认值terser
// esbuild 打包更快,但是不能去除 console.logterser打包慢但能去除 console.log
minify: 'terser',
// 用于配置 Terser 的选项
terserOptions: {
// 用于配置压缩选项
compress: {
drop_console: true, // 是否删除代码中的 console 语句, 默认值false
drop_debugger: true, // 是否删除代码中的 debugger 语句, 默认值false
},
},
// 禁用 gzip 压缩大小报告,可略微减少打包时间
reportCompressedSize: false,
// 用于指定是否生成源映射文件。源映射文件可以帮助调试和定位源代码中的错误。当设置为false时构建过程不会生成源映射文件
sourcemap: false,
// 用于配置 CommonJS 模块的选项
commonjsOptions: {
// 用于指定是否忽略 CommonJS 模块中的 try-catch 语句。当设置为false时构建过程会保留 CommonJS 模块中的 try-catch 语句
ignoreTryCatch: false,
},
// 规定触发警告的 chunk 大小, 当某个代码分块的大小超过该限制时Vite 会发出警告
chunkSizeWarningLimit: 2000,
// 用于配置 Rollup 打包工具的选项
rollupOptions: {
// 用于配置输出选项
output: {
// 静态资源分类和包装
chunkFileNames: 'js/[name]-[hash].js', // 用于指定代码分块的输出文件名格式
entryFileNames: 'js/[name]-[hash].js', // 用于指定入口文件的输出文件名格式
assetFileNames: 'assets/[ext]/[name]-[hash].[ext]', // 用于指定静态资源的输出文件名格式
// ? 配置文件生成方式
manualChunks: (id, meta) => {
// 如果是包含在包中则打包成 vendor
if (id.includes('mode_modules')) {
return 'vendor';
}
},
},
},
},
}),
(): UserConfig => ({
// base: './', // ? 在每个文件前加上这个前缀
// publicDir: './static',// ? 设置静态资源目录
envPrefix: "BUNNY",
resolve: {
alias: {
"@": resolve(__dirname, "./src"),
"vue-i18n": "vue-i18n/dist/vue-i18n.cjs.js"
}
},
server: {
host: "0.0.0.0",
port: 6261,
open: true,
cors: true,
proxy: {
"/api": {
target: process.env.BUNNY_APP_URL,
changeOrigin: true,
rewrite: (path: string) => path.replace(/^\/api/, "/api")
},
"/mock": {
target: process.env.BUNNY_APP_URL,
changeOrigin: true,
rewrite: (path: string) => path.replace(/^\/mock/, "/mock")
}
}
},
plugins: [
vue(),
legacy({ targets: ["defaults", "not IE 11"] }),
vueJsx(),
compression(),
cdn({
modules: []
}),
viteMockServe({ mockPath: "src/mock" })
],
esbuild: {
pure: ["console.log", "debugger"],
jsxFactory: "h",
jsxFragment: "Fragment",
jsxInject: "import { h } from 'vue';"
},
// 配置构建过程的选项,例如是否生成压缩文件和源映射
build: {
assetsInlineLimit: 20000,
// 构建输出的目录,默认值为"dist"
outDir: "dist",
// 用于指定使用的代码压缩工具。在这里minify 被设置为 'terser',表示使用 Terser 进行代码压缩。默认值terser
// esbuild 打包更快,但是不能去除 console.logterser打包慢但能去除 console.log
minify: "terser",
// 用于配置 Terser 的选项
terserOptions: {
// 用于配置压缩选项
compress: {
drop_console: true, // 是否删除代码中的 console 语句, 默认值false
drop_debugger: true // 是否删除代码中的 debugger 语句, 默认值false
}
},
// 禁用 gzip 压缩大小报告,可略微减少打包时间
reportCompressedSize: false,
// 用于指定是否生成源映射文件。源映射文件可以帮助调试和定位源代码中的错误。当设置为false时构建过程不会生成源映射文件
sourcemap: false,
// 用于配置 CommonJS 模块的选项
commonjsOptions: {
// 用于指定是否忽略 CommonJS 模块中的 try-catch 语句。当设置为false时构建过程会保留 CommonJS 模块中的 try-catch 语句
ignoreTryCatch: false
},
// 规定触发警告的 chunk 大小, 当某个代码分块的大小超过该限制时Vite 会发出警告
chunkSizeWarningLimit: 2000,
// 用于配置 Rollup 打包工具的选项
rollupOptions: {
// 用于配置输出选项
output: {
// 静态资源分类和包装
chunkFileNames: "js/[name]-[hash].js", // 用于指定代码分块的输出文件名格式
entryFileNames: "js/[name]-[hash].js", // 用于指定入口文件的输出文件名格式
assetFileNames: "assets/[ext]/[name]-[hash].[ext]", // 用于指定静态资源的输出文件名格式
// ? 配置文件生成方式
manualChunks: (id, meta) => {
// 如果是包含在包中则打包成 vendor
if (id.includes("node_modules")) {
return "vendor";
}
}
}
}
}
})
);