Files
ai-kefu-admin/admin/vite.config.ts
T
浅念 7cdb4fc970 chore: 锁屏与通知组件删除(enabled:false的最终清理)
Phase 3 终审 M-1/M-2 摘入口后组件保留待决,本提交最终删除:
- art-screen-lock/ 与 art-notification/ 组件目录
- component.ts screen-lock 全局组件项、headerBar.ts notification 项
- types/config HeaderBarFeatureConfig.notification 字段、
  useHeaderBar shouldShowNotification
- art-header-bar 通知按钮/挂载/showNotice/visibleNotice/
  bodyCloseNotice 与 document 点击监听、.notice-button 样式
- components.d.ts 两条目;crypto-js 依赖全套(env.d.ts 声明/
  package.json/lockfile/optimizeDeps)——唯一消费方是锁屏
- en/zh 孤儿语言键(notice.* / lockScreen.* / topBar.user.lockScreen)
  与 mittBus openLockScreen 事件类型(无发射/订阅方)

grep 零残留;vitest 164 passed;build 通过(主 chunk 358.45→355.84 kB,
crypto-js 出预构建);auto-imports.d.ts 行尾漂移已还原。
CLAUDE.md Phase 4 清理单 6/7 结项(并补记 8/9 随 Task 5E/5D 结项)。

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-14 10:43:13 +08:00

178 lines
5.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { defineConfig, loadEnv } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'
import { fileURLToPath } from 'url'
import vueDevTools from 'vite-plugin-vue-devtools'
import viteCompression from 'vite-plugin-compression'
import Components from 'unplugin-vue-components/vite'
import AutoImport from 'unplugin-auto-import/vite'
import ElementPlus from 'unplugin-element-plus/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
import tailwindcss from '@tailwindcss/vite'
// import { visualizer } from 'rollup-plugin-visualizer'
export default ({ mode }: { mode: string }) => {
const root = process.cwd()
const env = loadEnv(mode, root)
const {
VITE_VERSION,
VITE_PORT,
VITE_BASE_URL,
VITE_API_URL,
VITE_API_PROXY_URL,
VITE_TENANT_PREVIEW_HOST
} = env
console.log(`🚀 API_URL = ${VITE_API_URL}`)
console.log(`🚀 VERSION = ${VITE_VERSION}`)
// 代理策略(后端 TenantHostMiddleware 事实源 app/platform/host_middleware.py:
// 仅 /health 精确与 /api/platform/ 前缀豁免租户 Host 解析,其余按 Host 找租户):
// - /api/platform/*:豁免前缀,changeOrigin 直转即可(Host=127.0.0.1:8018 无碍);
// - /api/public/*:品牌/头像公开端点依赖租户 Host——用 headers.Host 改写成
// VITE_TENANT_PREVIEW_HOST(种子租户域名),changeOrigin 必须为 false
// 否则 Host 会被改回目标地址使解析 404;
// - /static/*:静态资源同样过租户解析,与 /api/public 同策略。
// 注意对象键序:更长的 /api/public 前缀必须排在 /api 之前(http-proxy 按序首配命中)。
const tenantHostProxy = {
target: VITE_API_PROXY_URL,
changeOrigin: false,
headers: { Host: VITE_TENANT_PREVIEW_HOST }
}
return defineConfig({
define: {
__APP_VERSION__: JSON.stringify(VITE_VERSION)
},
base: VITE_BASE_URL,
server: {
port: Number(VITE_PORT),
proxy: {
'/api/public': { ...tenantHostProxy },
'/api': {
target: VITE_API_PROXY_URL,
changeOrigin: true
},
'/static': { ...tenantHostProxy }
},
host: true
},
// 路径别名
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url)),
'@views': resolvePath('src/views'),
'@imgs': resolvePath('src/assets/images'),
'@icons': resolvePath('src/assets/icons'),
'@utils': resolvePath('src/utils'),
'@stores': resolvePath('src/store'),
'@styles': resolvePath('src/assets/styles')
}
},
build: {
// Windows 本机 es2015 曾在 rendering chunks 阶段触发 esbuild 原生崩溃
//(退出码 0xC0000409,多次复现),改 esnext 后连续构建稳定;
// 管理后台仅面向现代浏览器,不做低版本降级。
target: 'esnext',
outDir: 'dist',
chunkSizeWarningLimit: 2000,
minify: 'terser',
terserOptions: {
compress: {
// 生产环境去除 console
drop_console: true,
// 生产环境去除 debugger
drop_debugger: true
}
},
dynamicImportVarsOptions: {
warnOnError: true,
exclude: [],
include: ['src/views/**/*.vue']
}
},
plugins: [
vue(),
tailwindcss(),
// 自动按需导入 API
AutoImport({
imports: ['vue', 'vue-router', 'pinia', '@vueuse/core'],
dts: 'src/types/import/auto-imports.d.ts',
resolvers: [ElementPlusResolver()],
eslintrc: {
enabled: true,
filepath: './.auto-import.json',
globalsPropValue: true
}
}),
// 自动按需导入组件
Components({
dts: 'src/types/import/components.d.ts',
resolvers: [ElementPlusResolver()]
}),
// 按需定制主题配置
ElementPlus({
useSource: true
}),
// 压缩
viteCompression({
verbose: false, // 是否在控制台输出压缩结果
disable: false, // 是否禁用
algorithm: 'gzip', // 压缩算法
ext: '.gz', // 压缩后的文件名后缀
threshold: 10240, // 只有大小大于该值的资源会被处理 10240B = 10KB
deleteOriginFile: false // 压缩后是否删除原文件
}),
vueDevTools()
// 打包分析
// visualizer({
// open: true,
// gzipSize: true,
// brotliSize: true,
// filename: 'dist/stats.html' // 分析图生成的文件名及路径
// }),
],
// 依赖预构建:避免运行时重复请求与转换,提升首次加载速度
optimizeDeps: {
include: [
'echarts/core',
'echarts/charts',
'echarts/components',
'echarts/renderers',
'element-plus/es',
'element-plus/es/components/*/style/css',
'element-plus/es/components/*/style/index'
]
},
css: {
preprocessorOptions: {
// sass variable and mixin
scss: {
additionalData: `
@use "@styles/core/el-light.scss" as *;
@use "@styles/core/mixin.scss" as *;
`
}
},
postcss: {
plugins: [
{
postcssPlugin: 'internal:charset-removal',
AtRule: {
charset: (atRule) => {
if (atRule.name === 'charset') {
atRule.remove()
}
}
}
}
]
}
}
})
}
function resolvePath(paths: string) {
return path.resolve(__dirname, paths)
}