feat: 初始化考培练系统项目
- 从服务器拉取完整代码 - 按框架规范整理项目结构 - 配置 Drone CI 测试环境部署 - 包含后端(FastAPI)、前端(Vue3)、管理端 技术栈: Vue3 + TypeScript + FastAPI + MySQL
This commit is contained in:
223
frontend/src/config/env.ts
Normal file
223
frontend/src/config/env.ts
Normal file
@@ -0,0 +1,223 @@
|
||||
/**
|
||||
* 环境配置管理
|
||||
*/
|
||||
|
||||
// 环境变量接口
|
||||
// Vite已提供ImportMetaEnv接口,此处仅作为文档参考
|
||||
/*
|
||||
interface ImportMetaEnv {
|
||||
// 应用配置
|
||||
readonly VITE_APP_TITLE: string
|
||||
readonly VITE_APP_VERSION: string
|
||||
readonly VITE_APP_ENV: 'development' | 'production' | 'staging'
|
||||
readonly VITE_APP_BASE_URL: string
|
||||
|
||||
// API配置
|
||||
readonly VITE_API_BASE_URL: string
|
||||
readonly VITE_API_TIMEOUT: string
|
||||
readonly VITE_USE_MOCK_DATA: string
|
||||
|
||||
// WebSocket配置
|
||||
readonly VITE_WS_BASE_URL: string
|
||||
readonly VITE_WS_RECONNECT_INTERVAL: string
|
||||
readonly VITE_WS_MAX_RECONNECT_ATTEMPTS: string
|
||||
|
||||
// 上传配置
|
||||
readonly VITE_UPLOAD_BASE_URL: string
|
||||
readonly VITE_UPLOAD_MAX_SIZE: string
|
||||
readonly VITE_UPLOAD_ALLOWED_TYPES: string
|
||||
|
||||
// 第三方服务配置
|
||||
readonly VITE_COZE_BOT_ID: string
|
||||
readonly VITE_DIFY_API_KEY: string
|
||||
|
||||
// 功能开关
|
||||
readonly VITE_ENABLE_MOCK: string
|
||||
readonly VITE_ENABLE_DEVTOOLS: string
|
||||
readonly VITE_ENABLE_ERROR_REPORTING: string
|
||||
readonly VITE_ENABLE_ANALYTICS: string
|
||||
|
||||
// 安全配置
|
||||
readonly VITE_JWT_EXPIRE_TIME: string
|
||||
readonly VITE_REFRESH_TOKEN_EXPIRE_TIME: string
|
||||
|
||||
// 性能配置
|
||||
readonly VITE_ENABLE_LAZY_LOADING: string
|
||||
readonly VITE_ENABLE_CODE_SPLITTING: string
|
||||
readonly VITE_CHUNK_SIZE_WARNING_LIMIT: string
|
||||
|
||||
// 调试配置
|
||||
readonly VITE_LOG_LEVEL: string
|
||||
readonly VITE_ENABLE_REQUEST_LOG: string
|
||||
readonly VITE_ENABLE_PERFORMANCE_LOG: string
|
||||
}
|
||||
*/
|
||||
|
||||
// ImportMeta接口扩展已由Vite提供,此处仅作为类型说明
|
||||
// interface ImportMeta {
|
||||
// readonly env: ImportMetaEnv
|
||||
// }
|
||||
|
||||
// 环境配置类
|
||||
class EnvConfig {
|
||||
// 应用配置
|
||||
public readonly APP_TITLE = import.meta.env.VITE_APP_TITLE || '考培练系统'
|
||||
public readonly APP_VERSION = import.meta.env.VITE_APP_VERSION || '1.0.0'
|
||||
public readonly APP_ENV = import.meta.env.VITE_APP_ENV || 'development'
|
||||
public readonly APP_BASE_URL = import.meta.env.VITE_APP_BASE_URL || '/'
|
||||
|
||||
// API配置
|
||||
public readonly API_BASE_URL = (() => {
|
||||
// 开发环境使用空字符串,让请求使用相对路径(通过Vite proxy转发)
|
||||
if (import.meta.env.DEV || import.meta.env.VITE_APP_ENV === 'development') {
|
||||
console.log('[开发] 使用相对路径API请求,通过Vite proxy转发')
|
||||
return ''
|
||||
}
|
||||
// 生产环境:始终使用当前访问的域名,支持多域名部署
|
||||
// 这样同一份构建可以部署到任何域名
|
||||
return window.location.origin
|
||||
})()
|
||||
public readonly API_TIMEOUT = parseInt(import.meta.env.VITE_API_TIMEOUT || '10000')
|
||||
public readonly USE_MOCK_DATA = import.meta.env.VITE_USE_MOCK_DATA === 'true'
|
||||
|
||||
// WebSocket配置
|
||||
public readonly WS_BASE_URL = (() => {
|
||||
// 开发环境
|
||||
if (import.meta.env.DEV || import.meta.env.VITE_APP_ENV === 'development') {
|
||||
const wsProtocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'
|
||||
return `${wsProtocol}//${window.location.host}`
|
||||
}
|
||||
// 生产环境:使用wss + 当前域名,支持多域名部署
|
||||
return `wss://${window.location.host}`
|
||||
})()
|
||||
public readonly WS_RECONNECT_INTERVAL = parseInt(import.meta.env.VITE_WS_RECONNECT_INTERVAL || '5000')
|
||||
public readonly WS_MAX_RECONNECT_ATTEMPTS = parseInt(import.meta.env.VITE_WS_MAX_RECONNECT_ATTEMPTS || '5')
|
||||
|
||||
// 上传配置
|
||||
public readonly UPLOAD_BASE_URL = import.meta.env.VITE_UPLOAD_BASE_URL || `${this.API_BASE_URL}/api/v1/upload`
|
||||
public readonly UPLOAD_MAX_SIZE = parseInt(import.meta.env.VITE_UPLOAD_MAX_SIZE || '15728640') // 15MB (Dify限制)
|
||||
public readonly UPLOAD_ALLOWED_TYPES = import.meta.env.VITE_UPLOAD_ALLOWED_TYPES?.split(',') || [
|
||||
'.txt', '.md', '.mdx', '.pdf', '.html', '.htm', '.xlsx', '.xls', '.docx', '.csv', '.vtt', '.properties'
|
||||
]
|
||||
|
||||
// 第三方服务配置
|
||||
public readonly COZE_BOT_ID = import.meta.env.VITE_COZE_BOT_ID || ''
|
||||
public readonly DIFY_API_KEY = import.meta.env.VITE_DIFY_API_KEY || ''
|
||||
|
||||
// 功能开关
|
||||
public readonly ENABLE_MOCK = import.meta.env.VITE_ENABLE_MOCK === 'true'
|
||||
public readonly ENABLE_DEVTOOLS = import.meta.env.VITE_ENABLE_DEVTOOLS === 'true'
|
||||
public readonly ENABLE_ERROR_REPORTING = import.meta.env.VITE_ENABLE_ERROR_REPORTING === 'true'
|
||||
public readonly ENABLE_ANALYTICS = import.meta.env.VITE_ENABLE_ANALYTICS === 'true'
|
||||
|
||||
// 安全配置
|
||||
public readonly JWT_EXPIRE_TIME = parseInt(import.meta.env.VITE_JWT_EXPIRE_TIME || '86400') // 24小时
|
||||
public readonly REFRESH_TOKEN_EXPIRE_TIME = parseInt(import.meta.env.VITE_REFRESH_TOKEN_EXPIRE_TIME || '604800') // 7天
|
||||
|
||||
// 性能配置
|
||||
public readonly ENABLE_LAZY_LOADING = import.meta.env.VITE_ENABLE_LAZY_LOADING === 'true'
|
||||
public readonly ENABLE_CODE_SPLITTING = import.meta.env.VITE_ENABLE_CODE_SPLITTING === 'true'
|
||||
public readonly CHUNK_SIZE_WARNING_LIMIT = parseInt(import.meta.env.VITE_CHUNK_SIZE_WARNING_LIMIT || '1000')
|
||||
|
||||
// 调试配置
|
||||
public readonly LOG_LEVEL = import.meta.env.VITE_LOG_LEVEL || 'info'
|
||||
public readonly ENABLE_REQUEST_LOG = import.meta.env.VITE_ENABLE_REQUEST_LOG === 'true'
|
||||
public readonly ENABLE_PERFORMANCE_LOG = import.meta.env.VITE_ENABLE_PERFORMANCE_LOG === 'true'
|
||||
|
||||
// 环境判断
|
||||
public readonly isDevelopment = this.APP_ENV === 'development'
|
||||
public readonly isProduction = this.APP_ENV === 'production'
|
||||
public readonly isStaging = this.APP_ENV === 'staging'
|
||||
|
||||
/**
|
||||
* 获取完整的API地址
|
||||
*/
|
||||
public getApiUrl(path: string): string {
|
||||
// 移除路径开头的斜杠,避免重复
|
||||
const cleanPath = path.startsWith('/') ? path.slice(1) : path
|
||||
// 确保API基础URL不以斜杠结尾
|
||||
const baseUrl = this.API_BASE_URL.endsWith('/') ? this.API_BASE_URL.slice(0, -1) : this.API_BASE_URL
|
||||
return `${baseUrl}/${cleanPath}`
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取完整的WebSocket地址
|
||||
*/
|
||||
public getWsUrl(path: string): string {
|
||||
const cleanPath = path.startsWith('/') ? path.slice(1) : path
|
||||
const baseUrl = this.WS_BASE_URL.endsWith('/') ? this.WS_BASE_URL.slice(0, -1) : this.WS_BASE_URL
|
||||
return `${baseUrl}/${cleanPath}`
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取完整的上传地址
|
||||
*/
|
||||
public getUploadUrl(path?: string): string {
|
||||
if (!path) return this.UPLOAD_BASE_URL
|
||||
const cleanPath = path.startsWith('/') ? path.slice(1) : path
|
||||
const baseUrl = this.UPLOAD_BASE_URL.endsWith('/') ? this.UPLOAD_BASE_URL.slice(0, -1) : this.UPLOAD_BASE_URL
|
||||
return `${baseUrl}/${cleanPath}`
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查文件类型是否允许
|
||||
*/
|
||||
public isAllowedFileType(fileName: string): boolean {
|
||||
const extension = fileName.toLowerCase().substring(fileName.lastIndexOf('.'))
|
||||
return this.UPLOAD_ALLOWED_TYPES.includes(extension)
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查文件大小是否超限
|
||||
*/
|
||||
public isFileSizeValid(size: number): boolean {
|
||||
return size <= this.UPLOAD_MAX_SIZE
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化文件大小
|
||||
*/
|
||||
public formatFileSize(bytes: number): string {
|
||||
if (bytes === 0) return '0 Bytes'
|
||||
const k = 1024
|
||||
const sizes = ['Bytes', 'KB', 'MB', 'GB']
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k))
|
||||
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取最大上传大小的友好显示
|
||||
*/
|
||||
public getMaxUploadSizeText(): string {
|
||||
return this.formatFileSize(this.UPLOAD_MAX_SIZE)
|
||||
}
|
||||
|
||||
/**
|
||||
* 打印环境配置信息(仅开发环境)
|
||||
*/
|
||||
public printConfig(): void {
|
||||
if (!this.isDevelopment) return
|
||||
|
||||
console.group('🔧 环境配置信息')
|
||||
console.log('应用环境:', this.APP_ENV)
|
||||
console.log('应用标题:', this.APP_TITLE)
|
||||
console.log('应用版本:', this.APP_VERSION)
|
||||
console.log('API地址:', this.API_BASE_URL)
|
||||
console.log('WebSocket地址:', this.WS_BASE_URL)
|
||||
console.log('使用模拟数据:', this.USE_MOCK_DATA)
|
||||
console.log('启用开发工具:', this.ENABLE_DEVTOOLS)
|
||||
console.log('最大上传大小:', this.getMaxUploadSizeText())
|
||||
console.log('允许的文件类型:', this.UPLOAD_ALLOWED_TYPES.join(', '))
|
||||
console.groupEnd()
|
||||
}
|
||||
}
|
||||
|
||||
// 导出环境配置实例
|
||||
export const env = new EnvConfig()
|
||||
|
||||
// 在开发环境下打印配置信息
|
||||
if (env.isDevelopment && env.ENABLE_REQUEST_LOG) {
|
||||
env.printConfig()
|
||||
}
|
||||
|
||||
export default env
|
||||
Reference in New Issue
Block a user