feat: 功能优化
This commit is contained in:
@@ -69,7 +69,15 @@
|
|||||||
"Bash(npm run)",
|
"Bash(npm run)",
|
||||||
"Skill(plan)",
|
"Skill(plan)",
|
||||||
"Skill(plan:*)",
|
"Skill(plan:*)",
|
||||||
"Bash(py:*)"
|
"Bash(py:*)",
|
||||||
|
"mcp__firecrawl__firecrawl_search",
|
||||||
|
"mcp__firecrawl__firecrawl_scrape",
|
||||||
|
"Bash(winget install:*)",
|
||||||
|
"mcp__context7__resolve-library-id",
|
||||||
|
"mcp__context7__query-docs",
|
||||||
|
"Bash(netstat:*)",
|
||||||
|
"Bash(npm run dev)",
|
||||||
|
"Bash(curl:*)"
|
||||||
],
|
],
|
||||||
"deny": [],
|
"deny": [],
|
||||||
"ask": []
|
"ask": []
|
||||||
|
|||||||
@@ -55,6 +55,7 @@
|
|||||||
"tailwindcss": "^4.1.14",
|
"tailwindcss": "^4.1.14",
|
||||||
"typescript": "^5.7.3",
|
"typescript": "^5.7.3",
|
||||||
"vite": "^7.1.7",
|
"vite": "^7.1.7",
|
||||||
|
"vite-plugin-compression2": "^2.4.0",
|
||||||
"vite-plugin-vue-devtools": "^8.0.2",
|
"vite-plugin-vue-devtools": "^8.0.2",
|
||||||
"vue-tsc": "^2.1.28"
|
"vue-tsc": "^2.1.28"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,106 +1,125 @@
|
|||||||
import { message, Modal } from 'ant-design-vue'
|
import { message, Modal } from 'ant-design-vue'
|
||||||
|
|
||||||
|
// 配置常量
|
||||||
|
const API_SUCCESS_CODE = 0
|
||||||
|
const DOWNLOAD_INTERVAL = 500
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 任务操作通用逻辑 Composable
|
* 任务操作通用逻辑 Composable
|
||||||
* @param {Object} apis - API 对象,包含 deleteApi, cancelApi, retryApi, getSignedUrlsApi
|
*
|
||||||
* @param {Function} onSuccess - 操作成功后的回调函数
|
* @param {Object} apiHandlers - API 处理器对象
|
||||||
* @returns {Object} 操作方法
|
* @param {Function} apiHandlers.deleteApi - 删除任务的 API 函数 (id) => Promise<void>
|
||||||
|
* @param {Function} [apiHandlers.cancelApi] - 取消任务的 API 函数 (id) => Promise<void>
|
||||||
|
* @param {Function} [apiHandlers.retryApi] - 重试任务的 API 函数 (id) => Promise<void>
|
||||||
|
* @param {Function} [apiHandlers.getSignedUrlsApi] - 获取签名URL的 API 函数 (taskId) => Promise<{code: number, data: string[]}>
|
||||||
|
* @param {Function} [onSuccess] - 操作成功后的回调函数 () => void
|
||||||
|
* @returns {Object} 操作方法集合
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```javascript
|
||||||
|
* const { handleDelete, handleCancel, handleRetry, handleBatchDownload, handlePreview } = useTaskOperations({
|
||||||
|
* deleteApi: (id) => taskApi.delete(id),
|
||||||
|
* cancelApi: (id) => taskApi.cancel(id),
|
||||||
|
* retryApi: (id) => taskApi.retry(id),
|
||||||
|
* getSignedUrlsApi: (taskId) => taskApi.getSignedUrls(taskId)
|
||||||
|
* }, () => {
|
||||||
|
* // 刷新列表
|
||||||
|
* fetchTasks()
|
||||||
|
* })
|
||||||
|
* ```
|
||||||
*/
|
*/
|
||||||
export function useTaskOperations(apis, onSuccess) {
|
export function useTaskOperations(apiHandlers, onSuccess) {
|
||||||
const { deleteApi, cancelApi, retryApi, getSignedUrlsApi } = apis
|
if (!apiHandlers || typeof apiHandlers !== 'object') {
|
||||||
|
throw new Error('apiHandlers must be an object')
|
||||||
|
}
|
||||||
|
|
||||||
// 删除任务
|
if (!apiHandlers.deleteApi || typeof apiHandlers.deleteApi !== 'function') {
|
||||||
const handleDelete = (id) => {
|
throw new Error('deleteApi is required and must be a function')
|
||||||
|
}
|
||||||
|
|
||||||
|
const {
|
||||||
|
deleteApi,
|
||||||
|
cancelApi,
|
||||||
|
retryApi,
|
||||||
|
getSignedUrlsApi
|
||||||
|
} = apiHandlers
|
||||||
|
|
||||||
|
// 通用模态框确认
|
||||||
|
function confirmModal({ title, content, okType = 'primary', onOk }) {
|
||||||
Modal.confirm({
|
Modal.confirm({
|
||||||
title: '确认删除',
|
title,
|
||||||
content: '确定删除这个任务吗?删除后无法恢复。',
|
content,
|
||||||
okText: '确认',
|
okText: '确认',
|
||||||
cancelText: '取消',
|
cancelText: '取消',
|
||||||
okType: 'danger',
|
okType,
|
||||||
onOk: async () => {
|
onOk: async () => {
|
||||||
try {
|
try {
|
||||||
await deleteApi(id)
|
await onOk()
|
||||||
message.success('删除成功')
|
|
||||||
onSuccess && onSuccess()
|
onSuccess && onSuccess()
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('删除任务失败:', error)
|
message.error('操作失败')
|
||||||
message.error('删除失败')
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 执行 API 操作并显示成功消息
|
||||||
|
async function executeApiOperation(apiFn, successMessage) {
|
||||||
|
await apiFn()
|
||||||
|
message.success(successMessage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除任务
|
||||||
|
function deleteTask(id) {
|
||||||
|
confirmModal({
|
||||||
|
title: '确认删除',
|
||||||
|
content: '确定删除这个任务吗?删除后无法恢复。',
|
||||||
|
okType: 'danger',
|
||||||
|
onOk: () => executeApiOperation(() => deleteApi(id), '删除成功')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// 取消任务
|
// 取消任务
|
||||||
const handleCancel = (id) => {
|
function cancelTask(id) {
|
||||||
Modal.confirm({
|
confirmModal({
|
||||||
title: '确认取消',
|
title: '确认取消',
|
||||||
content: '确定要取消这个任务吗?',
|
content: '确定要取消这个任务吗?',
|
||||||
okText: '确认',
|
onOk: () => executeApiOperation(() => cancelApi(id), '已取消任务')
|
||||||
cancelText: '取消',
|
|
||||||
onOk: async () => {
|
|
||||||
try {
|
|
||||||
await cancelApi(id)
|
|
||||||
message.success('已取消任务')
|
|
||||||
onSuccess && onSuccess()
|
|
||||||
} catch (error) {
|
|
||||||
console.error('取消任务失败:', error)
|
|
||||||
message.error('操作失败')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 重试任务
|
// 重试任务
|
||||||
const handleRetry = (id) => {
|
function retryTask(id) {
|
||||||
Modal.confirm({
|
confirmModal({
|
||||||
title: '确认重试',
|
title: '确认重试',
|
||||||
content: '确定要重新生成这个任务吗?',
|
content: '确定要重新生成这个任务吗?',
|
||||||
okText: '确认',
|
onOk: () => executeApiOperation(() => retryApi(id), '已重新提交任务')
|
||||||
cancelText: '取消',
|
|
||||||
onOk: async () => {
|
|
||||||
try {
|
|
||||||
await retryApi(id)
|
|
||||||
message.success('已重新提交任务')
|
|
||||||
onSuccess && onSuccess()
|
|
||||||
} catch (error) {
|
|
||||||
console.error('重试任务失败:', error)
|
|
||||||
message.error('操作失败')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 批量删除
|
// 批量删除
|
||||||
const handleBatchDelete = async (ids, deleteApiFn) => {
|
async function batchDeleteTasks(ids, deleteApiFn) {
|
||||||
if (!ids || ids.length === 0) {
|
if (!ids || ids.length === 0) {
|
||||||
message.warning('请选择要删除的任务')
|
message.warning('请选择要删除的任务')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
Modal.confirm({
|
confirmModal({
|
||||||
title: '确认批量删除',
|
title: '确认批量删除',
|
||||||
content: `确定要删除选中的 ${ids.length} 个任务吗?删除后无法恢复。`,
|
content: `确定要删除选中的 ${ids.length} 个任务吗?删除后无法恢复。`,
|
||||||
okText: '确认',
|
|
||||||
cancelText: '取消',
|
|
||||||
okType: 'danger',
|
okType: 'danger',
|
||||||
onOk: async () => {
|
onOk: async () => {
|
||||||
try {
|
const deleteFn = deleteApiFn || deleteApi
|
||||||
const deleteFn = deleteApiFn || deleteApi
|
for (const id of ids) {
|
||||||
for (const id of ids) {
|
await deleteFn(id)
|
||||||
await deleteFn(id)
|
|
||||||
}
|
|
||||||
message.success(`成功删除 ${ids.length} 个任务`)
|
|
||||||
onSuccess && onSuccess()
|
|
||||||
} catch (error) {
|
|
||||||
console.error('批量删除失败:', error)
|
|
||||||
message.error('批量删除失败')
|
|
||||||
}
|
}
|
||||||
|
message.success(`成功删除 ${ids.length} 个任务`)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 下载单个文件
|
// 下载单个文件
|
||||||
const handleDownload = (url, filename = 'download') => {
|
function downloadFile(url, filename = 'download') {
|
||||||
const link = document.createElement('a')
|
const link = document.createElement('a')
|
||||||
link.href = url
|
link.href = url
|
||||||
link.download = filename
|
link.download = filename
|
||||||
@@ -110,66 +129,67 @@ export function useTaskOperations(apis, onSuccess) {
|
|||||||
document.body.removeChild(link)
|
document.body.removeChild(link)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 批量下载
|
// 获取签名URL
|
||||||
const handleBatchDownload = async (urls, getSignedUrlsApi, taskId) => {
|
async function fetchSignedUrl(getSignedUrlsApi, taskId) {
|
||||||
if (!urls || urls.length === 0) {
|
const res = await getSignedUrlsApi(taskId)
|
||||||
message.warning('没有可下载的文件')
|
if (res.code === API_SUCCESS_CODE && res.data) {
|
||||||
return
|
return res.data
|
||||||
}
|
}
|
||||||
|
throw new Error('获取签名URL失败')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 批量下载
|
||||||
|
async function batchDownload(urls, getSignedUrlsApi, taskId) {
|
||||||
try {
|
try {
|
||||||
message.loading('正在获取下载链接...', 0)
|
message.loading('正在准备下载...', 0)
|
||||||
let downloadUrls = urls
|
let downloadUrls = urls
|
||||||
|
|
||||||
// 如果需要获取签名URL
|
// 如果需要获取签名URL
|
||||||
if (getSignedUrlsApi && taskId) {
|
if (getSignedUrlsApi && taskId) {
|
||||||
const res = await getSignedUrlsApi(taskId)
|
downloadUrls = await fetchSignedUrl(getSignedUrlsApi, taskId)
|
||||||
if (res.code === 0 && res.data) {
|
}
|
||||||
downloadUrls = res.data
|
|
||||||
} else {
|
// 检查下载链接
|
||||||
message.warning('获取下载链接失败')
|
if (!downloadUrls || downloadUrls.length === 0) {
|
||||||
return
|
message.warning('没有可下载的文件')
|
||||||
}
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
message.destroy()
|
message.destroy()
|
||||||
message.loading('正在准备下载...', 0)
|
message.loading('正在下载文件...', 0)
|
||||||
|
|
||||||
// 逐个触发下载,避免浏览器阻止多个弹窗
|
// 逐个触发下载,避免浏览器阻止多个弹窗
|
||||||
downloadUrls.forEach((url, index) => {
|
downloadUrls.forEach((url, index) => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
handleDownload(url)
|
downloadFile(url)
|
||||||
}, index * 500) // 每个下载间隔500ms
|
}, index * DOWNLOAD_INTERVAL)
|
||||||
})
|
})
|
||||||
|
|
||||||
message.destroy()
|
message.destroy()
|
||||||
message.success(`已触发 ${downloadUrls.length} 个文件的下载`)
|
message.success(`已触发 ${downloadUrls.length} 个文件的下载`)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('批量下载失败:', error)
|
|
||||||
message.destroy()
|
message.destroy()
|
||||||
message.error('获取下载链接失败')
|
message.error('下载失败,请稍后重试')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取签名URL
|
// 获取单个签名URL
|
||||||
const getSignedUrl = async (getSignedUrlsApi, taskId, index) => {
|
async function getSignedUrl(getSignedUrlsApi, taskId, index) {
|
||||||
try {
|
try {
|
||||||
const res = await getSignedUrlsApi(taskId)
|
const res = await getSignedUrlsApi(taskId)
|
||||||
if (res.code === 0 && res.data && res.data[index]) {
|
if (res.code === API_SUCCESS_CODE && res.data && res.data[index]) {
|
||||||
return res.data[index]
|
return res.data[index]
|
||||||
} else {
|
|
||||||
message.warning('获取预览链接失败')
|
|
||||||
return null
|
|
||||||
}
|
}
|
||||||
|
message.warning('获取预览链接失败')
|
||||||
|
return null
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('获取签名URL失败:', error)
|
|
||||||
message.error('获取预览链接失败')
|
message.error('获取预览链接失败')
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 预览
|
// 预览文件
|
||||||
const handlePreview = async (getSignedUrlsApi, taskId, index) => {
|
async function previewFile(getSignedUrlsApi, taskId, index) {
|
||||||
try {
|
try {
|
||||||
message.loading('正在获取预览链接...', 0)
|
message.loading('正在获取预览链接...', 0)
|
||||||
const url = await getSignedUrl(getSignedUrlsApi, taskId, index)
|
const url = await getSignedUrl(getSignedUrlsApi, taskId, index)
|
||||||
@@ -179,7 +199,6 @@ export function useTaskOperations(apis, onSuccess) {
|
|||||||
window.open(url, '_blank')
|
window.open(url, '_blank')
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('预览失败:', error)
|
|
||||||
message.destroy()
|
message.destroy()
|
||||||
message.error('预览失败')
|
message.error('预览失败')
|
||||||
}
|
}
|
||||||
@@ -187,17 +206,17 @@ export function useTaskOperations(apis, onSuccess) {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
// 基本操作
|
// 基本操作
|
||||||
handleDelete,
|
handleDelete: deleteTask,
|
||||||
handleCancel,
|
handleCancel: cancelTask,
|
||||||
handleRetry,
|
handleRetry: retryTask,
|
||||||
|
|
||||||
// 批量操作
|
// 批量操作
|
||||||
handleBatchDelete,
|
handleBatchDelete: batchDeleteTasks,
|
||||||
handleBatchDownload,
|
handleBatchDownload: batchDownload,
|
||||||
|
|
||||||
// 下载和预览
|
// 下载和预览
|
||||||
handleDownload,
|
handleDownload: downloadFile,
|
||||||
handlePreview,
|
handlePreview: previewFile,
|
||||||
getSignedUrl
|
getSignedUrl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,6 @@
|
|||||||
"moduleResolution": "bundler",
|
"moduleResolution": "bundler",
|
||||||
"allowSyntheticDefaultImports": true
|
"allowSyntheticDefaultImports": true
|
||||||
},
|
},
|
||||||
"include": ["vite.config.js"]
|
"include": ["vite.config.ts"]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,78 +0,0 @@
|
|||||||
/* eslint-env node */
|
|
||||||
import path from 'node:path'
|
|
||||||
import { defineConfig, loadEnv } from 'vite'
|
|
||||||
import { fileURLToPath, URL } from 'node:url'
|
|
||||||
import tailwindcss from '@tailwindcss/vite'
|
|
||||||
import process from 'node:process'
|
|
||||||
import vue from '@vitejs/plugin-vue'
|
|
||||||
import vueJsx from '@vitejs/plugin-vue-jsx'
|
|
||||||
import vueDevTools from 'vite-plugin-vue-devtools'
|
|
||||||
import UnoCSS from 'unocss/vite'
|
|
||||||
// import electron from 'vite-plugin-electron/simple'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Vite 配置文件
|
|
||||||
* 支持 TypeScript 和 JavaScript
|
|
||||||
* @param {Object} param0 - 配置参数
|
|
||||||
* @param {string} param0.mode - 环境模式
|
|
||||||
* @returns {import('vite').UserConfig}
|
|
||||||
*/
|
|
||||||
export default defineConfig(({ mode }) => {
|
|
||||||
const env = loadEnv(mode, process.cwd(), '')
|
|
||||||
const DEV_TOKEN = env.VITE_DEV_TOKEN || ''
|
|
||||||
const TENANT_ID = env.VITE_TENANT_ID || '1'
|
|
||||||
const API_TARGET = env.VITE_PROXY_TARGET || 'http://localhost:9900'
|
|
||||||
|
|
||||||
return {
|
|
||||||
plugins: [
|
|
||||||
vue(),
|
|
||||||
vueJsx(),
|
|
||||||
UnoCSS(),
|
|
||||||
vueDevTools(),
|
|
||||||
tailwindcss()
|
|
||||||
|
|
||||||
],
|
|
||||||
resolve: {
|
|
||||||
alias: {
|
|
||||||
'@': fileURLToPath(new URL('./src', import.meta.url)),
|
|
||||||
'@gold': fileURLToPath(new URL('../../', import.meta.url))
|
|
||||||
},
|
|
||||||
},
|
|
||||||
server: {
|
|
||||||
proxy: {
|
|
||||||
// 代理 /webApi 开头的请求
|
|
||||||
'/webApi': {
|
|
||||||
target: API_TARGET,
|
|
||||||
changeOrigin: true,
|
|
||||||
rewrite: (path) => path.replace(/^\/webApi/, ''),
|
|
||||||
configure: (proxy, options) => {
|
|
||||||
proxy.on('proxyReq', (proxyReq, req) => {
|
|
||||||
// 从客户端请求头中获取 authorization
|
|
||||||
const authHeader = req.headers?.authorization
|
|
||||||
if (authHeader) {
|
|
||||||
proxyReq.setHeader('authorization', authHeader)
|
|
||||||
} else if (DEV_TOKEN) {
|
|
||||||
// 兜底:使用环境变量中的 token
|
|
||||||
proxyReq.setHeader('authorization', `Bearer ${DEV_TOKEN}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 添加 RuoYi 租户 ID
|
|
||||||
proxyReq.setHeader('tenant-id', TENANT_ID)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
},
|
|
||||||
// OSS 代理 - 用于直传上传
|
|
||||||
'/oss': {
|
|
||||||
target: 'https://muye-ai-chat.oss-cn-hangzhou.aliyuncs.com',
|
|
||||||
changeOrigin: true,
|
|
||||||
rewrite: (path) => path.replace(/^\/oss/, ''),
|
|
||||||
headers: {
|
|
||||||
'Access-Control-Allow-Origin': '*',
|
|
||||||
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
|
|
||||||
'Access-Control-Allow-Headers': '*',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
})
|
|
||||||
117
frontend/app/web-gold/vite.config.ts
Normal file
117
frontend/app/web-gold/vite.config.ts
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
import { defineConfig, loadEnv } from 'vite'
|
||||||
|
import { fileURLToPath, URL } from 'node:url'
|
||||||
|
import tailwindcss from '@tailwindcss/vite'
|
||||||
|
import process from 'node:process'
|
||||||
|
import vue from '@vitejs/plugin-vue'
|
||||||
|
import vueJsx from '@vitejs/plugin-vue-jsx'
|
||||||
|
import vueDevTools from 'vite-plugin-vue-devtools'
|
||||||
|
import UnoCSS from 'unocss/vite'
|
||||||
|
import { compression, defineAlgorithm } from 'vite-plugin-compression2'
|
||||||
|
import zlib from 'zlib'
|
||||||
|
|
||||||
|
// 压缩配置常量
|
||||||
|
const COMPRESSION_THRESHOLD = 1024
|
||||||
|
|
||||||
|
// 环境变量默认值
|
||||||
|
const DEFAULT_ENV_VALUES = {
|
||||||
|
DEV_TOKEN: '',
|
||||||
|
TENANT_ID: '1',
|
||||||
|
API_TARGET: 'http://localhost:9900',
|
||||||
|
}
|
||||||
|
|
||||||
|
export default defineConfig(({ mode }) => {
|
||||||
|
const env = loadEnv(mode, process.cwd(), '')
|
||||||
|
const DEV_TOKEN = env.VITE_DEV_TOKEN || DEFAULT_ENV_VALUES.DEV_TOKEN
|
||||||
|
const TENANT_ID = env.VITE_TENANT_ID || DEFAULT_ENV_VALUES.TENANT_ID
|
||||||
|
const API_TARGET = env.VITE_PROXY_TARGET || DEFAULT_ENV_VALUES.API_TARGET
|
||||||
|
|
||||||
|
return {
|
||||||
|
plugins: [
|
||||||
|
vue(),
|
||||||
|
vueJsx(),
|
||||||
|
UnoCSS(),
|
||||||
|
vueDevTools(),
|
||||||
|
tailwindcss(),
|
||||||
|
// 压缩配置:同时生成 gzip 和 brotli 压缩文件
|
||||||
|
compression({
|
||||||
|
algorithms: [
|
||||||
|
defineAlgorithm('gzip', { level: 9 }),
|
||||||
|
defineAlgorithm('brotliCompress', {
|
||||||
|
params: {
|
||||||
|
[zlib.constants.BROTLI_PARAM_QUALITY]: 11
|
||||||
|
}
|
||||||
|
})
|
||||||
|
],
|
||||||
|
threshold: COMPRESSION_THRESHOLD,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
'@': fileURLToPath(new URL('./src', import.meta.url)),
|
||||||
|
'@gold': fileURLToPath(new URL('../../', import.meta.url)),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
server: {
|
||||||
|
proxy: {
|
||||||
|
'/webApi': {
|
||||||
|
target: API_TARGET,
|
||||||
|
changeOrigin: true,
|
||||||
|
rewrite: (path: string) => path.replace(/^\/webApi/, ''),
|
||||||
|
configure: (proxy: any) => {
|
||||||
|
proxy.on('proxyReq', (proxyReq: any, req: any) => {
|
||||||
|
const authHeader = req.headers?.authorization
|
||||||
|
if (authHeader) {
|
||||||
|
proxyReq.setHeader('authorization', authHeader)
|
||||||
|
} else if (DEV_TOKEN) {
|
||||||
|
proxyReq.setHeader('authorization', `Bearer ${DEV_TOKEN}`)
|
||||||
|
}
|
||||||
|
proxyReq.setHeader('tenant-id', TENANT_ID)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'/oss': {
|
||||||
|
target: 'https://muye-ai-chat.oss-cn-hangzhou.aliyuncs.com',
|
||||||
|
changeOrigin: true,
|
||||||
|
rewrite: (path: string) => path.replace(/^\/oss/, ''),
|
||||||
|
headers: {
|
||||||
|
'Access-Control-Allow-Origin': '*',
|
||||||
|
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
|
||||||
|
'Access-Control-Allow-Headers': '*',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
build: {
|
||||||
|
// 生产环境去除 console 和 debugger
|
||||||
|
esbuild: {
|
||||||
|
drop: mode === 'production' ? ['console', 'debugger'] : [],
|
||||||
|
},
|
||||||
|
// 使用 esbuild 压缩
|
||||||
|
minify: 'esbuild',
|
||||||
|
// 关闭 source map 以减小体积
|
||||||
|
sourcemap: false,
|
||||||
|
// 块大小警告阈值
|
||||||
|
chunkSizeWarningLimit: 1500,
|
||||||
|
// 浏览器兼容性目标(使用最新的广泛支持版本)
|
||||||
|
target: 'baseline-widely-available',
|
||||||
|
// Rollup 配置优化
|
||||||
|
rollupOptions: {
|
||||||
|
output: {
|
||||||
|
// 手动代码分割
|
||||||
|
manualChunks: {
|
||||||
|
// Vue 生态系统
|
||||||
|
'vue-vendor': ['vue', 'vue-router', 'pinia'],
|
||||||
|
// UI 组件库
|
||||||
|
'ui-vendor': ['ant-design-vue', '@ant-design/icons-vue'],
|
||||||
|
// 工具库
|
||||||
|
'utils': ['dayjs', 'qs', 'path-to-regexp'],
|
||||||
|
// AI 相关
|
||||||
|
'ai-sdk': ['@ai-sdk/anthropic', '@ai-sdk/openai', 'ai'],
|
||||||
|
// 文件处理
|
||||||
|
'file-tools': ['xlsx', 'xlsx-js-style'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
"github-markdown-css": "^5.8.1",
|
"github-markdown-css": "^5.8.1",
|
||||||
"localforage": "^1.10.0",
|
"localforage": "^1.10.0",
|
||||||
"unocss": "^66.5.4",
|
"unocss": "^66.5.4",
|
||||||
|
"vite-plugin-compression2": "^2.4.0",
|
||||||
"web-storage-cache": "^1.1.1"
|
"web-storage-cache": "^1.1.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user