升级vite版本和部分依赖

This commit is contained in:
yangjian
2026-07-03 17:32:13 +08:00
parent c3b9a801c7
commit df49364a94
20 changed files with 425 additions and 329 deletions
-9
View File
@@ -1,9 +0,0 @@
/build/
/config/
/dist/
/*.js
/src/components/verifition
/test/unit/coverage/
/src/icons/iconfont.js
/components.d.ts
/src/auto-import
-94
View File
@@ -1,94 +0,0 @@
{
"globals": {
"$t": true,
"Component": true,
"ComponentPublicInstance": true,
"ComputedRef": true,
"Debounce": true,
"EffectScope": true,
"InjectionKey": true,
"PropType": true,
"Ref": true,
"VNode": true,
"clearLoginInfo": true,
"computed": true,
"configDefInfo": true,
"createApp": true,
"customRef": true,
"defineAsyncComponent": true,
"defineComponent": true,
"effectScope": true,
"encrypt": true,
"flatten": true,
"checkFileUrl": true,
"formatConfigInfo": true,
"getCurrentInstance": true,
"getCurrentScope": true,
"getLevels": true,
"getUUID": true,
"h": true,
"http": true,
"idList": true,
"inject": true,
"isAuth": true,
"isEmail": true,
"isHtmlNull": true,
"isMobile": true,
"isPhone": true,
"isProxy": true,
"isQq": true,
"isReactive": true,
"isReadonly": true,
"isRef": true,
"isURL": true,
"markRaw": true,
"nextTick": true,
"onActivated": true,
"onBeforeMount": true,
"onBeforeRouteLeave": true,
"onBeforeRouteUpdate": true,
"onBeforeUnmount": true,
"onBeforeUpdate": true,
"onDeactivated": true,
"onErrorCaptured": true,
"onMounted": true,
"onRenderTracked": true,
"onRenderTriggered": true,
"onScopeDispose": true,
"onServerPrefetch": true,
"onUnmounted": true,
"onUpdated": true,
"provide": true,
"reactive": true,
"readonly": true,
"ref": true,
"resolveComponent": true,
"shallowReactive": true,
"shallowReadonly": true,
"shallowRef": true,
"toRaw": true,
"toRef": true,
"toRefs": true,
"treeDataTranslate": true,
"triggerRef": true,
"unref": true,
"uploadFile": true,
"useAttrs": true,
"useCommonStore": true,
"scoreProdStore":true,
"useCssModule": true,
"useCssVars": true,
"useLink": true,
"useRoute": true,
"useRouter": true,
"useSlots": true,
"useUserStore": true,
"useWebConfigStore": true,
"validHtmlLength": true,
"validNoEmptySpace": true,
"watch": true,
"watchEffect": true,
"watchPostEffect": true,
"watchSyncEffect": true
}
}
-79
View File
@@ -1,79 +0,0 @@
module.exports = {
root: true,
env: {
browser: true,
es2021: true
},
globals: {
BMap: 'readonly'
},
extends: [
'standard',
'./.eslintrc-auto-import.json',
'plugin:vue/vue3-recommended',
'plugin:vue-scoped-css/vue3-recommended'
],
overrides: [],
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module'
},
plugins: ['vue'],
rules: {
// Possible Errors
// 要求使用 let 或 const 而不是 var
'no-var': 'error',
// 强制 "for" 循环中更新子句的计数器朝着正确的方向移动
'for-direction': 'error',
// 强制 getter 函数中出现 return 语句
'getter-return': 'error',
// 禁止在嵌套的块中出现变量声明或 function 声明
'no-inner-declarations': 'error',
// 禁止由于 await 或 yield的使用而可能导致出现竞态条件的赋值
'require-atomic-updates': 'error',
// console 警告
'no-console': 'warn',
// 禁止出现未使用过的变量
'no-unused-vars': [
'warn',
{
args: 'all',
caughtErrors: 'none',
ignoreRestSiblings: true,
vars: 'all'
}
],
// 关闭名称校验
'vue/multi-word-component-names': 'off',
// 非生产环境启用 debugger
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
// Best Practices
eqeqeq: 'off',
// Stylistic Issues
// 强制可嵌套的块的最大深度
'max-depth': ['error', 5],
// 强制函数最大代码行数
'max-lines-per-function': [
'error',
{
max: 150,
skipBlankLines: true
}
],
// 强制回调函数最大嵌套深度
'max-nested-callbacks': ['error', { max: 10 }],
// 强制函数定义中最多允许的参数数量
'max-params': ['error', { max: 5 }],
// 强制每一行中所允许的最大语句数量
'max-statements-per-line': ['error', { max: 1 }],
// 三目运算符换行
'multiline-ternary': ['error', 'never'],
// 传值给组件时的使用 kebab-case
'vue/v-on-event-hyphenation': ['warn', 'always', {
autofix: true,
ignore: []
}]
}
}
+18
View File
@@ -0,0 +1,18 @@
{
// 指向本地 schema,方便编辑器识别 Oxfmt 的配置字段。
"$schema": "./node_modules/oxfmt/configuration_schema.json",
// 与现有项目代码风格保持一致:不自动补分号。
"semi": false,
// 与既有 JS / Vue 文件风格保持一致:优先使用单引号。
"singleQuote": true,
// 单参数箭头函数也强制保留括号,避免保存时因默认值或编辑器差异出现风格漂移。
"arrowParens": "always",
// HTML、Vue、JSX 标签中的属性强制一行一个,和原有 ESLint 风格保持一致。
"singleAttributePerLine": true,
// 避免保存时自动补尾逗号,减少无意义 diff。
"trailingComma": "none",
// package.json 保持人工控制字段顺序,避免依赖区块被自动重排。
"sortPackageJson": false,
// 忽略生成物与公开静态资源,避免格式化覆盖工具产物。
"ignorePatterns": ["dist/**", "public/**", "src/auto-import/**", "types/auto-import/**"]
}
+90
View File
@@ -0,0 +1,90 @@
{
// 指向本地 schema,方便编辑器做字段提示和校验。
"$schema": "./node_modules/oxlint/configuration_schema.json",
// 声明当前项目默认运行在浏览器环境,并启用 ES6 全局变量集。
"env": {
"browser": true,
"es6": true
},
// 注册项目里会直接访问的全局变量,避免被误判成未定义。
"globals": {},
// 显式声明迁移期真正需要的插件集合,避免继续吃到默认插件带来的额外噪音。
// 这里先只保留最接近原 ESLint 8 方案的 eslint 核心规则和 vue 脚本规则。
// 注意:设置 plugins 会覆盖 Oxlint 默认插件集合,所以需要的插件必须全部写全。
"plugins": ["eslint", "vue"],
// 统一维护不参与 lint 的目录,减少本地与 CI 结果偏差。
"ignorePatterns": [
"build/**",
"config/**",
"dist/**",
"public/**",
"test/unit/coverage/**",
"src/icons/iconfont.js",
"src/auto-import/**",
"types/auto-import/**"
],
// 先启用最有价值的规则分类,避免一次性引入过多历史噪音。
"categories": {
"correctness": "error",
"suspicious": "warn"
},
// 这里放项目级基础规则,优先覆盖原先 ESLint 中保留下来的核心校验。
// 迁移初期先追求和旧项目体感接近,再逐步补回更严格的规则。
"rules": {
// 禁止随手输出调试日志,但保留 console.error 作为异常排查和兜底告警的输出通道。
"no-console": [
"warn",
{
"allow": ["error"]
}
],
// 允许在本地联调阶段临时使用 debugger,避免影响现有排查流程。
"no-debugger": "off",
// 禁止继续使用 var,统一收敛到 let / const,减少变量提升带来的作用域问题。
"no-var": "error",
// 防止 for 循环的自增自减方向写反,避免出现死循环或根本不执行的情况。
"for-direction": "error",
// 要求 getter 必须显式返回值,避免读取属性时得到难以排查的 undefined。
"getter-return": "error",
// 禁止在块级作用域中声明易产生歧义的函数或变量,降低兼容性风险。
"no-inner-declarations": "error",
// 避免异步场景对同一变量的读写互相覆盖,减少竞态条件问题。
"require-atomic-updates": "error",
// 旧项目里这类变量名遮蔽并没有被大量提示,迁移期先关闭避免噪音过高。
"no-shadow": "off",
// 兼容现有代码里常见的“条件成立才执行”写法,避免把短路表达式都判成错误。
"no-unused-expressions": [
"error",
{
"allowShortCircuit": true,
"allowTernary": true
}
],
// 旧项目并没有强制限制字符串拼接,这里先关闭避免产生额外迁移噪音。
"no-useless-concat": "off"
},
// 按文件类型细分规则,降低 JS 与 Vue 场景下的误报。
"overrides": [
{
// JS 文件继续保留较宽松的未使用变量策略,兼容现有代码风格。
"files": ["src/**/*.js"],
"rules": {
"no-unused-vars": [
"warn",
{
// 继续检查函数参数,帮助发现历史遗留的无效入参。
"args": "all",
// 不强制要求 catch 参数必须被使用,兼容现有异常捕获写法。
"caughtErrors": "none",
// 允许对象剩余解构时的兄弟字段暂时未使用,减少常见场景下的误报。
"ignoreRestSiblings": true,
// 对局部变量仍然给出提示,便于逐步清理废弃状态和冗余逻辑。
"vars": "all",
// 保留项目里常见的占位参数命名,避免批量改名造成无意义 diff。
"argsIgnorePattern": "^[rule, value, i, to, from, binding]"
}
]
}
}
]
}
+18
View File
@@ -0,0 +1,18 @@
{
// 仅为编辑器与 Volar 提供路径别名和自动生成声明文件的索引能力。
"compilerOptions": {
// 对齐 Vite 的 @ 别名,避免业务源码和自动生成声明文件中的路径在编辑器里报错。
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
},
// 当前项目以 JavaScript 为主,不启用严格的 TS 检查。
"allowJs": true,
"checkJs": false,
"skipLibCheck": true
},
// 排除依赖目录与构建产物,减少编辑器项目分析开销。
"exclude": ["node_modules", "dist"],
// 同时索引业务源码与自动生成声明文件,和 b2c 项目保持一致。
"include": ["src/**/*.js", "src/**/*.vue", "types/**/*.d.ts"]
}
+41 -39
View File
@@ -9,57 +9,59 @@
"dev:test": "vite --mode testing",
"build": "vite build",
"build:test": "vite build --mode testing",
"lint": "eslint --ext .js,.vue src",
"lint:fix": "eslint --fix --ext .js,.vue src",
"lint": "oxlint src",
"lint:fix": "oxlint --fix src",
"fmt": "oxfmt .",
"fmt:check": "oxfmt --check .",
"preview": "vite preview",
"lint:staged": "lint-staged"
},
"engines": {
"node": ">=16",
"pnpm": ">=6"
},
"dependencies": {
"@element-plus/icons-vue": "2.1.0",
"@element-plus/icons-vue": "2.3.1",
"@smallwei/avue": "3.2.22",
"axios": "1.3.4",
"big.js": "6.2.1",
"crypto-js": "4.1.1",
"echarts": "5.4.1",
"element-plus": "2.3.6",
"axios": "1.7.9",
"big.js": "6.2.2",
"crypto-js": "4.2.0",
"echarts": "5.6.0",
"element-plus": "2.9.3",
"element-resize-detector": "1.2.4",
"js-base64": "3.7.5",
"lodash": "4.17.21",
"moment": "2.29.4",
"pinia": "2.0.33",
"qs": "6.11.1",
"vue": "3.2.47",
"vue-cookies": "1.8.3",
"vue-draggable-next": "2.1.1",
"vue-router": "4.1.6"
"moment": "2.30.1",
"pinia": "2.3.0",
"qs": "6.14.0",
"vue": "3.5.13",
"vue-cookies": "1.8.5",
"vue-draggable-next": "2.2.1",
"vue-router": "4.5.0"
},
"devDependencies": {
"@babel/eslint-parser": "7.21.3",
"@vitejs/plugin-vue": "4.1.0",
"eslint": "8.38.0",
"eslint-config-standard": "17.0.0",
"eslint-plugin-import": "2.27.5",
"eslint-plugin-n": "15.7.0",
"eslint-plugin-promise": "6.1.1",
"eslint-plugin-vue": "9.10.0",
"eslint-plugin-vue-scoped-css": "2.4.0",
"lint-staged": "13.2.2",
"sass": "1.59.3",
"unplugin-auto-import": "0.15.1",
"unplugin-vue-components": "0.24.1",
"vite": "4.3.9",
"vite-plugin-compression": "0.5.1",
"vite-plugin-eslint": "1.8.1",
"vite-plugin-svg-icons": "2.0.1",
"vue-eslint-parser": "9.1.1"
"@vitejs/plugin-vue": "6.0.5",
"lint-staged": "15.3.0",
"oxfmt": "0.41.0",
"oxlint": "1.56.0",
"sass": "1.83.4",
"sortablejs": "1.15.6",
"unplugin-auto-import": "19.0.0",
"unplugin-vue-components": "28.0.0",
"vite": "8.0.1",
"vite-plugin-compression2": "2.5.3",
"vite-plugin-svg-icons": "2.0.1"
},
"lint-staged": {
"*.{js,vue}": [
"eslint --fix"
"src/**/*.{js,vue}": [
"oxlint --fix",
"oxfmt"
],
"src/**/*.{css,scss}": [
"oxfmt"
],
"*.{json,md,html,yml,yaml}": [
"oxfmt"
]
},
"engines": {
"node": "^20.19.0 || >=22.12.0",
"pnpm": ">=7"
}
}
+18 -18
View File
@@ -1,3 +1,6 @@
@use "sass:color";
@use "./variables" as *;
*,
*:before,
*:after {
@@ -11,11 +14,11 @@ body {
background-color: #fff;
}
a {
color: mix(#fff, $--color-primary, 20%);
color: color.mix(#fff, $color-primary, 20%);
text-decoration: none;
&:focus,
&:hover {
color: $--color-primary;
color: $color-primary;
text-decoration: underline;
}
}
@@ -132,7 +135,7 @@ img {
z-index: 1030;
height: 50px;
box-shadow: 0 2px 4px rgba(0, 0, 0, .08);
background-color: $navbar--background-color;
background-color: $navbar-background-color;
&--inverse {
.site-navbar__body {
@@ -145,12 +148,12 @@ img {
&:focus,
&:hover {
color: #fff;
background-color: mix(#000, $navbar--background-color, 15%);
background-color: color.mix(#000, $navbar-background-color, 15%);
}
}
> .el-menu-item.is-active,
> .el-submenu.is-active > .el-submenu__title {
border-bottom-color: mix(#fff, $navbar--background-color, 85%);
border-bottom-color: color.mix(#fff, $navbar-background-color, 85%);
}
.el-menu-item i,
.el-submenu__title i,
@@ -159,7 +162,7 @@ img {
}
}
.el-menu--popup-bottom-start {
background-color: $navbar--background-color;
background-color: $navbar-background-color;
}
}
@@ -266,26 +269,26 @@ img {
&--dark,
&--dark-popper {
background-color: $sidebar--background-color-dark;
background-color: $sidebar-background-color-dark;
.site-sidebar__menu.el-menu,
> .el-menu--popup {
background-color: $sidebar--background-color-dark;
background-color: $sidebar-background-color-dark;
.el-menu-item,
.el-submenu > .el-submenu__title {
color: $sidebar--color-text-dark;
color: $sidebar-color-text-dark;
&:focus,
&:hover {
color: mix(#fff, $sidebar--color-text-dark, 50%);
background-color: mix(#fff, $sidebar--background-color-dark, 2.5%);
color: color.mix(#fff, $sidebar-color-text-dark, 50%);
background-color: color.mix(#fff, $sidebar-background-color-dark, 2.5%);
}
}
.el-menu,
.el-submenu.is-opened {
background-color: mix(#000, $sidebar--background-color-dark, 15%);
background-color: color.mix(#000, $sidebar-background-color-dark, 15%);
}
.el-menu-item.is-active,
.el-submenu.is-active > .el-submenu__title {
color: mix(#fff, $sidebar--color-text-dark, 80%);
color: color.mix(#fff, $sidebar-color-text-dark, 80%);
}
}
}
@@ -322,10 +325,7 @@ img {
padding-top: 50px;
margin-left: 230px;
min-height: 100%;
background: $content--background-color;
}
&--tabs {
padding: 55px 0 0;
background: $content-background-color;
}
> .el-tabs {
> .el-tabs__header {
@@ -355,7 +355,7 @@ img {
padding: 0 12px;
font-size: 16px;
line-height: 40px;
background-color: $content--background-color;
background-color: $content-background-color;
cursor: pointer;
.el-icon--right {
margin-left: 0;
+6 -6
View File
@@ -1,13 +1,13 @@
// 站点主色
// tips: 要达到整站主题修改效果, 请确保[$--color-primary]站点主色与[/src/element-ui-theme/index.js]文件中[import './element-[#17B3A3]/index.css']当前主题色一致
$--color-primary: #02A1E9;
// tips: 要达到整站主题修改效果, 请确保[$color-primary]站点主色与[/src/element-ui-theme/index.js]文件中[import './element-[#17B3A3]/index.css']当前主题色一致
$color-primary: #02A1E9;
// Navbar
$navbar--background-color: $--color-primary;
$navbar-background-color: $color-primary;
// Sidebar
$sidebar--background-color-dark: #263238;
$sidebar--color-text-dark: #8a979e;
$sidebar-background-color-dark: #263238;
$sidebar-color-text-dark: #8a979e;
// Content
$content--background-color: #f1f4f5;
$content-background-color: #f1f4f5;
+2 -3
View File
@@ -1,3 +1,2 @@
@import "normalize"; // api: https://github.com/necolas/normalize.css/
@import "variables"; // 站点变量
@import "base";
@use "./normalize"; // api: https://github.com/necolas/normalize.css/
@use "./base";
+1 -1
View File
@@ -6,7 +6,7 @@ import moment from 'moment'
import 'element-plus/dist/index.css'
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
import router from '@/router'
import locale from 'element-plus/lib/locale/lang/zh-cn'
import locale from 'element-plus/es/locale/lang/zh-cn'
import Avue from '@smallwei/avue'
import '@smallwei/avue/lib/index.css'
-1
View File
@@ -24,7 +24,6 @@ const globalRoutes = [
export const mainRoutes = {
path: '/',
component: Layout,
name: 'home',
redirect: '/home',
children: [
{
+8 -8
View File
@@ -1,3 +1,6 @@
@use "sass:color";
@use "./variables" as *;
*,
*:before,
*:after {
@@ -11,11 +14,11 @@ body {
background-color: #fff;
}
a {
color: mix(#fff, $--color-primary, 20%);
color: color.mix(#fff, $color-primary, 20%);
text-decoration: none;
&:focus,
&:hover {
color: $--color-primary;
color: $color-primary;
text-decoration: underline;
}
}
@@ -108,7 +111,7 @@ img {
z-index: 1030;
height: 50px;
// box-shadow: 0 2px 4px rgba(0, 0, 0, .08);
background-color: $navbar--background-color;
background-color: $navbar-background-color;
&__header {
position: relative;
@@ -199,7 +202,7 @@ img {
&--dark,
&--dark-popper {
background-color: $sidebar--background-color-dark;
background-color: $sidebar-background-color-dark;
}
&__inner {
position: relative;
@@ -235,10 +238,7 @@ img {
padding-top: 50px;
margin-left: 230px;
min-height: 100%;
background: $content--background-color;
}
&--tabs {
padding: 55px 0 0;
background: $content-background-color;
}
}
+5 -5
View File
@@ -1,14 +1,14 @@
// css 变量
$--color-primary: #155BD4;
$color-primary: #155BD4;
// Navbar
$navbar--background-color: $--color-primary;
$navbar-background-color: $color-primary;
// Sidebar
$sidebar--background-color-dark: #263238;
$sidebar--color-text-dark: #8a979e;
$sidebar-background-color-dark: #263238;
$sidebar-color-text-dark: #8a979e;
// Content
$content--background-color: #f1f4f5;
$content-background-color: #f1f4f5;
+3 -4
View File
@@ -1,7 +1,6 @@
@import "_normalize"; // api: https://github.com/necolas/normalize.css/
@import "_variables";
@import "_base";
@import "@/styles/element-variables.scss";
@use "./normalize"; // api: https://github.com/necolas/normalize.css/
@use "./base";
@use "./element-variables";
.element-error-message-zindex {
z-index:3000 !important;
+3
View File
@@ -555,5 +555,8 @@ const getSoldExcel = () => {
margin: 50px 0;
color: #999;
}
.el-select {
width: 200px
}
}
</style>
@@ -92,7 +92,7 @@ const dataForm = ref({
status: 1,
isDefault: null,
prodCount: null,
seq: null,
seq: 0,
style: 0
})
@@ -120,6 +120,9 @@ const dataFormRef = ref(null)
* 表单提交
*/
const onSubmit = Debounce(() => {
if (!dataForm.value.seq) {
dataForm.value.seq = 0
}
dataFormRef.value?.validate((valid) => {
if (valid) {
http({
-15
View File
@@ -1,15 +0,0 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"sourceMap": true,
"skipLibCheck": true
},
"exclude": [
"node_modules"
],
"include": [
"src/auto-import/components.d.ts",
"src/auto-import/imports.d.ts"
]
}
+96
View File
@@ -0,0 +1,96 @@
/* eslint-disable */
/* prettier-ignore */
// @ts-nocheck
// noinspection JSUnusedGlobalSymbols
// Generated by unplugin-auto-import
// biome-ignore lint: disable
export {}
declare global {
const Debounce: typeof import('../../src/utils/debounce.js')['Debounce']
const EffectScope: typeof import('vue')['EffectScope']
const checkFileUrl: typeof import('../../src/utils/index.js')['checkFileUrl']
const clearLoginInfo: typeof import('../../src/utils/index.js')['clearLoginInfo']
const computed: typeof import('vue')['computed']
const createApp: typeof import('vue')['createApp']
const customRef: typeof import('vue')['customRef']
const defineAsyncComponent: typeof import('vue')['defineAsyncComponent']
const defineComponent: typeof import('vue')['defineComponent']
const effectScope: typeof import('vue')['effectScope']
const encrypt: typeof import('../../src/utils/crypto.js')['encrypt']
const getCurrentInstance: typeof import('vue')['getCurrentInstance']
const getCurrentScope: typeof import('vue')['getCurrentScope']
const getUUID: typeof import('../../src/utils/index.js')['getUUID']
const h: typeof import('vue')['h']
const http: typeof import('../../src/utils/http.js')['default']
const idList: typeof import('../../src/utils/index.js')['idList']
const inject: typeof import('vue')['inject']
const isAuth: typeof import('../../src/utils/index.js')['isAuth']
const isEmail: typeof import('../../src/utils/validate.js')['isEmail']
const isMobile: typeof import('../../src/utils/validate.js')['isMobile']
const isPhone: typeof import('../../src/utils/validate.js')['isPhone']
const isProxy: typeof import('vue')['isProxy']
const isQq: typeof import('../../src/utils/validate.js')['isQq']
const isReactive: typeof import('vue')['isReactive']
const isReadonly: typeof import('vue')['isReadonly']
const isRef: typeof import('vue')['isRef']
const isURL: typeof import('../../src/utils/validate.js')['isURL']
const markRaw: typeof import('vue')['markRaw']
const nextTick: typeof import('vue')['nextTick']
const onActivated: typeof import('vue')['onActivated']
const onBeforeMount: typeof import('vue')['onBeforeMount']
const onBeforeRouteLeave: typeof import('vue-router')['onBeforeRouteLeave']
const onBeforeRouteUpdate: typeof import('vue-router')['onBeforeRouteUpdate']
const onBeforeUnmount: typeof import('vue')['onBeforeUnmount']
const onBeforeUpdate: typeof import('vue')['onBeforeUpdate']
const onDeactivated: typeof import('vue')['onDeactivated']
const onErrorCaptured: typeof import('vue')['onErrorCaptured']
const onMounted: typeof import('vue')['onMounted']
const onRenderTracked: typeof import('vue')['onRenderTracked']
const onRenderTriggered: typeof import('vue')['onRenderTriggered']
const onScopeDispose: typeof import('vue')['onScopeDispose']
const onServerPrefetch: typeof import('vue')['onServerPrefetch']
const onUnmounted: typeof import('vue')['onUnmounted']
const onUpdated: typeof import('vue')['onUpdated']
const onWatcherCleanup: typeof import('vue')['onWatcherCleanup']
const provide: typeof import('vue')['provide']
const reactive: typeof import('vue')['reactive']
const readonly: typeof import('vue')['readonly']
const ref: typeof import('vue')['ref']
const resolveComponent: typeof import('vue')['resolveComponent']
const scoreProdStore: typeof import('../../src/stores/prod.js')['scoreProdStore']
const shallowReactive: typeof import('vue')['shallowReactive']
const shallowReadonly: typeof import('vue')['shallowReadonly']
const shallowRef: typeof import('vue')['shallowRef']
const toRaw: typeof import('vue')['toRaw']
const toRef: typeof import('vue')['toRef']
const toRefs: typeof import('vue')['toRefs']
const toValue: typeof import('vue')['toValue']
const treeDataTranslate: typeof import('../../src/utils/index.js')['treeDataTranslate']
const triggerRef: typeof import('vue')['triggerRef']
const unitOption: typeof import('../../src/utils/unitOption.js')['unitOption']
const unref: typeof import('vue')['unref']
const uploadFile: typeof import('../../src/utils/http.js')['uploadFile']
const useAttrs: typeof import('vue')['useAttrs']
const useCommonStore: typeof import('../../src/stores/common.js')['useCommonStore']
const useCssModule: typeof import('vue')['useCssModule']
const useCssVars: typeof import('vue')['useCssVars']
const useId: typeof import('vue')['useId']
const useLink: typeof import('vue-router')['useLink']
const useModel: typeof import('vue')['useModel']
const useRoute: typeof import('vue-router')['useRoute']
const useRouter: typeof import('vue-router')['useRouter']
const useSlots: typeof import('vue')['useSlots']
const useTemplateRef: typeof import('vue')['useTemplateRef']
const useUserStore: typeof import('../../src/stores/user.js')['useUserStore']
const validNoEmptySpace: typeof import('../../src/utils/validate.js')['validNoEmptySpace']
const watch: typeof import('vue')['watch']
const watchEffect: typeof import('vue')['watchEffect']
const watchPostEffect: typeof import('vue')['watchPostEffect']
const watchSyncEffect: typeof import('vue')['watchSyncEffect']
}
// for type re-export
declare global {
// @ts-ignore
export type { Component, ComponentPublicInstance, ComputedRef, DirectiveBinding, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, MaybeRef, MaybeRefOrGetter, VNode, WritableComputedRef } from 'vue'
import('vue')
}
+111 -45
View File
@@ -1,57 +1,118 @@
import { defineConfig, loadEnv } from 'vite'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
import viteCompression from 'vite-plugin-compression'
import { compression } from 'vite-plugin-compression2'
// eslint
import eslintPlugin from 'vite-plugin-eslint'
// 开发态预扫描全部业务源码入口,尽量在冷启动阶段就发现懒路由里的第三方依赖。
const optimizeDepEntries = [
'index.html',
'src/main.js',
'src/**/*.js',
'src/**/*.vue',
'!dist/**',
'!types/**'
]
// 显式预构建插件动态注入的深层依赖,避免首次访问新页面时才触发依赖重优化并整页刷新。
const optimizeDepIncludes = [
'element-plus/es/components/**',
'element-plus/es/components/**/style/css'
]
// 自动组件扫描时,排除仅供容器组件内部手动引用的私有子组件目录。
const componentGlobs = [
'src/components/**/*.vue',
'!src/components/decorate-dialog-select/components/**/*.vue'
]
// 预先记录 Element Plus 图标组件名,供自动按需解析使用。
const elementPlusIconNames = new Set(Object.keys(ElementPlusIconsVue))
/**
* 解析第三方依赖的分包名称
* @param {String} moduleId 模块路径
* @returns {String|null} 分包名称
*/
function resolveVendorChunkName(moduleId) {
// 统一路径分隔符,避免 Windows 反斜杠路径导致分包命名逻辑失效。
const normalizedModuleId = moduleId.replace(/\\/g, '/')
// 只对第三方依赖做分包命名,业务代码继续走 Vite 默认拆分策略。
if (!normalizedModuleId.includes('node_modules')) {
return null
}
// 兼容 pnpm 的物理目录结构,保持历史产物命名规则稳定。
if (normalizedModuleId.includes('.pnpm/')) {
return normalizedModuleId.split('.pnpm/')[1].split('/')[0].toString()
}
// 兼容普通 node_modules 目录结构,避免不同包管理方式下 chunk 名称漂移。
if (normalizedModuleId.includes('node_modules/')) {
return normalizedModuleId.split('node_modules/')[1].split('/')[0].toString()
}
return 'vendor'
}
/**
* 解析 Element Plus 图标组件
* @param {String} componentName 组件名称
* @returns {{name: String, from: String}|null} 自动导入配置
*/
function resolveElementPlusIcon(componentName) {
// 只有命中 Element Plus 图标导出名时,才按需导入对应图标组件。
if (elementPlusIconNames.has(componentName)) {
return {
name: componentName,
from: '@element-plus/icons-vue'
}
}
return null
}
// https://vitejs.dev/config/
export default defineConfig(({ command })=> {
export default defineConfig(() => {
return {
optimizeDeps: {
// 扩大开发态依赖扫描范围,提前覆盖懒加载页面里的直接依赖导入。
entries: optimizeDepEntries,
// 显式纳入插件运行时生成的 Element Plus 深层导入,避免访问新路由时补优化触发 reload。
include: optimizeDepIncludes
},
plugins: [
vue(),
createSvgIconsPlugin({
iconDirs: [path.resolve(process.cwd(), 'src/icons/svg')],
symbolId: 'icon-[dir]-[name]'
}),
// 自动引入内容
// 自动引入组合式 API、路由 API 以及 Element Plus 指令/方法。
AutoImport({
imports: [
'vue',
'vue-router'
],
dirs: [
'src/hooks/**',
'src/stores/**',
'src/utils/**'
],
resolvers: command === 'build' ? [ElementPlusResolver()] : [],
dts: 'src/auto-import/imports.d.ts',
eslintrc: {
enabled: false
}
imports: ['vue', 'vue-router'],
dirs: ['src/hooks/**', 'src/stores/**', 'src/utils/**'],
// 开发态和生产态统一走同一套 Element Plus 解析链路,减少两边行为差异。
resolvers: [ElementPlusResolver()],
// 将自动生成的声明文件移出 src,避免开发态写入声明时触发页面整刷。
dts: 'types/auto-import/imports.d.ts'
}),
// 自动引入组件
// 自动引入业务组件与 Element Plus 组件。
Components({
dirs: [
'src/components'
],
resolvers: command === 'build' ? [ElementPlusResolver()] : [],
dts: 'src/auto-import/components.d.ts'
// 使用精确 globs 控制自动注册范围,避免内部私有子组件参与全局组件命名。
globs: componentGlobs,
// 同时补齐 Element Plus 图标的按需注册,替代 main.js 里的整包全局注册。
resolvers: [resolveElementPlusIcon, ElementPlusResolver()],
// 将自动生成的组件声明移出 src,减少首次访问新页面时的全量刷新概率。
dts: 'types/auto-import/components.d.ts'
}),
// 对大于 1k 的文件进行压缩
viteCompression({
threshold: 1000,
// 对大于 1 KB 的静态资源生成 gzip 预压缩文件。
compression({
threshold: 1024,
algorithms: ['gzip']
})
].concat(
// eslint
command !== 'build' ? [eslintPlugin({ include: ['src/**/*.js', 'src/**/*.vue', 'src/*.js', 'src/*.vue'] })] : []
),
],
server: {
host: true,
port: 9527,
@@ -64,27 +125,32 @@ export default defineConfig(({ command })=> {
}
},
build: {
base: './',
rollupOptions: {
// 静态资源分类打包
rolldownOptions: {
// 静态资源分类打包。
output: {
chunkFileNames: 'static/js/[name]-[hash].js',
entryFileNames: 'static/js/[name]-[hash].js',
assetFileNames: 'static/[ext]/[name]-[hash].[ext]',
// 静态资源分拆打包
manualChunks (id) {
if (id.includes('node_modules')) {
if (id.toString().indexOf('.pnpm/') !== -1) {
return id.toString().split('.pnpm/')[1].split('/')[0].toString();
} else if (id.toString().indexOf('node_modules/') !== -1) {
return id.toString().split('node_modules/')[1].split('/')[0].toString();
// 使用 Rolldown 的 codeSplitting 配置替代旧链路中的 manualChunks 写法。
codeSplitting: {
groups: [
{
// 动态计算第三方依赖的 chunk 名称,延续原有按包拆分的缓存策略。
name(moduleId) {
return resolveVendorChunkName(moduleId)
},
// 仅捕获第三方依赖模块,避免业务代码被强行归并到 vendor chunk。
test: /node_modules[\\/]/
}
}
]
}
}
},
sourcemap: false,
target: 'es2015',
// 使用 Vite 8 默认的 Oxc 压缩链路,避免引入额外压缩依赖。
minify: 'oxc',
// 保留对超大共享库的提醒,同时减少后台项目常规 chunk 的误报。
chunkSizeWarningLimit: 700,
reportCompressedSize: false
}
}